Team Ai
Datasetpublic

hschumann2/TempleOS-Source-Code

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes847downloads
FileSysRedSea.txt637 linesDownload Raw Back to BlkDev
1 2// See RedSea File System3 4U0 RedSeaFreeFreeLst(CDrv *dv)5{6  CFreeLst *tmpf,*tmpf1;7  Bool unlock;8  try {9    unlock=DrvLock(dv);10    if (tmpf=dv->next_free) {11      while (tmpf!=&dv->next_free) {12        tmpf1=tmpf->next;13        Free(tmpf);14        tmpf=tmpf1;15      }16    }17    dv->next_free=NULL;18    if (unlock)19      DrvUnlock(dv);20  } catch21    if (unlock)22      DrvUnlock(dv);23}24 25U0 RedSeaFreeLstBuild(CDrv *dv)26{27  Bool unlock;28  CFreeLst *tmpf;29  I64 i,first=dv->data_area,max_blk=dv->size+dv->drv_offset;30  try {31    unlock=DrvLock(dv);32    if (dv->next_free)33      RedSeaFreeFreeLst(dv);34    QueInit(&dv->next_free);35    while (first<max_blk) {36      i=0;  //count free clus37      while (first+i<max_blk) {38        DrvFATBlkSet(dv,first+i);39        if (Bt(dv->cur_fat_blk,(first+i-dv->data_area)&(BLK_SIZE<<3-1)))40          break;41        else42          i++;43      }44      if (i) {45        tmpf=AMAlloc(sizeof(CFreeLst));46        tmpf->size=i;47        tmpf->start=first;48        QueIns(tmpf,dv->last_free);49      }50      first+=i+1;51    }52    if (unlock)53      DrvUnlock(dv);54  } catch55    if (unlock)56      DrvUnlock(dv);57}58 59U0 RedSeaInit(CDrv *dv)60{61  CRedSeaBoot br;62  Bool unlock;63  try {64    unlock=DrvLock(dv);65    BlkRead(dv,&br,dv->drv_offset,1);66    if (br.signature!=MBR_PT_REDSEA || br.signature2!=0xAA55)67      throw('Drv');68    dv->fs_type=FSt_REDSEA;69    RedSeaFreeFreeLst(dv);70    dv->spc=1;71    dv->size=br.sects;72    dv->data_area=dv->drv_offset+br.bitmap_sects;73    dv->root_clus=br.root_clus;74    dv->fat1=dv->fat2=dv->drv_offset+1;75    DrvFATBlkAlloc(dv);76    if (unlock)77      DrvUnlock(dv);78  } catch79    if (unlock)80      DrvUnlock(dv);81}82 83Bool RedSeaValidate(U8 drv_let)84{85  CDrv *dv;86  CRedSeaBoot br;87  if ((dv=Let2Drv(drv_let,FALSE)) && dv->fs_type==FSt_REDSEA &&88        BlkRead(dv,&br,dv->drv_offset,1) && br.signature==MBR_PT_REDSEA &&89        br.signature2==0xAA55 && br.sects==dv->size)90    return TRUE;91  else92    return FALSE;93}94 95U0 RedSeaFmt(U8 drv_let,Bool quick=TRUE)96{97  U8 *root_dir;98  CDirEntry *d_native;99  CRedSeaBoot *br=CAlloc(BLK_SIZE);100  CDrv *dv=Let2Drv(drv_let);101  I64 i,n,root_dir_blks;102  try {103    DrvLock(dv);104//      DrvTypeSet(drv_let,FSt_REDSEA);105    DrvTypeSet(drv_let,FSt_FAT32);106    dv->fs_type=FSt_REDSEA;107    br->signature=MBR_PT_REDSEA;108    br->signature2=0xAA55;109    br->drv_offset=dv->drv_offset; //For CD/DVD image copy.110    br->sects=dv->size;111    n=(br->sects+BLK_SIZE<<3-1)/BLK_SIZE<<3;112    br->bitmap_sects=n;113    br->unique_id=GetTSC^Now()(U64);114    br->root_clus=0;115 116    if (quick)117      i=n+1;118    else119      i=dv->size;120    BlkWriteZero(dv,dv->drv_offset,i);121 122    BlkWrite(dv,br,dv->drv_offset,1);123    RedSeaInit(dv);124    ClusAlloc(dv,0,1,FALSE);    //Alloc #1125 126    root_dir_blks=MaxI64(1,dv->bd->init_root_dir_blks);127    br->root_clus=ClusAlloc(dv,0,root_dir_blks,FALSE);128    BlkWrite(dv,br,dv->drv_offset,1);129    root_dir=CAlloc(BLK_SIZE*root_dir_blks);130 131    d_native=root_dir-offset(CDirEntry.start);132 133    d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS;134    *d_native->name='.';135    d_native->clus=br->root_clus;136    d_native->size=BLK_SIZE*root_dir_blks;137    d_native->datetime=Now;138 139    d_native(U8 *)+=CDIR_SIZE;140 141    *d_native->name='.';142    d_native->name[1]='.';143    d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS;144    d_native->clus=br->root_clus;145    d_native->datetime=Now;146 147    BlkWrite(dv,root_dir,br->root_clus,root_dir_blks);148    RedSeaInit(dv);149    DrvUnlock(dv);150  } catch151    DrvUnlock(dv);152  Free(br);153  Free(root_dir);154}155 156Bool RedSeaFileFind(CDrv *dv,I64 cur_dir_clus,U8 *name,157        CDirEntry *_res,I64 fuf_flags=0)158{//FUF_JUST_DIRS, FUF_JUST_FILES159  CDirEntry *buf,*buf2,*ptr;160  U8 dname[CDIR_FILENAME_LEN];161  I64 ch;162  Bool res=FALSE,unlock;163  if (fuf_flags&~FUG_FILE_FIND)164    throw('FUF');165  MemSet(_res,0,sizeof(CDirEntry));166  DrvChk(dv);167  if (dv->fs_type!=FSt_REDSEA)168    PrintErr("Not RedSea Drv\n");169  else if (!CFileNameTo(dname,name))170    PrintErr("Invalid FileName: \"%s\".\n",name);171  else172    try {173      unlock=DrvLock(dv);174      buf2=MAlloc(BLK_SIZE);175      BlkRead(dv,buf2,cur_dir_clus,1);176 177      ptr=buf2(U8 *)-offset(CDirEntry.start);178      buf=MAlloc(ptr->size);179      BlkRead(dv,buf,cur_dir_clus,ptr->size>>BLK_SIZE_BITS);180      Free(buf2);181 182      ptr=buf(U8 *)-offset(CDirEntry.start);183      *ptr->name='.';184      ptr->name[1]=0;185      while (TRUE) {186        if (!(ch=*ptr->name))187          break;188        else if (!(ptr->attr & RS_ATTR_DELETED) &&189              !(fuf_flags&FUF_JUST_DIRS && !(ptr->attr & RS_ATTR_DIR)) &&190              !(fuf_flags&FUF_JUST_FILES && ptr->attr & RS_ATTR_DIR) &&191              !StrCmp(dname,ptr->name)) {192          MemCpy(&_res->attr,&ptr->attr,CDIR_SIZE);193          res=TRUE;194          goto rsff_done;195        }196        ptr(U8 *)+=CDIR_SIZE;197      }198rsff_done:199      Free(buf);200      if (unlock)201        DrvUnlock(dv);202    } catch203      if (unlock)204        DrvUnlock(dv);205  return res;206}207 208U8 *RedSeaFileRead(CDrv *dv,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)209{210  U8 *buf=NULL;211  CDirEntry de;212  I64 c,blk_cnt,cur_dir_clus;213  DrvChk(dv);214  *_size=0;215  *_attr=0;216  if (dv->fs_type!=FSt_REDSEA)217    PrintErr("Not RedSea Drv\n");218  else219    try {220      DrvLock(dv);221      cur_dir_clus=Name2DirClus(dv,cur_dir);222      if (RedSeaFileFind(dv,cur_dir_clus,filename,&de,FUF_JUST_FILES)) {223        blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;224        buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);225        c=de.clus;226        c=BlkRead(dv,buf,c,blk_cnt);227        buf[de.size]=0; //Terminate228        *_size=de.size;229        *_attr=FileAttr(de.name,de.attr);230      }231      DrvUnlock(dv);232    } catch233      DrvUnlock(dv);234  return buf;235}236 237Bool RedSeaCd(U8 *name,I64 cur_dir_clus)238{239  CDirEntry de;240  if (Fs->cur_dv->fs_type!=FSt_REDSEA)241    PrintErr("Not RedSea Drv\n");242  else if (RedSeaFileFind(Fs->cur_dv,cur_dir_clus,name,&de,FUF_JUST_DIRS))243    return TRUE;244  else245    PrintErr("File not found: \"%s\".\n",name);246  return FALSE;247}248 249U0 RedSeaFreeClus(CDrv *dv,I64 c,I64 cnt)250{251  CFreeLst *tmpf;252  Bool found=FALSE,unlock,unlock_break;253  DrvChk(dv);254  if (!c) return;255  if (dv->fs_type!=FSt_REDSEA)256    PrintErr("Not RedSea Drv\n");257  else258    try {259      unlock_break=BreakLock;260      unlock=DrvLock(dv);261      if (!dv->next_free)262        RedSeaFreeLstBuild(dv);263      tmpf=dv->next_free;264      while (!found && tmpf!=&dv->next_free) {265        if (tmpf->start+tmpf->size==c) {266          tmpf->size+=cnt;267          found=TRUE;268        } else if (c+cnt==tmpf->start) {269          tmpf->size+=cnt;270          tmpf->start=c;271          found=TRUE;272        }273        tmpf=tmpf->next;274      }275      if (!found) {276        tmpf=AMAlloc(sizeof(CFreeLst));277        tmpf->size=cnt;278        tmpf->start=c;279        QueIns(tmpf,dv->last_free);280      }281      while (cnt-->0) {282        DrvFATBlkSet(dv,c);283        LBtr(dv->cur_fat_blk,(c-dv->data_area)&(BLK_SIZE<<3-1));284        LBts(&dv->fat_blk_dirty,0);285        c++;286      }287      DrvFATBlkClean(dv);288 289      if (unlock)290        DrvUnlock(dv);291      if (unlock_break)292        BreakUnlock;293    } catch {294      if (unlock)295        DrvUnlock(dv);296      if (unlock_break)297        BreakUnlock;298    }299}300 301I64 RedSeaAllocClus(CDrv *dv,I64 cnt)302{303  CFreeLst *tmpf,*best_free=NULL;304  I64 i,first,best_size=I64_MAX;305  Bool unlock,unlock_break;306  if (cnt<=0)307    throw('Drv');308  try {309    unlock_break=BreakLock;310    unlock=DrvLock(dv);311    if (!dv->next_free)312      RedSeaFreeLstBuild(dv);313    tmpf=dv->next_free;314    while (tmpf!=&dv->next_free) {315      if (tmpf->size>=cnt && tmpf->size<best_size) {316        best_free=tmpf;317        best_size=tmpf->size;318        if (tmpf->size==cnt)319          break;320      }321      tmpf=tmpf->next;322    }323    if (!best_free)324      throw('Drv');325    first=best_free->start;326    for (i=0;i<cnt;i++) {327      DrvFATBlkSet(dv,first+i);328      LBts(dv->cur_fat_blk,(first+i-dv->data_area)&(BLK_SIZE<<3-1));329      LBts(&dv->fat_blk_dirty,0);330    }331    DrvFATBlkClean(dv);332    if (best_free->size-=cnt)333      best_free->start+=cnt;334    else {335      QueRem(best_free);336      Free(best_free);337    }338    if (unlock)339      DrvUnlock(dv);340    if (unlock_break)341      BreakUnlock;342  } catch {343    if (unlock)344      DrvUnlock(dv);345    if (unlock_break)346      BreakUnlock;347  }348  return first;349}350 351Bool RedSeaDirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tmpde,Bool free_old_chain)352{353  CDirEntry *buf,*buf2,*ptr,de2;354  CRedSeaBoot *br;355  I64 c,ch,i=1,j=0,n=BLK_SIZE/CDIR_SIZE,dir_size,cur_dir_clus;356  Bool written=FALSE,unlock,unlock_break;357  U8 *tmp,*parent_dir;358  try {359    unlock_break=BreakLock;360    tmpde->attr|=RS_ATTR_CONTIGUOUS;361    unlock=DrvLock(dv);362    cur_dir_clus=Name2DirClus(dv,cur_dir);363    buf2=MAlloc(BLK_SIZE);364    BlkRead(dv,buf2,cur_dir_clus,1);365 366    ptr=buf2(U8 *)-offset(CDirEntry.start);367    buf=MAlloc(ptr->size);368    BlkRead(dv,buf,cur_dir_clus,ptr->size>>BLK_SIZE_BITS);369 370    dir_size=ptr->size;371    ptr=buf(U8 *)-offset(CDirEntry.start)+CDIR_SIZE;372    Free(buf2);373    while (TRUE) {374      if (!(ch=*ptr->name)) {375        if (!written)376          MemCpy(&ptr->start,&tmpde->start,CDIR_SIZE);377        if ((i+1)*CDIR_SIZE+j<<BLK_SIZE_BITS<dir_size)378          BlkWrite(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_clus+j,1);379        else {380          buf2=CAlloc(dir_size+BLK_SIZE);381          MemCpy(buf2,buf,dir_size);382          RedSeaFreeClus(dv,cur_dir_clus,dir_size>>BLK_SIZE_BITS);383          dir_size+=BLK_SIZE;384          c=ClusAlloc(dv,0,dir_size>>BLK_SIZE_BITS,TRUE);385          Free(buf);386          buf=buf2;387          ptr=buf(U8 *)-offset(CDirEntry.start);388          ptr->size=dir_size;389          ptr->clus=c;390          BlkWrite(dv,buf,c,dir_size>>BLK_SIZE_BITS);391          if (cur_dir_clus==dv->root_clus) {392            br=CAlloc(BLK_SIZE);393            BlkRead(dv,br,dv->drv_offset,1);394            br->root_clus=c;395            BlkWrite(dv,br,dv->drv_offset,1);396            Free(br);397            dv->root_clus=c;398          } else {399            tmp=StrNew(cur_dir);400            parent_dir=StrNew(cur_dir);401            StrLastRem(parent_dir,"/",tmp);402            if (!*parent_dir) {403              Free(parent_dir);404              parent_dir=StrNew("/");405            }406            if (RedSeaFileFind(dv,Name2DirClus(dv,parent_dir),407                  tmp,&de2,FUF_JUST_DIRS)) {408              de2.clus=c;409              de2.size=dir_size;410              RedSeaDirNew(dv,parent_dir,&de2,FALSE);411            } else412              throw('Drv');413            Free(tmp);414            Free(parent_dir);415          }416        }417        break;418      } else if (ptr->attr & RS_ATTR_DELETED) {419        if (!written) {420          MemCpy(&ptr->start,&tmpde->start,CDIR_SIZE);421          BlkWrite(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_clus+j,1);422          written=TRUE;423        }424      } else {425        if (!StrCmp(tmpde->name,ptr->name)) {426          if (free_old_chain)427            RedSeaFreeClus(dv,ptr->clus,428                  (ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS);429          if (!written)430            MemCpy(&ptr->start,&tmpde->start,CDIR_SIZE);431          else432            ptr->attr|=RS_ATTR_DELETED;433          BlkWrite(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_clus+j,1);434          break;435        }436      }437      ptr(U8 *)+=CDIR_SIZE;438      if (++i>=n) {439        j++;440        i=0;441      }442    }443    Free(buf);444    if (unlock)445      DrvUnlock(dv);446    if (unlock_break)447      BreakUnlock;448  } catch {449    if (unlock)450      DrvUnlock(dv);451    if (unlock_break)452      BreakUnlock;453  }454  return FALSE;455}456 457I64 RedSeaFilesDel(CDrv *dv,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,458                     Bool del_dir,Bool print_msg)459{460  CDirEntry *buf,*buf2,*ptr;461  I64 i=0,res=0,ch,j=0,n=BLK_SIZE/CDIR_SIZE,cur_dir_clus;462  Bool unlock_break;463  try {464    unlock_break=BreakLock;465    DrvLock(dv);466    cur_dir_clus=Name2DirClus(dv,cur_dir);467    buf2=MAlloc(BLK_SIZE);468    BlkRead(dv,buf2,cur_dir_clus,1);469 470    ptr=buf2(U8 *)-offset(CDirEntry.start);471    buf=MAlloc(ptr->size);472    BlkRead(dv,buf,cur_dir_clus,ptr->size>>BLK_SIZE_BITS);473    Free(buf2);474 475    ptr=buf(U8 *)-offset(CDirEntry.start);476    *ptr->name='.';477    ptr->name[1]=0;478    while (TRUE) {479      if (!(ch=*ptr->name))480        break;481      else if (!(ptr->attr & RS_ATTR_DELETED) && ch!='.' && (del_dir ||482            !(ptr->attr & RS_ATTR_DIR)) &&483            FilesFindMatch(ptr->name,files_find_mask,fuf_flags)) {484        if (!(ptr->attr & RS_ATTR_DIR)) res++;485        if (print_msg)486          "Del %s\n",ptr->name;487        ptr->attr|=RS_ATTR_DELETED;488        BlkWrite(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_clus+j,1);489        RedSeaFreeClus(dv,ptr->clus,490              (ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS);491      }492      ptr(U8 *)+=CDIR_SIZE;493      if (++i>=n) {494        j++;495        i=0;496      }497    }498    Free(buf);499    DrvUnlock(dv);500    if (unlock_break)501      BreakUnlock;502  } catch {503    DrvUnlock(dv);504    if (unlock_break)505      BreakUnlock;506  }507  return res;508}509 510I64 RedSeaFileWrite(CDrv *dv,U8 *cur_dir,U8 *name,U8 *buf,I64 size,511        CDate cdt,I64 attr)512{513  CDirEntry de;514  I64 c=0,blk_cnt;515  MemSet(&de,0,sizeof(CDirEntry));516  if (size<0) size=0;517  if (dv->fs_type!=FSt_REDSEA)518    PrintErr("Not RedSea Drv\n");519  else if (!CFileNameTo(de.name,name))520    PrintErr("Invalid FileName: \"%s\".\n",name);521  else {522    RedSeaFilesDel(dv,cur_dir,de.name,0,FALSE,FALSE);523    de.size=size;524    if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)525      c=ClusAlloc(dv,0,blk_cnt,TRUE); //Always contiguous526    else527      c=INVALID_CLUS;528    de.clus=c;529    de.attr=attr|RS_ATTR_CONTIGUOUS;530    de.datetime=cdt;531    if (blk_cnt)532      BlkWrite(dv,buf,c,blk_cnt);533    RedSeaDirNew(dv,cur_dir,&de,TRUE);534  }535  return c;536}537 538CDirEntry *RedSeaFilesFind(U8 *files_find_mask,I64 fuf_flags,539        CDirEntry *parent=NULL)540{541  CDrv *dv=Fs->cur_dv;542  CDirEntry *buf,*buf2,*ptr,*res=NULL,*tmpde;543  I64 ch,cur_dir_clus;544  if (fuf_flags&~FUG_FILES_FIND)545    throw('FUF');546  try {547    DrvLock(dv);548    cur_dir_clus=Name2DirClus(dv,Fs->cur_dir);549    buf2=MAlloc(BLK_SIZE);550    BlkRead(dv,buf2,cur_dir_clus,1);551 552    ptr=buf2(U8 *)-offset(CDirEntry.start);553    buf=MAlloc(ptr->size);554    BlkRead(dv,buf,cur_dir_clus,ptr->size>>BLK_SIZE_BITS);555    Free(buf2);556 557    ptr=buf(U8 *)-offset(CDirEntry.start);558    *ptr->name='.';559    ptr->name[1]=0;560    ptr(U8 *)+=CDIR_SIZE;561    ptr->clus=Name2ParentDirClus(dv,Fs->cur_dir);562    ptr(U8 *)-=CDIR_SIZE;563    while (TRUE) {564      if (!(ch=*ptr->name))565        break;566      else if (!(ptr->attr & RS_ATTR_DELETED)) {567        tmpde=CAlloc(sizeof(CDirEntry));568        MemCpy(&tmpde->start,&ptr->start,CDIR_SIZE);569        tmpde->parent=parent;570        if (Bt(&fuf_flags,FUf_RECURSE) && tmpde->attr&RS_ATTR_DIR &&571              *tmpde->name!='.') {572          tmpde->next=res;573          res=tmpde;574          tmpde->full_name=DirNameAbs(tmpde->name);575          DrvUnlock(dv);576          if (Cd(tmpde->name)) {577            tmpde->sub=RedSeaFilesFind(files_find_mask,fuf_flags,tmpde);578            Cd("..");579          }580          DrvLock(dv);581        } else {582          tmpde->full_name=FileNameAbs(tmpde->name);583          if ((tmpde->attr&RS_ATTR_DIR ||584                !Bt(&fuf_flags,FUf_JUST_DIRS)) &&585                !(Bt(&fuf_flags,FUf_RECURSE) && *tmpde->name=='.' &&586                tmpde->attr&RS_ATTR_DIR) &&587                FilesFindMatch(tmpde->full_name,files_find_mask,fuf_flags)) {588            tmpde->next=res;589            res=tmpde;590          } else591            DirEntryDel(tmpde);592        }593      }594      ptr(U8 *)+=CDIR_SIZE;595    }596    Free(buf);597    DrvUnlock(dv);598  } catch599    DrvUnlock(dv);600  return res;601}602 603Bool RedSeaMkDir(CDrv *dv,U8 *cur_dir,U8 *name,I64 entry_cnt)604{//entry_cnt is for preallocating dir blks.605  I64   c,cur_dir_clus=Name2DirClus(dv,cur_dir),606        size=CeilU64((entry_cnt+3)<<6,BLK_SIZE);607#assert CDIR_SIZE==64608  U8 *buf=CAlloc(size);609  CDirEntry *d_native=buf-offset(CDirEntry.start);610  Bool unlock_break;611  try {612    unlock_break=BreakLock;613    c=FileWrite(name,buf,size,0,RS_ATTR_DIR);614    d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS;615    StrCpy(d_native->name,name);616    d_native->clus=c;617    d_native->size=size;618    d_native->datetime=Now;619    d_native(U8 *)+=CDIR_SIZE;620 621    d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS;622    *d_native->name='.';623    d_native->name[1]='.';624    d_native->name[2]=0;625    d_native->clus=cur_dir_clus;626    d_native->size=0;627    d_native->datetime=Now;628    BlkWrite(dv,buf,c,1);629    Free(buf);630    if (unlock_break)631      BreakUnlock;632  } catch633    if (unlock_break)634      BreakUnlock;635  return TRUE;636}637