Team Ai
Datasetpublic

hschumann2/TempleOS-Source-Code

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes847downloads
FileSysFAT.txt961 linesDownload Raw Back to BlkDev
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