diff options
author | nrootconauto@gmail.com <nrootconauto@gmail.com> | 2022-10-07 16:15:00 -0400 |
---|---|---|
committer | nrootconauto@gmail.com <nrootconauto@gmail.com> | 2022-10-07 16:15:00 -0400 |
commit | 99f534380b1c64920f0871a34b147d03234a255a (patch) | |
tree | d17578b0b9d3fcae0d0dbae77c424070ef2c13b5 | |
parent | 77e99bcef0adec6fe3ebb0dcd734c71d1ec72116 (diff) |
Reworked File system.
Signed-off-by: nrootconauto@gmail.com <nrootconauto@gmail.com>
38 files changed, 5205 insertions, 1244 deletions
@@ -189,3 +189,5 @@ void SetupDebugger(); void GrPalleteSet(int c,int64_t colors); char *GrPalleteGet(int64_t c); extern char *cipher_passwd; +char **VFsDir(char *fn); +FILE *VFsFOpen(char *path,char*); Binary files differdiff --git a/T/BlkDev/DskA.HC b/T/ADskA.HC index 3b48caf..7580979 100644 --- a/T/BlkDev/DskA.HC +++ b/T/ADskA.HC @@ -1,4 +1,64 @@ -Bool Copy(U8 *src_files_find_mask,U8 *dst_files_find_mask=".") +#help_index "File/Cmd Line (Typically);Cmd Line (Typically)" +public U8 *DBlk(I64 blk,Bool write=FALSE) +{//Dump disk block. Optionally, write. +//If you set write to TRUE, the block will + //be written when you press <ESC>. + //See $LK,"::/Demo/Dsk/DskRaw.HC"$. + U8 *buf=MAlloc(BLK_SIZE); + + BlkRead(Fs->cur_dv,buf,blk,1); + DocD(buf,BLK_SIZE); + if (write) { + "Edit and press <ESC> to write or <SHIFT-ESC>\n"; + if (View) { + "Write\n"; + BlkWrite(Fs->cur_dv,buf,blk,1); + } + } + return buf; +} + +public U8 *DClus(I64 c,Bool write=FALSE,I64 num=0) +{//Dump disk clus. Optionally, write. +//If you set write to TRUE, the clus will + //be written when you press <ESC>. + //See $LK,"::/Demo/Dsk/DskRaw.HC"$. + //Do $LK,"Dir",A="MN:Dir"$("*",TRUE); to get clus numbers of files. + U8 *buf=MAlloc(Fs->cur_dv->spc<<BLK_SIZE_BITS); + c=ClusNumNext(Fs->cur_dv,c,num); + ClusRead(Fs->cur_dv,buf,c,1); + "Clus:%X\n",c; + DocD(buf,Fs->cur_dv->spc<<BLK_SIZE_BITS); + if (write) { + "Edit and press <ESC> to write or <SHIFT-ESC>\n"; + if (View) { + "Write\n"; + ClusWrite(Fs->cur_dv,buf,c,1); + } + } + return buf; +} + +public U8 *Dump(U8 *filename,Bool write=FALSE) +{//Dump file. Optionally, write. +//If you set write to TRUE, the file will + //be written when you press <ESC>. + U8 *buf; + I64 size; + if (buf=FileRead(filename,&size)) { + DocD(buf,size); + if (write) { + "Edit and press <ESC> to write or <SHIFT-ESC>\n"; + if (View) { + "Write\n"; + FileWrite(filename,buf,size); + } + } + } + return buf; +} + +public Bool Copy(U8 *src_files_find_mask,U8 *dst_files_find_mask=".") {//Copy files. //If the name ends in ".Z", it will //be stored compressed. If not ".Z" @@ -9,47 +69,31 @@ Bool Copy(U8 *src_files_find_mask,U8 *dst_files_find_mask=".") U8 *st; if (!(tmpde1=FilesFind(src_files_find_mask,FUF_CLUS_ORDER))) return FALSE; - if (IsDir(dst_files_find_mask)) - { - if (dirc=DirContextNew(dst_files_find_mask,TRUE)) - { + if (IsDir(dst_files_find_mask)) { + if (dirc=DirContextNew(dst_files_find_mask,TRUE)) { tmpde=tmpde1; - while (tmpde) - { - if (!IsDir(tmpde->full_name)) - { - st=FileNameAbs(tmpde->name); - if (!CopySingle(tmpde->full_name,st)) - res=FALSE; - Free(st); - } - tmpde=tmpde->next; + while (tmpde) { + if (!(tmpde->attr & RS_ATTR_DIR)) { + st=FileNameAbs(tmpde->name); + if (!CopySingle(tmpde->full_name,st)) + res=FALSE; + Free(st); + } + tmpde=tmpde->next; } DirContextDel(dirc); } DirTreeDel(tmpde1); return res; - } - else - { + } else { DirTreeDel(tmpde1); return CopySingle(src_files_find_mask,dst_files_find_mask); } } -public Bool Del(U8 *f1) { - CDirEntry *finds=FilesFind(f1),*cur=NULL; - for(cur=finds;cur;cur=cur->next) { - if(!StrCmp(".",cur->name)||!StrCmp("..",cur->name)) - ; - else - __Del(cur->full_name); - } - DirTreeDel(finds); -} + public Bool Move(U8 *f1,U8 *f2) {//Move files from one location to another or rename. - if (Copy(f1,f2)) - { + if (Copy(f1,f2)) { Del(f1); return TRUE; } @@ -60,54 +104,50 @@ I64 CopyTree2(CDirEntry *tmpde,I64 src_dir_len,I64 dst_dir_len,U8 *dst_dir) { U8 *st; I64 res=1; - while (tmpde) - { + while (tmpde) { st=MAlloc(StrLen(tmpde->full_name)+dst_dir_len+2); MemCpy(st,dst_dir,dst_dir_len); StrCpy(st+dst_dir_len,tmpde->full_name+src_dir_len); - if (IsDir(tmpde->full_name)) - { - DirMk(st); + if (tmpde->attr & RS_ATTR_DIR) { + DirMk(st,LinkedLstCnt(tmpde->sub)); res+=CopyTree2(tmpde->sub,src_dir_len,dst_dir_len,dst_dir); - } - else if (CopySingle(tmpde->full_name,st)) - res++; + } else + if (CopySingle(tmpde->full_name,st)) + res++; Free(st); tmpde=tmpde->next; } return res; } public I64 CopyTree(U8 *src_files_find_mask,U8 *dst_files_find_mask, - Bool no_mask=TRUE) + Bool no_mask=TRUE) {//Copy directory tree. //Returns the count of copied files (not dirs). CDirContext *dirc; CDirEntry *tmpde=NULL; I64 res=0,i1,i2; U8 *st1,*st2; + st1=DirNameAbs(src_files_find_mask); st2=DirNameAbs(dst_files_find_mask); i1=StrLen(st1); - if (!StrNCmp(st1,st2,i1) && (st2[i1]=='/' || !st2[i1]) ) - { + if (!StrNCmp(st1,st2,i1) && (st2[i1]=='/' || !st2[i1]) ) { Free(st1); Free(st2); return 0; } Free(st1); Free(st2); - if (dirc=DirContextNew(src_files_find_mask,TRUE,,no_mask)) - { + if (dirc=DirContextNew(src_files_find_mask,TRUE,,no_mask)) { tmpde=FilesFind(dirc->mask,FUF_RECURSE); st1=DirCur; DirContextDel(dirc); i1=StrLen(st1); if (i1==3) i1--; - if (dirc=DirContextNew(dst_files_find_mask,TRUE,TRUE)) - { + if (dirc=DirContextNew(dst_files_find_mask,TRUE,TRUE)) { st2=DirCur; i2=StrLen(st2); - //if (i2==3) i2--; TODO URGENT ??? DirCur returns [letter]:/[path] + if (i2==3) i2--; res=CopyTree2(tmpde,i1,i2,st2); DirContextDel(dirc); Free(st2); @@ -122,14 +162,12 @@ I64 DelTreeDirs(CDirEntry *tmpde1) { I64 res=0; CDirEntry *tmpde2; - while (tmpde1) - { + while (tmpde1) { tmpde2=tmpde1->next; - if (IsDir(tmpde1->full_name)&&!StrCmp(tmpde1->name,".")&&!StrCmp(tmpde1->name,"..")) - { + if (tmpde1->attr & RS_ATTR_DIR) { if (tmpde1->sub) - res+=DelTreeDirs(tmpde1->sub); - res+=__Del(tmpde1->full_name); + res+=DelTreeDirs(tmpde1->sub); + res+=Del(tmpde1->full_name,TRUE,TRUE); } DirEntryDel(tmpde1); tmpde1=tmpde2; @@ -140,19 +178,13 @@ I64 DelTreeFiles(CDirEntry *tmpde1) { I64 res=0; CDirEntry *tmpde2; - while (tmpde1) - { + while (tmpde1) { tmpde2=tmpde1->next; - if(!StrCmp(tmpde1->name,".")&&!StrCmp(tmpde1->name,"..")) - goto next; - if (IsDir(tmpde1->full_name)) - { + if (tmpde1->attr & RS_ATTR_DIR) { if (tmpde1->sub) - res+=DelTreeFiles(tmpde1->sub); - } - else - res+=__Del(tmpde1->full_name); - next: + res+=DelTreeFiles(tmpde1->sub); + } else + res+=Del(tmpde1->full_name,FALSE,TRUE); DirEntryDel(tmpde1); tmpde1=tmpde2; } @@ -163,65 +195,58 @@ public I64 DelTree(U8 *files_find_mask,U8 *fu_flags=NULL) I64 res=0,fuf_flags=0; ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r"); ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags); - if (IsDir(files_find_mask)) - { + if (IsDir(files_find_mask)) { res=DelTreeDirs(FilesFind(files_find_mask,fuf_flags)); - res+=__Del(files_find_mask); - } - else + res+=Del(files_find_mask,TRUE,TRUE); + res+=Del(files_find_mask,FALSE,TRUE); + } else res=DelTreeFiles(FilesFind(files_find_mask,fuf_flags)); return res; } -/* + U0 TouchFile(U8 *filename,U8 *attr,CDate cdt=I64_MIN) { CDrv *dv=Let2Drv(*filename); CDirEntry de; U8 *cur_dir=StrNew(filename),buf[STR_LEN]; - if (FileFind(filename,&de,FUF_JUST_FILES)) - { + if (FileFind(filename,&de,FUF_JUST_FILES)) { Free(de.full_name); if (!StrCmp(attr,"+?")) "%-48ts%s\n",filename,StrPrintFlags(buf,Define("ST_FILE_ATTRS"),de.attr); - else - { + else { StrFirstRem(cur_dir,":"); StrLastRem(cur_dir,"/"); if (!*cur_dir) - StrCpy(cur_dir,"/"); + StrCpy(cur_dir,"/"); ScanFlags(&de.attr,Define("ST_FILE_ATTRS"),attr); if (cdt==I64_MIN) - de.datetime=Now; + de.datetime=Now; else - de.datetime=cdt; + de.datetime=cdt; DirNew(dv,cur_dir,&de,FALSE); } - } - else + } else PrintErr("File not found: \"%s\".\n",filename); Free(cur_dir); } public U0 Touch(U8 *files_find_mask="*",U8 *attr="+?", - U8 *fu_flags=NULL,CDate cdt=I64_MIN) -{ - /*Touch file attributes and DateTime. - Default lists attributes. - attr: "+?" =show current - "+T" =resident - $LK,"RS_ATTR_READ_ONLY",A="MN:RS_ATTR_READ_ONLY"$ $LK,"ST_FILE_ATTRS",A="MN:ST_FILE_ATTRS"$ - To Set DateL: - Touch(filename,"",,datetime); - */ + U8 *fu_flags=NULL,CDate cdt=I64_MIN) +{/*Touch file attributes and DateTime. +Default lists attributes. +attr: "+?" =show current +"+T" =resident +$LK,"RS_ATTR_READ_ONLY",A="MN:RS_ATTR_READ_ONLY"$ $LK,"ST_FILE_ATTRS",A="MN:ST_FILE_ATTRS"$ +To Set DateL: +Touch(filename,"",,datetime); +*/ I64 fuf_flags=0; CDirEntry *tmpde,*tmpde1; ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+f+F"); ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags); tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags); - while (tmpde) - { + while (tmpde) { TouchFile(tmpde->full_name,attr,cdt); tmpde=tmpde->next; } DirTreeDel(tmpde1); } -*/ diff --git a/T/BlkDev/DskCopy.HC b/T/BlkDev/DskCopy.HC deleted file mode 100644 index 894ea7c..0000000 --- a/T/BlkDev/DskCopy.HC +++ /dev/null @@ -1,27 +0,0 @@ -Bool CopySingleZ(U8 *f1,U8 *f2) //Just one file -{ - U8 *file_buf=NULL; - I64 size,attr=0,c; - CDirEntry de; - if (FileFind(f1,&de,FUF_JUST_FILES)) - { - Free(de.full_name); - file_buf=FileRead(f1,&size /*,&attr*/ ); - //attr=FileAttr(f2,attr); TODO RESTORE - if (file_buf) - { - "Copying%s to %s\n",f1,f2; - c=FileWrite(f2,file_buf,size /*,de.datetime,attr*/ ); //TODO RESTORE - Free(file_buf); - return ToBool(c); - } - else - PrintErr("File not found: \"%s\".\n",f1); - } - else - PrintErr("File not found: \"%s\".\n",f1); - return FALSE; -} -Bool CopySingle(U8 *f1,U8 *f2) { - return CopySingleZ(f1,f2); -} diff --git a/T/BlkDev2/DskATA.HC b/T/BlkDev2/DskATA.HC new file mode 100644 index 0000000..beba116 --- /dev/null +++ b/T/BlkDev2/DskATA.HC @@ -0,0 +1,107 @@ +U0 ATABlkSel(CBlkDev *bd,I64 blk,I64 cnt) +{ +} + +Bool ATAWaitNotBUSY(CBlkDev *bd,F64 timeout) +{ +} + +Bool ATAWaitDRQ(CBlkDev *bd,F64 timeout) +{ +} + +Bool ATANop(CBlkDev *bd,F64 timeout) +{ +} + +U0 ATACmd(CBlkDev *bd,U8 cmd) +{ +} + +Bool ATAGetRes(CBlkDev *bd,F64 timeout,U8 *buf,I64 cnt, + I64 _avail,Bool one_read) +{ +} + +Bool ATAPIWritePktWord(CBlkDev *bd,F64 timeout,...) +{ +} + +Bool ATAPISetMaxSpeed(CBlkDev *bd) +{ +} + +Bool ATAPISeek(CBlkDev *bd,I64 native_blk) +{ +} + +Bool ATAPIStartStop(CBlkDev *bd,F64 timeout,Bool start) +{ +} + +I64 ATAGetDevId(CBlkDev *bd,F64 timeout,Bool keep_id_record) +{ +} + +I64 ATAReadNativeMax(CBlkDev *bd,F64 timeout) +{//Returns zero on err +} + +I64 ATAPIReadCapacity(CBlkDev *bd,I64 *_blk_size=NULL) +{//Supposedly this can return a res +/- 75 sects. +//Error might just be for music. +} + +CATAPITrack *ATAPIReadTrackInfo(CBlkDev *bd,I64 blk) +{ +} + +Bool ATAInit(CBlkDev *bd) +{ +} + +Bool ATAPIWaitReady(CBlkDev *bd,F64 timeout) +{ +} + +U0 ATAReadBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 cnt) +{ +} + +I64 ATAProbe(I64 base0,I64 base1,I64 unit) +{ +} + +Bool ATAPIReadBlks2(CBlkDev *bd,F64 timeout,U8 *buf, + I64 native_blk, I64 cnt,Bool lock) +{ +} + +U0 ATAPIReadBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 cnt) +{ +} + +Bool ATARBlks(CDrv *dv,U8 *buf, I64 blk, I64 cnt) +{ +} + +U0 ATAWriteBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 cnt) +{ +} + +Bool ATAPISync(CBlkDev *bd) +{ +} + +U0 ATAPIClose(CBlkDev *bd,I64 close_field=0x200,I64 track=0) +{ +} + +U0 ATAPIWriteBlks(CBlkDev *bd,U8 *buf, I64 native_blk, I64 cnt) +{ +} + +Bool ATAWBlks(CDrv *dv,U8 *buf, I64 blk, I64 cnt) +{ +} +
\ No newline at end of file diff --git a/T/BlkDev2/DskATAId.HC b/T/BlkDev2/DskATAId.HC new file mode 100644 index 0000000..36aa998 --- /dev/null +++ b/T/BlkDev2/DskATAId.HC @@ -0,0 +1,36 @@ +Bool BootDVDProbe(CBlkDev *bd) +{ +} + +Bool BootDVDProbeAll(CBlkDev *bd) +{ +} + +U0 ATARepEntry(I64 base0,I64 base1,I64 unit,U8 *msg, + CATARep **_head,I64 *num_hints) +{ +} + +Bool ATARepExitAllApplications() +{ +} + +public I64 ATARep(Bool pmt=TRUE,Bool just_ide=FALSE,CATARep **_head=NULL) +{//Report possible ATA devices by probing. Hard disks and CD/DVDs. +} + +CATARep *ATARepFind(CATARep *haystack_head,I64 needle_num) +{ +} + +CATARep *ATAIDDrvs(CATARep *head,CATARep **_ata_drv,CATARep **_atapi_drv) +{ +} + +CBlkDev *ATAMount(U8 first_drv_let,I64 type,I64 base0,I64 base1,I64 unit) +{ +} + +I64 MountIDEAuto() +{ +} diff --git a/T/BlkDev2/DskAddDev.HC b/T/BlkDev2/DskAddDev.HC new file mode 100644 index 0000000..c8bcba4 --- /dev/null +++ b/T/BlkDev2/DskAddDev.HC @@ -0,0 +1,215 @@ +U0 BlkDevLockFwdingSet(CBlkDev *bd) +{ //If two blkdevs on same controller, use just one lock + CBlkDev *bd1; + I64 i; + switch (bd->type) { + case BDT_RAM: + break; + case BDT_ISO_FILE_READ: + case BDT_ISO_FILE_WRITE: + bd->lock_fwding=Let2BlkDev(*bd->file_dsk_name); + break; + case BDT_ATA: + case BDT_ATAPI: + for (i=0;i<BLKDEVS_NUM;i++) { + bd1=&blkdev.blkdevs[i]; + if (bd1->bd_signature==BD_SIGNATURE_VAL && bd!=bd1 && + (bd1->type==BDT_ATAPI || bd1->type==BDT_ATA) && + bd1->base0==bd->base0) { + bd->lock_fwding=bd1; + break; + } + } + break; + } +} + +I64 BlkDevAdd(CBlkDev *bd,I64 prt_num=I64_MIN, + Bool whole_drv,Bool make_free) +{//It will mount just one partition of prt_num>=0. +//When repartitioing whole drive, whole_drv=TRUE. + I64 i,j,ext_base,offset,res=0,num=0; + CDrv *dv; + CRedSeaBoot br; + CMasterBoot mbr; + + bd->bd_signature=BD_SIGNATURE_VAL; + if (make_free) + dv=DrvMakeFreeSlot(bd->first_drv_let); + else + dv=DrvMakeFreeSlot(DrvNextFreeLet(bd->first_drv_let)); + dv->bd=bd; + dv->drv_offset=bd->drv_offset; + dv->size=bd->max_blk+1-bd->drv_offset; + switch (bd->type) { + case BDT_VIRT: + dv->dv_signature=DRV_SIGNATURE_VAL; + dv->prt_num=num; + dv->fs_type=FSt_VIRT; +//This is to force creation of a RAM + //drive during boot, so it is probably + //MAlloced to the same addr and can + //be assumed to be already formatted. + //If this line is removed, RAM Drives + //will be alloced on a just-in-time + //basis. + if (BlkDevInit(bd)) + res++; + else + dv->dv_signature=0; + break; + case BDT_RAM: + case BDT_ISO_FILE_READ: + case BDT_ISO_FILE_WRITE: + dv->dv_signature=DRV_SIGNATURE_VAL; + dv->prt_num=num; + dv->fs_type=FSt_REDSEA; +//This is to force creation of a RAM + //drive during boot, so it is probably + //MAlloced to the same addr and can + //be assumed to be already formatted. + //If this line is removed, RAM Drives + //will be alloced on a just-in-time + //basis. + if (BlkDevInit(bd)) + res++; + else + dv->dv_signature=0; + break; + case BDT_ATA: + dv->dv_signature=DRV_SIGNATURE_VAL; //Temporarily validate + if (!BlkDevInit(bd)) + dv->dv_signature=0; //Revoke validation + else { + dv->dv_signature=0; //Revoke validation + if (whole_drv) { + dv->dv_signature=DRV_SIGNATURE_VAL; + dv->prt_num=num; + res++; + dv->fs_type=FSt_REDSEA; + dv->size=bd->max_blk+1-bd->drv_offset; +//The following read is a test read. + //if it hangs, the drive is not supported. + break; + } + offset=0; + ext_base=INVALID_CLUS; + while (prt_num<0 || num<=prt_num) { + if (mbr.signature!=0xAA55) + break; + j=-1; + for (i=0;i<4 && (prt_num<0 || num<=prt_num);i++) { + if (mbr.p[i].type) { + if (make_free) + dv=DrvMakeFreeSlot(bd->first_drv_let+res); + else + dv=DrvMakeFreeSlot(DrvNextFreeLet(bd->first_drv_let+res)); + dv->bd=bd; + dv->drv_offset=mbr.p[i].offset+offset; + dv->size =mbr.p[i].size; + switch (mbr.p[i].type) { + case MBR_PT_REDSEA: + dv->dv_signature=DRV_SIGNATURE_VAL; + dv->prt_num=num; + res++; + dv->fs_type=FSt_REDSEA; + RedSeaInit(dv); + break; + case MBR_PT_FAT32a: + case MBR_PT_FAT32b: + case MBR_PT_FAT32c: + case MBR_PT_FAT32d: + case MBR_PT_FAT32e: + case MBR_PT_FAT32f: + dv->dv_signature=DRV_SIGNATURE_VAL; + dv->prt_num=num; + res++; + if (br.signature==MBR_PT_REDSEA) { + dv->fs_type=FSt_REDSEA; + RedSeaInit(dv); + } else { + dv->fs_type=FSt_FAT32; + FAT32Init(dv); + } + break; + case MBR_PT_NTFS: + dv->dv_signature=DRV_SIGNATURE_VAL; + dv->prt_num=num; + res++; + dv->fs_type=FSt_NTFS; + break; + case 5: + case 15: + j=i; + break; + default: + dv->dv_signature=DRV_SIGNATURE_VAL; + dv->prt_num=num; + res++; + dv->fs_type=FSt_UNKNOWN; + } + num++; + } + } + if (Let2BlkDevType(bd->first_drv_let+res)!=bd->type) + break; + if (j<0) + break; + if (!mbr.p[j].offset) + break; + if (ext_base==INVALID_CLUS) { + offset=mbr.p[j].offset; + ext_base=offset; + } else + offset=mbr.p[j].offset+ext_base; + } + } + break; + case BDT_ATAPI: + dv->dv_signature=DRV_SIGNATURE_VAL; + dv->prt_num=num; + res++; + dv->fs_type=FSt_ISO9660; //Start with this + dv->size=0; + break; + } + if (res) + BlkDevLockFwdingSet(bd); + else + BlkDevDel(bd); + return res; +} + +Bool DrvEnable(U8 drv_let,Bool val) +{//Can unmount or remount, but not mount the first time. + CDrv *dv; + if (dv=Let2Drv(drv_let,FALSE)) + return !LBEqu(&dv->fs_type,FStf_DISABLE,!val); + else + return FALSE; +} + + +U0 BlkDevsInitAll() +{ + CBlkDev *bd; + I64 i; + blkdev.blkdevs=CAlloc(sizeof(CBlkDev)*BLKDEVS_NUM); + blkdev.drvs=CAlloc(sizeof(CDrv)*DRVS_NUM); + for (i=0;i<DRVS_NUM;i++) + blkdev.let_to_drv[i]=&blkdev.drvs[i]; + bd=BlkDevNextFreeSlot('T',BDT_VIRT);bd->unit=0; + BlkDevAdd(bd,0,0,0); + Fs->cur_dv=Let2Drv('T'); + Fs->cur_dir=StrNew("/"); + blkdev.boot_drv_let='T'; +/* #exe { + if (kernel_cfg->opts[CFG_MOUNT_IDE_AUTO]) + StreamPrint("MountIDEAuto;"); + StreamPrint("#exe {Option(OPTf_WARN_PAREN,OFF);}"); + StreamDoc(kernel_cfg->add_dev); + StreamPrint("#exe {Option(OPTf_WARN_PAREN,ON);}"); + };*/ +} +BlkDevsInitAll; +HomeSet("/");
\ No newline at end of file diff --git a/T/BlkDev2/DskBlk.HC b/T/BlkDev2/DskBlk.HC new file mode 100644 index 0000000..02e76fe --- /dev/null +++ b/T/BlkDev2/DskBlk.HC @@ -0,0 +1,110 @@ +#define ZERO_BUF_SIZE 2048 +U0 BlkWriteZero(CDrv *dv,I64 blk,I64 cnt) +{ +//Fill blk cnt with zeros in Drv. + I64 n; + U8 *z=CAlloc(ZERO_BUF_SIZE<<BLK_SIZE_BITS); + Bool show_progress; + if (cnt>ZERO_BUF_SIZE && dv->bd->type!=BDT_RAM) { + progress1=0; progress1_max=cnt; + StrCpy(progress1_desc,"Zeroing"); + show_progress=TRUE; + } else + show_progress=FALSE; + while (cnt>0) { + n=cnt; + if (n>ZERO_BUF_SIZE) + n=ZERO_BUF_SIZE; + BlkWrite(dv,z,blk,n); + blk+=n; + cnt-=n; + if (show_progress) + progress1+=n; + Yield; //Prevent locking + } + Free(z); + if (show_progress) { + *progress1_desc=0; + progress1=progress1_max=0; + } +} + +Bool BlkRead(CDrv *dv,U8 *buf, I64 blk, I64 cnt) +{ + //Read blk cnt from Drv to buf. + Bool res=TRUE,unlock; + CBlkDev *bd=dv->bd; + if (cnt<=0) return TRUE; + DrvChk(dv); + try { + unlock=DrvLock(dv); + BlkDevInit(bd); + if (dv->drv_offset && blk<dv->drv_offset || + blk+cnt>dv->drv_offset+dv->size) + throw('Drv'); + if (bd->flags & BDF_READ_CACHE) + RCache(dv,&buf,&blk,&cnt); + if (cnt>0) { + switch (bd->type) { + case BDT_RAM: + MemCpy(buf,bd->RAM_dsk+blk<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS); + break; + case BDT_ISO_FILE_READ: + case BDT_ISO_FILE_WRITE: + FBlkRead(bd->file_dsk,buf,blk,cnt); + break; + case BDT_ATA: + case BDT_ATAPI: + break; + } + bd->last_time=tS; + if (bd->flags & BDF_READ_CACHE) + DskCacheAdd(dv,buf,blk,cnt); + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + return res; +} + +Bool BlkWrite(CDrv *dv,U8 *buf, I64 blk, I64 cnt) +{ + //Write blk cnt from buf to Drv. + Bool res=TRUE,unlock; + CBlkDev *bd=dv->bd; + if (cnt<=0) return TRUE; + DrvChk(dv); + try { + unlock=DrvLock(dv); + BlkDevInit(bd); + if (bd->flags&BDF_READ_ONLY && !(bd->flags & BDF_READ_ONLY_OVERRIDE)) + throw('BlkDev'); + if (dv->drv_offset && blk<dv->drv_offset || + blk+cnt>dv->drv_offset+dv->size) + throw('Drv'); + if (cnt>0) { + switch (bd->type) { + case BDT_RAM: + MemCpy(bd->RAM_dsk+blk<<BLK_SIZE_BITS,buf,cnt<<BLK_SIZE_BITS); + break; + case BDT_ISO_FILE_READ: + case BDT_ISO_FILE_WRITE: + FBlkWrite(bd->file_dsk,buf,blk,cnt); + break; + case BDT_ATA: + case BDT_ATAPI: + break; + } + bd->last_time=tS; + if (bd->flags & BDF_READ_CACHE) + DskCacheAdd(dv,buf,blk,cnt); + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + return res; +} diff --git a/T/BlkDev2/DskBlkDev.HC b/T/BlkDev2/DskBlkDev.HC new file mode 100644 index 0000000..4ca7a85 --- /dev/null +++ b/T/BlkDev2/DskBlkDev.HC @@ -0,0 +1,173 @@ +Bool BlkDevLock(CBlkDev *bd) +{//Make this task have exclusive access to BlkDev. + BlkDevChk(bd); + while (bd->lock_fwding) + bd=bd->lock_fwding; //If two blkdevs on same controller, use just one lock + if (!Bt(&bd->locked_flags,BDlf_LOCKED) || bd->owning_task!=Fs) { + while (LBts(&bd->locked_flags,BDlf_LOCKED)) + Yield; + bd->owning_task=Fs; + return TRUE; + } else + return FALSE; +} + +Bool BlkDevUnlock(CBlkDev *bd,Bool rst=FALSE) +{//Release exclusive lock on access to BlkDev. + BlkDevChk(bd); + while (bd->lock_fwding) + bd=bd->lock_fwding; //If two blkdevs on same controller, use just one lock + if (Bt(&bd->locked_flags,BDlf_LOCKED) && bd->owning_task==Fs) { + if (rst) + bd->flags&=~(BDF_INITIALIZED|BDF_INIT_IN_PROGRESS); + bd->owning_task=NULL; + LBtr(&bd->locked_flags,BDlf_LOCKED); + Yield; //Prevent deadlock + return TRUE; + } else + return FALSE; +} + +Bool BlkDevInit(CBlkDev *bd) +{ + CDirEntry de; + U8 buf[STR_LEN]; + CDrv *dv=Let2Drv(bd->first_drv_let); + Bool res=FALSE; + if (!LBts(&bd->flags,BDf_INITIALIZED)) { + bd->flags|=BDF_INIT_IN_PROGRESS; + switch (bd->type) { + case BDT_VIRT: + res=TRUE; + break; + case BDT_RAM: + if (!bd->RAM_dsk) { + bd->RAM_dsk=AMAlloc((bd->max_blk+1)<<BLK_SIZE_BITS); + bd->max_blk=MSize(bd->RAM_dsk)>>BLK_SIZE_BITS-1; + } + dv->fs_type=FSt_REDSEA; + dv->size=bd->max_blk+1-bd->drv_offset; + if (RedSeaValidate(bd->first_drv_let)) + RedSeaInit(dv); + else + RedSeaFmt(bd->first_drv_let); + res=TRUE; + break; + case BDT_ISO_FILE_READ: + if (FileFind(bd->file_dsk_name,&de,FUF_JUST_FILES)) { + bd->max_blk=de.size>>BLK_SIZE_BITS-1; + try bd->file_dsk=FOpen(bd->file_dsk_name,"rc",bd->max_blk+1); + catch { + if (Fs->except_ch=='File') + PrintErr("Not Contiguous.Move file to filename.ISO.C.\n"); + Fs->catch_except=TRUE; + } + if (bd->file_dsk) { + dv->fs_type=FSt_REDSEA; + dv->size=bd->max_blk+1-bd->drv_offset; + if (RedSeaValidate(bd->first_drv_let)) { + RedSeaInit(dv); + res=TRUE; + } else + PrintErr("Not RedSea\n"); + } + } + break; + case BDT_ISO_FILE_WRITE: + if (!bd->file_dsk_name) { + StrPrint(buf,"%C:/Drv%C.ISO.C", + blkdev.boot_drv_let,bd->first_drv_let); + bd->file_dsk_name=AStrNew(buf); + } + if (bd->max_blk<7) + bd->max_blk=7; + bd->file_dsk=FOpen(bd->file_dsk_name,"wc",bd->max_blk+1); + dv->fs_type=FSt_REDSEA; + dv->size=bd->max_blk+1-bd->drv_offset; + RedSeaFmt(bd->first_drv_let); + CallExtStr("RedSeaISO9660",bd->file_dsk_name,bd->first_drv_let); + res=TRUE; + break; + } + if (res && bd->flags & BDF_READ_CACHE) + DskCacheInvalidate(dv); + bd->flags&=~BDF_INIT_IN_PROGRESS; + } else + res=TRUE; + return res; +} + +U0 BlkDevsRelease() +{//When task dies, release all owned BlkDevs. + I64 i; + CBlkDev *bd; + for (i=0;i<BLKDEVS_NUM;i++) { + bd=&blkdev.blkdevs[i]; + if (bd->owning_task==Fs && bd->bd_signature==BD_SIGNATURE_VAL) + BlkDevUnlock(bd,TRUE); + } +} + +CBlkDev *BlkDevNextFreeSlot(U8 first_drv_let,I64 type) +{//Locate free slot for new BlkDev, like during $LK,"Mount",A="MN:Mount"$(). + I64 i=0; + CBlkDev *res; + if (Let2BlkDevType(first_drv_let)!=type) + throw('BlkDev'); + do { + res=&blkdev.blkdevs[i]; + if (res->bd_signature!=BD_SIGNATURE_VAL) { + MemSet(res,0,sizeof(CBlkDev)); + res->first_drv_let=first_drv_let; + res->type=type; + res->flags=BDF_READ_CACHE; + res->blk_size=BLK_SIZE; + res->max_blk=0xEFFFFFFF; + switch (type) { + case BDT_RAM: + res->flags&=~BDF_READ_CACHE; + break; + case BDT_ISO_FILE_READ: + res->flags|=BDF_READ_ONLY; + break; + case BDT_ATAPI: + res->flags|=BDF_REMOVABLE|BDF_READ_ONLY; + res->blk_size=DVD_BLK_SIZE; + break; + } + return res; + } + } while (++i<BLKDEVS_NUM); + throw('BlkDev'); + return NULL; //never gets here +} + +U0 BlkDevDel(CBlkDev *bd) +{//Delete BlkDev + DrvBlkDevDel(bd); + FClose(bd->file_dsk); + Free(bd->file_dsk_name); + Free(bd->dev_id_record); + MemSet(bd,0,sizeof(CBlkDev)); +} + +CBlkDev *BlkDevChk(CBlkDev *bd,Bool except=TRUE) +{//Check for valid BlkDev. Throw exception. + if (!bd || bd->bd_signature!=BD_SIGNATURE_VAL || + !(BDT_NULL<bd->type<BDT_TYPES_NUM)) { + if (except) + throw('BlkDev'); + else + return NULL; + } else + return bd; +} + +CBlkDev *Let2BlkDev(U8 drv_let=0,Bool except=TRUE) +{//Drv letter to BlkDev ptr. + CDrv *dv; + if (dv=Let2Drv(drv_let,except)) + return BlkDevChk(dv->bd,except); + else + return NULL; +} diff --git a/T/BlkDev2/DskCDDVD.HC b/T/BlkDev2/DskCDDVD.HC new file mode 100644 index 0000000..6f95c9b --- /dev/null +++ b/T/BlkDev2/DskCDDVD.HC @@ -0,0 +1,81 @@ +Bool ISOInit(CDrv *dv,I64 blk) +{ + CBlkDev *bd=dv->bd; + I64 spc=bd->blk_size>>BLK_SIZE_BITS,i=blk/spc,drv_offset=0; + CISOPriDesc *iso=MAlloc(bd->blk_size); + CISODirEntry *de; + Bool unlock,res=FALSE; + U8 buf[8]; + + try { + unlock=DrvLock(dv); + dv->fs_type=FSt_ISO9660; + dv->spc=spc; + dv->data_area=dv->root_clus=dv->drv_offset=bd->drv_offset=dv->size=0; + while (TRUE) { + dv->size=MaxI64(dv->size,(i+1)*spc); + BlkRead(dv,iso,i*spc,spc); + buf[0](U32)=iso->id[0](U32); + buf[4](U16)=iso->id[4](U8); + switch (LstMatch(buf,"CD001\0CDW02\0BEA01\0BOOT2\0NSR02\0NSR03\0TEA01\0", + LMF_EXACT)) { + case 0: + switch (iso->type) { + case ISOT_BOOT_RECORD: + drv_offset+=(2*DVD_BLK_SIZE+DVD_BLK_SIZE)/BLK_SIZE; + break; + case ISOT_SUPPLEMENTARY_DESC: + de=&iso->root_dir_record; + dv->size=iso->vol_space_size.little*bd->blk_size>>BLK_SIZE_BITS; + if (!StrCmp(iso->publisher_id,"TempleOS RedSea")) { + dv->fs_type=FSt_REDSEA; + bd->drv_offset=dv->drv_offset=19<<2+drv_offset; + bd->max_blk=dv->size-1; + dv->size-=bd->drv_offset; + RedSeaInit(dv); + } else + dv->root_clus=de->loc.little; + res=TRUE; + goto di_done; + case ISOT_TERMINATOR: + throw('Drv'); + } + break; + default: //Its normal for ISO3346 to read NULL blk as terminator + PrintErr("File System Not Supported\n"); + throw('Drv'); + } + i++; + } +di_done: + Free(iso); + if (unlock) + DrvUnlock(dv); + } catch { + dv->fs_type=FSt_ISO9660; + dv->spc=spc; + dv->drv_offset=bd->drv_offset=dv->data_area=dv->root_clus=0; + Free(iso); + if (unlock) + DrvUnlock(dv); + } + return res; +} + +U0 DVDImageRead(U8 dvd_drv_let,U8 *out_name) +{} + +class CDualBuf +{ + U8 *buf0,*buf1; + I64 in_buf,out_buf,cnt; + U8 *filename; + CBlkDev *dvd_bd; +}; + +U0 DVDImageWriteTask(CDualBuf *d) +{ +} + +U0 DVDImageWrite(U8 dvd_drv_let,U8 *in_name=NULL,I64 media_type=MT_DVD) +{} diff --git a/T/BlkDev2/DskCFile.HC b/T/BlkDev2/DskCFile.HC new file mode 100644 index 0000000..06a0e73 --- /dev/null +++ b/T/BlkDev2/DskCFile.HC @@ -0,0 +1,306 @@ +I64 FSize(CFile *f) +{//Report size of opened file in bytes. + if (f) + return f->de.size; + else + return 0; +} + +CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0) +{//Allows flags "r","w","w+". "c" for contiguous. +//(It uses $LK,"StrOcc",A="MN:StrOcc"$() for 'w', 'r', '+', 'c') + CFile *f=CAlloc(sizeof(CFile)); + CDirContext *dirc; + U8 *full_name; + Bool contiguous=StrOcc(flags,'c'); + + f->clus=INVALID_CLUS; + f->fblk_num=0; + if (cnt>0) + f->max_blk=cnt-1; + else + f->max_blk=I64_MAX; + f->file_clus_num=INVALID_CLUS; + full_name=FileNameAbs(filename); + f->dv=Let2Drv(*full_name); + if (f->dv->fs_type==FSt_REDSEA) + contiguous=TRUE; + if (contiguous) { + f->flags|=FF_CONTIGUOUS; + if (f->dv->fs_type!=FSt_REDSEA && + !(FileAttr(filename) & RS_ATTR_CONTIGUOUS)) + throw('File'); + } + f->clus_buf=CAlloc(f->dv->spc<<BLK_SIZE_BITS); + if (StrOcc(flags,'w')) { + f->flags=f->flags|FF_WRITE|FF_NEEDS_WRITE; + if (StrOcc(flags,'+')) { + if (FileFind(full_name,&f->de,FUF_JUST_FILES)) { +//Nroot's edit + if(Let2BlkDevType(*full_name)==BDT_VIRT) { + dirc=DirContextNew(full_name); + VFsSetPwd(Fs->cur_dir); + f->_3days_virt=VFsFOpenW(&f->de.name); + DirContextDel(dirc); + } +// + Free(full_name); + if (contiguous) + f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1; + return f; + } + } else + Del(full_name,,,FALSE); + f->de.full_name=full_name; + f->flags|=FF_NEW_FILE; + if (dirc=DirContextNew(full_name)) { + StrCpy(f->de.name,dirc->mask); + if (cnt>0) {//We pre-alloc the whole thing. +//Nroot was here + if(Let2BlkDevType(*full_name)!=BDT_VIRT) { + f->de.clus=ClusAlloc(f->dv,0, + (cnt+f->dv->spc-1)/f->dv->spc,contiguous); + DirNew(dirc->dv,Fs->cur_dir,&f->de,TRUE); + } + f->de.size=cnt<<BLK_SIZE_BITS; + f->flags&=~FF_NEW_FILE; + + } +//Nroot's edit + if(Let2BlkDevType(*full_name)==BDT_VIRT) { + VFsSetPwd(Fs->cur_dir); + f->_3days_virt=VFsFOpenW(&f->de.name); + } +// + DirContextDel(dirc); + return f; + } + } else { + if (FileFind(full_name,&f->de,FUF_JUST_FILES)) { +//Nroot's edit + if(Let2BlkDevType(*full_name)==BDT_VIRT) { + dirc=DirContextNew(full_name); + VFsSetPwd(Fs->cur_dir); + f->_3days_virt=VFsFOpenR(&f->de.name); + DirContextDel(dirc); + } +// + Free(full_name); + f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1; + return f; + } + } + Free(f->clus_buf); + Free(full_name); + Free(f); + return NULL; +} + +U0 FClose(CFile *f) +{//Close CFile, updating directory. + CDirContext *dirc; + if(f->_3days_virt) { + VFsFClose(f->_3days_virt); + return; + } + if (f) { + if (f->flags & FF_BUF_DIRTY) { + ClusWrite(f->dv,f->clus_buf,f->clus,1); + f->flags&=~FF_BUF_DIRTY; + } + if (f->flags & FF_NEEDS_WRITE) { + if (dirc=DirContextNew(f->de.full_name)) { + if (!(f->flags & FF_USE_OLD_DATETIME)) + f->de.datetime=Now; + if (f->flags & FF_NEW_FILE) + DirNew(dirc->dv,Fs->cur_dir,&f->de,TRUE); + else + DirNew(dirc->dv,Fs->cur_dir,&f->de,FALSE); + DirContextDel(dirc); + } else + throw('File'); + } + Free(f->clus_buf); + Free(f->de.full_name); + Free(f); + } +} + +I64 FSetClus(CFile *f,I64 c,I64 blk,Bool read) +{ + CDrv *dv=f->dv; + I64 i; + if (f->clus!=c) { + if (f->flags & FF_BUF_DIRTY) { + i=dv->spc; + if (f->max_blk!=I64_MAX) { + i=f->max_blk+1-f->file_clus_num*dv->spc; + if (i>dv->spc) + i=dv->spc; + } + ClusBlkWrite(dv,f->clus_buf,f->clus,i); + f->flags=f->flags & ~FF_BUF_DIRTY; + } + f->clus=c; + f->file_clus_num=blk/dv->spc; + if (read) { + i=dv->spc; + if (f->max_blk!=I64_MAX) { + i=f->max_blk+1-f->file_clus_num*dv->spc; + if (i>dv->spc) + i=dv->spc; + } + c=ClusBlkRead(dv,f->clus_buf,c,i); + } + } + return c; +} + +Bool FBlkRead(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1) +{//Read [nth,n+cnt) blks of file. + if(f->_3days_virt) { + if(blk!=FFB_NEXT_BLK) + VFsFSeek(blk<<BLK_SIZE_BITS,f->_3days_virt); + return VFsFBlkRead(buf,1<<BLK_SIZE_BITS,cnt,f->_3days_virt); + } + CDrv *dv=f->dv; + I64 spc=dv->spc,i,j,c=f->de.clus; + if (!f || !dv) return FALSE; + if (blk==FFB_NEXT_BLK) + blk=f->fblk_num; + if (blk+cnt-1>f->max_blk) + return FALSE; + if (cnt<=0) return TRUE; + + if (f->flags & FF_CONTIGUOUS) { + BlkRead(dv,buf,Clus2Blk(dv,c)+blk,cnt); + blk+=cnt; + } else { + i=blk/spc; + if (0<=f->file_clus_num<=i) { + c=f->clus; + i-=f->file_clus_num; + } + if (i>0) + c=ClusNumNext(dv,c,i); + + if (i=blk%spc) { + c=FSetClus(f,c,blk,TRUE); + if (cnt<spc-i) + j=cnt; + else + j=spc-i; + MemCpy(buf,f->clus_buf+i<<BLK_SIZE_BITS,j<<BLK_SIZE_BITS); + buf+=j<<BLK_SIZE_BITS; + cnt-=j; + blk+=j; + } + while (cnt>=spc) { + c=FSetClus(f,c,blk,TRUE); + MemCpy(buf,f->clus_buf,spc<<BLK_SIZE_BITS); + buf+=spc<<BLK_SIZE_BITS; + cnt-=spc; + blk+=spc; + } + if (cnt>0) { + c=FSetClus(f,c,blk,TRUE); + MemCpy(buf,f->clus_buf,cnt<<BLK_SIZE_BITS); + buf+=cnt<<BLK_SIZE_BITS; + blk+=cnt; + } + } + f->fblk_num=blk; + return TRUE; +} + +Bool FBlkWrite(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1) +{//Write [nth,n+cnt) blks of file. + if(f->_3days_virt) { + if(blk!=FFB_NEXT_BLK) + VFsFSeek(blk<<BLK_SIZE_BITS,f->_3days_virt); + VFsFBlkWrite(buf,1<<BLK_SIZE_BITS,cnt,f->_3days_virt); + return TRUE; + } + CDrv *dv=f->dv; + I64 spc=dv->spc,i,j,c=f->de.clus,c1; + if (!f || !dv) return FALSE; + if (blk==FFB_NEXT_BLK) + blk=f->fblk_num; + if (blk+cnt-1>f->max_blk) + return FALSE; + if (!(f->flags & FF_WRITE)) + return FALSE; + if (cnt<=0) return TRUE; + if (f->flags & FF_CONTIGUOUS) { + BlkWrite(dv,buf,Clus2Blk(dv,c)+blk,cnt); + blk+=cnt; + } else { + if (!c) { + c=ClusAlloc(dv,0,1,FALSE); + f->file_clus_num=0; + f->clus=c; + f->de.clus=c; + f->flags|=FF_NEEDS_WRITE|FF_NEW_FILE; + } + i=blk/spc; + if (0<=f->file_clus_num<=i) { + c=f->clus; + i-=f->file_clus_num; + } + while (i>0) { + c1=c; + c=ClusNumNext(dv,c1,1); + if (c==INVALID_CLUS) { + c=ClusAlloc(dv,c1,i,FALSE); + if (i>1) + c=ClusNumNext(dv,c,i-1); + break; + } else + i--; + } + + if (i=blk%spc) { + FSetClus(f,c,blk,TRUE); + if (cnt<spc-i) + j=cnt; + else + j=spc-i; + MemCpy(f->clus_buf+BLK_SIZE*i,buf,j<<BLK_SIZE_BITS); + f->flags|=FF_BUF_DIRTY; + buf+=j<<BLK_SIZE_BITS; + cnt-=j; + blk+=j; + if (cnt>0) { + c1=c; + c=ClusNumNext(dv,c1,1); + if (c==INVALID_CLUS) + c=ClusAlloc(dv,c1,1,FALSE); + } + } + while (cnt>=spc) { + FSetClus(f,c,blk,FALSE); + MemCpy(f->clus_buf,buf,spc<<BLK_SIZE_BITS); + f->flags|=FF_BUF_DIRTY; + buf+=spc<<BLK_SIZE_BITS; + cnt-=spc; + blk+=spc; + if (cnt>0) { + c1=c; + c=ClusNumNext(dv,c1,1); + if (c==INVALID_CLUS) + c=ClusAlloc(dv,c1,1,FALSE); + } + } + if (cnt>0) { + FSetClus(f,c,blk,TRUE); + MemCpy(f->clus_buf,buf,cnt<<BLK_SIZE_BITS); + f->flags|=FF_BUF_DIRTY; + buf+=cnt<<BLK_SIZE_BITS; + blk+=cnt; + } + if (f->de.size<blk<<BLK_SIZE_BITS) + f->de.size=blk<<BLK_SIZE_BITS; + } + f->fblk_num=blk; + return TRUE; +} diff --git a/T/BlkDev2/DskCache.HC b/T/BlkDev2/DskCache.HC new file mode 100644 index 0000000..988f458 --- /dev/null +++ b/T/BlkDev2/DskCache.HC @@ -0,0 +1,145 @@ +U0 DskCacheInit(I64 size_in_U8s) +{ + CCacheBlk *tmpc; + I64 i,cnt; + + while (LBts(&sys_semas[SEMA_DSK_CACHE],0)) + Yield; + Free(blkdev.cache_ctrl); + Free(blkdev.cache_base); + Free(blkdev.cache_hash_table); + if (size_in_U8s<0x2000) { + blkdev.cache_ctrl=NULL; + blkdev.cache_base=NULL; + blkdev.cache_hash_table=NULL; + } else { + blkdev.cache_ctrl=ACAlloc(offset(CCacheBlk.body)); + blkdev.cache_base=AMAlloc(size_in_U8s); + QueInit(blkdev.cache_ctrl); + + cnt=MSize(blkdev.cache_base)/sizeof(CCacheBlk); + blkdev.cache_size=cnt*BLK_SIZE; + for (i=0;i<cnt;i++) { + tmpc=blkdev.cache_base+i; + QueIns(tmpc,blkdev.cache_ctrl->last_lru); + tmpc->next_hash=tmpc->last_hash=tmpc; + tmpc->dv=NULL; + tmpc->blk=0; + } + + blkdev.cache_hash_table=AMAlloc(DSK_CACHE_HASH_SIZE*sizeof(U8 *)*2); + for (i=0;i<DSK_CACHE_HASH_SIZE;i++) { + tmpc=blkdev.cache_hash_table(U8 *)+i*sizeof(U8 *)*2 + -offset(CCacheBlk.next_hash); + tmpc->next_hash=tmpc->last_hash=tmpc; + } + } + LBtr(&sys_semas[SEMA_DSK_CACHE],0); +} + +I64 DskCacheHash(I64 blk) +{ + I64 i=blk & (DSK_CACHE_HASH_SIZE-1); + return blkdev.cache_hash_table(U8 *)+i<<4-offset(CCacheBlk.next_hash); +} + +U0 DskCacheQueRem(CCacheBlk *tmpc) +{ + QueRem(tmpc); + tmpc->next_hash->last_hash=tmpc->last_hash; + tmpc->last_hash->next_hash=tmpc->next_hash; +} + +U0 DskCacheQueIns(CCacheBlk *tmpc) +{ + CCacheBlk *tmp_n,*tmp_l; + QueIns(tmpc,blkdev.cache_ctrl->last_lru); + tmp_l=DskCacheHash(tmpc->blk); + tmp_n=tmp_l->next_hash; + tmpc->last_hash=tmp_l; + tmpc->next_hash=tmp_n; + tmp_l->next_hash=tmp_n->last_hash=tmpc; +} + +CCacheBlk *DskCacheFind(CDrv *dv,I64 blk) +{ + CCacheBlk *tmpc,*tmpc1=DskCacheHash(blk); + tmpc=tmpc1->next_hash; + while (tmpc!=tmpc1) { + if (tmpc->dv==dv && tmpc->blk==blk) + return tmpc; + tmpc=tmpc->next_hash; + } + return NULL; +} + +U0 DskCacheAdd(CDrv *dv,U8 *buf, I64 blk, I64 cnt) +{ + CCacheBlk *tmpc; + if (blkdev.cache_base) { + while (LBts(&sys_semas[SEMA_DSK_CACHE],0)) + Yield; + while (cnt-->0) { + if (!(tmpc=DskCacheFind(dv,blk))) + tmpc=blkdev.cache_ctrl->next_lru; + DskCacheQueRem(tmpc); + MemCpy(&tmpc->body,buf,BLK_SIZE); + tmpc->dv=dv; + tmpc->blk=blk; + DskCacheQueIns(tmpc); + blk++; + buf+=BLK_SIZE; + } + LBtr(&sys_semas[SEMA_DSK_CACHE],0); + } +} + +U0 DskCacheInvalidate2(CDrv *dv) +{ + CCacheBlk *tmpc,*tmpc1; + if (blkdev.cache_base) { + while (LBts(&sys_semas[SEMA_DSK_CACHE],0)) + Yield; + tmpc=blkdev.cache_ctrl->last_lru; + while (tmpc!=blkdev.cache_ctrl) { + tmpc1=tmpc->last_lru; + if (tmpc->dv==dv) { + DskCacheQueRem(tmpc); + tmpc->dv=NULL; + tmpc->blk=0; + tmpc->next_hash=tmpc->last_hash=tmpc; + QueIns(tmpc,blkdev.cache_ctrl->last_lru); + } + tmpc=tmpc1; + } + LBtr(&sys_semas[SEMA_DSK_CACHE],0); + } +} + +U0 RCache(CDrv *dv,U8 **_buf, I64 *_blk, I64 *_cnt) +{ + CCacheBlk *tmpc; + if (blkdev.cache_base) { + while (LBts(&sys_semas[SEMA_DSK_CACHE],0)) + Yield; +//fetch leading blks from cache + while (*_cnt>0) { + if (tmpc=DskCacheFind(dv,*_blk)) { + MemCpy(*_buf,&tmpc->body,BLK_SIZE); + *_cnt-=1; + *_buf+=BLK_SIZE; + *_blk+=1; + } else + break; + } +//fetch trailing blks from cache + while (*_cnt>0) { + if (tmpc=DskCacheFind(dv,*_blk+*_cnt-1)) { + MemCpy(*_buf+(*_cnt-1)<<BLK_SIZE_BITS,&tmpc->body,BLK_SIZE); + *_cnt-=1; + } else + break; + } + LBtr(&sys_semas[SEMA_DSK_CACHE],0); + } +} diff --git a/T/BlkDev2/DskClus.HC b/T/BlkDev2/DskClus.HC new file mode 100644 index 0000000..ec841dd --- /dev/null +++ b/T/BlkDev2/DskClus.HC @@ -0,0 +1,145 @@ +I64 ClusNumNext(CDrv *dv,I64 c,I64 cnt=1) +{//Return next cnt'th clus in chain. + Bool unlock; + DrvChk(dv); + if (cnt<=0) return c; + try { + unlock=DrvLock(dv); + switch (dv->fs_type) { + case FSt_REDSEA: + c+=cnt; + break; + case FSt_FAT32: + while (cnt-->0 && 0<c<0x0FFFFFF8) { + DrvFATBlkSet(dv,c); + c=dv->cur_fat_blk[c & (BLK_SIZE/4-1)]; + } + if (!(0<c<0x0FFFFFF8)) + c=INVALID_CLUS; + break; + default: + throw('Drv'); + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + return c; +} + +I64 Clus2Blk(CDrv *dv,I64 c) +{//Drv clus num to blk num. + DrvChk(dv); + switch (dv->fs_type) { + case FSt_REDSEA: + return c; + case FSt_FAT32: + return dv->data_area+c*dv->spc; + default: + throw('Drv'); + } +} + +I64 ClusBlkRead(CDrv *dv,U8 *buf,I64 c,I64 blks) +{//Accepts blk count, so padding on last clus is not read. + I64 i; + Bool unlock; + DrvChk(dv); + if (blks<=0) return c; + try { + unlock=DrvLock(dv); + switch (dv->fs_type) { + case FSt_REDSEA: + BlkRead(dv,buf,c,blks); + c+=blks; + break; + case FSt_FAT32: + while (blks && 0<c<0x0FFFFFF8) { + i=blks; + if (i>dv->spc) + i=dv->spc; + BlkRead(dv,buf,dv->data_area+c*dv->spc,i); + buf+=i<<BLK_SIZE_BITS; + c=ClusNumNext(dv,c,1); + blks-=i; + } + if (blks) + throw('Drv'); + break; + default: + throw('Drv'); + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + return c; +} + +I64 ClusRead(CDrv *dv,U8 *buf,I64 c,I64 cnt) +{//Read clus cnt from drv to buf. + return ClusBlkRead(dv,buf,c,cnt*dv->spc); +} + +I64 ClusBlkWrite(CDrv *dv,U8 *buf,I64 c,I64 blks) +{//Accepts blk count, so padding on last clus is not written. + I64 i; + Bool unlock; + DrvChk(dv); + if (blks<=0) return c; + try { + unlock=DrvLock(dv); + switch (dv->fs_type) { + case FSt_REDSEA: + BlkWrite(dv,buf,c,blks); + c=0; + break; + case FSt_FAT32: + while (blks) { + if (!(0<c<0x0FFFFFF8)) + throw('Drv'); + i=blks; + if (i>dv->spc) + i=dv->spc; + BlkWrite(dv,buf,dv->data_area+c*dv->spc,i); + buf+=i<<BLK_SIZE_BITS; + c=ClusNumNext(dv,c); + blks-=i; + } + break; + default: + throw('Drv'); + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + return c; +} + +I64 ClusWrite(CDrv *dv,U8 *buf,I64 c,I64 cnt) +{//Write clus cnt from buf to drv. + return ClusBlkWrite(dv,buf,c,cnt*dv->spc); +} + +I64 ClusAlloc(CDrv *dv,I64 c=0,I64 cnt=1,Bool contiguous=FALSE) +{//Alloc clus cnt into chain. +//c=0 means first clus in chain + DrvChk(dv); + if (cnt<=0) return c; + switch (dv->fs_type) { + case FSt_REDSEA: + return RedSeaAllocClus(dv,cnt); + case FSt_FAT32: + if (contiguous) { + if (c) throw('File'); + return FAT32AllocContiguousClus(dv,cnt); + } else + return FAT32AllocClus(dv,c,cnt); + default: + throw('Drv'); + } +} diff --git a/T/BlkDev2/DskCopy.HC b/T/BlkDev2/DskCopy.HC new file mode 100644 index 0000000..d646c6a --- /dev/null +++ b/T/BlkDev2/DskCopy.HC @@ -0,0 +1,107 @@ +Bool CopySingleZ(U8 *f1,U8 *f2) //Just one file +{ + U8 *file_buf=NULL; + I64 size,attr=0,c; + CDirEntry de; + if (FileFind(f1,&de,FUF_JUST_FILES)) { + Free(de.full_name); + file_buf=FileRead(f1,&size,&attr); + attr=FileAttr(f2,attr); + if (file_buf) { + "Copying%s to %s\n",f1,f2; + c=FileWrite(f2,file_buf,size,de.datetime,attr); + Free(file_buf); + return ToBool(c); + } else + PrintErr("File not found: \"%s\".\n",f1); + } else + PrintErr("File not found: \"%s\".\n",f1); + return FALSE; +} + +#define COPY_BUF_BLKS 0x80 +Bool CopySingle(U8 *f1,U8 *f2) //Just one file +{ + U8 *absf1=FileNameAbs(f1),*absf2=FileNameAbs(f2),*buf; + I64 cnt,n,size,attr1=FileAttr(f1),attr2=FileAttr(f2),i,j; + CFile *in_file=NULL,*out_file=NULL; + if (!StrCmp(absf1,absf2)) {//onto self? + Free(absf1); + Free(absf2); + return FALSE; + } + Free(absf1); + Free(absf2); + if (attr1!=attr2) + return CopySingleZ(f1,f2); + buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS); + if (attr1 & RS_ATTR_CONTIGUOUS) + in_file=FOpen(f1,"rc"); + else + in_file=FOpen(f1,"r"); + if (in_file) { + size=FSize(in_file); + cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS; + if (attr2 & RS_ATTR_CONTIGUOUS) + out_file=FOpen(f2,"wc",cnt); + else + out_file=FOpen(f2,"w",cnt); + if (out_file) { + "Copying %s to %s\n",f1,f2; + j=size; + while (cnt>0) { + if (cnt>COPY_BUF_BLKS) { + n=COPY_BUF_BLKS; + i=n<<BLK_SIZE_BITS; + } else { + n=cnt; + i=j; + } + FBlkRead(in_file, buf,FFB_NEXT_BLK,n); + FBlkWrite(out_file,buf,FFB_NEXT_BLK,n); + cnt-=n; + j-=n<<BLK_SIZE_BITS; + } + out_file->flags|=FF_USE_OLD_DATETIME; + out_file->de.datetime=in_file->de.datetime; + out_file->de.size=size; + out_file->de.attr=FileAttr(f2,in_file->de.attr); + FClose(out_file); + FClose(in_file); + Free(buf); + return TRUE; + } else + PrintErr("File not found: \"%s\".\n",f2); + FClose(in_file); + } else + PrintErr("File not found: \"%s\".\n",f1); + Free(buf); + return FALSE; +} + +I64 Del(U8 *files_find_mask,Bool make_mask=FALSE, + Bool del_dir=FALSE,Bool print_msg=TRUE) +{//Delete files. + I64 res=0; + CDirContext *dirc; + if (dirc=DirContextNew(files_find_mask,make_mask)) { + switch (dirc->dv->fs_type) { + case FSt_VIRT: + res=VirtFilesDel(dirc->dv,Fs->cur_dir,dirc->mask, + 0,del_dir,print_msg); + break; + case FSt_REDSEA: + res=RedSeaFilesDel(dirc->dv,Fs->cur_dir,dirc->mask, + 0,del_dir,print_msg); + break; + case FSt_FAT32: + res=FAT32FilesDel(dirc->dv,Fs->cur_dir,dirc->mask, + 0,del_dir,print_msg); + break; + default: + PrintErr("File System Not Supported\n"); + } + DirContextDel(dirc); + } + return res; +} diff --git a/T/BlkDev2/DskDirA.HC b/T/BlkDev2/DskDirA.HC new file mode 100644 index 0000000..a572d90 --- /dev/null +++ b/T/BlkDev2/DskDirA.HC @@ -0,0 +1,213 @@ +Bool DirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tmpde,Bool free_old_chain=TRUE) +{//Makes a directory entry in the directory from a $LK,"CDirEntry",A="MN:CDirEntry"$ node. + switch (dv->fs_type) { + case FSt_VIRT: + return VirtFileFind(dv,cur_dir,".",tmpde); + case FSt_REDSEA: + return RedSeaDirNew(dv,cur_dir,tmpde,free_old_chain); + case FSt_FAT32: + return FAT32DirNew(dv,cur_dir,tmpde,free_old_chain); + default: + PrintErr("File System Not Supported\n"); + return FALSE; + } +} + +U0 DirEntryDel(CDirEntry *tmpde) +{//Free node returned from $LK,"FilesFind",A="MN:FilesFind"$(). Doesn't Free user_data. +//Does not change the directory on disk. + if (tmpde) { + Free(tmpde->full_name); + Free(tmpde); + } +} + +U0 DirEntryDel2(CDirEntry *tmpde) +{//Free node returned from $LK,"FilesFind",A="MN:FilesFind"$(). Frees user_data +//Does not change the directory on disk. + if (tmpde) { + Free(tmpde->full_name); + Free(tmpde->user_data); + Free(tmpde); + } +} + +U0 DirTreeDel(CDirEntry *tmpde) +{//Free tree returned from $LK,"FilesFind",A="MN:FilesFind"$(). Doesn't Free user_data. +//Does not change the directory on disk. + CDirEntry *tmpde2; + while (tmpde) { + tmpde2=tmpde->next; + if (tmpde->sub) + DirTreeDel(tmpde->sub); + DirEntryDel(tmpde); + tmpde=tmpde2; + } +} + +U0 DirTreeDel2(CDirEntry *tmpde) +{//Free tree returned from $LK,"FilesFind",A="MN:FilesFind"$(). Frees user_data +//Does not change the directory on disk. + CDirEntry *tmpde2; + while (tmpde) { + tmpde2=tmpde->next; + if (tmpde->sub) + DirTreeDel2(tmpde->sub); + DirEntryDel2(tmpde); + tmpde=tmpde2; + } +} + +I64 DirEntryCompareName(CDirEntry *e1,CDirEntry *e2) +{ + U8 buf1[CDIR_FILENAME_LEN],buf2[CDIR_FILENAME_LEN], + buf3[CDIR_FILENAME_LEN],buf4[CDIR_FILENAME_LEN]; + I64 d1=0,d2=0; + if (e1->attr & RS_ATTR_DIR) + d1=1; + if (e2->attr & RS_ATTR_DIR) + d2=1; + if (d1!=d2) + return d2-d1; + else { + StrCpy(buf1,e1->name); + StrCpy(buf2,e2->name); + FileExtRem(buf1,buf3); + FileExtRem(buf2,buf4); + if (d1=StrCmp(buf3,buf4)) + return d1; + return StrCmp(buf1,buf2); + } +} + +I64 DirEntryCompareClus(CDirEntry *e1,CDirEntry *e2) +{ + return e1->clus-e2->clus; +} + +#define SK_NAME 0 +#define SK_CLUS 1 + +U0 DirFilesSort(CDirEntry **_tmpde,I64 key) +{ + I64 i,cnt; + CDirEntry *tmpde=*_tmpde,*tmpde1,**sort_buf; + if (tmpde) { + cnt=LinkedLstCnt(tmpde); + if (cnt>1) { + sort_buf=MAlloc(cnt*sizeof(U8 *)); + i=0; + tmpde1=tmpde; + while (tmpde1) { + sort_buf[i++]=tmpde1; + tmpde1=tmpde1->next; + } + switch [key] { + case SK_NAME: + QSortI64(sort_buf,cnt,&DirEntryCompareName); + break; + case SK_CLUS: + QSortI64(sort_buf,cnt,&DirEntryCompareClus); + break; + } + tmpde=sort_buf[0]; + *_tmpde=tmpde; + for (i=0;i<cnt-1;i++) { + tmpde1=sort_buf[i]; + tmpde1->next=sort_buf[i+1]; + } + tmpde1=sort_buf[i]; + tmpde1->next=NULL; + Free(sort_buf); + + tmpde1=tmpde; + while (tmpde1) { + if (tmpde1->sub) + DirFilesSort(&tmpde1->sub,key); + tmpde1=tmpde1->next; + } + } else + if (tmpde->sub) + DirFilesSort(&tmpde->sub,key); + } +} + +CDirEntry *DirFilesFlatten(CDirEntry *tmpde,CDirEntry **_res,I64 fuf_flags) +{//Returns last node + CDirEntry *tmpde1; + Bool del; + if (tmpde) + while (TRUE) { + tmpde1=tmpde->next; + if (!(tmpde->attr&RS_ATTR_DIR)||!(fuf_flags&FUF_JUST_FILES)) { + _res=*_res=tmpde; + del=FALSE; + } else + del=TRUE; + if (tmpde->sub) { + _res=DirFilesFlatten(tmpde->sub,_res,fuf_flags); + tmpde->sub=NULL; + } + if (del) + DirEntryDel(tmpde); + if (tmpde1) + tmpde=tmpde1; + else + break; + } + *_res=NULL; + return _res; +} + +U0 PutFileLink(U8 *filename,U8 *full_name=NULL,I64 line=0,Bool plain_text=FALSE) +{//Put $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"$ file,line link to StdOut, $LK,"DocPut",A="MN:DocPut"$. + U8 *st; + if (!filename) return; + if (IsRaw) { + if (line) + "%s,%04d",filename,line; + else + "%s",filename; + } else { +//LK_DOC,LK_DOC_ANCHOR,LK_DOC_FIND,LK_DOC_LINE + if (filename[0]=='A'&&filename[2]==':') { + if (line) //See $LK,"SpriteEdText",A="MN:SpriteEdText"$() + "$$LK,\"%s,%04d\",A=\"AL:%s,%d\"$$",filename+3,line,filename+3,line; + else + "$$LK,\"%s\",A=\"AI:%s\"$$",filename+3,filename+3; + } else { + if (!full_name) + full_name=st=FileNameAbs(filename); + else + st=NULL; + if (plain_text) { + if (line) + "$$LK,\"%s,%04d\",A=\"PL:%s,%d\"$$",filename,line,full_name,line; + else + "$$LK,\"%s\",A=\"PI:%s\"$$",filename,full_name; + } else { + if (line) + "$$LK,\"%s,%04d\",A=\"FL:%s,%d\"$$",filename,line,full_name,line; + else + "$$LK,\"%s\",A=\"FI:%s\"$$",filename,full_name; + } + Free(st); + } + } +} + +U0 PutDirLink(U8 *dirname,U8 *full_name=NULL) +{//Put $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"$ dir macro to StdOut, $LK,"DocPut",A="MN:DocPut"$. + U8 *st; + if (!dirname) return; + if (IsRaw) + "%s",dirname; + else { + if (!full_name) + full_name=st=DirNameAbs(dirname); + else + st=NULL; + "$$MA,T=\"%s\",LM=\"Cd(\\\"%s\\\");Dir;\n\"$$",dirname,full_name; + Free(st); + } +} diff --git a/T/BlkDev2/DskDirB.HC b/T/BlkDev2/DskDirB.HC new file mode 100644 index 0000000..b3ec593 --- /dev/null +++ b/T/BlkDev2/DskDirB.HC @@ -0,0 +1,201 @@ +U0 HomeSet(U8 *dirname) +{//Change home directory. + dirname=DirNameAbs(dirname); + Free(blkdev.home_dir); + blkdev.home_dir=AStrNew(dirname); + Free(dirname); +} + +Bool Cd(U8 *dirname=NULL,Bool make_dirs=FALSE) +{//Change directory. Optionally, make directories, too. + I64 maxlen,cur_dir_clus=0; + U8 *chg_to_buf,*new_cur_dir,*buf; + CDrv *dv; + Bool res=TRUE; + if (!dirname) + dirname="~"; + else if (!*dirname) + return TRUE; + if (dirname[1]==':') { + if (*dirname==':') { + if (Fs->cur_dv!=Let2Drv(':') && !Drv(*dirname)) + return FALSE; + } else if (Fs->cur_dv!=Let2Drv(*dirname) && !Drv(*dirname)) + return FALSE; + dirname+=2; + } + if (*dirname=='/' || !*dirname || !Fs->cur_dir) { + Free(Fs->cur_dir); + Fs->cur_dir=StrNew("/"); + if (*dirname=='/') + dirname++; + } + chg_to_buf=MStrUtil(dirname, + SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS); + maxlen=StrLen(Fs->cur_dir)+1+StrLen(chg_to_buf)+1; + new_cur_dir=MAlloc(maxlen); + buf=MAlloc(maxlen); + StrCpy(new_cur_dir,Fs->cur_dir); + while (*chg_to_buf && res) { + StrFirstRem(chg_to_buf,"/",buf); + if (!*buf) + StrCpy(new_cur_dir,"/"); + else if (!StrCmp(buf,"..")) { + StrLastRem(new_cur_dir,"/"); + if (!*new_cur_dir) + StrCpy(new_cur_dir,"/"); + } else if (!StrCmp(buf,"~")) { + Free(new_cur_dir); + new_cur_dir=MAlloc(StrLen(blkdev.home_dir+2)+1+StrLen(chg_to_buf)+1); + StrCpy(new_cur_dir,blkdev.home_dir+2); + if (Fs->cur_dv!=Let2Drv('~') && !Drv('~')) + return FALSE; + } else if (StrCmp(buf,".") && *buf) { + dv=Fs->cur_dv; + switch (dv->fs_type) { + case FSt_VIRT: + res=VirtCd(buf,new_cur_dir); + break; + case FSt_REDSEA: + cur_dir_clus=Name2DirClus(dv,new_cur_dir); + res=RedSeaCd(buf,cur_dir_clus); + break; + case FSt_FAT32: + cur_dir_clus=Name2DirClus(dv,new_cur_dir); + res=FAT32Cd(buf,cur_dir_clus); + break; + default: + PrintErr("File System Not Supported\n"); + res=FALSE; + } + if (!res && make_dirs) { + Free(Fs->cur_dir); + Fs->cur_dir=StrNew(new_cur_dir); + res=DirMk(buf); + } + if (res) { + if (StrCmp(new_cur_dir,"/")) + CatPrint(new_cur_dir,"/"); + CatPrint(new_cur_dir,buf); + } + } + } + Free(Fs->cur_dir); + Fs->cur_dir=StrNew(new_cur_dir); + Free(buf); + Free(chg_to_buf); + Free(new_cur_dir); + return res; +} + +Bool IsDir(U8 *dir_name) +{//Is a str a valid, existing Dir? + U8 *mask=MStrPrint("%s/*",dir_name); + Bool res,old_silent=Silent; + CDirContext *dirc; + if (dirc=DirContextNew(mask)) { + DirContextDel(dirc); + res=TRUE; + } else + res=FALSE; + Free(mask); + Silent(old_silent); + return res; +} + +I64 Dir(U8 *files_find_mask,Bool full) +{//List directory. + CDirEntry *tmpde1=NULL,*tmpde2; + U8 *st; + CDateStruct ds; + I64 csize=0xFFFF,c=0xFFFF,res=0; + tmpde1=FilesFind(files_find_mask); + if (!(st=DirCur)) + PrintErr("Invalid Drive\n"); + else { + if (tmpde1) { + Free(st); + st=MAllocIdent(tmpde1->full_name); + StrLastRem(st,"/"); + if (!st[2]) + StrCpy(st+2,"/"); +//Find max columns + tmpde2=tmpde1; + while (tmpde2) { + if (tmpde2->size>csize) + csize=tmpde2->size; + if (tmpde2->clus>c) + c=tmpde2->clus; + tmpde2=tmpde2->next; + } + csize=Bsr(csize)/4+1; + c=Bsr(c)/4+1; + + "$$MA,T=\"Directory\",LM=\"PopUpCd;Dir;\n\"$$of%s\n",st; + if (full) + "__DATE____TIME__%*ts%*ts\n", + csize,"SIZE",c,"BLK"; + else + "DATE_TIME_%*ts\n",csize,"SIZE"; + while (tmpde1) { + tmpde2=tmpde1->next; + res++; + if (full) + "%D%T%0*tX%0*tX ",tmpde1->datetime,tmpde1->datetime, + csize,tmpde1->size,c,tmpde1->clus; + else { + Date2Struct(&ds,tmpde1->datetime); + "%02d/%02d%02d:%02d%0*tX ",ds.mon,ds.day_of_mon,ds.hour,ds.min, + csize,tmpde1->size; + } + if (tmpde1->attr & RS_ATTR_DIR) + PutDirLink(tmpde1->name,tmpde1->full_name); + else + PutFileLink(tmpde1->name,tmpde1->full_name); + '\n'; + DirEntryDel(tmpde1); + tmpde1=tmpde2; + } + } else + "No matching entries\n"; + Free(st); + } + return res; +} + +Bool DirMk(U8 *filename,I64 entry_cnt=0) +{//Make directory. $LK,"Cd",A="MN:Cd"$() can also make directories. +//entry_cnt is for preallocating dir blks, leave it zero if you like. + U8 *name; + CDirContext *dirc; + Bool res=FALSE; + if (FileFind(filename,,FUF_JUST_DIRS)) + return FALSE; + if (dirc=DirContextNew(filename)) { + if (*dirc->mask) { + if (!FileNameChk(dirc->mask)) + PrintErr("Invalid FileName: \"%s\".\n",dirc->mask); + else { + "Make Directory:%s\n",filename; + name=MStrUtil(dirc->mask, + SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS); + switch (dirc->dv->fs_type) { + case FSt_VIRT: + res=VirtMkDir(dirc->dv,Fs->cur_dir,name,entry_cnt); + break; + case FSt_REDSEA: + res=RedSeaMkDir(dirc->dv,Fs->cur_dir,name,entry_cnt); + break; + case FSt_FAT32: + res=FAT32MkDir(dirc->dv,Fs->cur_dir,name,entry_cnt); + break; + default: + PrintErr("File System Not Supported\n"); + } + Free(name); + } + } + DirContextDel(dirc); + } + return res; +} diff --git a/T/BlkDev2/DskDirContext.HC b/T/BlkDev2/DskDirContext.HC new file mode 100644 index 0000000..7a62e94 --- /dev/null +++ b/T/BlkDev2/DskDirContext.HC @@ -0,0 +1,87 @@ +U0 DirContextDel(CDirContext *dirc,Bool restore=TRUE) +{//Change back to old cur_dir and drv. + CBlkDev *bd; + if (!dirc) return; + if (restore) { + bd=dirc->old_dv->bd; + if (!(bd->flags & BDF_INIT_IN_PROGRESS)) { + if (dirc->old_dir) { + Drv(Drv2Let(dirc->old_dv)); + Cd(dirc->old_dir); + } + } else { + Fs->cur_dv=dirc->old_dv; + Free(Fs->cur_dir); + Fs->cur_dir=StrNew("/"); + } + } + Free(dirc->old_dir); + Free(dirc->mask); + Free(dirc); +} + +CDirContext *DirContextNew(U8 *_mask,Bool make_mask=FALSE, + Bool make_dirs=FALSE,Bool no_mask=FALSE) +{//Save cur_dir and drv. Change to new dir. + Bool valid=TRUE,old_silent; + I64 mask_len=StrLen(_mask); + U8 *buf,*mask,*tmp_mask,*semicolon_mask; + CDirContext *dirc=CAlloc(sizeof(CDirContext)); + dirc->old_dir=StrNew(Fs->cur_dir); + dirc->old_dv=Fs->cur_dv; + mask=MStrUtil(_mask,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS); + tmp_mask=mask; + if (*mask && mask[1]==':') { + if (Fs->cur_dv!=Let2Drv(*mask) && !Drv(*mask)) + valid=FALSE; + mask+=2; + } + if (*mask=='~' && Fs->cur_dv!=Let2Drv('~') && !Drv('~')) + valid=FALSE; + dirc->dv=Fs->cur_dv; + DrvChk(dirc->dv); + buf=MAlloc(mask_len+2); + StrCpy(buf,mask); + + dirc->mask=MAlloc(mask_len+2); + if (no_mask) + *dirc->mask=0; + else if (StrOcc(buf,';')) { + semicolon_mask=MAlloc(mask_len+2); + StrCpy(semicolon_mask,mask); + StrFirstRem(semicolon_mask,";",buf); + StrLastRem(buf,"/",dirc->mask); + CatPrint(dirc->mask,";%s",semicolon_mask); + Free(semicolon_mask); + } else + StrLastRem(buf,"/",dirc->mask); + + if (*mask=='/' && !*buf) + StrCpy(buf,"/"); +//If began with Dir, change to Dir. + if (*buf && !Cd(buf,make_dirs)) + valid=FALSE; + if (valid && make_mask) { + if (!*dirc->mask) { + Free(dirc->mask); + dirc->mask=StrNew("*"); + } else { + if (!make_dirs || FileNameChk(dirc->mask)) { + old_silent=Silent; +//Try mask to see if Dir. If Dir, change to dir and set to "*". + if (Cd(dirc->mask,make_dirs)) { + Free(dirc->mask); + dirc->mask=StrNew("*"); + } + Silent(old_silent); + } + } + } + Free(buf); + Free(tmp_mask); + if (!valid) { + DirContextDel(dirc); + dirc=NULL; + } + return dirc; +} diff --git a/T/BlkDev2/DskDrv.HC b/T/BlkDev2/DskDrv.HC new file mode 100644 index 0000000..e9a685e --- /dev/null +++ b/T/BlkDev2/DskDrv.HC @@ -0,0 +1,367 @@ +Bool DrvLock(CDrv *dv) +{//Make this task have exclusive access to drv & BlkDev. + DrvChk(dv); + BlkDevLock(dv->bd); + if (!Bt(&dv->locked_flags,DVlf_LOCKED) || dv->owning_task!=Fs) { + while (LBts(&dv->locked_flags,DVlf_LOCKED)) + Yield; + dv->owning_task=Fs; + return TRUE; + } else + return FALSE; +} + +Bool DrvUnlock(CDrv *dv,Bool rst=FALSE) +{//Release exclusive lock on access to drv & BlkDev. + DrvChk(dv); + if (Bt(&dv->locked_flags,DVlf_LOCKED) && dv->owning_task==Fs) { + BlkDevUnlock(dv->bd,rst); + dv->owning_task=NULL; + LBtr(&dv->locked_flags,DVlf_LOCKED); + Yield; //Prevent deadlock + return TRUE; + } else + return FALSE; +} + +U0 DrvsRelease() +{//When task dies, release all owned drvs. + I64 i; + CDrv *dv; + for (i=0;i<DRVS_NUM;i++) { + dv=&blkdev.drvs[i]; + if (dv->owning_task==Fs && dv->dv_signature==DRV_SIGNATURE_VAL) + DrvUnlock(dv,TRUE); + } +} + +CDrv *DrvMakeFreeSlot(U8 drv_let) +{//Make a slot free for a new drv, like during $LK,"Mount",A="MN:Mount"$(). +//!!! drv_let is not a $LK,"remapped",A="MN:DrvMap"$ drv. + I64 i=Let2Let(drv_let)-'A'; + CDrv *res; + if (!(0<=i<DRVS_NUM)) + throw('Drv'); + res=&blkdev.drvs[i]; + MemSet(res,0,sizeof(CDrv)); + res->drv_let='A'+i; + return res; +} + +U8 DrvNextFreeLet(U8 first_drv_let='C') +{//Locate free slot for new drv, like during $LK,"Mount",A="MN:Mount"$(). +//!!! first_drv_let is not a $LK,"remapped",A="MN:DrvMap"$ drv. + I64 i=Let2Let(first_drv_let)-'A',type=Let2BlkDevType(first_drv_let); + if (!(0<=i<DRVS_NUM)) + throw('Drv'); + do + if (blkdev.drvs[i].dv_signature!=DRV_SIGNATURE_VAL) { + if (Let2BlkDevType(i+'A')!=type) + throw('Drv'); + else + return i+'A'; + } + while (++i<DRVS_NUM); + throw('Drv'); + return 0; //Never gets here. +} + +U0 DrvDel(CDrv *dv) +{//Delete drv + if (dv->fs_type==FSt_REDSEA && dv->next_free) + RedSeaFreeFreeLst(dv); + Free(dv->cur_fat_blk); + Free(dv->fis); + MemSet(dv,0,sizeof(CDrv)); +} + +U0 DrvBlkDevDel(CBlkDev *bd) +{//Delete drv's of BlkDev + I64 i; + CDrv *dv; + for (i=0;i<DRVS_NUM;i++) { + dv=&blkdev.drvs[i]; + if (dv->bd==bd) + DrvDel(dv); + } +} + +U0 DrvFATBlkAlloc(CDrv *dv) +{ + DrvChk(dv); + Free(dv->cur_fat_blk); + dv->cur_fat_blk=AMAlloc(BLK_SIZE); + dv->cur_fat_blk_num=0; + dv->fat_blk_dirty=0; + BlkRead(dv,dv->cur_fat_blk,dv->fat1,1); +} + +U0 DrvFATBlkClean(CDrv *dv,I64 fat_sel=3) +{ + if ((dv->fs_type==FSt_FAT32 || dv->fs_type==FSt_REDSEA) && + Bt(&dv->fat_blk_dirty,0)) { + if (dv->fat1==dv->fat2) { + BlkWrite(dv,dv->cur_fat_blk,dv->fat1+dv->cur_fat_blk_num,1); + LBtr(&dv->fat_blk_dirty,0); + } else { + if (fat_sel==3 || !fat_sel) + BlkWrite(dv,dv->cur_fat_blk,dv->fat1+dv->cur_fat_blk_num,1); + if (fat_sel==3 || fat_sel==1) { + BlkWrite(dv,dv->cur_fat_blk,dv->fat2+dv->cur_fat_blk_num,1); + LBtr(&dv->fat_blk_dirty,0); + } + } + } +} + +U0 DrvFATBlkSet(CDrv *dv,I64 c,I64 fat_sel=3) +{ + I64 fat_blk_num; + if (c==INVALID_CLUS) + throw('Drv'); + switch (dv->fs_type) { + case FSt_FAT32: + fat_blk_num=c>>(BLK_SIZE_BITS-2); + break; + case FSt_REDSEA: + fat_blk_num=(c-dv->data_area)>>(BLK_SIZE_BITS+3); + break; + default: + throw('Drv'); + } + if (fat_blk_num!=dv->cur_fat_blk_num) { + DrvFATBlkClean(dv,fat_sel); + dv->cur_fat_blk_num=fat_blk_num; + if (fat_sel==3 || !fat_sel) + BlkRead(dv,dv->cur_fat_blk,dv->fat1+dv->cur_fat_blk_num,1); + else + BlkRead(dv,dv->cur_fat_blk,dv->fat2+dv->cur_fat_blk_num,1); + } +} + +CDrv *DrvChk(CDrv *dv,Bool except=TRUE) +{//Check for valid drv. Throw exception. + if (!dv || dv->dv_signature!=DRV_SIGNATURE_VAL) { + if (except) { + throw('Drv'); + } + else + return NULL; + } else + return dv; +} + +U8 Drv2Let(CDrv *dv=NULL) +{//Drv ptr to Drv letter. + if (!dv) + dv=Fs->cur_dv; + DrvChk(dv); + return dv->drv_let; +} + +U8 Let2Let(U8 drv_let=0) +{//Drv letter to Drv letter. + if (!drv_let) + drv_let=Drv2Let(Fs->cur_dv); + else if (drv_let==':') + drv_let=blkdev.boot_drv_let; + else if (drv_let=='~') + drv_let=*blkdev.home_dir; + return ToUpper(drv_let); +} + +I64 Let2BlkDevType(U8 drv_let) +{//Drv letter to BlkDev Type. drv_let=0 not allowed. See $LK,"BDT_NULL",A="MN:BDT_NULL"$. + drv_let=Let2Let(drv_let); + if ('A'<=drv_let<='B') + return BDT_RAM; + if ('C'<=drv_let<='L') + return BDT_VIRT; + if ('M'<=drv_let<='P') + return BDT_ISO_FILE_READ; + if ('Q'<=drv_let<='S') + return BDT_ISO_FILE_WRITE; + if ('T'<=drv_let<='Z') + return BDT_VIRT; + return BDT_NULL; +} + +CDrv *Let2Drv(U8 drv_let=0,Bool except=TRUE) +{//Drv letter to Drv ptr. + CDrv *dv; + if (!drv_let) + dv=Fs->cur_dv; + else { + drv_let=Let2Let(drv_let); + if (!('A'<=drv_let<='Z')) { + if (except) + throw('Drv'); + else + return NULL; + } + dv=blkdev.let_to_drv[drv_let-'A']; + } + return DrvChk(dv,except); +} + +CBlkDev *DrvIsWritable(U8 drv_let=0,Bool except=FALSE) +{//Is drive writable? + CBlkDev *bd; + if (!(bd=Let2BlkDev(drv_let,except)) || bd->flags & BDF_READ_ONLY) { + if (except) + throw('Drv'); + else + return NULL; + } else + return bd; +} + +U0 DskCacheInvalidate(CDrv *dv) +{//Needed for removable media. Called by $LK,"DskChg",A="MN:DskChg"$(). + Bool unlock; + CBlkDev *bd=dv->bd; + DrvChk(dv); + try { + unlock=DrvLock(dv); + BlkDevInit(bd); + if (bd->flags & BDF_READ_CACHE) + DskCacheInvalidate2(dv); + if (bd->type==BDT_ATAPI && !(bd->flags & BDF_READ_ONLY_OVERRIDE)) + ISOInit(dv,(32767/bd->blk_size+1)*bd->blk_size>>BLK_SIZE_BITS); + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); +} + +U0 DskChg(U8 drv_let=0) +{//Change disk. (Needed for removable media.) + CDrv *dv=Let2Drv(drv_let); + CBlkDev *bd=dv->bd; + if (!(bd->flags&BDF_INITIALIZED)) + BlkDevInit(bd); + else if (bd->flags&BDF_REMOVABLE) { + if (bd->type==BDT_ATAPI) + DskCacheInvalidate(dv); + } + Drv(drv_let); + RedSeaFreeFreeLst(dv); +} + +Bool DrvMap(U8 drv_let,CDrv *dv) +{//Make drive letter map to another. + drv_let=Let2Let(drv_let); + if ('A'<=drv_let<='Z') { + blkdev.let_to_drv[drv_let-'A']=dv; + dv->drv_let=drv_let; + return TRUE; + } else + return FALSE; +} + +Bool Drv(U8 drv_let) +{//Change drive. You can set drive with $LK,"Cd",A="MN:Cd"$() as well. + CDrv *dv=Let2Drv(drv_let); + CBlkDev *bd; + bd=BlkDevChk(dv->bd); + if (dv!=Fs->cur_dv) { + if (bd->flags & BDF_REMOVABLE && !(bd->flags & BDF_INITIALIZED)) + DskChg(Drv2Let(dv)); + if (bd->type==BDT_RAM || + bd->type==BDT_ISO_FILE_READ || bd->type==BDT_ISO_FILE_WRITE) + BlkDevInit(bd); + } + Fs->cur_dv=dv; + Free(Fs->cur_dir); + Fs->cur_dir=StrNew("/"); + switch (dv->fs_type) { + case FSt_VIRT: + case FSt_REDSEA: + case FSt_FAT32: + return TRUE; + default: + PrintErr("File System Not Supported\n"); + return FALSE; + } +} + +U8 *DrvSerialNum(U8 drv_let=0) +{//20 bytes max. + CBlkDev *bd=Let2BlkDev(drv_let); + U16 *st,*res=NULL; + I64 i; + if (bd->dev_id_record) { + st=CAlloc(20+1); + for (i=0;i<10;i++) + st[i]=EndianU16(bd->dev_id_record[10+i]); + res=MStrUtil(st,SUF_REM_LEADING|SUF_REM_TRAILING); + Free(st); + } + return res; +} + +U8 *DrvModelNum(U8 drv_let=0) +{//40 bytes max. + CBlkDev *bd=Let2BlkDev(drv_let); + U16 *st,*res=NULL; + I64 i; + if (bd->dev_id_record) { + st=CAlloc(40+1); + for (i=0;i<20;i++) + st[i]=EndianU16(bd->dev_id_record[27+i]); + res=MStrUtil(st,SUF_REM_LEADING|SUF_REM_TRAILING); + Free(st); + } + return res; +} + +U8 blkdev_text_attr[BDT_TYPES_NUM]={BLACK,LTCYAN,WHITE,LTGREEN,LTRED,LTBLUE,GREEN}; +U8 drv_text_attr[3]={BLACK,BLUE,RED}; + +U8 DrvTextAttrGet(U8 drv_let=0) +{//Get color of drive. + drv_let=Let2Let(drv_let); + if ('A'<=drv_let<='Z') + return blkdev_text_attr[Let2BlkDevType(drv_let)]<<4| + drv_text_attr[drv_let%sizeof(drv_text_attr)]; + else + return BLACK<<4|WHITE; +} + +U0 DrvRep() +{//Drive report. + CDrv *dv; + CBlkDev *bd; + I64 ch,i,drv_let,attr; + U8 *st; + "\nDefined Drives:\n"; + for (i=0,dv=blkdev.drvs;i<DRVS_NUM;i++,dv++) { + if (dv->dv_signature==DRV_SIGNATURE_VAL) { + bd=dv->bd; + drv_let=Drv2Let(dv); + if (Bt(&dv->fs_type,FStf_DISABLE)) + ch='-'; + else if (drv_let==blkdev.boot_drv_let) + ch=':'; + else + ch='+'; + attr=DrvTextAttrGet(drv_let); + "$$FG,%d$$$$BG,%d$$%C %-8Z %-10Z %04X %04X %02X\n", + attr&15,attr>>4,drv_let,dv->fs_type&FSG_TYPE_MASK,"ST_DRV_TYPES", + bd->type,"ST_BLKDEV_TYPES",bd->base0,bd->base1,bd->unit; + if (st=DrvModelNum(drv_let)) { + "Model#:%s\n",st; + Free(st); + } + if (st=DrvSerialNum(drv_let)) { + "Serial#:%s\n",st; + Free(st); + } + if (bd->type==BDT_ISO_FILE_READ || bd->type==BDT_ISO_FILE_WRITE) + "File=\"%s\"\n",bd->file_dsk_name; + "%016X-%016X\n$$FG$$$$BG$$",dv->drv_offset,dv->drv_offset+dv->size-1; + } + } + "Home Dir:\"%s\"\n",blkdev.home_dir; +} diff --git a/T/BlkDev2/DskFile.HC b/T/BlkDev2/DskFile.HC new file mode 100644 index 0000000..3c5ff80 --- /dev/null +++ b/T/BlkDev2/DskFile.HC @@ -0,0 +1,127 @@ +U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL) +{//Read whole file from disk. + CHashGeneric *tmph; + U8 *absname,*altname,*curname,*res=NULL; + I64 i,size=0,attr=0; + CDirContext *dirc; + CArcCompress *arc; + absname=FileNameAbs(filename); + altname=ToggleZorNotZ(absname); + if ((tmph=HashFind(absname,adam_task->hash_table,HTT_FILE))|| + (tmph=HashFind(altname,adam_task->hash_table,HTT_FILE))) { + size=tmph->user_data1; + res=MAlloc(size+1); + MemCpy(res,tmph->user_data0,size); + res[size]=0; //Terminate + attr=FileAttr(tmph->str,attr); + } else { + for (i=0;i<2 && !res;i++) {//Try name, then altname + if (!i) + curname=absname; + else + curname=altname; + if (dirc=DirContextNew(curname)) { + switch (dirc->dv->fs_type) { + case FSt_VIRT: + res=VirtFileRead(dirc->dv,Fs->cur_dir,dirc->mask,&size,&attr); + break; + case FSt_REDSEA: + res=RedSeaFileRead(dirc->dv,Fs->cur_dir,dirc->mask,&size,&attr); + break; + case FSt_FAT32: + res=FAT32FileRead(dirc->dv,Fs->cur_dir,dirc->mask,&size,&attr); + break; + default: + PrintErr("File System Not Supported\n"); + } + DirContextDel(dirc); + } + } + + //Search parent directories. + for (i=0;i<2 && !res;i++) {//Try name, then altname + if (!i) + curname=absname; + else + curname=altname; + if (dirc=DirContextNew(curname)) { + while (!res && StrCmp(Fs->cur_dir,"/")) { + Cd(".."); + switch (Fs->cur_dv->fs_type) { + case FSt_VIRT: + res=VirtFileRead(dirc->dv,Fs->cur_dir,dirc->mask,&size,&attr); + break; + case FSt_REDSEA: + res=RedSeaFileRead(dirc->dv,Fs->cur_dir,dirc->mask,&size,&attr); + break; + case FSt_FAT32: + res=FAT32FileRead(dirc->dv,Fs->cur_dir,dirc->mask,&size,&attr); + break; + default: + PrintErr("File System Not Supported\n"); + } + } + DirContextDel(dirc); + } + } + if (!res) + PrintErr("File not found: \"%s\".\n",filename); + if (res && attr & RS_ATTR_RESIDENT) + HashGenericAdd(curname,HTT_FILE,AMAllocIdent(res),size,0,adam_task); + } + if (res && attr & RS_ATTR_COMPRESSED) { + arc=res; + size=arc->expanded_size; + res=ExpandBuf(arc,Fs); + Free(arc); + } + if (_attr) *_attr=attr; + if (_size) *_size=size; + Free(absname); + Free(altname); + return res; +} + +I64 FileWrite(U8 *filename,U8 *fbuf,I64 size,CDate cdt=0,I64 attr=0) +{//Write whole file to disk. + I64 c=0; + CHashGeneric *tmph; + CDirContext *dirc; + U8 *fbuf2,*absname=FileNameAbs(filename); + if (dirc=DirContextNew(filename,FALSE,TRUE)) { + attr=FileAttr(dirc->mask,attr); + if (attr&RS_ATTR_COMPRESSED) { + fbuf=CompressBuf(fbuf,size); + size=fbuf(CArcCompress *)->compressed_size; + fbuf2=fbuf; + } else + fbuf2=NULL; + if (!cdt) cdt=Now; + switch (dirc->dv->fs_type) { + case FSt_VIRT: + c=VirtFileWrite(dirc->dv,Fs->cur_dir,dirc->mask,fbuf,size,cdt,attr); + break; + case FSt_REDSEA: + c=RedSeaFileWrite(dirc->dv,Fs->cur_dir,dirc->mask,fbuf,size,cdt,attr); + break; + case FSt_FAT32: + c=FAT32FileWrite(dirc->dv,Fs->cur_dir,dirc->mask,fbuf,size,cdt,attr); + break; + default: + PrintErr("File System Not Supported\n"); + } + if (tmph=HashFind(absname,adam_task->hash_table,HTT_FILE)) { + if (attr & RS_ATTR_RESIDENT) { + Free(tmph->user_data0); + tmph->user_data0=AMAllocIdent(fbuf); + tmph->user_data1=size; + } else + HashRemDel(tmph,adam_task->hash_table); + } else if (attr & RS_ATTR_RESIDENT) + HashGenericAdd(absname,HTT_FILE,AMAllocIdent(fbuf),size,0,adam_task); + Free(fbuf2); + DirContextDel(dirc); + } + Free(absname); + return c; +} diff --git a/T/BlkDev2/DskFind.HC b/T/BlkDev2/DskFind.HC new file mode 100644 index 0000000..6f3cdc1 --- /dev/null +++ b/T/BlkDev2/DskFind.HC @@ -0,0 +1,163 @@ +CDirEntry *FilesFind2(U8 *files_find_mask,I64 fuf_flags) +{ + CDrv *dv=Fs->cur_dv; + CDirEntry *res=NULL; + DrvChk(dv); + switch (dv->fs_type) { + case FSt_VIRT: + res=VirtFilesFind(files_find_mask,fuf_flags); + break; + case FSt_REDSEA: + res=RedSeaFilesFind(files_find_mask,fuf_flags); + break; + case FSt_FAT32: + res=FAT32FilesFind(files_find_mask,fuf_flags); + break; + default: + PrintErr("File System Not Supported\n"); + res=NULL; + } + if (res) { + DirFilesSort(&res,SK_NAME); + if (fuf_flags&(FUF_FLATTEN_TREE|FUF_JUST_FILES)) + DirFilesFlatten(res,&res,fuf_flags); + if (fuf_flags&FUF_CLUS_ORDER) + DirFilesSort(&res,SK_CLUS); + } + return res; +} + +CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0) +{/* See $LK,"::/Doc/FileUtils.DD"$. + +Find files and make a directory tree in memory. + +When done, you free with $LK,"DirEntryDel",A="MN:DirEntryDel"$(),$LK,"DirEntryDel2",A="MN:DirEntryDel2"$(), +$LK,"DirTreeDel",A="MN:DirTreeDel"$() or $LK,"DirTreeDel2",A="MN:DirTreeDel2"$(). + +*/ + CDirEntry *res; + CDirContext *dirc; + if (fuf_flags&~FUG_FILES_FIND) + throw('FUF'); + if (fuf_flags&FUF_SINGLE) { + res=MAlloc(sizeof(CDirEntry)); + if (!FileFind(files_find_mask,res)) { + Free(res); + return NULL; + } + } else if (dirc=DirContextNew(files_find_mask,TRUE)) { + res=FilesFind2(dirc->mask,fuf_flags); + DirContextDel(dirc); + } else + return NULL; + return res; +} + +Bool FileFind(U8 *filename,CDirEntry *_de=NULL,I64 fuf_flags=0) +{//$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$, $LK,"FUF_Z_OR_NOT_Z",A="MN:FUF_Z_OR_NOT_Z"$, $LK,"FUF_SCAN_PARENTS",A="MN:FUF_SCAN_PARENTS"$ +//If you pass _de, you must Free(_de->full_name); + I64 i,j,cur_dir_clus; + U8 *altname,*curname,*full_name=NULL; + CDirEntry de; + CDirContext *dirc; + Bool res=FALSE,old_silent; + if (fuf_flags&~FUG_FILE_FIND) + throw('FUF'); + if (!filename || *filename && filename[1]==':' && !Let2Drv(*filename,FALSE)) + return FALSE; + altname=ToggleZorNotZ(filename); + if (fuf_flags&FUF_Z_OR_NOT_Z) + j=2; + else + j=1; + for (i=0;i<j && !res;i++) { + if (!i) + curname=filename; + else + curname=altname; + old_silent=Silent; + if (!(dirc=DirContextNew(curname))) + Silent(old_silent); + else { + Silent(old_silent); + switch (dirc->dv->fs_type) { + case FSt_VIRT: + res=VirtFileFind(dirc->dv,Fs->cur_dir,dirc->mask, + &de,fuf_flags); + break; + case FSt_REDSEA: + cur_dir_clus=Name2DirClus(dirc->dv,Fs->cur_dir); + res=RedSeaFileFind(dirc->dv,cur_dir_clus,dirc->mask, + &de,fuf_flags); + break; + case FSt_FAT32: + cur_dir_clus=Name2DirClus(dirc->dv,Fs->cur_dir); + res=FAT32FileFind(dirc->dv,cur_dir_clus,dirc->mask, + &de,fuf_flags); + break; + default: + PrintErr("File System Not Supported\n"); + } + if (res && _de) { + if (StrCmp(Fs->cur_dir,"/")) + full_name=MStrPrint("%C:%s/%s", + Drv2Let(Fs->cur_dv),Fs->cur_dir,de.name); + else + full_name=MStrPrint("%C:/%s",Drv2Let(Fs->cur_dv),de.name); + } + DirContextDel(dirc); + } + } + for (i=0;i<j && !res && fuf_flags&FUF_SCAN_PARENTS;i++) { + if (!i) + curname=filename; + else + curname=altname; + old_silent=Silent; + if (!(dirc=DirContextNew(curname))) + Silent(old_silent); + else { + Silent(old_silent); + while (!res && StrCmp(Fs->cur_dir,"/")) { + Cd(".."); + switch (dirc->dv->fs_type) { + case FSt_VIRT: + res=VirtFileFind(dirc->dv,Fs->cur_dir, + dirc->mask,&de,fuf_flags); + break; + case FSt_REDSEA: + cur_dir_clus=Name2DirClus(dirc->dv,Fs->cur_dir); + res=RedSeaFileFind(dirc->dv,cur_dir_clus, + dirc->mask,&de,fuf_flags); + break; + case FSt_FAT32: + cur_dir_clus=Name2DirClus(dirc->dv,Fs->cur_dir); + res=FAT32FileFind(dirc->dv,cur_dir_clus, + dirc->mask,&de,fuf_flags); + break; + default: + PrintErr("File System Not Supported\n"); + } + } + if (res && _de) { + if (StrCmp(Fs->cur_dir,"/")) + full_name=MStrPrint("%C:%s/%s", + Drv2Let(Fs->cur_dv),Fs->cur_dir,de.name); + else + full_name=MStrPrint("%C:/%s", + Drv2Let(Fs->cur_dv),de.name); + } + DirContextDel(dirc); + } + } + if (_de) { + if (res) { + MemCpy(_de,&de,sizeof(CDirEntry)); + _de->full_name=full_name; + } else + MemSet(_de,0,sizeof(CDirEntry)); + } + Free(altname); + return res; +} diff --git a/T/BlkDev2/DskFmt.HC b/T/BlkDev2/DskFmt.HC new file mode 100644 index 0000000..3bffb8d --- /dev/null +++ b/T/BlkDev2/DskFmt.HC @@ -0,0 +1,90 @@ +Bool DrvTypeSet(U8 drv_let,I64 type=FSt_REDSEA) +{//Very dangerous + I64 i,j,ext_base,drv_num,offset,cur_type; + CMasterBoot mbr; + CBlkDev *bd; + drv_let=Let2Let(drv_let); + bd=Let2BlkDev(drv_let); + drv_num=bd->first_drv_let-'A'; + switch (bd->type) { + case BDT_ATA: + offset=0; + ext_base=INVALID_CLUS; + while (TRUE) { + j=-1; + for (i=0;i<4;i++) { + cur_type=mbr.p[i].type; + if (cur_type) { + if (cur_type==5 || cur_type==15) + j=i; + else { + if (drv_num+'A'==drv_let) { + switch (type) { + case FSt_REDSEA: + mbr.p[i].type=MBR_PT_REDSEA; + break; + case FSt_FAT32: + mbr.p[i].type=MBR_PT_FAT32a; + break; + default: + throw('Drv'); + } + mbr.p[i].active=0x80; + return TRUE; + } + drv_num++; + } + } + } + if (j<0) + break; + if (!mbr.p[j].offset) + break; + if (ext_base==INVALID_CLUS) { + offset=mbr.p[j].offset; + ext_base=offset; + } else + offset=mbr.p[j].offset+ext_base; + } + break; + } +} + +U0 Fmt(I64 drv_let,Bool quick=TRUE,Bool confirm=TRUE,I64 type=FSt_FAT32) +{//Format hard drive or RAM drive. +//$BK,1$Warning:$BK,0$ Destroys all prev info. + //quick=FALSE means fill entire drive with zeros. + //Choose $LK,"FSt_FAT32",A="MN:FSt_FAT32"$ or $LK,"FSt_REDSEA",A="MN:FSt_REDSEA"$. + //You don't format a CD/DVD with this. + CDrv *dv=Let2Drv(drv_let); + Bool old_silent=IsSilent; + if (confirm && !AreYouSure) + return; + if (!dv) { + PrintErr("Invalid Drive\n"); + return; + } + switch (type) { + case FSt_FAT32: + if (dv->bd->type==BDT_ATA) { + Silent; + Drv(drv_let); + Silent(old_silent); + FAT32Fmt(drv_let,quick); + DskCacheInvalidate(Let2Drv(drv_let)); + Drv(drv_let); + break; + } + "Using RedSea File System.\n"; + case FSt_REDSEA: + Silent; + Drv(drv_let); + Silent(old_silent); + RedSeaFmt(drv_let,quick); + DskCacheInvalidate(Let2Drv(drv_let)); + Drv(drv_let); + break; + default: + PrintErr("File System Not Supported\n"); + } +} diff --git a/T/DSKSTR.HC b/T/BlkDev2/DskStrA.HC index f3f755f..1be49bc 100644 --- a/T/DSKSTR.HC +++ b/T/BlkDev2/DskStrA.HC @@ -38,8 +38,7 @@ Bool IsDotC(U8 *filename) } Bool FilesFindMatch(U8 *_test_name,U8 *files_find_mask,I64 fuf_flags=0) -{//Does filename meet \dLK,"Files Find",A="FI:::/Doc/FileUtils.DD"\d mask? - if(!_test_name) return FALSE; +{//Does filename meet $LK,"Files Find",A="FI:::/Doc/FileUtils.DD"$ mask? I64 tn_len=StrLen(_test_name),mask_len=StrLen(files_find_mask); U8 *mask1=MAlloc(mask_len+1),*mask2=MAlloc(mask_len+1), *ptr,*test_name1,*test_name2; @@ -105,6 +104,102 @@ Bool FilesFindMatch(U8 *_test_name,U8 *files_find_mask,I64 fuf_flags=0) Free(mask2); return res; } + +U8 *DirNameAbs(U8 *_dirname) +{//MAlloc absolute dir string with drv letter. + I64 maxlen; + U8 drv[3],*res,*buf,*buf2,*buf3,*buf4,*dirname,*free_dirname; + if (!Fs->cur_dir || !*Fs->cur_dir) + return StrNew(_dirname); + free_dirname=dirname=MStrUtil(_dirname, + SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS); + *drv=Drv2Let; + drv[1]=':'; + drv[2]=0; + if (*dirname && dirname[1]==':') { + if (*dirname==':') + *drv=blkdev.boot_drv_let; + else if (*dirname=='~') + *drv=*blkdev.home_dir; + else + *drv=*dirname; + dirname=dirname+2; + buf=StrNew("/"); + } else + buf=StrNew(Fs->cur_dir); + if (*dirname=='/') { + Free(buf); + buf=StrNew("/"); + dirname++; + } + buf2=StrNew(dirname); + maxlen=StrLen(buf)+1+StrLen(buf2)+1; + buf3=MAlloc(maxlen); + buf4=MAlloc(maxlen); + StrCpy(buf3,buf); + while (*buf2) { + StrFirstRem(buf2,"/",buf4); + if (!*buf4) + StrCpy(buf3,"/"); + else if (!StrCmp(buf4,"..")) { + StrLastRem(buf3,"/"); + if (!*buf3) + StrCpy(buf3,"/"); + } else if (!StrCmp(buf4,"~")) { + Free(buf3); + buf3=MAlloc(StrLen(blkdev.home_dir+2)+1+StrLen(buf2)+1); + StrCpy(buf3,blkdev.home_dir+2); + *drv=*blkdev.home_dir; + } else if (!StrCmp(buf4,".")); + else if (*buf4) { + if (StrCmp(buf3,"/")) + CatPrint(buf3,"/"); + CatPrint(buf3,buf4); + } + } + Free(buf); + res=MAlloc(StrLen(buf3)+3); + StrCpy(res,drv); + StrCpy(res+2,buf3); + Free(buf2); + Free(buf3); + Free(buf4); + Free(free_dirname); + return res; +} + +U8 *FileNameAbs(U8 *_filename,I64 fuf_flags=0) +{//Absolute filename. Accepts $LK,"FUF_Z_OR_NOT_Z",A="MN:FUF_Z_OR_NOT_Z"$, $LK,"FUF_SCAN_PARENTS",A="MN:FUF_SCAN_PARENTS"$. + U8 *res,*filename,*buf,*buf_file,*buf_dir,*free_filename,*free_buf; + CDirEntry de; + free_filename=filename=MStrUtil(_filename, + SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS); + free_buf=buf=StrNew(filename); + if (*buf && buf[1]==':') { + buf+=2; + filename+=2; + } + buf_file=MAlloc(StrLen(free_filename)+1); + StrLastRem(buf,"/",buf_file); + if (*filename=='/' && !*buf) + StrCpy(buf,"/"); + buf_dir=DirNameAbs(free_buf); + Free(free_buf); + res=MAlloc(StrLen(buf_dir)+1+StrLen(buf_file)+1); + StrCpy(res,buf_dir); + if (res[StrLen(res)-1]!='/') + CatPrint(res,"/"); + CatPrint(res,buf_file); + Free(buf_file); + Free(buf_dir); + Free(free_filename); + if (fuf_flags && FileFind(res,&de,fuf_flags|FUF_JUST_FILES)) { + Free(res); + res=de.full_name; + } + return res; +} + U8 *ExtChg(U8 *filename,U8 *extension) {//Change filename extension. U8 *res=MAlloc(StrLen(filename)+1+StrLen(extension)+1); @@ -123,6 +218,34 @@ U8 *ExtDft(U8 *filename,U8 *extension) return res; } +CDirEntry *Cd2DirEntry(CDirEntry *tmpde,U8 *abs_name) +{ + I64 i; + while (tmpde) { + i=StrLen(tmpde->full_name); + if (StrNCmp(tmpde->full_name,abs_name,i)|| + i && tmpde->full_name[i-1]!='/' && abs_name[i] && abs_name[i]!='/') + tmpde=tmpde->next; + else + if (StrLen(abs_name)==i) + return tmpde; + else + return Cd2DirEntry(tmpde->sub,abs_name); + } + return NULL; +} + +I64 FileAttr(U8 *name,I64 attr=0) +{ + if (IsDotZ(name)) + attr|=RS_ATTR_COMPRESSED; + else + attr&=~RS_ATTR_COMPRESSED; + if (IsDotC(name)) + attr|=RS_ATTR_CONTIGUOUS; + return attr; +} + Bool FileNameChk(U8 *filename) {//Return check for valid filename, not checking existence. U8 *ptr=filename; @@ -150,6 +273,24 @@ U8 *ToggleZorNotZ(U8 *name) return res; } +U8 *FileNameTmpTxt() +{//Make pretty-safe tmp filename in home dir. + return MStrPrint("~/SysTmp%X.DD.Z",RandI64); +} + +U8 *DirCur(CTask *task=NULL,CTask *mem_task=NULL) +{//MAlloc copy of cur dir with drv letter. + U8 *st; + if (!task) task=Fs; + if (!task->cur_dir) + return NULL; + st=MAlloc(StrLen(task->cur_dir)+3,mem_task); + *st=Drv2Let(task->cur_dv); + st[1]=':'; + StrCpy(st+2,task->cur_dir); + return st; +} + U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL) {/*Strips file from dirname, scans for file upward until found or returns default. @@ -200,20 +341,3 @@ returns default. Free(ext); return dft; } -CDirEntry *Cd2DirEntry(CDirEntry *tmpde,U8 *abs_name) -{ - I64 i; - while (tmpde) { - i=StrLen(tmpde->full_name); - if (StrNCmp(tmpde->full_name,abs_name,i)|| - i && tmpde->full_name[i-1]!='/' && abs_name[i] && abs_name[i]!='/') - tmpde=tmpde->next; - else - if (StrLen(abs_name)==i) - return tmpde; - else - return Cd2DirEntry(tmpde->sub,abs_name); - } - return NULL; -} - diff --git a/T/BlkDev2/DskStrB.HC b/T/BlkDev2/DskStrB.HC new file mode 100644 index 0000000..d485dc4 --- /dev/null +++ b/T/BlkDev2/DskStrB.HC @@ -0,0 +1,95 @@ +Bool CFileNameTo(U8 *dst,U8 *src) +{ + MemSet(dst,0,CDIR_FILENAME_LEN); + if (!FileNameChk(src)) + return FALSE; + StrCpy(dst,src); + return TRUE; +} + +I64 Name2DirClus(CDrv *dv,U8 *dirname) +{ + Bool cont=TRUE,unlock; + I64 cur_dir_clus; + CDirEntry de; + U8 *buf=StrNew(dirname),*buf2=StrNew(dirname); + DrvChk(dv); + try { + unlock=DrvLock(dv); + cur_dir_clus=dv->root_clus; + while (*buf && cont) { + StrFirstRem(buf,"/",buf2); + if (*buf2) { + switch (dv->fs_type) { + case FSt_VIRT: + cont=VirtFileFind(dv,cur_dir_clus,buf2,&de,FUF_JUST_DIRS); + break; + case FSt_REDSEA: + cont=RedSeaFileFind(dv,cur_dir_clus,buf2,&de,FUF_JUST_DIRS); + break; + case FSt_FAT32: + cont=FAT32FileFind(dv,cur_dir_clus,buf2,&de,FUF_JUST_DIRS); + break; + default: + throw('Drv'); + } + cur_dir_clus=de.clus; + } + } + if (!cont) { + PrintErr("File not found: \"%s\".\n",dirname); + cur_dir_clus=0; + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + Free(buf); + Free(buf2); + return cur_dir_clus; +} + +I64 Name2ParentDirClus(CDrv *dv,U8 *dirname) +{ + Bool cont=TRUE,unlock; + I64 cur_dir_clus,cur_dir_clus2; + CDirEntry de; + U8 *buf=StrNew(dirname),*buf2=StrNew(dirname); + DrvChk(dv); + try { + unlock=DrvLock(dv); + cur_dir_clus=cur_dir_clus2=dv->root_clus; + while (*buf && cont) { + cur_dir_clus2=cur_dir_clus; + StrFirstRem(buf,"/",buf2); + if (*buf2) { + switch (dv->fs_type) { + case FSt_VIRT: + cont=VirtFileFind(dv,cur_dir_clus,buf2,&de,FUF_JUST_DIRS); + break; + case FSt_REDSEA: + cont=RedSeaFileFind(dv,cur_dir_clus,buf2,&de,FUF_JUST_DIRS); + break; + case FSt_FAT32: + cont=FAT32FileFind(dv,cur_dir_clus,buf2,&de,FUF_JUST_DIRS); + break; + default: + throw('Drv'); + } + cur_dir_clus=de.clus; + } + } + if (!cont) { + PrintErr("File not found: \"%s\".\n",dirname); + cur_dir_clus2=0; + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + Free(buf); + Free(buf2); + return cur_dir_clus2; +} diff --git a/T/BlkDev2/FileSysFAT.HC b/T/BlkDev2/FileSysFAT.HC new file mode 100644 index 0000000..0de4ac2 --- /dev/null +++ b/T/BlkDev2/FileSysFAT.HC @@ -0,0 +1,959 @@ +U0 CDate2Dos(U16 *t,U16 *d,CDate cdt) +{ + CDateStruct ds; + Date2Struct(&ds,cdt); + *d=ds.day_of_mon+(ds.mon+(ds.year-1980)<<4)<<5; + *t=ds.sec>>1+(ds.min+ds.hour<<6)<<5; +} + +CDate Dos2CDate(U16 t,U16 d) +{ + CDateStruct ds; + MemSet(&ds,0,sizeof(CDateStruct)); + ds.day_of_mon=d&0x1F; d=d>>5; + ds.mon=d&0xF; + ds.year=d>>4+1980; + ds.sec=(t&0x1F)*2; t=t>>5; + ds.min=t&0x3F; + ds.hour=t>>6; + return Struct2Date(&ds); +} + +U0 FAT32Init(CDrv *dv) +{ + CFAT32Boot br32; + Bool unlock; + try { + unlock=DrvLock(dv); + dv->fs_type=FSt_FAT32; + BlkRead(dv,&br32,dv->drv_offset,1); + dv->file_system_info_sect=dv->drv_offset+br32.file_system_info_sect; + dv->fat1=dv->drv_offset+br32.reserved_sects; + dv->fat2=dv->fat1+br32.sects_per_fat; + dv->data_area=dv->fat2+br32.sects_per_fat + -2*br32.sects_per_clus; //Starts at Clus 2 + dv->spc=br32.sects_per_clus; + dv->root_clus=br32.root_clus; + DrvFATBlkAlloc(dv); + Free(dv->fis); + dv->fis=AMAlloc(BLK_SIZE); + BlkRead(dv,dv->fis,dv->file_system_info_sect,1); + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); +} + +U0 FAT32Fmt(U8 drv_let,Bool quick=TRUE) +{ + CFAT32Boot *br=CAlloc(BLK_SIZE); + CFAT32FileInfoSect *fis=CAlloc(BLK_SIZE); + CDrv *dv=Let2Drv(drv_let); + I64 i,l; + try { + DrvLock(dv); + DrvTypeSet(drv_let,FSt_FAT32); + dv->fs_type=FSt_FAT32; + br->jump_and_nop[0]=OC_JMP_REL8; + br->jump_and_nop[1]=offset(CFAT32Boot.code)-2; + br->jump_and_nop[2]=OC_NOP; + br->oem_name[0](I64)='MSWIN4.1'; + br->bytes_per_sect=BLK_SIZE; + if (dv->size<= 500000) + br->sects_per_clus=1; + else if (dv->size<=2000000) + br->sects_per_clus=2; + else if (dv->size<=6000000) + br->sects_per_clus=4; + else if (dv->size<=12000000) + br->sects_per_clus=8; + else if (dv->size<=33000000) + br->sects_per_clus=16; + else if (dv->size<=67000000) + br->sects_per_clus=32; + else + br->sects_per_clus=64; + + br->reserved_sects=32; + br->copies_of_fat=2; + br->media_desc=0xF8; + br->sects=dv->size; + l=(br->sects/br->sects_per_clus)>>(BLK_SIZE_BITS-2)+1; + br->sects_per_fat=l; + br->root_clus=2; + br->file_system_info_sect=1; + br->log_drv_num=0x80; + br->ext_signature=0x29; + br->serial_num=RandU32; + MemCpy(br->vol_name,"NONAME",11); + br->fat_name[0](I64)='FAT32'; + br->signature=0xAA55; + fis->signature1='RRaA'; + fis->signature2='rrAa'; + fis->free_clus=-1; + fis->most_recently_alloced=0; + fis->signature3=0xAA550000; + + if (quick) + i=br->reserved_sects+2*l+4*br->sects_per_clus; + else + i=dv->size; + BlkWriteZero(dv,dv->drv_offset,i); + + BlkWrite(dv,fis,dv->drv_offset+br->file_system_info_sect,1); + BlkWrite(dv,br,dv->drv_offset,1); + FAT32Init(dv); + ClusAlloc(dv,0,1,FALSE); //Alloc #1 + br->root_clus=ClusAlloc(dv,0,1,FALSE); + BlkWrite(dv,br,dv->drv_offset,1); + FAT32Init(dv); + DrvUnlock(dv); + } catch + DrvUnlock(dv); + Free(br); + Free(fis); +} + +Bool FATNameTo(U8 *dst,U8 *src) +{ + I64 i; + MemSet(dst,CH_SPACE,11); + if (!FileNameChk(src)) + return FALSE; + if (!StrCmp(src,"..")) { + *dst='.'; + dst[1]='.'; + return TRUE; + } else if (!StrCmp(src,".")) { + *dst='.'; + return TRUE; + } + i=0; + while (i<8 && *src && *src!='.') + dst[i++]=ToUpper(*src++); + i=8; + if (*src=='.') src++; + while (*src) + if (*src!='.') + dst[i++]=ToUpper(*src++); + else + src++; + return TRUE; +} + +I64 FATNameXSum(U8 *src) +{ + I64 i,res=0; + for (i=0;i<11;i++) + if (res&1) + res.u8[0]=0x80+res>>1+*src++; + else + res.u8[0]=res>>1+*src++; + return res; +} + +Bool FATFromName(U8 *dst,U8 *src) +{ + I64 i,j,k=0; + for (j=7;j>=0 && src[j]==CH_SPACE;j--); + for(i=0;i<=j;i++) + dst[k++]=src[i]; + for (j=10;j>=8 && src[j]==CH_SPACE;j--); + if (*src!='.' && j!=7) + dst[k++]='.'; + for(i=8;i<=j;i++) + dst[k++]=src[i]; + dst[k++]=0; + return FileNameChk(dst); +} + +U8 fat_long_name_map[13]={ + offset(CFAT32DirEntryLong.name1), + offset(CFAT32DirEntryLong.name1)+2, + offset(CFAT32DirEntryLong.name1)+4, + offset(CFAT32DirEntryLong.name1)+6, + offset(CFAT32DirEntryLong.name1)+8, + offset(CFAT32DirEntryLong.name2), + offset(CFAT32DirEntryLong.name2)+2, + offset(CFAT32DirEntryLong.name2)+4, + offset(CFAT32DirEntryLong.name2)+6, + offset(CFAT32DirEntryLong.name2)+8, + offset(CFAT32DirEntryLong.name2)+10, + offset(CFAT32DirEntryLong.name3), + offset(CFAT32DirEntryLong.name3)+2 +}; + +Bool DirLongNameFill(CDirEntry *tmpde,CFAT32DirEntryLong *de,I64 *xsum) +{ + I64 i; + U8 *ptr=de; + if (de->ord&0x40) { + MemSet(tmpde,0,sizeof(CDirEntry)); + *xsum=de->xsum; + } else if (de->type || de->zero || de->xsum!=*xsum) { + MemSet(tmpde,0,sizeof(CDirEntry)); + *xsum=0; + return FALSE; + } + switch (de->ord&0x3F) { + case 1: + for (i=0;i<13;i++) + if (!(tmpde->name[i]=ptr[fat_long_name_map[i]])) + return TRUE; + break; + case 2: + for (i=0;i<12;i++) + if (!(tmpde->name[i+13]=ptr[fat_long_name_map[i]])) + return TRUE; + break; + } + return TRUE; +} + +Bool FAT32CDirFill(CDirEntry *tmpde, + CFAT32DirEntry *de,CDate _local_time_offset) +{ + Bool res; + if (*tmpde->name) + res=TRUE; + else + res=FATFromName(tmpde->name,de->name); + tmpde->clus=de->clus_lo+de->clus_hi<<16; + tmpde->size=de->size; + tmpde->attr=de->attr; + tmpde->datetime=Dos2CDate(de->WrtTime,de->WrtDate)-_local_time_offset; + return res; +} + +Bool FAT32DirFill(CFAT32DirEntry *de, + CDirEntry *tmpde,I64 *_de_cnt,CDate _local_time_offset) +{//Fill up to 3 entries and store cnt of entries. + I64 de_cnt=0,i,l,xsum,ord; + U8 *ptr,dname[16]; + CFAT32DirEntryLong *ld=de; + Bool res; + + MemSet(de,0,sizeof(CFAT32DirEntry)); + res=FATNameTo(de->name,tmpde->name); + FATFromName(dname,de->name); + if (StrCmp(dname,tmpde->name)) { + ord=0x41; + xsum=FATNameXSum(de->name); + if ((l=StrLen(tmpde->name))>13) { + ptr=&ld[de_cnt]; + MemSet(ptr,0,sizeof(CFAT32DirEntryLong)); + ld[de_cnt].attr=RS_ATTR_LONG_NAME; + ld[de_cnt].xsum=xsum; + ld[de_cnt].ord=0x42; + for (i=13;i<l;i++) + ptr[fat_long_name_map[i-13]]=tmpde->name[i]; + i++; + for (;i<26;i++) + ptr[fat_long_name_map[i-13]](U16)=0xFFFF; + ord=1; + l=13; + de_cnt++; + } + ptr=&de[de_cnt]; + MemSet(ptr,0,sizeof(CFAT32DirEntryLong)); + ld[de_cnt].attr=RS_ATTR_LONG_NAME; + ld[de_cnt].xsum=xsum; + ld[de_cnt].ord=ord; + for (i=0;i<l;i++) + ptr[fat_long_name_map[i]]=tmpde->name[i]; + i++; + for (;i<13;i++) + ptr[fat_long_name_map[i]](U16)=0xFFFF; + de_cnt++; + MemSet(&de[de_cnt],0,sizeof(CFAT32DirEntry)); + res=FATNameTo(de[de_cnt].name,tmpde->name); + } + de[de_cnt].clus_lo=tmpde->clus.u16[0]; + de[de_cnt].clus_hi=tmpde->clus.u16[1]; + if (!(tmpde->attr&RS_ATTR_DIR)) + de[de_cnt].size=tmpde->size; + de[de_cnt].attr=tmpde->attr; + if (!tmpde->datetime) + tmpde->datetime=Now; + CDate2Dos(&de[de_cnt].WrtTime,&de[de_cnt].WrtDate, + tmpde->datetime+_local_time_offset); + if (_de_cnt) + *_de_cnt=de_cnt+1; + return res; +} + +Bool FAT32FileFind(CDrv *dv,I64 cur_dir_clus, + U8 *name,CDirEntry *_res,I64 fuf_flags=0) +{//$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$ + Bool res=FALSE,unlock; + CFAT32DirEntry *buf; + I64 xsum=0,attr,cur_dir_entry,entries_per_clus; + U8 dname[CDIR_FILENAME_LEN],ch; + CDirEntry long_name; + if (fuf_flags&~FUG_FILE_FIND) + throw('FUF'); + MemSet(_res,0,sizeof(CDirEntry)); + MemSet(&long_name,0,sizeof(CDirEntry)); + DrvChk(dv); + if (dv->fs_type!=FSt_FAT32) + PrintErr("Not FAT32 Drv\n"); + else if (!CFileNameTo(dname,name)) + PrintErr("Invalid FileName: \"%s\".\n",name); + else + try { + unlock=DrvLock(dv); + buf=MAlloc(BLK_SIZE*dv->spc); + entries_per_clus=dv->spc<<FAT32_ENTRIES_BITS; + ClusRead(dv,buf,cur_dir_clus,1); + cur_dir_entry=0; + while (ch=*buf[cur_dir_entry].name) { + attr=buf[cur_dir_entry].attr; + if (ch!=0xE5) { + if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME) + DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum); + else { + if (!(attr&RS_ATTR_VOL_ID)) { + if (xsum==FATNameXSum(buf[cur_dir_entry].name)) + MemCpy(_res,&long_name,sizeof(CDirEntry)); + else + MemSet(_res,0,sizeof(CDirEntry)); + if (!(fuf_flags&FUF_JUST_DIRS && !(attr & RS_ATTR_DIR)) && + !(fuf_flags&FUF_JUST_FILES && attr & RS_ATTR_DIR) && + FAT32CDirFill(_res,&buf[cur_dir_entry], + dv->fat32_local_time_offset) && + !StrCmp(dname,_res->name)) { + res=TRUE; + goto fff_done; + } + } + MemSet(&long_name,0,sizeof(CDirEntry)); + } + } else + MemSet(&long_name,0,sizeof(CDirEntry)); + if (++cur_dir_entry==entries_per_clus) { + cur_dir_clus=ClusNumNext(dv,cur_dir_clus); + if (!(0<cur_dir_clus<0x0FFFFFF8)) + break; + else { + ClusRead(dv,buf,cur_dir_clus,1); + cur_dir_entry=0; + } + } + } + MemSet(_res,0,sizeof(CDirEntry)); +fff_done: + Free(buf); + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + return res; +} + +U8 *FAT32FileRead(CDrv *dv,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr) +{ + U8 *buf=NULL; + CDirEntry de; + I64 c,blk_cnt,cur_dir_clus; + DrvChk(dv); + *_size=0; + *_attr=0; + if (dv->fs_type!=FSt_FAT32) + PrintErr("Not FAT32 Drv\n"); + else + try { + DrvLock(dv); + cur_dir_clus=Name2DirClus(dv,cur_dir); + if (FAT32FileFind(dv,cur_dir_clus,filename,&de,FUF_JUST_FILES)) { + blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS; + buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1); + c=de.clus; + if (!(0<c<0x0FFFFFF8)) + c=0x0FFFFFFF; + else + c=ClusBlkRead(dv,buf,c,blk_cnt); + buf[de.size]=0; //Terminate + *_size=de.size; + *_attr=FileAttr(de.name,de.attr); + } + DrvUnlock(dv); + } catch + DrvUnlock(dv); + return buf; +} + +Bool FAT32Cd(U8 *name,I64 cur_dir_clus) +{ + CDirEntry de; + if (Fs->cur_dv->fs_type!=FSt_FAT32) + PrintErr("Not FAT32 Drv\n"); + else if (FAT32FileFind(Fs->cur_dv,cur_dir_clus,name,&de,FUF_JUST_DIRS)) + return TRUE; + else + PrintErr("File not found: \"%s\".\n",name); + return FALSE; +} + +U0 FAT32FreeClus(CDrv *dv,I64 c) +{ + I64 next,saved_c=c; + Bool unlock,unlock_break; + DrvChk(dv); + if (!(0<c<0x0FFFFFF8)) return; + if (dv->fs_type!=FSt_FAT32) + PrintErr("Not FAT32 Drv\n"); + else + try { + unlock_break=BreakLock; + unlock=DrvLock(dv); + DrvFATBlkClean(dv); + do { + DrvFATBlkSet(dv,c,0); + next=dv->cur_fat_blk[c&(BLK_SIZE/4-1)]; + dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0; + LBts(&dv->fat_blk_dirty,0); + c=next; + } while (0<c<0x0FFFFFF8); + DrvFATBlkClean(dv,0); + + c=saved_c; + do { + DrvFATBlkSet(dv,c,1); + next=dv->cur_fat_blk[c&(BLK_SIZE/4-1)]; + dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0; + LBts(&dv->fat_blk_dirty,0); + c=next; + } while (0<c<0x0FFFFFF8); + DrvFATBlkClean(dv,1); + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } catch { + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } +} + +I64 FAT32AllocClus(CDrv *dv,I64 c,I64 cnt) +{ + Bool wrap_around=FALSE,unlock,unlock_break; + I64 first=INVALID_CLUS,j,l; + + if (cnt<=0) return 0x0FFFFFFF; + try { + unlock_break=BreakLock; + unlock=DrvLock(dv); + l=(dv->size+dv->drv_offset-dv->data_area)/dv->spc-1; + j=dv->fis->most_recently_alloced; + while (cnt-->0) { + while (TRUE) { + j++; + if (j<1) j=1; + if (j>=l) { + if (wrap_around) + throw('Drv'); + j=1; + wrap_around=TRUE; + } + DrvFATBlkSet(dv,j); + if (!dv->cur_fat_blk[j&(BLK_SIZE/4-1)]) + break; + } + if (!(0<first<0x0FFFFFF8)) + first=j; + if (0<c<l) { + DrvFATBlkSet(dv,c); + dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=j; + LBts(&dv->fat_blk_dirty,0); + } + c=j; + } + + if (0<c<l) { + DrvFATBlkSet(dv,c); + dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0x0FFFFFFF; + LBts(&dv->fat_blk_dirty,0); + } + DrvFATBlkClean(dv); + + dv->fis->most_recently_alloced=j; + dv->fis->free_clus=-1; + BlkWrite(dv,dv->fis,dv->file_system_info_sect,1); + } catch { + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + return first; +} + +I64 FAT32AllocContiguousClus(CDrv *dv,I64 cnt) +{ + I64 i,first=1; + Bool cont,unlock,unlock_break; + + if (cnt<=0) return 0x0FFFFFFF; + try { + unlock_break=BreakLock; + unlock=DrvLock(dv); + while (TRUE) { + first++; + i=0; + cont=TRUE; + while (cont && i<cnt) { + if ((first+i+1)*dv->spc+dv->data_area>dv->size+dv->drv_offset) + throw('Drv'); + DrvFATBlkSet(dv,first+i); + if (dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]) + cont=FALSE; + else + i++; + } + if (!cont) + first=first+i; + else { + DrvFATBlkClean(dv); + + for (i=0;i<cnt;i++) { + DrvFATBlkSet(dv,first+i,0); + if (i+1==cnt) + dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF; + else + dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1; + LBts(&dv->fat_blk_dirty,0); + } + DrvFATBlkClean(dv,0); + + for (i=0;i<cnt;i++) { + DrvFATBlkSet(dv,first+i,1); + if (i+1==cnt) + dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF; + else + dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1; + LBts(&dv->fat_blk_dirty,0); + } + DrvFATBlkClean(dv,1); + break; + } + } + } catch { + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + return first; +} + +Bool FAT32DirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tmpde,Bool free_old_chain) +{ +//See $LK,"::/Doc/CutCorners.DD"$. + CFAT32DirEntry *buf,*last_buf,*tmp_buf,de[3]; + I64 i,attr,avail_cnt,de_cnt,c, + cur_dir_entry,entries_per_clus, + cur_dir_clus,xsum=0,last_dir_clus=INVALID_CLUS; + U8 ch; + Bool written=FALSE,unlock,unlock_break; + CDirEntry long_name; + FAT32DirFill(&de,tmpde,&de_cnt,dv->fat32_local_time_offset); + MemSet(&long_name,0,sizeof(CDirEntry)); + try { + unlock_break=BreakLock; + unlock=DrvLock(dv); + cur_dir_clus=Name2DirClus(dv,cur_dir); + buf =MAlloc(BLK_SIZE*dv->spc); + last_buf=CAlloc(BLK_SIZE*dv->spc); + entries_per_clus=dv->spc<<FAT32_ENTRIES_BITS; + ClusRead(dv,buf,cur_dir_clus,1); + cur_dir_entry=0; + while (ch=*buf[cur_dir_entry].name) { + attr=buf[cur_dir_entry].attr; + if (ch!=0xE5 && attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME) + DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum); + else { + avail_cnt=FAT32_ENTRIES_PER_BLK-cur_dir_entry + &(FAT32_ENTRIES_PER_BLK-1); + for (i=0;i<avail_cnt;i++) + if (*buf[cur_dir_entry+i].name!=0xE5) { + if (*buf[cur_dir_entry+i].name) + avail_cnt=i; + break; + } + if (ch==0xE5 && !written && avail_cnt>=de_cnt) { + MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry)); + BlkWrite(dv,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK], + dv->data_area+cur_dir_clus*dv->spc + +cur_dir_entry>>FAT32_ENTRIES_BITS,1); + cur_dir_entry+=de_cnt-1; //gets inc'ed + written=TRUE; + } else if (ch!=0xE5 && !(attr&RS_ATTR_VOL_ID)) { + if (xsum!=FATNameXSum(buf[cur_dir_entry].name)) + MemSet(&long_name,0,sizeof(CDirEntry)); + if (!*long_name.name) + FATFromName(long_name.name,buf[cur_dir_entry].name); +//Del old entry with same name + if (!StrCmp(long_name.name,tmpde->name)) { + if (free_old_chain) + FAT32FreeClus(dv,buf[cur_dir_entry].clus_lo+ + buf[cur_dir_entry].clus_hi<<16); + if (!written) { + MemCpy(&buf[cur_dir_entry],&de[de_cnt-1],sizeof(CFAT32DirEntry)); + BlkWrite(dv,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK], + dv->data_area+cur_dir_clus*dv->spc + +cur_dir_entry>>FAT32_ENTRIES_BITS,1); + written=TRUE; + } else { + *buf[cur_dir_entry].name=0xE5; + i=1; + while (i<=cur_dir_entry && + buf[cur_dir_entry-i].attr&RS_ATTR_LONG_NAME_MASK + ==RS_ATTR_LONG_NAME) + *buf[cur_dir_entry-i++].name=0xE5; + i--; + BlkWrite(dv,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK], + dv->data_area+cur_dir_clus*dv->spc + +(cur_dir_entry-i)>>FAT32_ENTRIES_BITS, + (i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS); + if (i==cur_dir_entry && 0<last_dir_clus<0x0FFFFFF8) { + i=1; + while (i<=entries_per_clus && + last_buf[entries_per_clus-i].attr + &RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME) + *last_buf[entries_per_clus-i++].name=0xE5; + if (--i>0) + BlkWrite(dv,&buf[(entries_per_clus-i)&-FAT32_ENTRIES_PER_BLK], + dv->data_area+last_dir_clus*dv->spc + +(entries_per_clus-i)>>FAT32_ENTRIES_BITS, + (i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS); + } + } + break; + } + } + MemSet(&long_name,0,sizeof(CDirEntry)); + } + if (++cur_dir_entry==entries_per_clus) { + last_dir_clus=cur_dir_clus; + tmp_buf=buf; buf=last_buf; last_buf=tmp_buf; + c=ClusNumNext(dv,cur_dir_clus); + if (!(0<c<0x0FFFFFF8)) { + c=ClusAlloc(dv,cur_dir_clus,1,FALSE); + MemSet(buf,0,BLK_SIZE*dv->spc); + ClusWrite(dv,buf,c,1); + } else + ClusRead(dv,buf,c,1); + cur_dir_clus=c; + cur_dir_entry=0; + } + } + if (!written) { + avail_cnt=FAT32_ENTRIES_PER_BLK-cur_dir_entry & (FAT32_ENTRIES_PER_BLK-1); + if (avail_cnt<de_cnt) { + for (i=0;i<avail_cnt;i++) + *buf[cur_dir_entry+i].name=0xE5; + BlkWrite(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK], + dv->data_area+cur_dir_clus*dv->spc + +cur_dir_entry>>FAT32_ENTRIES_BITS,1); + cur_dir_entry+=avail_cnt; + if (cur_dir_entry==entries_per_clus) { + last_dir_clus=cur_dir_clus; + tmp_buf=buf; buf=last_buf; last_buf=tmp_buf; + cur_dir_clus=ClusAlloc(dv,cur_dir_clus,1); + cur_dir_entry=0; + MemSet(buf,0,BLK_SIZE*dv->spc); + ClusWrite(dv,buf,cur_dir_clus,1); + } + } + MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry)); + BlkWrite(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK], + dv->data_area+cur_dir_clus*dv->spc+ + cur_dir_entry>>FAT32_ENTRIES_BITS,1); + cur_dir_entry+=de_cnt; + if (cur_dir_entry==entries_per_clus) { + cur_dir_clus=ClusAlloc(dv,cur_dir_clus,1); + MemSet(buf,0,BLK_SIZE*dv->spc); + ClusWrite(dv,buf,cur_dir_clus,1); + } else { + MemSet(&buf[cur_dir_entry],0,sizeof(CFAT32DirEntry)); + BlkWrite(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK], + dv->data_area+cur_dir_clus*dv->spc + +cur_dir_entry>>FAT32_ENTRIES_BITS,1); + } + } + Free(last_buf); + Free(buf); + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } catch { + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } + return FALSE; +} + +I64 FAT32FilesDel(CDrv *dv,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags, + Bool del_dir,Bool print_msg) +{ + CFAT32DirEntry *buf,*last_buf,*tmp_buf; + I64 i,res=0,attr,xsum=0,last_dir_clus=INVALID_CLUS, + cur_dir_entry,entries_per_clus,cur_dir_clus; + U8 ch; + Bool unlock_break; + CDirEntry long_name; + MemSet(&long_name,0,sizeof(CDirEntry)); + try { + unlock_break=BreakLock; + DrvLock(dv); + cur_dir_clus=Name2DirClus(dv,cur_dir); + buf =MAlloc(BLK_SIZE*dv->spc); + last_buf=CAlloc(BLK_SIZE*dv->spc); + entries_per_clus=dv->spc<<FAT32_ENTRIES_BITS; + ClusRead(dv,buf,cur_dir_clus,1); + cur_dir_entry=0; + while (ch=*buf[cur_dir_entry].name) { + attr=buf[cur_dir_entry].attr; + if (ch!=0xE5 && ch!='.') { + if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME) + DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum); + else { + if (!(attr & RS_ATTR_VOL_ID) && + (del_dir || !(attr & RS_ATTR_DIR))) { + if (xsum!=FATNameXSum(buf[cur_dir_entry].name)) + MemSet(&long_name,0,sizeof(CDirEntry)); + if (!*long_name.name) + FATFromName(long_name.name,buf[cur_dir_entry].name); + if (FilesFindMatch(long_name.name,files_find_mask,fuf_flags)) { + if (!(attr & RS_ATTR_DIR)) res++; + if (print_msg) + "Del %s\n",long_name.name; + *buf[cur_dir_entry].name=0xE5; + i=1; + while (i<=cur_dir_entry && + buf[cur_dir_entry-i].attr&RS_ATTR_LONG_NAME_MASK + ==RS_ATTR_LONG_NAME) + *buf[cur_dir_entry-i++].name=0xE5; + i--; + BlkWrite(dv,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK], + dv->data_area+cur_dir_clus*dv->spc + +(cur_dir_entry-i)>>FAT32_ENTRIES_BITS, + (i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS); + if (i==cur_dir_entry && last_dir_clus!=INVALID_CLUS) { + i=1; + while (i<=entries_per_clus && + last_buf[entries_per_clus-i].attr + &RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME) + *last_buf[entries_per_clus-i++].name=0xE5; + if (--i>0) + BlkWrite(dv,&buf[(entries_per_clus-i)&-FAT32_ENTRIES_PER_BLK], + dv->data_area+last_dir_clus*dv->spc + +(entries_per_clus-i)>>FAT32_ENTRIES_BITS, + (i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS); + } + FAT32FreeClus(dv,buf[cur_dir_entry].clus_lo+ + buf[cur_dir_entry].clus_hi<<16); + } + } + MemSet(&long_name,0,sizeof(CDirEntry)); + } + } else + MemSet(&long_name,0,sizeof(CDirEntry)); + if (++cur_dir_entry==entries_per_clus) { + last_dir_clus=cur_dir_clus; + cur_dir_clus=ClusNumNext(dv,cur_dir_clus,1); + tmp_buf=buf; buf=last_buf; last_buf=tmp_buf; + ClusRead(dv,buf,cur_dir_clus,1); + cur_dir_entry=0; + } + } + Free(buf); + Free(last_buf); + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } catch { + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } + return res; +} + +I64 FAT32FileWrite(CDrv *dv,U8 *cur_dir,U8 *name,U8 *buf,I64 size, + CDate cdt,I64 attr) +{ + CDirEntry de; + I64 c=0,blk_cnt; + Bool contiguous; + MemSet(&de,0,sizeof(CDirEntry)); + if (size<0) size=0; + if (dv->fs_type!=FSt_FAT32) + PrintErr("Not FAT32 Drv\n"); + else if (!CFileNameTo(de.name,name)) + PrintErr("Invalid FileName: \"%s\".\n",name); + else { + FAT32FilesDel(dv,cur_dir,de.name,0,FALSE,FALSE); + if (attr & RS_ATTR_CONTIGUOUS) + contiguous=TRUE; + else + contiguous=FALSE; + de.size=size; + if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS) + c=ClusAlloc(dv,0,(blk_cnt+dv->spc-1)/dv->spc,contiguous); + else + c=0x0FFFFFFF; + de.clus=c; + de.attr=attr; + de.datetime=cdt; + if (blk_cnt) + ClusBlkWrite(dv,buf,c,blk_cnt); + FAT32DirNew(dv,cur_dir,&de,TRUE); + } + return c; +} + +CDirEntry *FAT32FilesFind(U8 *files_find_mask, + I64 fuf_flags,CDirEntry *parent=NULL,I64 *_dir_size=NULL) +{ + CDrv *dv=Fs->cur_dv; + CFAT32DirEntry *buf; + I64 attr,xsum=0,dir_size=0,sub_dir_size, + cur_dir_clus,cur_dir_entry,entries_per_clus; + U8 ch; + CDirEntry *res=NULL,*tmpde,long_name; + if (fuf_flags&~FUG_FILES_FIND) + throw('FUF'); + try { + MemSet(&long_name,0,sizeof(CDirEntry)); + DrvLock(dv); + cur_dir_clus=Name2DirClus(dv,Fs->cur_dir); + buf=MAlloc(BLK_SIZE*dv->spc); + entries_per_clus=dv->spc<<FAT32_ENTRIES_BITS; + ClusRead(dv,buf,cur_dir_clus,1); + dir_size+=dv->spc*BLK_SIZE; + cur_dir_entry=0; + while (ch=*buf[cur_dir_entry].name) { + attr=buf[cur_dir_entry].attr; + if (ch!=0xE5) { + if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME) + DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum); + else { + if (!(attr&RS_ATTR_VOL_ID)) { + tmpde=MAlloc(sizeof(CDirEntry)); + if (xsum==FATNameXSum(buf[cur_dir_entry].name)) + MemCpy(tmpde,&long_name,sizeof(CDirEntry)); + else + MemSet(tmpde,0,sizeof(CDirEntry)); + if (FAT32CDirFill(tmpde,&buf[cur_dir_entry], + dv->fat32_local_time_offset)) { + tmpde->parent=parent; + if (Bt(&fuf_flags,FUf_RECURSE) && attr&RS_ATTR_DIR && + *tmpde->name!='.') { + tmpde->next=res; + res=tmpde; + tmpde->full_name=DirNameAbs(tmpde->name); + DrvUnlock(dv); + if (Cd(tmpde->name)) { + tmpde->sub=FAT32FilesFind(files_find_mask,fuf_flags, + tmpde,&sub_dir_size); + tmpde->size=sub_dir_size; + Cd(".."); + } + DrvLock(dv); + } else { + tmpde->full_name=FileNameAbs(tmpde->name); + if ((attr&RS_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) && + !(Bt(&fuf_flags,FUf_RECURSE) && + *tmpde->name=='.' && attr&RS_ATTR_DIR) && + FilesFindMatch(tmpde->full_name,files_find_mask, + fuf_flags)) { + tmpde->next=res; + res=tmpde; + } else + DirEntryDel(tmpde); + } + } else + DirEntryDel(tmpde); + } + MemSet(&long_name,0,sizeof(CDirEntry)); + } + } else + MemSet(&long_name,0,sizeof(CDirEntry)); + if (++cur_dir_entry==entries_per_clus) { + cur_dir_clus=ClusNumNext(dv,cur_dir_clus); + if (cur_dir_clus==INVALID_CLUS) + break; + else { + ClusRead(dv,buf,cur_dir_clus,1); + dir_size+=dv->spc*BLK_SIZE; + cur_dir_entry=0; + } + } + } + Free(buf); + DrvUnlock(dv); + } catch + DrvUnlock(dv); + if (_dir_size) + *_dir_size=dir_size; + return res; +} + +Bool FAT32MkDir(CDrv *dv,U8 *cur_dir,U8 *name,I64 entry_cnt) +{ + I64 c,cur_dir_clus=Name2DirClus(dv,cur_dir), +//Rough estimate of size + size=CeilU64((entry_cnt+2)<<FAT32_ENTRIES_BITS,dv->spc<<BLK_SIZE_BITS); + U8 *buf=CAlloc(size); + CDirEntry d_native; + CFAT32DirEntry *dFAT=buf; + Bool unlock_break; + + try { + unlock_break=BreakLock; + c=FileWrite(name,buf,size,0,RS_ATTR_DIR); + MemSet(&d_native,0,sizeof(CDirEntry)); + d_native.attr=RS_ATTR_DIR; + *d_native.name='.'; + d_native.name[1]=0; + d_native.clus=c; + d_native.size=0; + d_native.datetime=Now; + FAT32DirFill(dFAT,&d_native,NULL,dv->fat32_local_time_offset); + dFAT++; + + MemSet(&d_native,0,sizeof(CDirEntry)); + d_native.attr=RS_ATTR_DIR; + *d_native.name='.'; + d_native.name[1]='.'; + d_native.name[2]=0; + d_native.clus=cur_dir_clus; + d_native.size=0; + d_native.datetime=Now; + FAT32DirFill(dFAT,&d_native,NULL,dv->fat32_local_time_offset); + ClusWrite(dv,buf,c,1); + Free(buf); + if (unlock_break) + BreakUnlock; + } catch + if (unlock_break) + BreakUnlock; + return TRUE; +} diff --git a/T/BlkDev2/FileSysRedSea.HC b/T/BlkDev2/FileSysRedSea.HC new file mode 100644 index 0000000..3221d74 --- /dev/null +++ b/T/BlkDev2/FileSysRedSea.HC @@ -0,0 +1,635 @@ +// See $LK,"RedSea File System",A="FI:::/Doc/RedSea.DD"$ + +U0 RedSeaFreeFreeLst(CDrv *dv) +{ + CFreeLst *tmpf,*tmpf1; + Bool unlock; + try { + unlock=DrvLock(dv); + if (tmpf=dv->next_free) { + while (tmpf!=&dv->next_free) { + tmpf1=tmpf->next; + Free(tmpf); + tmpf=tmpf1; + } + } + dv->next_free=NULL; + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); +} + +U0 RedSeaFreeLstBuild(CDrv *dv) +{ + Bool unlock; + CFreeLst *tmpf; + I64 i,first=dv->data_area,max_blk=dv->size+dv->drv_offset; + try { + unlock=DrvLock(dv); + if (dv->next_free) + RedSeaFreeFreeLst(dv); + QueInit(&dv->next_free); + while (first<max_blk) { + i=0; //count free clus + while (first+i<max_blk) { + DrvFATBlkSet(dv,first+i); + if (Bt(dv->cur_fat_blk,(first+i-dv->data_area)&(BLK_SIZE<<3-1))) + break; + else + i++; + } + if (i) { + tmpf=AMAlloc(sizeof(CFreeLst)); + tmpf->size=i; + tmpf->start=first; + QueIns(tmpf,dv->last_free); + } + first+=i+1; + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); +} + +U0 RedSeaInit(CDrv *dv) +{ + CRedSeaBoot br; + Bool unlock; + try { + unlock=DrvLock(dv); + BlkRead(dv,&br,dv->drv_offset,1); + if (br.signature!=MBR_PT_REDSEA || br.signature2!=0xAA55) + throw('Drv'); + dv->fs_type=FSt_REDSEA; + RedSeaFreeFreeLst(dv); + dv->spc=1; + dv->size=br.sects; + dv->data_area=dv->drv_offset+br.bitmap_sects; + dv->root_clus=br.root_clus; + dv->fat1=dv->fat2=dv->drv_offset+1; + DrvFATBlkAlloc(dv); + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); +} + +Bool RedSeaValidate(U8 drv_let) +{ + CDrv *dv; + CRedSeaBoot br; + if ((dv=Let2Drv(drv_let,FALSE)) && dv->fs_type==FSt_REDSEA && + BlkRead(dv,&br,dv->drv_offset,1) && br.signature==MBR_PT_REDSEA && + br.signature2==0xAA55) + return TRUE; + else + return FALSE; +} + +U0 RedSeaFmt(U8 drv_let,Bool quick=TRUE) +{ + U8 *root_dir; + CDirEntry *d_native; + CRedSeaBoot *br=CAlloc(BLK_SIZE); + CDrv *dv=Let2Drv(drv_let); + I64 i,n,root_dir_blks; + try { + DrvLock(dv); +// DrvTypeSet(drv_let,FSt_REDSEA); + DrvTypeSet(drv_let,FSt_FAT32); + dv->fs_type=FSt_REDSEA; + br->signature=MBR_PT_REDSEA; + br->signature2=0xAA55; + br->drv_offset=dv->drv_offset; //For CD/DVD image copy. + br->sects=dv->size; + n=(br->sects+BLK_SIZE<<3-1)/BLK_SIZE<<3; + br->bitmap_sects=n; + br->unique_id=Now()(U64); + br->root_clus=0; + + if (quick) + i=n+1; + else + i=dv->size; + BlkWriteZero(dv,dv->drv_offset,i); + + BlkWrite(dv,br,dv->drv_offset,1); + RedSeaInit(dv); + ClusAlloc(dv,0,1,FALSE); //Alloc #1 + + root_dir_blks=MaxI64(1,dv->bd->init_root_dir_blks); + br->root_clus=ClusAlloc(dv,0,root_dir_blks,FALSE); + BlkWrite(dv,br,dv->drv_offset,1); + root_dir=CAlloc(BLK_SIZE*root_dir_blks); + + d_native=root_dir-offset(CDirEntry.start); + + d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS; + *d_native->name='.'; + d_native->clus=br->root_clus; + d_native->size=BLK_SIZE*root_dir_blks; + d_native->datetime=Now; + + d_native(U8 *)+=CDIR_SIZE; + + *d_native->name='.'; + d_native->name[1]='.'; + d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS; + d_native->clus=br->root_clus; + d_native->datetime=Now; + + BlkWrite(dv,root_dir,br->root_clus,root_dir_blks); + RedSeaInit(dv); + DrvUnlock(dv); + } catch + DrvUnlock(dv); + Free(br); + Free(root_dir); +} + +Bool RedSeaFileFind(CDrv *dv,I64 cur_dir_clus,U8 *name, + CDirEntry *_res,I64 fuf_flags=0) +{//$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$ + CDirEntry *buf,*buf2,*ptr; + U8 dname[CDIR_FILENAME_LEN]; + I64 ch; + Bool res=FALSE,unlock; + if (fuf_flags&~FUG_FILE_FIND) + throw('FUF'); + MemSet(_res,0,sizeof(CDirEntry)); + DrvChk(dv); + if (dv->fs_type!=FSt_REDSEA) + PrintErr("Not RedSea Drv\n"); + else if (!CFileNameTo(dname,name)) + PrintErr("Invalid FileName: \"%s\".\n",name); + else + try { + unlock=DrvLock(dv); + buf2=MAlloc(BLK_SIZE); + BlkRead(dv,buf2,cur_dir_clus,1); + + ptr=buf2(U8 *)-offset(CDirEntry.start); + buf=MAlloc(ptr->size); + BlkRead(dv,buf,cur_dir_clus,ptr->size>>BLK_SIZE_BITS); + Free(buf2); + + ptr=buf(U8 *)-offset(CDirEntry.start); + *ptr->name='.'; + ptr->name[1]=0; + while (TRUE) { + if (!(ch=*ptr->name)) + break; + else if (!(ptr->attr & RS_ATTR_DELETED) && + !(fuf_flags&FUF_JUST_DIRS && !(ptr->attr & RS_ATTR_DIR)) && + !(fuf_flags&FUF_JUST_FILES && ptr->attr & RS_ATTR_DIR) && + !StrCmp(dname,ptr->name)) { + MemCpy(&_res->attr,&ptr->attr,CDIR_SIZE); + res=TRUE; + goto rsff_done; + } + ptr(U8 *)+=CDIR_SIZE; + } +rsff_done: + Free(buf); + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + return res; +} + +U8 *RedSeaFileRead(CDrv *dv,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr) +{ + U8 *buf=NULL; + CDirEntry de; + I64 c,blk_cnt,cur_dir_clus; + DrvChk(dv); + *_size=0; + *_attr=0; + if (dv->fs_type!=FSt_REDSEA) + PrintErr("Not RedSea Drv\n"); + else + try { + DrvLock(dv); + cur_dir_clus=Name2DirClus(dv,cur_dir); + if (RedSeaFileFind(dv,cur_dir_clus,filename,&de,FUF_JUST_FILES)) { + blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS; + buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1); + c=de.clus; + c=BlkRead(dv,buf,c,blk_cnt); + buf[de.size]=0; //Terminate + *_size=de.size; + *_attr=FileAttr(de.name,de.attr); + } + DrvUnlock(dv); + } catch + DrvUnlock(dv); + return buf; +} + +Bool RedSeaCd(U8 *name,I64 cur_dir_clus) +{ + CDirEntry de; + if (Fs->cur_dv->fs_type!=FSt_REDSEA) + PrintErr("Not RedSea Drv\n"); + else if (RedSeaFileFind(Fs->cur_dv,cur_dir_clus,name,&de,FUF_JUST_DIRS)) + return TRUE; + else + PrintErr("File not found: \"%s\".\n",name); + return FALSE; +} + +U0 RedSeaFreeClus(CDrv *dv,I64 c,I64 cnt) +{ + CFreeLst *tmpf; + Bool found=FALSE,unlock,unlock_break; + DrvChk(dv); + if (!c) return; + if (dv->fs_type!=FSt_REDSEA) + PrintErr("Not RedSea Drv\n"); + else + try { + unlock_break=BreakLock; + unlock=DrvLock(dv); + if (!dv->next_free) + RedSeaFreeLstBuild(dv); + tmpf=dv->next_free; + while (!found && tmpf!=&dv->next_free) { + if (tmpf->start+tmpf->size==c) { + tmpf->size+=cnt; + found=TRUE; + } else if (c+cnt==tmpf->start) { + tmpf->size+=cnt; + tmpf->start=c; + found=TRUE; + } + tmpf=tmpf->next; + } + if (!found) { + tmpf=AMAlloc(sizeof(CFreeLst)); + tmpf->size=cnt; + tmpf->start=c; + QueIns(tmpf,dv->last_free); + } + while (cnt-->0) { + DrvFATBlkSet(dv,c); + LBtr(dv->cur_fat_blk,(c-dv->data_area)&(BLK_SIZE<<3-1)); + LBts(&dv->fat_blk_dirty,0); + c++; + } + DrvFATBlkClean(dv); + + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } catch { + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } +} + +I64 RedSeaAllocClus(CDrv *dv,I64 cnt) +{ + CFreeLst *tmpf,*best_free=NULL; + I64 i,first,best_size=I64_MAX; + Bool unlock,unlock_break; + if (cnt<=0) + throw('Drv'); + try { + unlock_break=BreakLock; + unlock=DrvLock(dv); + if (!dv->next_free) + RedSeaFreeLstBuild(dv); + tmpf=dv->next_free; + while (tmpf!=&dv->next_free) { + if (tmpf->size>=cnt && tmpf->size<best_size) { + best_free=tmpf; + best_size=tmpf->size; + if (tmpf->size==cnt) + break; + } + tmpf=tmpf->next; + } + if (!best_free) + throw('Drv'); + first=best_free->start; + for (i=0;i<cnt;i++) { + DrvFATBlkSet(dv,first+i); + LBts(dv->cur_fat_blk,(first+i-dv->data_area)&(BLK_SIZE<<3-1)); + LBts(&dv->fat_blk_dirty,0); + } + DrvFATBlkClean(dv); + if (best_free->size-=cnt) + best_free->start+=cnt; + else { + QueRem(best_free); + Free(best_free); + } + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } catch { + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } + return first; +} + +Bool RedSeaDirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tmpde,Bool free_old_chain) +{ + CDirEntry *buf,*buf2,*ptr,de2; + CRedSeaBoot *br; + I64 c,ch,i=1,j=0,n=BLK_SIZE/CDIR_SIZE,dir_size,cur_dir_clus; + Bool written=FALSE,unlock,unlock_break; + U8 *tmp,*parent_dir; + try { + unlock_break=BreakLock; + tmpde->attr|=RS_ATTR_CONTIGUOUS; + unlock=DrvLock(dv); + cur_dir_clus=Name2DirClus(dv,cur_dir); + buf2=MAlloc(BLK_SIZE); + BlkRead(dv,buf2,cur_dir_clus,1); + + ptr=buf2(U8 *)-offset(CDirEntry.start); + buf=MAlloc(ptr->size); + BlkRead(dv,buf,cur_dir_clus,ptr->size>>BLK_SIZE_BITS); + + dir_size=ptr->size; + ptr=buf(U8 *)-offset(CDirEntry.start)+CDIR_SIZE; + Free(buf2); + while (TRUE) { + if (!(ch=*ptr->name)) { + if (!written) + MemCpy(&ptr->start,&tmpde->start,CDIR_SIZE); + if ((i+1)*CDIR_SIZE+j<<BLK_SIZE_BITS<dir_size) + BlkWrite(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_clus+j,1); + else { + buf2=CAlloc(dir_size+BLK_SIZE); + MemCpy(buf2,buf,dir_size); + RedSeaFreeClus(dv,cur_dir_clus,dir_size>>BLK_SIZE_BITS); + dir_size+=BLK_SIZE; + c=ClusAlloc(dv,0,dir_size>>BLK_SIZE_BITS,TRUE); + Free(buf); + buf=buf2; + ptr=buf(U8 *)-offset(CDirEntry.start); + ptr->size=dir_size; + ptr->clus=c; + BlkWrite(dv,buf,c,dir_size>>BLK_SIZE_BITS); + if (cur_dir_clus==dv->root_clus) { + br=CAlloc(BLK_SIZE); + BlkRead(dv,br,dv->drv_offset,1); + br->root_clus=c; + BlkWrite(dv,br,dv->drv_offset,1); + Free(br); + dv->root_clus=c; + } else { + tmp=StrNew(cur_dir); + parent_dir=StrNew(cur_dir); + StrLastRem(parent_dir,"/",tmp); + if (!*parent_dir) { + Free(parent_dir); + parent_dir=StrNew("/"); + } + if (RedSeaFileFind(dv,Name2DirClus(dv,parent_dir), + tmp,&de2,FUF_JUST_DIRS)) { + de2.clus=c; + de2.size=dir_size; + RedSeaDirNew(dv,parent_dir,&de2,FALSE); + } else + throw('Drv'); + Free(tmp); + Free(parent_dir); + } + } + break; + } else if (ptr->attr & RS_ATTR_DELETED) { + if (!written) { + MemCpy(&ptr->start,&tmpde->start,CDIR_SIZE); + BlkWrite(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_clus+j,1); + written=TRUE; + } + } else { + if (!StrCmp(tmpde->name,ptr->name)) { + if (free_old_chain) + RedSeaFreeClus(dv,ptr->clus, + (ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS); + if (!written) + MemCpy(&ptr->start,&tmpde->start,CDIR_SIZE); + else + ptr->attr|=RS_ATTR_DELETED; + BlkWrite(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_clus+j,1); + break; + } + } + ptr(U8 *)+=CDIR_SIZE; + if (++i>=n) { + j++; + i=0; + } + } + Free(buf); + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } catch { + if (unlock) + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } + return FALSE; +} + +I64 RedSeaFilesDel(CDrv *dv,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags, + Bool del_dir,Bool print_msg) +{ + CDirEntry *buf,*buf2,*ptr; + I64 i=0,res=0,ch,j=0,n=BLK_SIZE/CDIR_SIZE,cur_dir_clus; + Bool unlock_break; + try { + unlock_break=BreakLock; + DrvLock(dv); + cur_dir_clus=Name2DirClus(dv,cur_dir); + buf2=MAlloc(BLK_SIZE); + BlkRead(dv,buf2,cur_dir_clus,1); + + ptr=buf2(U8 *)-offset(CDirEntry.start); + buf=MAlloc(ptr->size); + BlkRead(dv,buf,cur_dir_clus,ptr->size>>BLK_SIZE_BITS); + Free(buf2); + + ptr=buf(U8 *)-offset(CDirEntry.start); + *ptr->name='.'; + ptr->name[1]=0; + while (TRUE) { + if (!(ch=*ptr->name)) + break; + else if (!(ptr->attr & RS_ATTR_DELETED) && ch!='.' && (del_dir || + !(ptr->attr & RS_ATTR_DIR)) && + FilesFindMatch(ptr->name,files_find_mask,fuf_flags)) { + if (!(ptr->attr & RS_ATTR_DIR)) res++; + if (print_msg) + "Del %s\n",ptr->name; + ptr->attr|=RS_ATTR_DELETED; + BlkWrite(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_clus+j,1); + RedSeaFreeClus(dv,ptr->clus, + (ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS); + } + ptr(U8 *)+=CDIR_SIZE; + if (++i>=n) { + j++; + i=0; + } + } + Free(buf); + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } catch { + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } + return res; +} + +I64 RedSeaFileWrite(CDrv *dv,U8 *cur_dir,U8 *name,U8 *buf,I64 size, + CDate cdt,I64 attr) +{ + CDirEntry de; + I64 c=0,blk_cnt; + MemSet(&de,0,sizeof(CDirEntry)); + if (size<0) size=0; + if (dv->fs_type!=FSt_REDSEA) + PrintErr("Not RedSea Drv\n"); + else if (!CFileNameTo(de.name,name)) + PrintErr("Invalid FileName: \"%s\".\n",name); + else { + RedSeaFilesDel(dv,cur_dir,de.name,0,FALSE,FALSE); + de.size=size; + if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS) + c=ClusAlloc(dv,0,blk_cnt,TRUE); //Always contiguous + else + c=INVALID_CLUS; + de.clus=c; + de.attr=attr|RS_ATTR_CONTIGUOUS; + de.datetime=cdt; + if (blk_cnt) + BlkWrite(dv,buf,c,blk_cnt); + RedSeaDirNew(dv,cur_dir,&de,TRUE); + } + return c; +} + +CDirEntry *RedSeaFilesFind(U8 *files_find_mask,I64 fuf_flags, + CDirEntry *parent=NULL) +{ + CDrv *dv=Fs->cur_dv; + CDirEntry *buf,*buf2,*ptr,*res=NULL,*tmpde; + I64 ch,cur_dir_clus; + if (fuf_flags&~FUG_FILES_FIND) + throw('FUF'); + try { + DrvLock(dv); + cur_dir_clus=Name2DirClus(dv,Fs->cur_dir); + buf2=MAlloc(BLK_SIZE); + BlkRead(dv,buf2,cur_dir_clus,1); + + ptr=buf2(U8 *)-offset(CDirEntry.start); + buf=MAlloc(ptr->size); + BlkRead(dv,buf,cur_dir_clus,ptr->size>>BLK_SIZE_BITS); + Free(buf2); + + ptr=buf(U8 *)-offset(CDirEntry.start); + *ptr->name='.'; + ptr->name[1]=0; + ptr(U8 *)+=CDIR_SIZE; + ptr->clus=Name2ParentDirClus(dv,Fs->cur_dir); + ptr(U8 *)-=CDIR_SIZE; + while (TRUE) { + if (!(ch=*ptr->name)) + break; + else if (!(ptr->attr & RS_ATTR_DELETED)) { + tmpde=CAlloc(sizeof(CDirEntry)); + MemCpy(&tmpde->start,&ptr->start,CDIR_SIZE); + tmpde->parent=parent; + if (Bt(&fuf_flags,FUf_RECURSE) && tmpde->attr&RS_ATTR_DIR && + *tmpde->name!='.') { + tmpde->next=res; + res=tmpde; + tmpde->full_name=DirNameAbs(tmpde->name); + DrvUnlock(dv); + if (Cd(tmpde->name)) { + tmpde->sub=RedSeaFilesFind(files_find_mask,fuf_flags,tmpde); + Cd(".."); + } + DrvLock(dv); + } else { + tmpde->full_name=FileNameAbs(tmpde->name); + if ((tmpde->attr&RS_ATTR_DIR || + !Bt(&fuf_flags,FUf_JUST_DIRS)) && + !(Bt(&fuf_flags,FUf_RECURSE) && *tmpde->name=='.' && + tmpde->attr&RS_ATTR_DIR) && + FilesFindMatch(tmpde->full_name,files_find_mask,fuf_flags)) { + tmpde->next=res; + res=tmpde; + } else + DirEntryDel(tmpde); + } + } + ptr(U8 *)+=CDIR_SIZE; + } + Free(buf); + DrvUnlock(dv); + } catch + DrvUnlock(dv); + return res; +} + +Bool RedSeaMkDir(CDrv *dv,U8 *cur_dir,U8 *name,I64 entry_cnt) +{//entry_cnt is for preallocating dir blks. + I64 c,cur_dir_clus=Name2DirClus(dv,cur_dir), + size=CeilU64((entry_cnt+3)<<6,BLK_SIZE); +#assert CDIR_SIZE==64 + U8 *buf=CAlloc(size); + CDirEntry *d_native=buf-offset(CDirEntry.start); + Bool unlock_break; + try { + unlock_break=BreakLock; + c=FileWrite(name,buf,size,0,RS_ATTR_DIR); + d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS; + StrCpy(d_native->name,name); + d_native->clus=c; + d_native->size=size; + d_native->datetime=Now; + d_native(U8 *)+=CDIR_SIZE; + + d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS; + *d_native->name='.'; + d_native->name[1]='.'; + d_native->name[2]=0; + d_native->clus=cur_dir_clus; + d_native->size=0; + d_native->datetime=Now; + BlkWrite(dv,buf,c,1); + Free(buf); + if (unlock_break) + BreakUnlock; + } catch + if (unlock_break) + BreakUnlock; + return TRUE; +} diff --git a/T/BlkDev2/FileSysVirt.HC b/T/BlkDev2/FileSysVirt.HC new file mode 100644 index 0000000..bb05ef4 --- /dev/null +++ b/T/BlkDev2/FileSysVirt.HC @@ -0,0 +1,216 @@ +U0 VirtInit(CDrv *dv) +{ + Bool unlock; + try { + unlock=DrvLock(dv); + dv->fs_type=FSt_VIRT; + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); +} + +Bool VirtFileFind(CDrv *dv,U8 *cur_dir,U8 *name, + CDirEntry *_res,I64 fuf_flags=0) +{//$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$ + CDirEntry *buf,*buf2,*ptr; + U8 dname[CDIR_FILENAME_LEN]; + I64 ch; + Bool res=FALSE,unlock; + U8 *vfs_pwd,*at; + if (fuf_flags&~FUG_FILE_FIND) + throw('FUF'); + MemSet(_res,0,sizeof(CDirEntry)); + DrvChk(dv); + if (dv->fs_type!=FSt_VIRT) + PrintErr("Not Virt Drv\n"); + else if (!CFileNameTo(dname,name)) + PrintErr("Invalid FileName: \"%s\".\n",name); + else + try { + unlock=DrvLock(dv); + VFsSetPwd(cur_dir); + at=name; + if(VFsExists(at)) { + StrCpy(_res->name,name); + res=TRUE; + if(VFsIsDir(at)) + _res->attr|=RS_ATTR_DIR; + if(IsDotZ(at)) + _res->attr|=RS_ATTR_COMPRESSED; + if(fuf_flags&FUF_JUST_DIRS&&!VFsIsDir(at)) + res=FALSE; + if(fuf_flags&FUF_JUST_FILES&&VFsIsDir(at)) + res=FALSE; + _res->size=VFsFSize(at); + } + if (unlock) + DrvUnlock(dv); + } catch + if (unlock) + DrvUnlock(dv); + return res; +} + +U8 *VirtFileRead(CDrv *dv,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr) +{ + U8 *buf=NULL; + CDirEntry de; + I64 c,blk_cnt,cur_dir_clus; + U8 *old; + DrvChk(dv); + *_size=0; + *_attr=0; + if (dv->fs_type!=FSt_VIRT) + PrintErr("Not Virt Drv\n"); + else + try { + DrvLock(dv); + if (VirtFileFind(dv,cur_dir,filename,&de,FUF_JUST_FILES)) { + blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS; + buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1); + VFsSetPwd(cur_dir); + buf=VFsFRead(de.name,&de.size); + buf[de.size]=0; //Terminate + *_size=de.size; + *_attr=FileAttr(de.name,de.attr); + } + DrvUnlock(dv); + } catch + DrvUnlock(dv); + return buf; +} + +Bool VirtCd(U8 *name,U8 *cur_dir) +{ + CDirEntry de; + if (Fs->cur_dv->fs_type!=FSt_VIRT) + PrintErr("Not Virt Drv\n"); + else if (VirtFileFind(Fs->cur_dv,cur_dir,name,&de,FUF_JUST_DIRS)) + return TRUE; + else + PrintErr("File not found: \"%s\".\n",name); + return FALSE; +} + +I64 VirtFilesDel(CDrv *dv,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags, + Bool del_dir,Bool print_msg) +{ + CDirEntry buf,*ptr=&buf; + I64 i=0,res=0,ch,j=0,n=BLK_SIZE/CDIR_SIZE,cur_dir_clus; + U8 **dirs; + Bool unlock_break; + try { + unlock_break=BreakLock; + DrvLock(dv); + VFsSetPwd(cur_dir); + dirs=VFsDir; + for(i=0;dirs[i];i++) { + VirtFileFind(dv,cur_dir,dirs[i],ptr,); + VFsSetPwd(cur_dir); + if(del_dir||!VFsIsDir(dirs[i])&&dirs[i][0]!='.'&& + FilesFindMatch(ptr->name,files_find_mask,fuf_flags)) { + if (print_msg) + "Del %s\n",ptr->name; + res++; + VFsDel(dirs[i]); + } + Free(dirs[i]); + } + Free(dirs); + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } catch { + DrvUnlock(dv); + if (unlock_break) + BreakUnlock; + } + return res; +} + +I64 VirtFileWrite(CDrv *dv,U8 *cur_dir,U8 *name,U8 *buf,I64 size, + CDate cdt,I64 attr) +{ + CDirEntry de; + I64 c=0,blk_cnt; + MemSet(&de,0,sizeof(CDirEntry)); + if (size<0) size=0; + if (dv->fs_type!=FSt_VIRT) + PrintErr("Not Virt Drv\n"); + else if (!CFileNameTo(de.name,name)) + PrintErr("Invalid FileName: \"%s\".\n",name); + else { + VirtFilesDel(dv,cur_dir,de.name,0,FALSE,FALSE); + VFsSetPwd(cur_dir); + c=VFsFWrite(name,buf,size); + } + return c; +} + +CDirEntry *VirtFilesFind(U8 *files_find_mask,I64 fuf_flags, + CDirEntry *parent=NULL) +{ + CDrv *dv=Fs->cur_dv; + CDirEntry *buf,*buf2,*ptr,*res=NULL,*tmpde; + I64 i; + U8 **dirs; + if (fuf_flags&~FUG_FILES_FIND) + throw('FUF'); + try { + DrvLock(dv); + VFsSetPwd(Fs->cur_dir); + dirs=VFsDir; + for (i=0;dirs[i];i++) { + tmpde=CAlloc(sizeof(CDirEntry)); + VirtFileFind(Fs->cur_dv,Fs->cur_dir,dirs[i],tmpde,0); + tmpde->parent=parent; + if (Bt(&fuf_flags,FUf_RECURSE) && tmpde->attr&RS_ATTR_DIR && + *tmpde->name!='.') { + tmpde->next=res; + res=tmpde; + tmpde->full_name=DirNameAbs(tmpde->name); + DrvUnlock(dv); + if (Cd(tmpde->name)) { + tmpde->sub=VirtFilesFind(files_find_mask,fuf_flags,tmpde); + Cd(".."); + } + DrvLock(dv); + } else { + tmpde->full_name=FileNameAbs(tmpde->name); + if ((tmpde->attr&RS_ATTR_DIR || + !Bt(&fuf_flags,FUf_JUST_DIRS)) && + !(Bt(&fuf_flags,FUf_RECURSE) && *tmpde->name=='.' && + tmpde->attr&RS_ATTR_DIR) && + FilesFindMatch(tmpde->full_name,files_find_mask,fuf_flags)) { + tmpde->next=res; + res=tmpde; + } else + DirEntryDel(tmpde); + } + Free(dirs[i]); + } + Free(dirs); + DrvUnlock(dv); + } catch + DrvUnlock(dv); + return res; +} + +Bool VirtMkDir(CDrv *dv,U8 *cur_dir,U8 *name,I64 entry_cnt) +{//entry_cnt is for preallocating dir blks. + I64 c; +#assert CDIR_SIZE==64 + Bool unlock_break; + try { + unlock_break=BreakLock; + VFsSetPwd(cur_dir); + VFsDirMk(name); + if (unlock_break) + BreakUnlock; + } catch + if (unlock_break) + BreakUnlock; + return TRUE; +} diff --git a/T/BlkDev2/MakeBlkDev.HC b/T/BlkDev2/MakeBlkDev.HC new file mode 100644 index 0000000..5b70537 --- /dev/null +++ b/T/BlkDev2/MakeBlkDev.HC @@ -0,0 +1,22 @@ +#exe {Cd(__DIR__);}; +#include "DskStrA" +#include "DskCache" +#include "DskBlkDev" +#include "DskDrv" +#include "DskBlk" +#include "DskClus" +#include"FileSysVirt" +#include "DskStrB" +#include "DskAddDev" +#include "DskDirA" +#include "FileSysRedSea" +#include "FileSysFAT" +#include "DskDirContext" +#include "DskFind" +#include "DskDirB" +#include "DskFile" +#include "DskCFile" +#include "DskCopy" +#include "DskCDDVD" +#include "DskFmt" +#exe {Cd("..");}; diff --git a/T/DSKDIRA.HC b/T/DSKDIRA.HC deleted file mode 100644 index ab99116..0000000 --- a/T/DSKDIRA.HC +++ /dev/null @@ -1,144 +0,0 @@ -U0 DirEntryDel(CDirEntry *tmpde) -{ //Free node returned from \dLK,"FilesFind",A="MN:FilesFind"\d(). Doesn't Free user_data. -//Does not change the directory on disk. - if (tmpde) { - Free(tmpde->full_name); - Free(tmpde); - } -} - -U0 DirEntryDel2(CDirEntry *tmpde) -{ //Free node returned from \dLK,"FilesFind",A="MN:FilesFind"\d(). Frees user_data -//Does not change the directory on disk. - if (tmpde) { - Free(tmpde->full_name); - Free(tmpde->user_data); - Free(tmpde); - } -} - -U0 DirTreeDel(CDirEntry *tmpde) -{ //Free tree returned from \dLK,"FilesFind",A="MN:FilesFind"\d(). Doesn't Free user_data. -//Does not change the directory on disk. - CDirEntry *tmpde2; - while (tmpde) { - tmpde2=tmpde->next; - if (tmpde->sub) - DirTreeDel(tmpde->sub); - DirEntryDel(tmpde); - tmpde=tmpde2; - } -} - -U0 DirTreeDel2(CDirEntry *tmpde) -{ //Free tree returned from \dLK,"FilesFind",A="MN:FilesFind"\d(). Frees user_data -//Does not change the directory on disk. - CDirEntry *tmpde2; - while (tmpde) { - tmpde2=tmpde->next; - if (tmpde->sub) - DirTreeDel2(tmpde->sub); - DirEntryDel2(tmpde); - tmpde=tmpde2; - } -} - -I64 DirEntryCompareName(CDirEntry *e1,CDirEntry *e2) -{ - U8 buf1[CDIR_FILENAME_LEN],buf2[CDIR_FILENAME_LEN], - buf3[CDIR_FILENAME_LEN],buf4[CDIR_FILENAME_LEN]; - I64 d1=0,d2=0; - if (IsDir(e1->full_name)) - d1=1; - if (IsDir(e2->full_name)) - d2=1; - if (d1!=d2) - return d2-d1; - else { - StrCpy(buf1,e1->name); - StrCpy(buf2,e2->name); - FileExtRem(buf1,buf3); - FileExtRem(buf2,buf4); - if (d1=StrCmp(buf3,buf4)) - return d1; - return StrCmp(buf1,buf2); - } -} - -I64 DirEntryCompareClus(CDirEntry *e1,CDirEntry *e2) -{ - return e1->clus-e2->clus; -} - -#define SK_NAME 0 -#define SK_CLUS 1 - -U0 DirFilesSort(CDirEntry **_tmpde,I64 key) -{ - I64 i,cnt; - CDirEntry *tmpde=*_tmpde,*tmpde1,**sort_buf; - if (tmpde) { - cnt=LinkedLstCnt(tmpde); - if (cnt>1) { - sort_buf=MAlloc(cnt*sizeof(U8 *)); - i=0; - tmpde1=tmpde; - while (tmpde1) { - sort_buf[i++]=tmpde1; - tmpde1=tmpde1->next; - } - switch [key] { - case SK_NAME: - QSortI64(sort_buf,cnt,&DirEntryCompareName); - break; - case SK_CLUS: - QSortI64(sort_buf,cnt,&DirEntryCompareClus); - break; - } - tmpde=sort_buf[0]; - *_tmpde=tmpde; - for (i=0; i<cnt-1; i++) { - tmpde1=sort_buf[i]; - tmpde1->next=sort_buf[i+1]; - } - tmpde1=sort_buf[i]; - tmpde1->next=NULL; - Free(sort_buf); - - tmpde1=tmpde; - while (tmpde1) { - if (tmpde1->sub) - DirFilesSort(&tmpde1->sub,key); - tmpde1=tmpde1->next; - } - } else if (tmpde->sub) - DirFilesSort(&tmpde->sub,key); - } -} - -CDirEntry *DirFilesFlatten(CDirEntry *tmpde,CDirEntry **_res,I64 fuf_flags) -{ //Returns last node - CDirEntry *tmpde1; - Bool del; - if (tmpde) - while (TRUE) { - tmpde1=tmpde->next; - if (!IsDir(tmpde->full_name)||!(fuf_flags&FUF_JUST_FILES)) { - _res=*_res=tmpde; - del=FALSE; - } else - del=TRUE; - if (tmpde->sub) { - _res=DirFilesFlatten(tmpde->sub,_res,fuf_flags); - tmpde->sub=NULL; - } - if (del) - DirEntryDel(tmpde); - if (tmpde1) - tmpde=tmpde1; - else - break; - } - *_res=NULL; - return _res; -} diff --git a/T/DSKFIND.HC b/T/DSKFIND.HC deleted file mode 100644 index dbecda1..0000000 --- a/T/DSKFIND.HC +++ /dev/null @@ -1,377 +0,0 @@ -U0 DirContextDel(CDirContext *dirc,Bool restore=TRUE) -{//Change back to old cur_dir and drv. - CBlkDev *bd; - if (!dirc) return; - if (restore) { - Cd(dirc->old_dir); - /* TODO RESTORE??? - bd=dirc->old_dv->bd; - if (!(bd->flags & BDF_INIT_IN_PROGRESS)) { - if (dirc->old_dir) { - - } - } else { - Fs->cur_dv=dirc->old_dv; - Free(Fs->cur_dir); - Fs->cur_dir=StrNew("/"); - } - */ - } - Free(dirc->old_dir); - Free(dirc->mask); - Free(dirc); -} -Bool Cd2(U8 *to,Bool make=FALSE) { - if(make&&!FileFind(to)) - DirMk(to); - return Cd(to); -} - -#define Cd Cd2 -CDirContext *DirContextNew(U8 *_mask,Bool make_mask=FALSE, - Bool make_dirs=FALSE,Bool no_mask=FALSE) -{//Save cur_dir and drv. Change to new dir. - Bool valid=TRUE,old_silent; - I64 mask_len=StrLen(_mask); - U8 *buf,*mask,*tmp_mask,*semicolon_mask; - CDirContext *dirc=CAlloc(sizeof(CDirContext)); - dirc->old_dir=DirCur; - mask=MStrUtil(_mask,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS); - tmp_mask=mask; - if (*mask && mask[1]==':') { - /*TODO RESTORE - if (Fs->cur_dv!=Let2Drv(*mask) && !Drv(*mask)) - valid=FALSE; - */ - mask+=2; - } - /* TODO RESTORE - if (*mask=='~' && Fs->cur_dv!=Let2Drv('~') && !Drv('~')) - valid=FALSE; - */ - //dirc->dv=Fs->cur_dv; - //DrvChk(dirc->dv); - buf=MAlloc(mask_len+2); - StrCpy(buf,mask); - - dirc->mask=MAlloc(mask_len+2); - if (no_mask) - *dirc->mask=0; - else if (StrOcc(buf,';')) { - semicolon_mask=MAlloc(mask_len+2); - StrCpy(semicolon_mask,mask); - StrFirstRem(semicolon_mask,";",buf); - StrLastRem(buf,"/",dirc->mask); - CatPrint(dirc->mask,";%s",semicolon_mask); - Free(semicolon_mask); - } else - StrLastRem(buf,"/",dirc->mask); - - if (*mask=='/' && !*buf) - StrCpy(buf,"/"); -//If began with Dir, change to Dir. - if (*buf && !Cd(buf ,make_dirs)) - valid=FALSE; - if (valid && make_mask) { - if (!*dirc->mask) { - Free(dirc->mask); - dirc->mask=StrNew("*"); - } else { - if (!make_dirs || FileNameChk(dirc->mask)) { - //old_silent=Silent; TODO RESTORE -//Try mask to see if Dir. If Dir, change to dir and set to "*". - if (Cd(dirc->mask ,make_dirs)) { //URGENT RESTORE - Free(dirc->mask); - dirc->mask=StrNew("*"); - } - //Silent(old_silent); TODO RESTORE - } - } - } - Free(buf); - Free(tmp_mask); - if (!valid) { - DirContextDel(dirc); - dirc=NULL; - } - return dirc; -} - -CDirEntry *FilesFind__(U8 *files_find_mask,I64 fuf_flags=0, - CDirEntry *parent=NULL) -{ - CDirEntry *res=NULL,*tmpde; - U8 **dir=__Dir("."); - I64 ch,idx; - if (fuf_flags&~FUG_FILES_FIND) - throw('FUF'); - try { - for (idx=0; dir&&dir[idx]; idx++) { - tmpde=CAlloc(sizeof(CDirEntry)); - StrCpy(&tmpde->name,dir[idx]); - tmpde->datetime=Unix2CDate(FUnixTime(dir[idx])); - tmpde->size=FSize(dir[idx]); - tmpde->parent=parent; - if (Bt(&fuf_flags,FUf_RECURSE) && IsDir(dir[idx]) && - *tmpde->name!='.'&&*tmpde->name!='..') { - tmpde->next=res; - res=tmpde; - tmpde->full_name=DirNameAbs(tmpde->name); - if (Cd(tmpde->name)) { - tmpde->sub=FilesFind__(files_find_mask,fuf_flags,tmpde); - Cd(".."); - } - } else { - tmpde->full_name=FileNameAbs(tmpde->name); - if ((IsDir(dir[idx]) || - !Bt(&fuf_flags,FUf_JUST_DIRS)) && - !(Bt(&fuf_flags,FUf_RECURSE) && *tmpde->name=='.' && - IsDir(dir[idx])) && - FilesFindMatch(tmpde->full_name,files_find_mask,fuf_flags)) { - tmpde->next=res; - res=tmpde; - } else if(!FilesFindMatch(tmpde->full_name,files_find_mask,fuf_flags)) { - DirEntryDel(tmpde); - } else { - tmpde->next=res; - res=tmpde; - } - } - } - } catch - ; - for(idx=0; dir&&dir[idx]; idx++) - Free(dir[idx]); - Free(dir); - return res; -} -CDirEntry *FilesFind2(U8 *files_find_mask,I64 fuf_flags) -{ - CDirEntry *res=FilesFind__(files_find_mask,fuf_flags); - if (res) { - DirFilesSort(&res,SK_NAME); - if (fuf_flags&(FUF_FLATTEN_TREE|FUF_JUST_FILES)) - DirFilesFlatten(res,&res,fuf_flags); - if (fuf_flags&FUF_CLUS_ORDER) - DirFilesSort(&res,SK_CLUS); - } - return res; -} -CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0) -{/* See \dLK,"::/Doc/FileUtils.DD"\d. - -Find files and make a directory tree in memory. - -When done, you free with \dLK,"DirEntryDel",A="MN:DirEntryDel"\d(),\dLK,"DirEntryDel2",A="MN:DirEntryDel2"\d(), -\dLK,"DirTreeDel",A="MN:DirTreeDel"\d() or \dLK,"DirTreeDel2",A="MN:DirTreeDel2"\d(). - -*/ - CDirEntry *res; - CDirContext *dirc; - if (fuf_flags&~FUG_FILES_FIND) - throw('FUF'); - if (fuf_flags&FUF_SINGLE) { - res=MAlloc(sizeof(CDirEntry)); - if (!FileFind(files_find_mask,res)) { - Free(res); - return NULL; - } - } else if (dirc=DirContextNew(files_find_mask,TRUE)) { - res=FilesFind2(dirc->mask,fuf_flags); - DirContextDel(dirc); - } else - return NULL; - return res; -} -static Bool IsAtRoot() { - U8 *r=DirCur; - Bool ret=r[2]=='/'&&!r[3]; - Free(r); - return ret; -} -Bool FileFind(U8 *filename,CDirEntry *_de=NULL,I64 fuf_flags=FUF_Z_OR_NOT_Z) -{//\dLK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"\d, \dLK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"\d, \dLK,"FUF_Z_OR_NOT_Z",A="MN:FUF_Z_OR_NOT_Z"\d, \dLK,"FUF_SCAN_PARENTS",A="MN:FUF_SCAN_PARENTS"\d -//If you pass _de, you must Free(_de->full_name); - I64 i,j,cur_dir_clus; - U8 *altname,*curname,*full_name=NULL,*dn; - CDirEntry de,*_de2; - CDirContext *dirc; - Bool res=FALSE,old_silent; - if (fuf_flags&~FUG_FILE_FIND) - throw('FUF'); - if (!filename /* || *filename && filename[1]==':' &&!Let2Drv(*filename,FALSE)*/) //TODO RESTORE - return FALSE; - altname=ToggleZorNotZ(filename); - if (fuf_flags&FUF_Z_OR_NOT_Z) - j=2; - else - j=1; - for (i=0;i<j && !res;i++) { - if (!i) - curname=filename; - else - curname=altname; - //old_silent=Silent; TODO RESTORE - if (!(dirc=DirContextNew(curname))) - ;//Silent(old_silent); - else { - ;//Silent(old_silent); - //cur_dir_clus=Name2DirClus(dirc->dv,Fs->cur_dir); - _de2=FilesFind__(dirc->mask); - res=NULL!=_de2; - if(res) { - MemCpy(&de,_de2,sizeof(de)); - de.full_name=StrNew(_de2->full_name); - } - DirEntryDel2(_de2); - if (res && _de) { - full_name=DirNameAbs(de.name); - } - DirContextDel(dirc); - } - } - for (i=0;i<j && !res && fuf_flags&FUF_SCAN_PARENTS;i++) { - if (!i) - curname=filename; - else - curname=altname; - //old_silent=Silent; TODO RESTORE - if (!(dirc=DirContextNew(curname))) - ;//Silent(old_silent); - else { - ;//Silent(old_silent); - //cur_dir_clus=FileNameAbs(dirc->dv,Fs->cur_dir); - //TODO CHECK IF AT ROOT ON WINDOWS - while (!res && !IsAtRoot) { - Cd(".."); - //cur_dir_clus=FileNameAbs(dirc->dv,Fs->cur_dir); - _de2=FilesFind__(dirc->mask); - res=NULL!=_de2; - if(res) { - MemCpy(&de,_de2,sizeof(de)); - de.full_name=StrNew(_de2->full_name); - } - DirEntryDel2(_de2); - } - if (res && _de) { - full_name=DirNameAbs(de.name); - } - DirContextDel(dirc); - } - } - if (_de) { - if (res) { - MemCpy(_de,&de,sizeof(CDirEntry)); - _de->full_name=full_name; - } else - MemSet(_de,0,sizeof(CDirEntry)); - } - Free(altname); - return res; -} -U0 PutFileLink(U8 *filename,U8 *full_name=NULL,I64 line=0,Bool plain_text=FALSE) -{//Put \dLK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"\d file,line link to StdOut, \dLK,"DocPut",A="MN:DocPut"\d. - U8 *st; - if (!filename) return; - if (IsRaw) { - if (line) - "%s,%04d",filename,line; - else - "%s",filename; - } else { -//LK_DOC,LK_DOC_ANCHOR,LK_DOC_FIND,LK_DOC_LINE - if (filename[0]=='A'&&filename[2]==':') { - if (line) //See \dLK,"SpriteEdText",A="MN:SpriteEdText"\d() - "\dLK,\"%s,%04d\",A=\"AL:%s,%d\"\d",filename+3,line,filename+3,line; - else - "\dLK,\"%s\",A=\"AI:%s\"\d",filename+3,filename+3; - } else { - if (!full_name) - full_name=st=FileNameAbs(filename); - else - st=NULL; - if (plain_text) { - if (line) - "\dLK,\"%s,%04d\",A=\"PL:%s,%d\"\d",filename,line,full_name,line; - else - "\dLK,\"%s\",A=\"PI:%s\"\d",filename,full_name; - } else { - if (line) - "\dLK,\"%s,%04d\",A=\"FL:%s,%d\"\d",filename,line,full_name,line; - else - "\dLK,\"%s\",A=\"FI:%s\"\d",filename,full_name; - } - Free(st); - } - } -} - -U0 PutDirLink(U8 *dirname,U8 *full_name=NULL) -{//Put \dLK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"\d dir macro to StdOut, \dLK,"DocPut",A="MN:DocPut"\d. - U8 *st; - if (!dirname) return; - if(IsRaw) { - "%s",dirname; - } else { - if (!full_name) - full_name=st=DirNameAbs(dirname); - else - st=NULL; - "\dMA,T=\"%s\",LM=\"Cd(\\\"%s\\\");Dir;\n\"\d",dirname,full_name; - Free(st); - } -} - -I64 Dir(U8 *files_find_mask,Bool full) -{//List directory. - CDirEntry *tmpde1=NULL,*tmpde2; - U8 *st; - CDateStruct ds; - I64 csize=0xFFFF,c=0xFFFF,res=0; - tmpde1=FilesFind(files_find_mask); - if (!(st=DirCur)) - PrintErr("Invalid Drive\n"); - else { - if (tmpde1) { - Free(st); - st=MAllocIdent(tmpde1->full_name); - StrLastRem(st,"/"); - if (!st[2]) - StrCpy(st+2,"/"); -//Find max columns - tmpde2=tmpde1; - while (tmpde2) { - if (tmpde2->size>csize) - csize=tmpde2->size; - if (tmpde2->clus>c) - c=tmpde2->clus; - tmpde2=tmpde2->next; - } - csize=Bsr(csize)/4+1; - c=Bsr(c)/4+1; - - "\dMA,T=\"Directory\",LM=\"PopUpCd;Dir;\n\"\d of %s\n",st; - if (full) - "__DATE__ __TIME__ %*ts %*ts\n", - csize,"SIZE",c,"BLK"; - else - "DATE_ TIME_ %*ts\n",csize,"SIZE"; - while (tmpde1) { - tmpde2=tmpde1->next; - res++; - "%D %T %0*tX %0*tX ",tmpde1->datetime,tmpde1->datetime, - csize,tmpde1->size,c,tmpde1->clus; - if (IsDir(tmpde1->full_name)) - PutDirLink(tmpde1->name,tmpde1->full_name); - else - PutFileLink(tmpde1->name,tmpde1->full_name); - "\n"; - DirEntryDel(tmpde1); - tmpde1=tmpde2; - } - } else - "No matching entries\n"; - Free(st); - } - return res; -} diff --git a/T/FILEMGR.HC b/T/FILEMGR.HC index 86c657b..815fdaa 100644 --- a/T/FILEMGR.HC +++ b/T/FILEMGR.HC @@ -213,10 +213,10 @@ U0 FMRebuildDoc(CDoc **_doc,CDirEntry **_head,I64 mode) } DocPrint(doc,"$$LTBLUE$$"); od=DirCur; - for (i=0;i<'Z'-'A';i++) { - st=MStrPrint("%C:/",i+'A'); - if(Cd(st)) - tmpde=FMRebuildDocDrv(i+'A',doc,_head,TRUE); + for (i=0;i<DRVS_NUM;i++) { + dv=&blkdev.drvs[i]; + if (dv->fs_type==FSt_REDSEA || dv->fs_type==FSt_FAT32 || dv->fs_type==FSt_VIRT) + FMRebuildDocDrv(Drv2Let(dv),doc,_head,TRUE); } Cd(od); Free(od); @@ -338,12 +338,11 @@ U0 FMMountISO(CDoc *doc) CDocEntry *doc_ce=doc->cur_entry; CDirEntry *tmpde; if (doc_ce->type_u8==DOCT_MENU_VAL && (tmpde=doc_ce->user_data)) - ;//MountFile(tmpde->full_name); + MountFile(tmpde->full_name); } U0 FMUnmount(CDoc *doc) { - /* CDocEntry *doc_ce=doc->cur_entry; CDirEntry *tmpde; I64 drv_let; @@ -356,9 +355,8 @@ U0 FMUnmount(CDoc *doc) tmpde=tmpde->parent; drv_let=*tmpde->full_name; if (Let2BlkDev(drv_let)!=Let2BlkDev(':')) - ;//Unmount(drv_let); + Unmount(drv_let); } - */ } U0 FMFmtDrv(CDoc *doc) diff --git a/T/FULL_PACKAGE.HC b/T/FULL_PACKAGE.HC index 8f2c1f9..a9defba 100644 --- a/T/FULL_PACKAGE.HC +++ b/T/FULL_PACKAGE.HC @@ -34,15 +34,19 @@ asm { }; U0 LoadImps() { - ExePrint2("#define FPTRS\n;;"); - ExePutS2(KERNELA_BIN,"/KERNELA.HH"); - __BootstrapForeachSymbol(&BootstrapImportSymbol); + try { + ExePutS2("#define FPTRS\n;;"); + ExePutS2(KERNELA_BIN,"/KERNELA.HH"); + __BootstrapForeachSymbol(&BootstrapImportSymbol); //Load asm externs second - ExePrint2("#define BOOT_3DAYS\n;;"); - ExePutS2(KERNELB_BIN,"/KERNELB.HH"); + ExePrint2("#define BOOT_3DAYS\n;;"); + ExePutS2(KERNELB_BIN,"/KERNELB.HH"); + } catch { + TOSPrint("FDSF:%s\n",&(Fs->except_ch)); + Fs->catch_except=TRUE; + }; } static U0 StartUpCore1(I64) { - ACInit("/KERNEL*.HH*"); } U0 StartUpTasks() { @@ -55,7 +59,8 @@ U0 StartUpTasks() ExeFile("/WallPaper.HC.Z"); ExePrint("WallPaperInit;;"); } catch - PutExcept; + PutExcept; + ACInit("/KERNEL*.HH*"); AutoComplete(ON); } U0 Adam(U8 *) { @@ -75,7 +80,7 @@ U0 Adam(U8 *) { DbgInfoRead("HCRT_BC.DBG.Z"); #endif if(__CmdLineBootText) - ExePrint2("%s;\n",__CmdLineBootText); + ExePrint2("%s;\n",__CmdLineBootText); if(!__IsCmdLine) { sys_winmgr_task=Spawn(&WinMgrTask); //Grab pointer @@ -94,4 +99,4 @@ Gs->seth_task=Spawn(&CoreAPSethTask,NULL,"Seth"); //Our entering thread doesnt have a cur_thrd,so spawn one adam_task=Spawn(&Adam,NULL,"Adam",,); //Dont Exit -DeathWait(adam_task);
\ No newline at end of file +DeathWait(&adam_task);
\ No newline at end of file diff --git a/T/HCRT.DBG.Z b/T/HCRT.DBG.Z Binary files differindex 4137e45..439cccf 100644 --- a/T/HCRT.DBG.Z +++ b/T/HCRT.DBG.Z diff --git a/T/HCRT_TOS.HC b/T/HCRT_TOS.HC index e0bf8a9..0235505 100644 --- a/T/HCRT_TOS.HC +++ b/T/HCRT_TOS.HC @@ -50,13 +50,11 @@ CTask *adam_task=Fs; #include "KDATATYPES.HC" #include "COMPRESS.HC" #include "QSORT.HC" -#include "DSKSTR.HC" -#include "DSKDIRA.HC" -#include "DSKFIND.HC" #include "KDBG.HC" #include "KEXCEPT.HC" #include "DISPLAY.HC" #include "MAlloc2.HC" +#include "BlkDev2/MakeBlkDev.HC" #ifdef COMPONET_COMPILER #include "CMP_PRJ.HC" CInit; @@ -70,8 +68,6 @@ CInit; #include "JOB.HC" #include "KTASK.HC" #include "KDefine.HC" -#include "BlkDev/DskCopy.HC" -#include "BlkDev/DskA.HC" #include "KLOAD.HC" #include "KEND.HC" #include "EDLITE.HC" @@ -132,6 +128,7 @@ U8 *MAllocIdent(U8 *s,CTask *t=0) { } #include "ARegistry.HC" #include "AHash.HC" +#include "ADskA.HC" #include "ADskB.HC" #include "ADBG.HC" #include "Sched.HC" @@ -141,8 +138,8 @@ U8 *MAllocIdent(U8 *s,CTask *t=0) { #include "Training.HC.Z" #include "InFile.HC" #include"Community-Heiresis/HolyCipher/CIPHER.HC"; - -I64 CheckSum(U8 *data,I64 len) { +#include "Mount.HC" +/*I64 CheckSum(U8 *data,I64 len) { I64 sum=0; while(--len>=0) sum+=data[len]; return sum; @@ -152,104 +149,9 @@ Bool IsEncryptedRight(U8 *file) { U8 *data=__FileRead(file,&len),*tmp,*buf2=CAlloc(len); tmp=GetCipherPasswd; Decrypt(data,buf2,len-8,tmp,StrLen(tmp)); //See above blinking note - ret=data[len-8](U64)==CheckSum(buf2,len-8); + ret=data[len-8](U64)==CheckSum(buf2,len-8); Free(data),Free(tmp); return ret; } -// -// $BK,1$Enc files will contain a extra 8 bytes that contain a checksum$BK,0$ -// -U8 *FileRead(U8 *fn,I64 *len=NULL,CTask *t=NULL) { - I64 len2; - U8 *tmp,*buf2; -//CHANGE,TempleOS grabs loaded files from RAM,some functions use - //blkdev.tmp_filename as a "defualt" file,so im going to assume its loaded - if(fn==blkdev.tmp_filename) { - return StrNew(""); - } - U8 *fn2=FileNameAbs(fn),*data=NULL,*exp; - if(!__FExists(fn2)) { - exp=MStrPrint("%s.Z",fn2); - if(!__FExists(exp)) { - Free(fn2),Free(exp); - PrintErr("File \"%s\" not found!",fn); - throw('FILE'); - } - Free(fn2); - fn2=exp; - } - if(!t) t=Fs; - Yield; - data=__FileRead(fn2,&len2,t); - if(IsDotZ(fn2)) { - exp=ExpandBuf(data,t); - len2=data(CArcCompress*)->expanded_size; - if(len) - *len=data(CArcCompress*)->expanded_size; - Free(data); - data=exp; - } else { - if(len) - *len=len2; - } - tmp=FileExtDot(fn2); - if(tmp) - if(!StrNCmp(tmp,".ENC",4)) { - tmp=GetCipherPasswd; - if(!tmp) throw('NoPasswd'); - buf2=MAlloc(len2-8+1);//+1 for NULL byte - buf2[len2-8]=0; - Decrypt(data,buf2,len2-8,tmp,StrLen(tmp)); //See above blinking note - if(data[len2-8](U64)!=CheckSum(buf2,len2-8)) { - Free(buf2); - buf2=StrNew(""); - len2=8; - } - len2-=8; - if(len) *len=len2; - Free(data); - data=buf2; - Free(tmp); - } - Free(fn2); - return data; -} -I64i FileWrite(U8i *fn,U8i *buf,I64i len) { - I64 len2,r; - Bool fr=FALSE;; - U8 *fn2=FileNameAbs(fn),*data=NULL,*tmp; - CArcCompress *cmp; - if(!fn2) return 0; - tmp=FileExtDot(fn2); - if(tmp) - if(!StrNCmp(tmp,".ENC",4)) { - if(FileFind(fn2)) { - if(!IsEncryptedRight(fn2)) { - Free(fn2); - return; - } - } - data=CAlloc(len+8); - MemCpy(data,buf,len); - tmp=GetCipherPasswd; - if(!tmp) throw('NoPasswd'); - Encrypt(data,buf,len,tmp,StrLen(tmp)); - data[len](U64)=CheckSum(buf,len); - len+=8; - Free(tmp); - fr=TRUE; - buf=data; - } - if(IsDotZ(fn2)) { - if(!buf) buf=""; - cmp=CompressBuf(buf,len,Fs); - r=__FileWrite(fn2,cmp,cmp->compressed_size); - Free(cmp); - } else - r=__FileWrite(fn2,buf,len); - Free(fn2); - if(fr) Free(buf); - return r; -} - +*/ #endif @@ -541,20 +541,22 @@ U0 CoreAPSethTask() do PAUSE while (LBts(&ctrl->flags,JOBCf_LOCKED)); } while (ctrl->next_waiting!=ctrl && JobRunOne(GetRFlags,ctrl)); - //LBts(&(Fs->task_flags),TASKf_AWAITING_MSG); +//LBts(&(Fs->task_flags),TASKf_AWAITING_MSG); LBtr(&ctrl->flags,JOBCf_LOCKED); LBts(&(Fs->task_flags),TASKf_IDLE); ms=100,t=__GetTicks; for(task=Fs->next_task;task!=task1;task=task->next_task) { - if(Bt(&task->task_flags,TASKf_SUSPENDED)||Bt(&task->task_flags,TASKf_AWAITING_MSG)) - goto next; - if(task->wake_jiffy&&task->wake_jiffy-t<ms) - ms=task->wake_jiffy-t; - next: + if(Bt(&task->task_flags,TASKf_SUSPENDED)||Bt(&task->task_flags,TASKf_AWAITING_MSG)) + goto next; + if(!task->wake_jiffy) + ms=0; + else if(task->wake_jiffy-t<ms) + ms=task->wake_jiffy-t; +next: } if(ms>=0) { - Gs->idle_pt_hits+=ms; - __Sleep(ms); + Gs->idle_pt_hits+=ms; + __Sleep(ms); } Yield; LBtr(&(Fs->task_flags),TASKf_IDLE); diff --git a/T/KERNELA.HH b/T/KERNELA.HH index 04a53ef..b4ff5f9 100644 --- a/T/KERNELA.HH +++ b/T/KERNELA.HH @@ -143,6 +143,23 @@ extern class CFile; extern class CCPU; extern class CDyadStream; #ifdef IMPORT_BUILTINS +import U8i *VFsFOpenR(U8i*); +import U8i *VFsFOpenW(U8i*); +import U0 VFsFClose(U8i*); +import U0 VFsFBlkRead(U8i*,I64i,I64i,U8i*); +import U0 VFsFBlkWrite(U8i*,I64i,I64i,U8i*); +import U0 VFsFSeek(I64i,U8i*); + +import U0 VFsSetPwd(U8i*); +import Bool VFsExists(U8i*); +import Bool VFsIsDir(U8i*); +import I64i VFsFSize(U8i*); +import U8i *VFsFRead(U8i*,I64i*); +import U8i *VFsDirMk(U8i*); +import U8i *VFsFWrite(U8i*,U8i*,I64i); +import Bool VFsDel(U8i*); +import U8i **VFsDir(); + import U8i __IsValidPtr(U8i *ptr); import U8i *GetCipherPasswd(); import U64i UnixNow(); @@ -180,26 +197,11 @@ import I64i FSize(U8i *); import I64i FUnixTime(U8i *); import U8i *GetClipboardText(); import U8i *SetClipboardText(U8i *); -public import Bool FBlkRead(CFile *f,U8i *buf,I64i blk=FFB_NEXT_BLK,I64i cnt=1); -public import Bool FBlkWrite(CFile *f,U8i *buf,I64i blk=FFB_NEXT_BLK,I64i cnt=1); -public import U0 FClose(CFile *f); -public import CFile *FOpen(U8i *filename,U8i *flags,I64i cnt=0); //public import I64i MSize(U8i *src); //size of heap object //public import I64i MSize2(U8i *src); //Internal size public import U8i *CAlloc(I64i size,CTask *t=0); public import U0i TOSPrint(U8i *,...); -public import U8i *__FileRead(U8i *filename,I64i *_size=0,CTask *t=0); -public import I64i __FileWrite(U8i *filename, - U8i *fbuf,I64i size); -public import U8 *DirNameAbs(U8i *dirname); -public import U8 *FileNameAbs(U8i *dirname); -public import Bool Cd(U8i *dirname=0); -public import Bool IsDir(U8i *dir_name); //TODO -public import Bool DirMk(U8i *filename); //TODO -public import U8 **__Dir(U8i *); //TODO -public import U8 *DirCur(); public import U8 *__GetStr(U8 *pmt=""); -import U8i ChDrv(U8i); import U0i SndFreq(I64i freq); import U0 __BootstrapForeachSymbol(U0 *fptr); extern C3DaysDrawWin; @@ -272,19 +274,8 @@ extern I64i FSize(U8i *); extern I64i FUnixTime(U8i *); extern U8i *GetClipboardText(); extern U8i *SetClipboardText(U8i *); -extern U0 __Del(U8 *); -public extern U8 *DirCur(); public extern U8i *CAlloc(I64i size,CTask *t=0); public extern U0i TOSPrint(U8i *,...); -public extern U8i *__FileRead(U8i *filename,I64i *_size=0,CTask *t=0); -public extern I64i __FileWrite(U8i *filename, - U8i *fbuf,I64i size); -public extern U8 *DirNameAbs(U8i *dirname); -public extern U8 *FileNameAbs(U8i *dirname); -public extern Bool Cd(U8i *dirname=0); -public extern Bool IsDir(U8i *dir_name); //TODO -public extern Bool DirMk(U8i *filename); //TODO -public extern U8 **__Dir(U8i *); //TODO public extern U0 Exit(); public extern U8 *__GetStr(U8 *pmt=""); extern U0 __SetThreadPtr(U0 *_3dt,U8 *ptr); @@ -2799,7 +2790,7 @@ class CISOPriDesc #define MT_DVD 2 //CDirEntry flags (Used by \dLK,"FileMgr",A="MN:FileMgr"\d()) -#define CDIR_FILENAME_LEN 2048 //Must include terminator zero +#define CDIR_FILENAME_LEN 38 //Must include terminator zero public class CDirEntry { CDirEntry *next,*parent,*sub; @@ -2885,7 +2876,8 @@ public class CDirEntry #define BDT_ISO_FILE_READ 3 #define BDT_ISO_FILE_WRITE 4 #define BDT_ATAPI 5 -#define BDT_TYPES_NUM 6 +#define BDT_VIRT 6 +#define BDT_TYPES_NUM 7 #define BDF_REMOVABLE 0x001 #define BDF_INITIALIZED 0x002 @@ -2943,6 +2935,7 @@ public class CBlkDev #define FSt_NTFS 4 //Not Supported #define FSt_UNKNOWN 5 #define FSt_TYPES_NUM 6 +#define FSt_VIRT 7 #define FSG_TYPE_MASK 0x7FFF //File system type flags #define FStf_DISABLE 15 @@ -3045,6 +3038,7 @@ public class CFile //See \dLK,"::/Demo/Dsk/DataBase.HC"\d. CDrv *dv; I64 fblk_num,clus,file_clus_num,max_blk; U8 *clus_buf; + U8 *_3days_virt; //points to FILE * from C }; #define _CFG_HEAP_DBG FALSE @@ -4258,8 +4252,6 @@ extern I64 PopUpColor(U8 *header=NULL, Bool allow_transparent=TRUE,Bool allow_dft=TRUE); extern I64 PopUpColorLighting(U8 *header=NULL); extern I64 PopUpColorDither(U8 *header=NULL); -extern U8 *FileRead(U8 *fn,I64 *len=NULL,CTask *t=NULL) ; -extern U8 *FileWrite(U8 *fn,I64 *len=NULL,CTask *t=NULL) ; extern Bool IsDotZ(U8 *filename); extern Bool IsDotC(U8 *filename); extern U8 *ExpandBuf(CArcCompress *arc,CTask*); @@ -6007,7 +5999,6 @@ extern CTask *adam_task; extern Bool YorN(); extern I64 PressAKey(); extern Bool AreYouSure(); -public extern Bool Del(U8 *f1); public extern U32 char_bmp_alpha[16],char_bmp_alpha_numeric[16], char_bmp_alpha_numeric_no_at[16], char_bmp_word[16], char_bmp_dec_numeric[16], char_bmp_hex_numeric[16], @@ -6375,4 +6366,157 @@ extern U8 *PopUpGetStr2(U8 *header,CTask *mem_task); extern U0 Decrypt(U8 *ciphertext=NULL,U8 *decryptedtext=NULL,U64 textlen=0,U8 *key=NULL,U64 keylen=0); extern U0 Decrypt(U8 *ciphertext=NULL,U8 *decryptedtext=NULL,U64 textlen=0,U8 *key=NULL,U64 keylen=0); extern U8i IsValidPtr(U8i *ptr,I64 sz=1); -extern Bool IsEncryptedRight(U8 *file);
\ No newline at end of file +extern Bool IsEncryptedRight(U8 *file); +extern U8 Drv2Let(CDrv *dv=NULL); +extern CBlkDev *BlkDevChk(CBlkDev *bd,Bool except=TRUE); +extern CDrv *Let2Drv(U8 drv_let=0,Bool except=TRUE); +extern Bool RedSeaValidate(U8 drv_let); +extern U0 RedSeaInit(CDrv *dv); +extern U0 RedSeaFmt(U8 drv_let,Bool quick=TRUE); +extern U0 DskCacheInvalidate(CDrv *dv); +extern U0 DskCacheInit(I64 size_in_U8s); +extern I64 DskCacheHash(I64 blk); +extern U0 DskCacheQueRem(CCacheBlk *tmpc); +extern U0 DskCacheQueIns(CCacheBlk *tmpc); +extern CCacheBlk *DskCacheFind(CDrv *dv,I64 blk); +extern U0 DskCacheAdd(CDrv *dv,U8 *buf, I64 blk, I64 cnt); +extern I64 Let2BlkDevType(U8 drv_let); +extern U0 DrvBlkDevDel(CBlkDev *bd); +extern CDrv *DrvChk(CDrv *dv,Bool except=TRUE); +extern U8 Let2Let(U8 drv_let=0); +extern U0 RedSeaFreeFreeLst(CDrv *dv); +extern Bool BlkRead(CDrv *dv,U8 *buf, I64 blk, I64 cnt); +extern Bool BlkWrite(CDrv *dv,U8 *buf, I64 blk, I64 cnt); +extern Bool ISOInit(CDrv *dv,I64 blk); +extern Bool Drv(U8 drv_let); +extern I64 RedSeaAllocClus(CDrv *dv,I64 cnt); +extern I64 FAT32AllocContiguousClus(CDrv *dv,I64 cnt); +extern I64 FAT32AllocClus(CDrv *dv,I64 c,I64 cnt); +extern Bool CFileNameTo(U8 *dst,U8 *src); +#help_index "File/Cmd Line (Typically);Cmd Line (Typically)" +public extern Bool Cd(U8 *dirname=NULL,Bool make_dirs=FALSE); +public extern I64 Del(U8 *files_find_mask,Bool make_mask=FALSE, + Bool del_dir=FALSE,Bool print_msg=TRUE); +public extern I64 Dir(U8 *files_find_mask="*",Bool full=FALSE); +public extern Bool DirMk(U8 *filename,I64 entry_cnt=0); +public extern Bool Drv(U8 drv_let); +public extern U0 DskChg(U8 drv_let=0); +public extern U0 HomeSet(U8 *dirname); + +#help_index "File/Cmd Line (Typically);Cmd Line (Typically);Install" +public extern Bool DrvMap(U8 drv_let,CDrv *dv); + +#help_index "File/FileNames" +extern CDirEntry *Cd2DirEntry(CDirEntry *tmpde,U8 *abs_name); +public extern U8 *DirCur(CTask *task=NULL,CTask *mem_task=NULL); +public extern U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL); +public extern U8 *DirNameAbs(U8 *dirname); +public extern CBlkDev *DrvIsWritable(U8 drv_let=0,Bool except=FALSE); +public extern U8 *ExtChg(U8 *filename,U8 *extension); +public extern U8 *ExtDft(U8 *filename,U8 *extension); +public extern U8 *FileExtDot(U8 *src); +public extern U8 *FileExtRem(U8 *src,U8 *dst=NULL); +public extern U8 *FileNameAbs(U8 *filename,I64 fuf_flags=0); +public extern Bool FileNameChk(U8 *filename); +public extern Bool FilesFindMatch(U8 *_test_name, + U8 *files_find_mask,I64 fuf_flags=0); +public extern Bool IsDir(U8 *dir_name); +public extern Bool IsDotC(U8 *filename); +public extern Bool IsDotZ(U8 *filename); +public extern U0 PutDirLink(U8 *dirname,U8 *full_name=NULL); +public extern U0 PutFileLink(U8 *filename,U8 *full_name=NULL, + I64 line=0,Bool plain_text=FALSE); +public extern U0 ToFileLine(U8 *_fl_file_line,U8 **_filename,I64 *_linenum); +public extern U8 *ToggleZorNotZ(U8 *name); + +#help_index "File/FileNames;Misc" +public extern U8 *FileNameTmpTxt(); + +#help_index "File/Internal" +public extern U0 DirContextDel(CDirContext *dirc,Bool restore=TRUE); +public extern CDirContext *DirContextNew(U8 *mask, + Bool make_mask=FALSE,Bool make_dirs=FALSE,Bool no_mask=FALSE); +public extern Bool DirNew(CDrv *dv,U8 *cur_dir, + CDirEntry *tmpde,Bool free_old_chain=TRUE); +extern I64 FileAttr(U8 *name,I64 old_attr=0); + +#help_index "File/Low Level" +#help_file "::/Doc/FileLowLevel" +public extern CBlkDev *BlkDevChk(CBlkDev *bd,Bool except=TRUE); +public extern U0 BlkDevDel(CBlkDev *bd); +public extern Bool BlkDevLock(CBlkDev *bd); +public extern CBlkDev *BlkDevNextFreeSlot(U8 first_drv_let,I64 type); +public extern Bool BlkDevUnlock(CBlkDev *bd,Bool rst=FALSE); +public extern U0 BlkDevsRelease(); +public extern Bool BlkRead(CDrv *dv,U8 *buf, I64 blk, I64 cnt); +public extern Bool BlkWrite(CDrv *dv,U8 *buf, I64 blk, I64 cnt); +public extern U0 BlkWriteZero(CDrv *dv,I64 blk,I64 cnt); +public extern I64 Clus2Blk(CDrv *dv,I64 c); +public extern I64 ClusAlloc(CDrv *dv,I64 c=0, + I64 cnt=1,Bool contiguous=FALSE); +public extern I64 ClusBlkRead(CDrv *dv,U8 *buf,I64 c,I64 blks); +public extern I64 ClusBlkWrite(CDrv *dv,U8 *buf,I64 c,I64 blks); +public extern I64 ClusNumNext(CDrv *dv,I64 c,I64 cnt=1); +public extern I64 ClusRead(CDrv *dv,U8 *buf,I64 c,I64 cnt); +public extern I64 ClusWrite(CDrv *dv,U8 *buf,I64 c,I64 cnt); +extern Bool CopySingle(U8 *f1,U8 *f2); //Just one file +public extern U8 Drv2Let(CDrv *dv=NULL); +public extern CDrv *DrvChk(CDrv *dv,Bool except=TRUE); +public extern U0 DrvDel(CDrv *dv); +public extern Bool DrvLock(CDrv *dv); +public extern CDrv *DrvMakeFreeSlot(U8 drv_let); +public extern U8 *DrvModelNum(U8 drv_let=0); +public extern U8 DrvNextFreeLet(U8 first_drv_let='C'); +public extern U8 *DrvSerialNum(U8 drv_let=0); +public extern U8 DrvTextAttrGet(U8 drv_let=0); +public extern Bool DrvUnlock(CDrv *dv,Bool rst=FALSE); +public extern U0 DrvsRelease(); +extern U0 FAT32FreeClus(CDrv *dv,I64 c); +public extern CBlkDev *Let2BlkDev(U8 drv_let=0,Bool except=TRUE); +public extern I64 Let2BlkDevType(U8 drv_let); +public extern CDrv *Let2Drv(U8 drv_let=0,Bool except=TRUE); +public extern U8 Let2Let(U8 drv_let=0); +extern I64 Name2DirClus(CDrv *dv,U8 *dirname); +extern I64 Name2ParentDirClus(CDrv *dv,U8 *dirname); +extern U0 RedSeaFreeClus(CDrv *dv,I64 c,I64 cnt); +public extern U0 DVDImageRead(U8 dvd_drv_let,U8 *out_name); +public extern U0 DVDImageWrite(U8 dvd_drv_let, + U8 *in_name=NULL,I64 media_type=MT_DVD); +public extern Bool FBlkRead(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1); +public extern Bool FBlkWrite(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1); +public extern U0 FClose(CFile *f); +public extern CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0); +public extern I64 FSize(CFile *f); + +extern I64 RedSeaAllocClus(CDrv *dv,I64 cnt); +extern Bool RedSeaDirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tmpde, + Bool free_old_chain); +extern Bool RedSeaFileFind(CDrv *dv,I64 cur_dir_clus,U8 *name, + CDirEntry *_res,I64 fuf_flags=0); +extern U0 RedSeaFmt(U8 drv_let,Bool quick=TRUE); +extern U0 RedSeaFreeFreeLst(CDrv *dv); +extern U0 RedSeaInit(CDrv *dv); +extern Bool RedSeaValidate(U8 drv_let); +extern I64 FAT32AllocClus(CDrv *dv,I64 c,I64 cnt); +extern I64 FAT32AllocContiguousClus(CDrv *dv,I64 cnt); +extern Bool FAT32DirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tmpde, + Bool free_old_chain); +extern Bool FAT32FileFind(CDrv *dv,I64 cur_dir_clus,U8 *name, + CDirEntry *_res,I64 fuf_flags=0); +extern U0 FAT32Init(CDrv *dv); +extern U8 Drv2Let(CDrv *dv=NULL); +extern U0 DrvBlkDevDel(CBlkDev *bd); +extern CDrv *DrvChk(CDrv *dv,Bool except=TRUE); +extern U8 DrvTextAttrGet(U8 drv_let=0); +extern Bool DrvTypeSet(U8 drv_let,I64 type=FSt_REDSEA); +extern U0 DrvsRelease(); +extern U0 DskCacheInvalidate(CDrv *dv); +extern U8 *FileExtRem(U8 *src,U8 *dst=NULL); +extern Bool FileFind(U8 *filename,CDirEntry *_de=NULL,I64 fuf_flags=0); +extern U8 *FileNameAbs(U8 *_filename,I64 fuf_flags=0); +extern U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL); +extern I64 FileWrite(U8 *filename,U8 *fbuf,I64 size,CDate cdt=0,I64 attr=0); +extern CDirEntry *VirtFilesFind(U8 *files_find_mask,I64 fuf_flags, + CDirEntry *parent=NULL); +public extern U8 MountFile(U8 *filename); +public extern U0 Unmount(U8 drv_let=0); @@ -70,6 +70,9 @@ return task; return task->parent_task; } + DrvsRelease; + BlkDevsRelease; + tmpt1=(&task->next_child_task)(U8 *)-offset(CTask.next_sibling_task); tmpt=tmpt1->next_sibling_task; if (tmpt!=tmpt1) { @@ -211,7 +214,7 @@ I64 ExeCmdLine(CCmpCtrl *cc) } Bool TaskValidate(CTask *task) {//return TRUE if task looks valid. - if(!__IsValidPtr(&task->task_signature)||!task) + if(!__IsValidPtr(&task->task_signature)||!task) return FALSE; if(task->task_signature!=TASK_SIGNATURE_VAL) return FALSE; @@ -260,16 +263,15 @@ I64 TaskInit(CTask *task,I64 stk_size) task->win_right =text.cols-2; task->win_top =13; task->win_bottom =text.rows-2; - - /* +/* if (blkdev.home_dir) {//Beware Adam \dLK,"TaskInit",A="FF:::/Kernel/KStart64.HC,TaskInit"\d. I guess ok until \dLK,"DskChg",A="FF:::/Kernel/KMain.HC,DskChg"\d(). task->cur_dv=blkdev.let_to_drv[*blkdev.home_dir-'A']; task->cur_dir=StrNew(blkdev.home_dir+2,task); } else task->cur_dir=StrNew("/Home",task); - */ - //TODO Restore - task->cur_dir=StrNew(Fs->cur_dir,task); +*/ + task->cur_dv=Fs->cur_dv; + task->cur_dir=StrNew(Fs->cur_dir,task); return task; } CTask *Spawn(U0 (*fp_start_addr)(U8 *data),U8 *data=NULL,U8 *task_name=NULL, @@ -345,7 +347,7 @@ U0 UserCmdLine(I64 dummy=0) UserStartUp; UserTaskCont; } - + CTask *User(U8 *fmt=NULL,...) {//Create user term task. U8 *st; @@ -11,8 +11,6 @@ #include <dirent.h> #include <sys/types.h> #include <time.h> -extern int64_t HCSetJmp(void *ptr); -extern void HCLongJmp(void *ptr); #include <stddef.h> #include <stdalign.h> #ifdef TARGET_WIN32 @@ -164,28 +162,6 @@ void* FileRead(char *fn,int64_t *sz) { if(sz) *sz=len; return data; } -static char **__Dir(char *fn) { - int64_t sz; - char **ret; - fn=__VFsFileNameAbs(fn); - DIR *dir=opendir(fn); - if(!dir) { - TD_FREE(fn); - return NULL; - } - struct dirent *ent; - vec_str_t items; - vec_init(&items); - while(ent=readdir(dir)) - vec_push(&items,HolyStrDup(ent->d_name)); - vec_push(&items,NULL); - TD_FREE(fn); - sz=items.length*sizeof(char*); - ret=memcpy(HolyMAlloc(sz),items.data,sz); - vec_deinit(&items); - closedir(dir); - return ret; -} static void STK_InteruptCore(int64_t *stk) { InteruptCore(stk[0]); } @@ -307,59 +283,6 @@ int64_t STK_ForeachFunc(int64_t *stk) { int64_t STK_TOSPrint(int64_t *stk) { TOSPrint(stk[0],stk[1],stk+2); } - int64_t STK_Del(int64_t *stk) { - return VFsDel(stk[0]); -} -int64_t STK_FOpen(int64_t *stk) { - char *fn=__VFsFileNameAbs(stk[0]); - FILE *f=fopen(fn,stk[1]); - TD_FREE(fn); - return f; -} -int64_t STK_FClose(int64_t *stk) { - return fclose(stk[0]); -} -#define NEXT_BLK 0x7FFFFFFFFFFFFFFFll -int64_t STK_FBlkRead(int64_t *stk) { - if(NEXT_BLK!=stk[2]) { - fseek(stk[0],stk[2]*(1<<9),SEEK_SET); - } - return fread(stk[1],1<<9,stk[3],stk[0]); -} -int64_t STK_FBlkWrite(int64_t *stk) { - if(NEXT_BLK!=stk[2]) { - fseek(stk[0],stk[2]*(1<<9),SEEK_SET); - } - return fwrite(stk[1],1<<9,stk[3],stk[0]); -} -int64_t STK___Move(int64_t *stk) { - return __Move(stk[0],stk[1]); -} -int64_t STK_Cd(int64_t *stk) { - return VFsCd(stk[0],0); -} -int64_t STK_DirCur(int64_t *stk) { - char *d=VFsDirCur(),*r; - r=HolyStrDup(d); - TD_FREE(d); - return r; -} -int64_t STK_DirMk(int64_t *stk) { - char *d=VFsDirCur(); - int r=VFsCd(stk[0],VFS_CDF_MAKE); - VFsCd(d,0); - TD_FREE(d); - return r; -} -int64_t STK_FileNameAbs(int64_t *stk) { - char *a=VFsFileNameAbs(stk[0]),*r; - r=HolyStrDup(a); - TD_FREE(a); - return r; -} -int64_t STK___Dir(int64_t *stk) { - return __Dir(stk[0]); -} int64_t STK_memset(int64_t *stk) { return memset(stk[0],stk[1],stk[2]); } @@ -473,9 +396,6 @@ int64_t STK_FUnixTime(int64_t *stk) { int64_t STK___FExists(int64_t *stk) { return VFsFileExists(stk[0]); } -int64_t STK_ChDrv(int64_t *stk) { - return VFsChDrv(stk[0]); -} #ifndef TARGET_WIN32 #include <time.h> int64_t STK_Now(int64_t *stk) { @@ -522,6 +442,52 @@ int64_t STK_NewVirtualChunk(int64_t *stk) { int64_t STK_FreeVirtualChunk(int64_t *stk) { FreeVirtualChunk(stk[0],stk[1]); } +int64_t STK_VFsSetPwd(int64_t *stk) { + VFsSetPwd(stk[0]); + return 1; +} +int64_t STK_VFsExists(int64_t *stk) { + return VFsFileExists(stk[0]); +} +int64_t STK_VFsIsDir(int64_t *stk) { + return VFsIsDir(stk[0]); +} +int64_t STK_VFsFileSize(int64_t *stk) { + return VFsFSize(stk[0]); +} +int64_t STK_VFsFRead(int64_t *stk) { + return VFsFileRead(stk[0],stk[1]); +} +int64_t STK_VFsFWrite(int64_t *stk) { + return VFsFileWrite(stk[0],stk[1],stk[2]); +} +int64_t STK_VFsDirMk(int64_t *stk) { + return VFsCd(stk[0],VFS_CDF_MAKE); +} +int64_t STK_VFsDir(int64_t *stk) { + return VFsDir(stk[0]); +} +int64_t STK_VFsDel(int64_t *stk) { + return VFsDel(stk[0]); +} +int64_t STK_VFsFOpenW(int64_t *stk) { + return VFsFOpen(stk[0],"wb+"); +} +int64_t STK_VFsFOpenR(int64_t *stk) { + return VFsFOpen(stk[0],"rb"); +} +int64_t STK_VFsFClose(int64_t *stk) { + fclose(stk[0]); +} +int64_t STK_VFsFBlkRead(int64_t *stk) { + fread(stk[0],stk[1],stk[2],stk[3]); +} +int64_t STK_VFsFBlkWrite(int64_t *stk) { + fwrite(stk[0],stk[1],stk[2],stk[3]); +} +int64_t STK_VFsFSeek(int64_t *stk) { + fseek(stk[1],stk[0],SEEK_SET); +} void TOS_RegisterFuncPtrs() { map_iter_t miter; const char *key; @@ -534,7 +500,6 @@ void TOS_RegisterFuncPtrs() { STK_RegisterFunctionPtr(&ffi_blob,"FreeVirtualChunk",STK_FreeVirtualChunk,2); STK_RegisterFunctionPtr(&ffi_blob,"__CmdLineBootText",CmdLineBootText,0); STK_RegisterFunctionPtr(&ffi_blob,"Exit3Days",__Shutdown,0); - STK_RegisterFunctionPtr(&ffi_blob,"ChDrv",STK_ChDrv,1); STK_RegisterFunctionPtr(&ffi_blob,"__GetStr",STK___GetStr,1); STK_RegisterFunctionPtr(&ffi_blob,"__IsCmdLine",IsCmdLine,0); STK_RegisterFunctionPtr(&ffi_blob,"__FExists",STK___FExists,1); @@ -547,10 +512,6 @@ void TOS_RegisterFuncPtrs() { STK_RegisterFunctionPtr(&ffi_blob,"__SleepUntilValue",STK___SleepUntilValue,3); STK_RegisterFunctionPtr(&ffi_blob,"SetClipboardText",STK_SetClipboardText,1); STK_RegisterFunctionPtr(&ffi_blob,"GetClipboardText",STK_GetClipboardText,0); - STK_RegisterFunctionPtr(&ffi_blob,"FOpen",STK_FOpen,3); - STK_RegisterFunctionPtr(&ffi_blob,"FClose",STK_FClose,1); - STK_RegisterFunctionPtr(&ffi_blob,"FBlkRead",STK_FBlkRead,4); - STK_RegisterFunctionPtr(&ffi_blob,"FBlkWrite",STK_FBlkWrite,4); STK_RegisterFunctionPtr(&ffi_blob,"SndFreq",STK_SndFreq,1); STK_RegisterFunctionPtr(&ffi_blob,"__Sleep",&STK_Sleep,1); STK_RegisterFunctionPtr(&ffi_blob,"GetFs",STK_GetFs,0); @@ -559,8 +520,6 @@ void TOS_RegisterFuncPtrs() { STK_RegisterFunctionPtr(&ffi_blob,"SetMSCallback",STK_SetMSCallback,1); STK_RegisterFunctionPtr(&ffi_blob,"__GetTicks",STK___GetTicks,0); STK_RegisterFunctionPtr(&ffi_blob,"__BootstrapForeachSymbol",STK_ForeachFunc,1); - STK_RegisterFunctionPtr(&ffi_blob,"__FileRead",STK_FileRead,3); - STK_RegisterFunctionPtr(&ffi_blob,"__FileWrite",STK_FileWrite,3); STK_RegisterFunctionPtr(&ffi_blob,"IsDir",STK_IsDir,1); STK_RegisterFunctionPtr(&ffi_blob,"DrawWindowDel",STK_DrawWindowDel,1); STK_RegisterFunctionPtr(&ffi_blob,"DrawWindowUpdate",STK_DrawWindowUpdate,4); @@ -568,13 +527,6 @@ void TOS_RegisterFuncPtrs() { STK_RegisterFunctionPtr(&ffi_blob,"UnblockSignals",UnblockSignals,0); //SPECIAL STK_RegisterFunctionPtr(&ffi_blob,"TOSPrint",STK_TOSPrint,0); - STK_RegisterFunctionPtr(&ffi_blob,"FileNameAbs",STK_FileNameAbs,1); - STK_RegisterFunctionPtr(&ffi_blob,"DirNameAbs",STK_FileNameAbs,1); - STK_RegisterFunctionPtr(&ffi_blob,"__Dir",STK___Dir,1); - STK_RegisterFunctionPtr(&ffi_blob,"Cd",STK_Cd,1); - STK_RegisterFunctionPtr(&ffi_blob,"DirCur",STK_DirCur,0); - STK_RegisterFunctionPtr(&ffi_blob,"DirMk",STK_DirMk,1); - STK_RegisterFunctionPtr(&ffi_blob,"__Del",STK_Del,1); #ifdef USE_NETWORKING STK_RegisterFunctionPtr(&ffi_blob,"DyadInit",&STK_DyadInit,0); STK_RegisterFunctionPtr(&ffi_blob,"DyadUpdate",&STK_DyadUpdate,0); @@ -589,10 +541,25 @@ void TOS_RegisterFuncPtrs() { STK_RegisterFunctionPtr(&ffi_blob,"DyadSetReadCallback",STK_DyadSetReadCallback,3); STK_RegisterFunctionPtr(&ffi_blob,"DyadSetOnListenCallback",STK_DyadSetOnListenCallback,3); #endif + STK_RegisterFunctionPtr(&ffi_blob,"VFsSetPwd",STK_VFsSetPwd,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsExists",STK_VFsExists,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsIsDir",STK_VFsIsDir,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFSize",STK_VFsFileSize,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFRead",STK_VFsFRead,2); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFWrite",STK_VFsFWrite,3); + STK_RegisterFunctionPtr(&ffi_blob,"VFsDel",STK_VFsDel,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsDir",STK_VFsDir,0); + STK_RegisterFunctionPtr(&ffi_blob,"VFsDirMk",STK_VFsDirMk,1); STK_RegisterFunctionPtr(&ffi_blob,"GrPaletteColorSet",STK_GrPalleteSet,2); STK_RegisterFunctionPtr(&ffi_blob,"GrPaletteColorGet",STK_GrPalleteGet,1); STK_RegisterFunctionPtr(&ffi_blob,"GetCipherPasswd",GetCipherPasswd,0); STK_RegisterFunctionPtr(&ffi_blob,"__IsValidPtr",IsValidPtr,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFBlkRead",STK_VFsFBlkRead,4); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFBlkWrite",STK_VFsFBlkWrite,4); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFOpenW",STK_VFsFOpenW,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFOpenR",STK_VFsFOpenR,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFClose",STK_VFsFClose,1); + STK_RegisterFunctionPtr(&ffi_blob,"VFsFSeek",STK_VFsFSeek,2); char *blob=NewVirtualChunk(ffi_blob.length,1); memcpy(blob,ffi_blob.data,ffi_blob.length); vec_deinit(&ffi_blob); @@ -22,22 +22,7 @@ static int64_t FILETIME2Unix(FILETIME *t) { return time/10000000ll; } #endif -#define VFS_T_FILE 1 -#define VFS_T_DIR 2 -#define VFS_T_DRIVE 3 -static __thread map_str_t drive_dirs; -#ifndef TARGET_WIN32 - pthread_mutex_t mp_mtx=PTHREAD_MUTEX_INITIALIZER; -#else - HANDLE mp_mtx=NULL; -#endif -static map_str_t mount_points; -#define cur_dir (*(char**)((char*)GetFs()+112)) void VFsGlobalInit() { - #ifdef TARGET_WIN32 - mp_mtx=CreateMutex(NULL,0,NULL); - #endif - map_init(&mount_points); } #define TOS_delim '/' #ifdef TARGET_WIN32 @@ -49,7 +34,6 @@ void VFsGlobalInit() { #include <sys/types.h> #include <sys/stat.h> #endif -static const char *static_root="T:/"; static char *VFsInplaceConvertDelims(char *p) { if(TOS_delim!=delim) for(;strchr(p,delim);) @@ -74,8 +58,13 @@ static char *VFsInplaceRemoveRepeatSlashes(char *p) { *dst=0; return o; } -char * VFsDirCur() { - return strdup(cur_dir); +__thread char thrd_pwd[1024]; +void VFsThrdInit() { + strcpy(thrd_pwd,"/"); +} +void VFsSetPwd(char *pwd) { + if(!pwd) pwd="/"; + strcpy(thrd_pwd,pwd); } #ifdef TARGET_WIN32 static int __FExists(char *path) { @@ -113,190 +102,21 @@ static int __FIsDir(char *path) { return (s.st_mode&S_IFMT)==S_IFDIR; } #endif -static int RootPathLen() { - char buffer[2]={*cur_dir,0},**base; - #ifndef TARGET_WIN32 - pthread_mutex_lock(&mp_mtx); - #else - WaitForSingleObject(mp_mtx,INFINITE); - #endif - assert(base=map_get(&mount_points,buffer)); - #ifndef TARGET_WIN32 - pthread_mutex_unlock(&mp_mtx); - #else - ReleaseMutex(mp_mtx); - #endif - int64_t r=strlen(*base); - if(base[0][r-1]==delim) - r--; - return r; -} -static char *GetHomeDirForDrive(char drv) { - char drv_buf[2]={drv,0}; - #ifndef TARGET_WIN32 - pthread_mutex_lock(&mp_mtx); - #else - WaitForSingleObject(mp_mtx,INFINITE); - #endif - char *root=*map_get(&mount_points,drv_buf); - #ifndef TARGET_WIN32 - pthread_mutex_unlock(&mp_mtx); - #else - ReleaseMutex(mp_mtx); - #endif - if(root) { - if(*root=='/') { //TODO check for windows - return HostHomeDir(); - } - } - return strdup("/Home"); -} int VFsCd(char *to,int flags) { - if(!to) { - to=VFsDirCur(); - int r=VFsCd(to,flags); + to=__VFsFileNameAbs(to); + if(__FExists(to)&&__FIsDir(to)) { TD_FREE(to); - return r; - } - int make=flags&VFS_CDF_MAKE; - int allow_fail=flags&VFS_CDF_FILENAME_ABS; - //int only_dirs=flags&VFS_ONLY_DIRS; - int failed=0; - int folder_depth=0; - char *d,*top,*top2,*root,drv=*cur_dir,*start; - int root_len; - vec_char_t path; - vec_init(&path); - if(strrchr(to,':')) { - switch(toupper(*to)) { - case 'A'...'Z': - drv=toupper(*to); - break; - case ':': - //Use dft drive? - break; - } - to=strrchr(to,':')+1; - } - char drv_buf[2]={drv,0}; - #ifndef TARGET_WIN32 - pthread_mutex_lock(&mp_mtx); - #else - WaitForSingleObject(mp_mtx,INFINITE); - #endif - if(!(root=map_get(&mount_points,drv_buf))) { - vec_deinit(&path); + return 1; + } else if(flags&VFS_CDF_MAKE) { #ifndef TARGET_WIN32 - pthread_mutex_unlock(&mp_mtx); + mkdir(to,0700); #else - ReleaseMutex(mp_mtx); + mkdir(to); #endif - return 0; - } - root=*(char**)root; - root_len=strlen(root); - #ifndef TARGET_WIN32 - pthread_mutex_unlock(&mp_mtx); - #else - ReleaseMutex(mp_mtx); - #endif - vec_pusharr(&path,root,strlen(root)); - if(to[0]==TOS_delim) { - //Is an absolute path - vec_push(&path,0); - } else if(to[0]=='~') { - to++; - root=GetHomeDirForDrive(drv); - vec_pusharr(&path,root,strlen(root)+1); - TD_FREE(root); - } else { - vec_pusharr(&path,cur_dir+2,strlen(cur_dir+2)+1); // +2 for 'drv-letter' and ':' - } - VFsInplaceHostDelims(path.data); - if(make) - if(!__FExists(path.data)) { - #ifndef TARGET_WIN32 - mkdir(path.data,0700); - #else - mkdir(path.data); - #endif - } - loop: - vec_pop(&path); - d=strchr(to,TOS_delim); - if(!d) - d=to+strlen(to); - vec_pusharr(&path,to,d-to); - vec_push(&path,0); - start=strrchr(path.data,delim); - if(start) start++; - else start=path.data; - if(!strcmp(start,".")) { - vec_pop(&path); - vec_pop(&path); - vec_push(&path,0); - goto next; - } else if(!strcmp(start,"..")) { - //Pop a directory item - top=strrchr(path.data,delim); - assert(top); - if(top-1>=path.data){ - //Swap out the delim byte so it doesnt appear while we look the the second-to-last delim - *(top2=top)=0; - top=strrchr(path.data,delim); - *top2=delim; - } - if(RootPathLen()>=top-path.data) { - path.length=RootPathLen(); - vec_push(&path,'/'); - vec_push(&path,0); - goto next; - } else if(top) { - path.length=top-path.data+1; //+1 for delim - vec_push(&path,0); - } - } else - folder_depth++; - vec_pop(&path); - if(path.data[path.length-1]!=delim) - vec_push(&path,delim); - vec_push(&path,0); - if(make) - if(!__FExists(path.data)) { - #ifndef TARGET_WIN32 - mkdir(path.data,0700); - #else - mkdir(path.data); - #endif - } - if(*d) { - next: - if(*d=='/') - to=++d; - else - to=d; - goto loop; - } - vec_pop(&path); - if(path.data[path.length-1]!=delim) - vec_push(&path,delim); - vec_push(&path,0); - failed|=!__FExists(path.data); - failed|=!__FIsDir(path.data); - if(!failed||allow_fail) { - if(static_root!=cur_dir) - HolyFree(cur_dir); - char buffer[4048]; - if(path.data[root_len]!='/') - sprintf(buffer,"%s:/%s",drv_buf,path.data+root_len); - else - sprintf(buffer,"%s:%s",drv_buf,path.data+root_len); - cur_dir=HolyStrDup(buffer); - VFsInplaceConvertDelims(cur_dir); - VFsInplaceRemoveRepeatSlashes(cur_dir); + TD_FREE(to); + return 1; } - vec_deinit(&path); - return !failed||allow_fail; + return 0; } #ifndef TARGET_WIN32 static void DelDir(char *p) { @@ -361,64 +181,16 @@ int64_t VFsDel(char *p) { } //Returns Host OS location of file char *__VFsFileNameAbs(char *name) { - int failed=0,root_len; - char *file,*old_dir=VFsDirCur(),drv=*cur_dir,*root; - if(strrchr(name,':')) { - switch(toupper(*name)) { - case 'A'...'Z': - drv=toupper(*name); - break; - case ':': - //Use dft drive? - break; - } - name=strrchr(name,':')+1; - } - char dbuf[2]={drv,0}; - vec_char_t path,head; - vec_init(&path); - vec_init(&head); - if(name[0]!=TOS_delim&&name[0]!='~') { - vec_pusharr(&path,old_dir,strlen(old_dir)); - vec_push(&path,TOS_delim); - vec_pusharr(&path,name,strlen(name)); - vec_push(&path,0); - } else { - vec_push(&path,drv); - vec_push(&path,':'); - vec_pusharr(&path,name,strlen(name)+1); - } - VFsInplaceHostDelims(path.data); - vec_pusharr(&head,path.data,path.length); - VFsInplaceConvertDelims(head.data); - file=strdup(1+strrchr(head.data,TOS_delim)); - strrchr(head.data,TOS_delim)[1]=0; - failed=!VFsCd(head.data,VFS_CDF_FILENAME_ABS); - vec_deinit(&path); - vec_init(&path); - #ifndef TARGET_WIN32 - pthread_mutex_lock(&mp_mtx); - #else - WaitForSingleObject(mp_mtx,INFINITE); - #endif - vec_pusharr(&path,*map_get(&mount_points,dbuf),strlen(*map_get(&mount_points,dbuf))); - #ifndef TARGET_WIN32 - pthread_mutex_unlock(&mp_mtx); - #else - ReleaseMutex(mp_mtx); - #endif - vec_pusharr(&path,cur_dir+2,strlen(cur_dir+2)); - vec_pusharr(&path,file,strlen(file)); - vec_push(&path,0); - VFsCd(old_dir,0); - end: - vec_deinit(&head); - TD_FREE(file); - VFsInplaceHostDelims(path.data); - if(!failed) - return path.data; - vec_deinit(&path); - return NULL; + char computed[1024]; + //TODO + strcpy(computed,"T"); + computed[strlen(computed)+1]=0; + computed[strlen(computed)]=delim; + strcat(computed,thrd_pwd); + computed[strlen(computed)+1]=0; + computed[strlen(computed)]=delim; + strcat(computed,name); + return strdup(computed); } #ifndef TARGET_WIN32 int64_t VFsUnixTime(char *name) { @@ -494,50 +266,6 @@ int64_t VFsFSize(char *name) { return s64; } #endif -char *VFsFileNameAbs(char *name) { - if(!name) - return VFsDirCur(); - char *tmp=__VFsFileNameAbs(name),*r; - if(!tmp) return NULL; - char buf[strlen(tmp)+1+3]; - int64_t offset=3; - if(tmp) { - if(tmp[0]==TOS_delim) - offset=2; - strcpy(buf+offset,tmp+RootPathLen()); - buf[0]=*cur_dir; - buf[1]=':'; - if(offset==3) - buf[2]=TOS_delim; - return strdup(VFsInplaceConvertDelims(buf)); - } - return NULL; -} -char VFsChDrv(char to) { - char old=*cur_dir,buf[2]={toupper(*cur_dir),0},drv; - switch(toupper(to)) { - case 'A'...'Z': - drv=toupper(to); - goto end; - break; - end: - if(map_get(&drive_dirs,buf)) - TD_FREE(*map_get(&drive_dirs,buf)); - map_set(&drive_dirs,buf,strdup(cur_dir)); - buf[0]=drv; - if(static_root!=cur_dir) - HolyFree(cur_dir); - if(map_get(&drive_dirs,buf)) { - cur_dir=HolyStrDup(*map_get(&drive_dirs,buf)); - } else { - char buf2[1024]; - snprintf(buf2,"%s:/",buf); - VFsInplaceRemoveRepeatSlashes(buf2); - cur_dir=HolyStrDup(buf2); - } - } - return old; -} int64_t VFsFileWrite(char *name,char *data,int64_t len) { FILE *f; name=__VFsFileNameAbs(name); @@ -575,20 +303,6 @@ int64_t VFsFileRead(char *name,int64_t *len) { TD_FREE(name); return data; } -void VFsThrdInit() { - #ifndef TARGET_WIN32 - pthread_mutex_lock(&mp_mtx); - #else - WaitForSingleObject(mp_mtx,INFINITE); - #endif - map_init(&drive_dirs); - cur_dir=static_root; - #ifndef TARGET_WIN32 - pthread_mutex_unlock(&mp_mtx); - #else - ReleaseMutex(mp_mtx); - #endif -} #ifdef TARGET_WIN32 #include <shlobj.h> char *HostHomeDir() { @@ -611,6 +325,28 @@ char *HostHomeDir() { return NULL; } #endif +char **VFsDir(char *fn) { + int64_t sz; + char **ret; + fn=__VFsFileNameAbs(""); + DIR *dir=opendir(fn); + if(!dir) { + TD_FREE(fn); + return NULL; + } + struct dirent *ent; + vec_str_t items; + vec_init(&items); + while(ent=readdir(dir)) + vec_push(&items,HolyStrDup(ent->d_name)); + vec_push(&items,NULL); + TD_FREE(fn); + sz=items.length*sizeof(char*); + ret=memcpy(HolyMAlloc(sz),items.data,sz); + vec_deinit(&items); + closedir(dir); + return ret; +} //Creates a virtual drive by a template static void CopyDir(char *dst,char *src) { if(!__FExists(dst)) { @@ -713,23 +449,25 @@ void CreateTemplateBootDrv(char *to,char *template,int overwrite) { CopyDir(to,buffer2); VFsMountDrive('T',to); } +int VFsIsDir(char *path) { + path=__VFsFileNameAbs(path); + int e=__FIsDir(path); + TD_FREE(path); + return e; +} int VFsFileExists(char *path) { path=__VFsFileNameAbs(path); int e=__FExists(path); TD_FREE(path); return e; } + int VFsMountDrive(char let,char *path) { - char buf[2]={let,0}; - #ifndef TARGET_WIN32 - pthread_mutex_lock(&mp_mtx); - #else - WaitForSingleObject(mp_mtx,INFINITE); - #endif - map_set(&mount_points,buf,strdup(path)); - #ifndef TARGET_WIN32 - pthread_mutex_unlock(&mp_mtx); - #else - ReleaseMutex(mp_mtx); - #endif + //TODO +} +FILE *VFsFOpen(char *path,char *m) { + path=__VFsFileNameAbs(path); + FILE *f=fopen(path,m); + TD_FREE(path); + return f; } |