hschumann2/TempleOS-Source-Code
0847
1 2U0 CDate2Dos(U16 *t,U16 *d,CDate cdt)3{4 CDateStruct ds;5 Date2Struct(&ds,cdt);6 *d=ds.day_of_mon+(ds.mon+(ds.year-1980)<<4)<<5;7 *t=ds.sec>>1+(ds.min+ds.hour<<6)<<5;8}9 10CDate Dos2CDate(U16 t,U16 d)11{12 CDateStruct ds;13 MemSet(&ds,0,sizeof(CDateStruct));14 ds.day_of_mon=d&0x1F; d=d>>5;15 ds.mon=d&0xF;16 ds.year=d>>4+1980;17 ds.sec=(t&0x1F)*2; t=t>>5;18 ds.min=t&0x3F;19 ds.hour=t>>6;20 return Struct2Date(&ds);21}22 23U0 FAT32Init(CDrv *dv)24{25 CFAT32Boot br32;26 Bool unlock;27 try {28 unlock=DrvLock(dv);29 dv->fs_type=FSt_FAT32;30 BlkRead(dv,&br32,dv->drv_offset,1);31 dv->file_system_info_sect=dv->drv_offset+br32.file_system_info_sect;32 dv->fat1=dv->drv_offset+br32.reserved_sects;33 dv->fat2=dv->fat1+br32.sects_per_fat;34 dv->data_area=dv->fat2+br32.sects_per_fat35 -2*br32.sects_per_clus; //Starts at Clus 236 dv->spc=br32.sects_per_clus;37 dv->root_clus=br32.root_clus;38 DrvFATBlkAlloc(dv);39 Free(dv->fis);40 dv->fis=AMAlloc(BLK_SIZE);41 BlkRead(dv,dv->fis,dv->file_system_info_sect,1);42 if (unlock)43 DrvUnlock(dv);44 } catch45 if (unlock)46 DrvUnlock(dv);47}48 49U0 FAT32Fmt(U8 drv_let,Bool quick=TRUE)50{51 CFAT32Boot *br=CAlloc(BLK_SIZE);52 CFAT32FileInfoSect *fis=CAlloc(BLK_SIZE);53 CDrv *dv=Let2Drv(drv_let);54 I64 i,l;55 try {56 DrvLock(dv);57 DrvTypeSet(drv_let,FSt_FAT32);58 dv->fs_type=FSt_FAT32;59 br->jump_and_nop[0]=OC_JMP_REL8;60 br->jump_and_nop[1]=offset(CFAT32Boot.code)-2;61 br->jump_and_nop[2]=OC_NOP;62 br->oem_name[0](I64)='MSWIN4.1';63 br->bytes_per_sect=BLK_SIZE;64 if (dv->size<= 500000)65 br->sects_per_clus=1;66 else if (dv->size<=2000000)67 br->sects_per_clus=2;68 else if (dv->size<=6000000)69 br->sects_per_clus=4;70 else if (dv->size<=12000000)71 br->sects_per_clus=8;72 else if (dv->size<=33000000)73 br->sects_per_clus=16;74 else if (dv->size<=67000000)75 br->sects_per_clus=32;76 else77 br->sects_per_clus=64;78 79 br->reserved_sects=32;80 br->copies_of_fat=2;81 br->media_desc=0xF8;82 br->sects=dv->size;83 l=(br->sects/br->sects_per_clus)>>(BLK_SIZE_BITS-2)+1;84 br->sects_per_fat=l;85 br->root_clus=2;86 br->file_system_info_sect=1;87 br->log_drv_num=0x80;88 br->ext_signature=0x29;89 br->serial_num=RandU32;90 MemCpy(br->vol_name,"NO NAME ",11);91 br->fat_name[0](I64)='FAT32 ';92 br->signature=0xAA55;93 fis->signature1='RRaA';94 fis->signature2='rrAa';95 fis->free_clus=-1;96 fis->most_recently_alloced=0;97 fis->signature3=0xAA550000;98 99 if (quick)100 i=br->reserved_sects+2*l+4*br->sects_per_clus;101 else102 i=dv->size;103 BlkWriteZero(dv,dv->drv_offset,i);104 105 BlkWrite(dv,fis,dv->drv_offset+br->file_system_info_sect,1);106 BlkWrite(dv,br,dv->drv_offset,1);107 FAT32Init(dv);108 ClusAlloc(dv,0,1,FALSE); //Alloc #1109 br->root_clus=ClusAlloc(dv,0,1,FALSE);110 BlkWrite(dv,br,dv->drv_offset,1);111 FAT32Init(dv);112 DrvUnlock(dv);113 } catch114 DrvUnlock(dv);115 Free(br);116 Free(fis);117}118 119Bool FATNameTo(U8 *dst,U8 *src)120{121 I64 i;122 MemSet(dst,CH_SPACE,11);123 if (!FileNameChk(src))124 return FALSE;125 if (!StrCmp(src,"..")) {126 *dst='.';127 dst[1]='.';128 return TRUE;129 } else if (!StrCmp(src,".")) {130 *dst='.';131 return TRUE;132 }133 i=0;134 while (i<8 && *src && *src!='.')135 dst[i++]=ToUpper(*src++);136 i=8;137 if (*src=='.') src++;138 while (*src)139 if (*src!='.')140 dst[i++]=ToUpper(*src++);141 else142 src++;143 return TRUE;144}145 146I64 FATNameXSum(U8 *src)147{148 I64 i,res=0;149 for (i=0;i<11;i++)150 if (res&1)151 res.u8[0]=0x80+res>>1+*src++;152 else153 res.u8[0]=res>>1+*src++;154 return res;155}156 157Bool FATFromName(U8 *dst,U8 *src)158{159 I64 i,j,k=0;160 for (j=7;j>=0 && src[j]==CH_SPACE;j--);161 for(i=0;i<=j;i++)162 dst[k++]=src[i];163 for (j=10;j>=8 && src[j]==CH_SPACE;j--);164 if (*src!='.' && j!=7)165 dst[k++]='.';166 for(i=8;i<=j;i++)167 dst[k++]=src[i];168 dst[k++]=0;169 return FileNameChk(dst);170}171 172U8 fat_long_name_map[13]={173 offset(CFAT32DirEntryLong.name1),174 offset(CFAT32DirEntryLong.name1)+2,175 offset(CFAT32DirEntryLong.name1)+4,176 offset(CFAT32DirEntryLong.name1)+6,177 offset(CFAT32DirEntryLong.name1)+8,178 offset(CFAT32DirEntryLong.name2),179 offset(CFAT32DirEntryLong.name2)+2,180 offset(CFAT32DirEntryLong.name2)+4,181 offset(CFAT32DirEntryLong.name2)+6,182 offset(CFAT32DirEntryLong.name2)+8,183 offset(CFAT32DirEntryLong.name2)+10,184 offset(CFAT32DirEntryLong.name3),185 offset(CFAT32DirEntryLong.name3)+2186};187 188Bool DirLongNameFill(CDirEntry *tmpde,CFAT32DirEntryLong *de,I64 *xsum)189{190 I64 i;191 U8 *ptr=de;192 if (de->ord&0x40) {193 MemSet(tmpde,0,sizeof(CDirEntry));194 *xsum=de->xsum;195 } else if (de->type || de->zero || de->xsum!=*xsum) {196 MemSet(tmpde,0,sizeof(CDirEntry));197 *xsum=0;198 return FALSE;199 }200 switch (de->ord&0x3F) {201 case 1:202 for (i=0;i<13;i++)203 if (!(tmpde->name[i]=ptr[fat_long_name_map[i]]))204 return TRUE;205 break;206 case 2:207 for (i=0;i<12;i++)208 if (!(tmpde->name[i+13]=ptr[fat_long_name_map[i]]))209 return TRUE;210 break;211 }212 return TRUE;213}214 215Bool FAT32CDirFill(CDirEntry *tmpde,216 CFAT32DirEntry *de,CDate _local_time_offset)217{218 Bool res;219 if (*tmpde->name)220 res=TRUE;221 else222 res=FATFromName(tmpde->name,de->name);223 tmpde->clus=de->clus_lo+de->clus_hi<<16;224 tmpde->size=de->size;225 tmpde->attr=de->attr;226 tmpde->datetime=Dos2CDate(de->WrtTime,de->WrtDate)-_local_time_offset;227 return res;228}229 230Bool FAT32DirFill(CFAT32DirEntry *de,231 CDirEntry *tmpde,I64 *_de_cnt,CDate _local_time_offset)232{//Fill up to 3 entries and store cnt of entries.233 I64 de_cnt=0,i,l,xsum,ord;234 U8 *ptr,dname[16];235 CFAT32DirEntryLong *ld=de;236 Bool res;237 238 MemSet(de,0,sizeof(CFAT32DirEntry));239 res=FATNameTo(de->name,tmpde->name);240 FATFromName(dname,de->name);241 if (StrCmp(dname,tmpde->name)) {242 ord=0x41;243 xsum=FATNameXSum(de->name);244 if ((l=StrLen(tmpde->name))>13) {245 ptr=&ld[de_cnt];246 MemSet(ptr,0,sizeof(CFAT32DirEntryLong));247 ld[de_cnt].attr=RS_ATTR_LONG_NAME;248 ld[de_cnt].xsum=xsum;249 ld[de_cnt].ord=0x42;250 for (i=13;i<l;i++)251 ptr[fat_long_name_map[i-13]]=tmpde->name[i];252 i++;253 for (;i<26;i++)254 ptr[fat_long_name_map[i-13]](U16)=0xFFFF;255 ord=1;256 l=13;257 de_cnt++;258 }259 ptr=&de[de_cnt];260 MemSet(ptr,0,sizeof(CFAT32DirEntryLong));261 ld[de_cnt].attr=RS_ATTR_LONG_NAME;262 ld[de_cnt].xsum=xsum;263 ld[de_cnt].ord=ord;264 for (i=0;i<l;i++)265 ptr[fat_long_name_map[i]]=tmpde->name[i];266 i++;267 for (;i<13;i++)268 ptr[fat_long_name_map[i]](U16)=0xFFFF;269 de_cnt++;270 MemSet(&de[de_cnt],0,sizeof(CFAT32DirEntry));271 res=FATNameTo(de[de_cnt].name,tmpde->name);272 }273 de[de_cnt].clus_lo=tmpde->clus.u16[0];274 de[de_cnt].clus_hi=tmpde->clus.u16[1];275 if (!(tmpde->attr&RS_ATTR_DIR))276 de[de_cnt].size=tmpde->size;277 de[de_cnt].attr=tmpde->attr;278 if (!tmpde->datetime)279 tmpde->datetime=Now;280 CDate2Dos(&de[de_cnt].WrtTime,&de[de_cnt].WrtDate,281 tmpde->datetime+_local_time_offset);282 if (_de_cnt)283 *_de_cnt=de_cnt+1;284 return res;285}286 287Bool FAT32FileFind(CDrv *dv,I64 cur_dir_clus,288 U8 *name,CDirEntry *_res,I64 fuf_flags=0)289{//FUF_JUST_DIRS, FUF_JUST_FILES290 Bool res=FALSE,unlock;291 CFAT32DirEntry *buf;292 I64 xsum=0,attr,cur_dir_entry,entries_per_clus;293 U8 dname[CDIR_FILENAME_LEN],ch;294 CDirEntry long_name;295 if (fuf_flags&~FUG_FILE_FIND)296 throw('FUF');297 MemSet(_res,0,sizeof(CDirEntry));298 MemSet(&long_name,0,sizeof(CDirEntry));299 DrvChk(dv);300 if (dv->fs_type!=FSt_FAT32)301 PrintErr("Not FAT32 Drv\n");302 else if (!CFileNameTo(dname,name))303 PrintErr("Invalid FileName: \"%s\".\n",name);304 else305 try {306 unlock=DrvLock(dv);307 buf=MAlloc(BLK_SIZE*dv->spc);308 entries_per_clus=dv->spc<<FAT32_ENTRIES_BITS;309 ClusRead(dv,buf,cur_dir_clus,1);310 cur_dir_entry=0;311 while (ch=*buf[cur_dir_entry].name) {312 attr=buf[cur_dir_entry].attr;313 if (ch!=0xE5) {314 if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)315 DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);316 else {317 if (!(attr&RS_ATTR_VOL_ID)) {318 if (xsum==FATNameXSum(buf[cur_dir_entry].name))319 MemCpy(_res,&long_name,sizeof(CDirEntry));320 else321 MemSet(_res,0,sizeof(CDirEntry));322 if (!(fuf_flags&FUF_JUST_DIRS && !(attr & RS_ATTR_DIR)) &&323 !(fuf_flags&FUF_JUST_FILES && attr & RS_ATTR_DIR) &&324 FAT32CDirFill(_res,&buf[cur_dir_entry],325 dv->fat32_local_time_offset) &&326 !StrCmp(dname,_res->name)) {327 res=TRUE;328 goto fff_done;329 }330 }331 MemSet(&long_name,0,sizeof(CDirEntry));332 }333 } else334 MemSet(&long_name,0,sizeof(CDirEntry));335 if (++cur_dir_entry==entries_per_clus) {336 cur_dir_clus=ClusNumNext(dv,cur_dir_clus);337 if (!(0<cur_dir_clus<0x0FFFFFF8))338 break;339 else {340 ClusRead(dv,buf,cur_dir_clus,1);341 cur_dir_entry=0;342 }343 }344 }345 MemSet(_res,0,sizeof(CDirEntry));346fff_done:347 Free(buf);348 if (unlock)349 DrvUnlock(dv);350 } catch351 if (unlock)352 DrvUnlock(dv);353 return res;354}355 356U8 *FAT32FileRead(CDrv *dv,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)357{358 U8 *buf=NULL;359 CDirEntry de;360 I64 c,blk_cnt,cur_dir_clus;361 DrvChk(dv);362 *_size=0;363 *_attr=0;364 if (dv->fs_type!=FSt_FAT32)365 PrintErr("Not FAT32 Drv\n");366 else367 try {368 DrvLock(dv);369 cur_dir_clus=Name2DirClus(dv,cur_dir);370 if (FAT32FileFind(dv,cur_dir_clus,filename,&de,FUF_JUST_FILES)) {371 blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;372 buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);373 c=de.clus;374 if (!(0<c<0x0FFFFFF8))375 c=0x0FFFFFFF;376 else377 c=ClusBlkRead(dv,buf,c,blk_cnt);378 buf[de.size]=0; //Terminate379 *_size=de.size;380 *_attr=FileAttr(de.name,de.attr);381 }382 DrvUnlock(dv);383 } catch384 DrvUnlock(dv);385 return buf;386}387 388Bool FAT32Cd(U8 *name,I64 cur_dir_clus)389{390 CDirEntry de;391 if (Fs->cur_dv->fs_type!=FSt_FAT32)392 PrintErr("Not FAT32 Drv\n");393 else if (FAT32FileFind(Fs->cur_dv,cur_dir_clus,name,&de,FUF_JUST_DIRS))394 return TRUE;395 else396 PrintErr("File not found: \"%s\".\n",name);397 return FALSE;398}399 400U0 FAT32FreeClus(CDrv *dv,I64 c)401{402 I64 next,saved_c=c;403 Bool unlock,unlock_break;404 DrvChk(dv);405 if (!(0<c<0x0FFFFFF8)) return;406 if (dv->fs_type!=FSt_FAT32)407 PrintErr("Not FAT32 Drv\n");408 else409 try {410 unlock_break=BreakLock;411 unlock=DrvLock(dv);412 DrvFATBlkClean(dv);413 do {414 DrvFATBlkSet(dv,c,0);415 next=dv->cur_fat_blk[c&(BLK_SIZE/4-1)];416 dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0;417 LBts(&dv->fat_blk_dirty,0);418 c=next;419 } while (0<c<0x0FFFFFF8);420 DrvFATBlkClean(dv,0);421 422 c=saved_c;423 do {424 DrvFATBlkSet(dv,c,1);425 next=dv->cur_fat_blk[c&(BLK_SIZE/4-1)];426 dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0;427 LBts(&dv->fat_blk_dirty,0);428 c=next;429 } while (0<c<0x0FFFFFF8);430 DrvFATBlkClean(dv,1);431 if (unlock)432 DrvUnlock(dv);433 if (unlock_break)434 BreakUnlock;435 } catch {436 if (unlock)437 DrvUnlock(dv);438 if (unlock_break)439 BreakUnlock;440 }441}442 443I64 FAT32AllocClus(CDrv *dv,I64 c,I64 cnt)444{445 Bool wrap_around=FALSE,unlock,unlock_break;446 I64 first=INVALID_CLUS,j,l;447 448 if (cnt<=0) return 0x0FFFFFFF;449 try {450 unlock_break=BreakLock;451 unlock=DrvLock(dv);452 l=(dv->size+dv->drv_offset-dv->data_area)/dv->spc-1;453 j=dv->fis->most_recently_alloced;454 while (cnt-->0) {455 while (TRUE) {456 j++;457 if (j<1) j=1;458 if (j>=l) {459 if (wrap_around)460 throw('Drv');461 j=1;462 wrap_around=TRUE;463 }464 DrvFATBlkSet(dv,j);465 if (!dv->cur_fat_blk[j&(BLK_SIZE/4-1)])466 break;467 }468 if (!(0<first<0x0FFFFFF8))469 first=j;470 if (0<c<l) {471 DrvFATBlkSet(dv,c);472 dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=j;473 LBts(&dv->fat_blk_dirty,0);474 }475 c=j;476 }477 478 if (0<c<l) {479 DrvFATBlkSet(dv,c);480 dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0x0FFFFFFF;481 LBts(&dv->fat_blk_dirty,0);482 }483 DrvFATBlkClean(dv);484 485 dv->fis->most_recently_alloced=j;486 dv->fis->free_clus=-1;487 BlkWrite(dv,dv->fis,dv->file_system_info_sect,1);488 } catch {489 if (unlock)490 DrvUnlock(dv);491 if (unlock_break)492 BreakUnlock;493 }494 if (unlock)495 DrvUnlock(dv);496 if (unlock_break)497 BreakUnlock;498 return first;499}500 501I64 FAT32AllocContiguousClus(CDrv *dv,I64 cnt)502{503 I64 i,first=1;504 Bool cont,unlock,unlock_break;505 506 if (cnt<=0) return 0x0FFFFFFF;507 try {508 unlock_break=BreakLock;509 unlock=DrvLock(dv);510 while (TRUE) {511 first++;512 i=0;513 cont=TRUE;514 while (cont && i<cnt) {515 if ((first+i+1)*dv->spc+dv->data_area>dv->size+dv->drv_offset)516 throw('Drv');517 DrvFATBlkSet(dv,first+i);518 if (dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)])519 cont=FALSE;520 else521 i++;522 }523 if (!cont)524 first=first+i;525 else {526 DrvFATBlkClean(dv);527 528 for (i=0;i<cnt;i++) {529 DrvFATBlkSet(dv,first+i,0);530 if (i+1==cnt)531 dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF;532 else533 dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1;534 LBts(&dv->fat_blk_dirty,0);535 }536 DrvFATBlkClean(dv,0);537 538 for (i=0;i<cnt;i++) {539 DrvFATBlkSet(dv,first+i,1);540 if (i+1==cnt)541 dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF;542 else543 dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1;544 LBts(&dv->fat_blk_dirty,0);545 }546 DrvFATBlkClean(dv,1);547 break;548 }549 }550 } catch {551 if (unlock)552 DrvUnlock(dv);553 if (unlock_break)554 BreakUnlock;555 }556 if (unlock)557 DrvUnlock(dv);558 if (unlock_break)559 BreakUnlock;560 return first;561}562 563Bool FAT32DirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tmpde,Bool free_old_chain)564{565//See ::/Doc/CutCorners.DD.566 CFAT32DirEntry *buf,*last_buf,*tmp_buf,de[3];567 I64 i,attr,avail_cnt,de_cnt,c,568 cur_dir_entry,entries_per_clus,569 cur_dir_clus,xsum=0,last_dir_clus=INVALID_CLUS;570 U8 ch;571 Bool written=FALSE,unlock,unlock_break;572 CDirEntry long_name;573 FAT32DirFill(&de,tmpde,&de_cnt,dv->fat32_local_time_offset);574 MemSet(&long_name,0,sizeof(CDirEntry));575 try {576 unlock_break=BreakLock;577 unlock=DrvLock(dv);578 cur_dir_clus=Name2DirClus(dv,cur_dir);579 buf =MAlloc(BLK_SIZE*dv->spc);580 last_buf=CAlloc(BLK_SIZE*dv->spc);581 entries_per_clus=dv->spc<<FAT32_ENTRIES_BITS;582 ClusRead(dv,buf,cur_dir_clus,1);583 cur_dir_entry=0;584 while (ch=*buf[cur_dir_entry].name) {585 attr=buf[cur_dir_entry].attr;586 if (ch!=0xE5 && attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)587 DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);588 else {589 avail_cnt=FAT32_ENTRIES_PER_BLK-cur_dir_entry590 &(FAT32_ENTRIES_PER_BLK-1);591 for (i=0;i<avail_cnt;i++)592 if (*buf[cur_dir_entry+i].name!=0xE5) {593 if (*buf[cur_dir_entry+i].name)594 avail_cnt=i;595 break;596 }597 if (ch==0xE5 && !written && avail_cnt>=de_cnt) {598 MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry));599 BlkWrite(dv,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK],600 dv->data_area+cur_dir_clus*dv->spc601 +cur_dir_entry>>FAT32_ENTRIES_BITS,1);602 cur_dir_entry+=de_cnt-1; //gets inc'ed603 written=TRUE;604 } else if (ch!=0xE5 && !(attr&RS_ATTR_VOL_ID)) {605 if (xsum!=FATNameXSum(buf[cur_dir_entry].name))606 MemSet(&long_name,0,sizeof(CDirEntry));607 if (!*long_name.name)608 FATFromName(long_name.name,buf[cur_dir_entry].name);609//Del old entry with same name610 if (!StrCmp(long_name.name,tmpde->name)) {611 if (free_old_chain)612 FAT32FreeClus(dv,buf[cur_dir_entry].clus_lo+613 buf[cur_dir_entry].clus_hi<<16);614 if (!written) {615 MemCpy(&buf[cur_dir_entry],&de[de_cnt-1],sizeof(CFAT32DirEntry));616 BlkWrite(dv,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK],617 dv->data_area+cur_dir_clus*dv->spc618 +cur_dir_entry>>FAT32_ENTRIES_BITS,1);619 written=TRUE;620 } else {621 *buf[cur_dir_entry].name=0xE5;622 i=1;623 while (i<=cur_dir_entry &&624 buf[cur_dir_entry-i].attr&RS_ATTR_LONG_NAME_MASK625 ==RS_ATTR_LONG_NAME)626 *buf[cur_dir_entry-i++].name=0xE5;627 i--;628 BlkWrite(dv,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK],629 dv->data_area+cur_dir_clus*dv->spc630 +(cur_dir_entry-i)>>FAT32_ENTRIES_BITS,631 (i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS);632 if (i==cur_dir_entry && 0<last_dir_clus<0x0FFFFFF8) {633 i=1;634 while (i<=entries_per_clus &&635 last_buf[entries_per_clus-i].attr636 &RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)637 *last_buf[entries_per_clus-i++].name=0xE5;638 if (--i>0)639 BlkWrite(dv,&buf[(entries_per_clus-i)&-FAT32_ENTRIES_PER_BLK],640 dv->data_area+last_dir_clus*dv->spc641 +(entries_per_clus-i)>>FAT32_ENTRIES_BITS,642 (i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS);643 }644 }645 break;646 }647 }648 MemSet(&long_name,0,sizeof(CDirEntry));649 }650 if (++cur_dir_entry==entries_per_clus) {651 last_dir_clus=cur_dir_clus;652 tmp_buf=buf; buf=last_buf; last_buf=tmp_buf;653 c=ClusNumNext(dv,cur_dir_clus);654 if (!(0<c<0x0FFFFFF8)) {655 c=ClusAlloc(dv,cur_dir_clus,1,FALSE);656 MemSet(buf,0,BLK_SIZE*dv->spc);657 ClusWrite(dv,buf,c,1);658 } else659 ClusRead(dv,buf,c,1);660 cur_dir_clus=c;661 cur_dir_entry=0;662 }663 }664 if (!written) {665 avail_cnt=FAT32_ENTRIES_PER_BLK-cur_dir_entry & (FAT32_ENTRIES_PER_BLK-1);666 if (avail_cnt<de_cnt) {667 for (i=0;i<avail_cnt;i++)668 *buf[cur_dir_entry+i].name=0xE5;669 BlkWrite(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],670 dv->data_area+cur_dir_clus*dv->spc671 +cur_dir_entry>>FAT32_ENTRIES_BITS,1);672 cur_dir_entry+=avail_cnt;673 if (cur_dir_entry==entries_per_clus) {674 last_dir_clus=cur_dir_clus;675 tmp_buf=buf; buf=last_buf; last_buf=tmp_buf;676 cur_dir_clus=ClusAlloc(dv,cur_dir_clus,1);677 cur_dir_entry=0;678 MemSet(buf,0,BLK_SIZE*dv->spc);679 ClusWrite(dv,buf,cur_dir_clus,1);680 }681 }682 MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry));683 BlkWrite(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],684 dv->data_area+cur_dir_clus*dv->spc+685 cur_dir_entry>>FAT32_ENTRIES_BITS,1);686 cur_dir_entry+=de_cnt;687 if (cur_dir_entry==entries_per_clus) {688 cur_dir_clus=ClusAlloc(dv,cur_dir_clus,1);689 MemSet(buf,0,BLK_SIZE*dv->spc);690 ClusWrite(dv,buf,cur_dir_clus,1);691 } else {692 MemSet(&buf[cur_dir_entry],0,sizeof(CFAT32DirEntry));693 BlkWrite(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],694 dv->data_area+cur_dir_clus*dv->spc695 +cur_dir_entry>>FAT32_ENTRIES_BITS,1);696 }697 }698 Free(last_buf);699 Free(buf);700 if (unlock)701 DrvUnlock(dv);702 if (unlock_break)703 BreakUnlock;704 } catch {705 if (unlock)706 DrvUnlock(dv);707 if (unlock_break)708 BreakUnlock;709 }710 return FALSE;711}712 713I64 FAT32FilesDel(CDrv *dv,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,714 Bool del_dir,Bool print_msg)715{716 CFAT32DirEntry *buf,*last_buf,*tmp_buf;717 I64 i,res=0,attr,xsum=0,last_dir_clus=INVALID_CLUS,718 cur_dir_entry,entries_per_clus,cur_dir_clus;719 U8 ch;720 Bool unlock_break;721 CDirEntry long_name;722 MemSet(&long_name,0,sizeof(CDirEntry));723 try {724 unlock_break=BreakLock;725 DrvLock(dv);726 cur_dir_clus=Name2DirClus(dv,cur_dir);727 buf =MAlloc(BLK_SIZE*dv->spc);728 last_buf=CAlloc(BLK_SIZE*dv->spc);729 entries_per_clus=dv->spc<<FAT32_ENTRIES_BITS;730 ClusRead(dv,buf,cur_dir_clus,1);731 cur_dir_entry=0;732 while (ch=*buf[cur_dir_entry].name) {733 attr=buf[cur_dir_entry].attr;734 if (ch!=0xE5 && ch!='.') {735 if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)736 DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);737 else {738 if (!(attr & RS_ATTR_VOL_ID) &&739 (del_dir || !(attr & RS_ATTR_DIR))) {740 if (xsum!=FATNameXSum(buf[cur_dir_entry].name))741 MemSet(&long_name,0,sizeof(CDirEntry));742 if (!*long_name.name)743 FATFromName(long_name.name,buf[cur_dir_entry].name);744 if (FilesFindMatch(long_name.name,files_find_mask,fuf_flags)) {745 if (!(attr & RS_ATTR_DIR)) res++;746 if (print_msg)747 "Del %s\n",long_name.name;748 *buf[cur_dir_entry].name=0xE5;749 i=1;750 while (i<=cur_dir_entry &&751 buf[cur_dir_entry-i].attr&RS_ATTR_LONG_NAME_MASK752 ==RS_ATTR_LONG_NAME)753 *buf[cur_dir_entry-i++].name=0xE5;754 i--;755 BlkWrite(dv,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK],756 dv->data_area+cur_dir_clus*dv->spc757 +(cur_dir_entry-i)>>FAT32_ENTRIES_BITS,758 (i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS);759 if (i==cur_dir_entry && last_dir_clus!=INVALID_CLUS) {760 i=1;761 while (i<=entries_per_clus &&762 last_buf[entries_per_clus-i].attr763 &RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)764 *last_buf[entries_per_clus-i++].name=0xE5;765 if (--i>0)766 BlkWrite(dv,&buf[(entries_per_clus-i)&-FAT32_ENTRIES_PER_BLK],767 dv->data_area+last_dir_clus*dv->spc768 +(entries_per_clus-i)>>FAT32_ENTRIES_BITS,769 (i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS);770 }771 FAT32FreeClus(dv,buf[cur_dir_entry].clus_lo+772 buf[cur_dir_entry].clus_hi<<16);773 }774 }775 MemSet(&long_name,0,sizeof(CDirEntry));776 }777 } else778 MemSet(&long_name,0,sizeof(CDirEntry));779 if (++cur_dir_entry==entries_per_clus) {780 last_dir_clus=cur_dir_clus;781 cur_dir_clus=ClusNumNext(dv,cur_dir_clus,1);782 tmp_buf=buf; buf=last_buf; last_buf=tmp_buf;783 ClusRead(dv,buf,cur_dir_clus,1);784 cur_dir_entry=0;785 }786 }787 Free(buf);788 Free(last_buf);789 DrvUnlock(dv);790 if (unlock_break)791 BreakUnlock;792 } catch {793 DrvUnlock(dv);794 if (unlock_break)795 BreakUnlock;796 }797 return res;798}799 800I64 FAT32FileWrite(CDrv *dv,U8 *cur_dir,U8 *name,U8 *buf,I64 size,801 CDate cdt,I64 attr)802{803 CDirEntry de;804 I64 c=0,blk_cnt;805 Bool contiguous;806 MemSet(&de,0,sizeof(CDirEntry));807 if (size<0) size=0;808 if (dv->fs_type!=FSt_FAT32)809 PrintErr("Not FAT32 Drv\n");810 else if (!CFileNameTo(de.name,name))811 PrintErr("Invalid FileName: \"%s\".\n",name);812 else {813 FAT32FilesDel(dv,cur_dir,de.name,0,FALSE,FALSE);814 if (attr & RS_ATTR_CONTIGUOUS)815 contiguous=TRUE;816 else817 contiguous=FALSE;818 de.size=size;819 if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)820 c=ClusAlloc(dv,0,(blk_cnt+dv->spc-1)/dv->spc,contiguous);821 else822 c=0x0FFFFFFF;823 de.clus=c;824 de.attr=attr;825 de.datetime=cdt;826 if (blk_cnt)827 ClusBlkWrite(dv,buf,c,blk_cnt);828 FAT32DirNew(dv,cur_dir,&de,TRUE);829 }830 return c;831}832 833CDirEntry *FAT32FilesFind(U8 *files_find_mask,834 I64 fuf_flags,CDirEntry *parent=NULL,I64 *_dir_size=NULL)835{836 CDrv *dv=Fs->cur_dv;837 CFAT32DirEntry *buf;838 I64 attr,xsum=0,dir_size=0,sub_dir_size,839 cur_dir_clus,cur_dir_entry,entries_per_clus;840 U8 ch;841 CDirEntry *res=NULL,*tmpde,long_name;842 if (fuf_flags&~FUG_FILES_FIND)843 throw('FUF');844 try {845 MemSet(&long_name,0,sizeof(CDirEntry));846 DrvLock(dv);847 cur_dir_clus=Name2DirClus(dv,Fs->cur_dir);848 buf=MAlloc(BLK_SIZE*dv->spc);849 entries_per_clus=dv->spc<<FAT32_ENTRIES_BITS;850 ClusRead(dv,buf,cur_dir_clus,1);851 dir_size+=dv->spc*BLK_SIZE;852 cur_dir_entry=0;853 while (ch=*buf[cur_dir_entry].name) {854 attr=buf[cur_dir_entry].attr;855 if (ch!=0xE5) {856 if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)857 DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);858 else {859 if (!(attr&RS_ATTR_VOL_ID)) {860 tmpde=MAlloc(sizeof(CDirEntry));861 if (xsum==FATNameXSum(buf[cur_dir_entry].name))862 MemCpy(tmpde,&long_name,sizeof(CDirEntry));863 else864 MemSet(tmpde,0,sizeof(CDirEntry));865 if (FAT32CDirFill(tmpde,&buf[cur_dir_entry],866 dv->fat32_local_time_offset)) {867 tmpde->parent=parent;868 if (Bt(&fuf_flags,FUf_RECURSE) && attr&RS_ATTR_DIR &&869 *tmpde->name!='.') {870 tmpde->next=res;871 res=tmpde;872 tmpde->full_name=DirNameAbs(tmpde->name);873 DrvUnlock(dv);874 if (Cd(tmpde->name)) {875 tmpde->sub=FAT32FilesFind(files_find_mask,fuf_flags,876 tmpde,&sub_dir_size);877 tmpde->size=sub_dir_size;878 Cd("..");879 }880 DrvLock(dv);881 } else {882 tmpde->full_name=FileNameAbs(tmpde->name);883 if ((attr&RS_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&884 !(Bt(&fuf_flags,FUf_RECURSE) &&885 *tmpde->name=='.' && attr&RS_ATTR_DIR) &&886 FilesFindMatch(tmpde->full_name,files_find_mask,887 fuf_flags)) {888 tmpde->next=res;889 res=tmpde;890 } else891 DirEntryDel(tmpde);892 }893 } else894 DirEntryDel(tmpde);895 }896 MemSet(&long_name,0,sizeof(CDirEntry));897 }898 } else899 MemSet(&long_name,0,sizeof(CDirEntry));900 if (++cur_dir_entry==entries_per_clus) {901 cur_dir_clus=ClusNumNext(dv,cur_dir_clus);902 if (cur_dir_clus==INVALID_CLUS)903 break;904 else {905 ClusRead(dv,buf,cur_dir_clus,1);906 dir_size+=dv->spc*BLK_SIZE;907 cur_dir_entry=0;908 }909 }910 }911 Free(buf);912 DrvUnlock(dv);913 } catch914 DrvUnlock(dv);915 if (_dir_size)916 *_dir_size=dir_size;917 return res;918}919 920Bool FAT32MkDir(CDrv *dv,U8 *cur_dir,U8 *name,I64 entry_cnt)921{922 I64 c,cur_dir_clus=Name2DirClus(dv,cur_dir),923//Rough estimate of size924 size=CeilU64((entry_cnt+2)<<FAT32_ENTRIES_BITS,dv->spc<<BLK_SIZE_BITS);925 U8 *buf=CAlloc(size);926 CDirEntry d_native;927 CFAT32DirEntry *dFAT=buf;928 Bool unlock_break;929 930 try {931 unlock_break=BreakLock;932 c=FileWrite(name,buf,size,0,RS_ATTR_DIR);933 MemSet(&d_native,0,sizeof(CDirEntry));934 d_native.attr=RS_ATTR_DIR;935 *d_native.name='.';936 d_native.name[1]=0;937 d_native.clus=c;938 d_native.size=0;939 d_native.datetime=Now;940 FAT32DirFill(dFAT,&d_native,NULL,dv->fat32_local_time_offset);941 dFAT++;942 943 MemSet(&d_native,0,sizeof(CDirEntry));944 d_native.attr=RS_ATTR_DIR;945 *d_native.name='.';946 d_native.name[1]='.';947 d_native.name[2]=0;948 d_native.clus=cur_dir_clus;949 d_native.size=0;950 d_native.datetime=Now;951 FAT32DirFill(dFAT,&d_native,NULL,dv->fat32_local_time_offset);952 ClusWrite(dv,buf,c,1);953 Free(buf);954 if (unlock_break)955 BreakUnlock;956 } catch957 if (unlock_break)958 BreakUnlock;959 return TRUE;960}961 