summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornrootconauto@gmail.com <nrootconauto@gmail.com>2022-10-07 16:15:00 -0400
committernrootconauto@gmail.com <nrootconauto@gmail.com>2022-10-07 16:15:00 -0400
commit99f534380b1c64920f0871a34b147d03234a255a (patch)
treed17578b0b9d3fcae0d0dbae77c424070ef2c13b5
parent77e99bcef0adec6fe3ebb0dcd734c71d1ec72116 (diff)
Reworked File system.
Signed-off-by: nrootconauto@gmail.com <nrootconauto@gmail.com>
-rw-r--r--3d.h2
-rw-r--r--HCRT.BINbin1045856 -> 1103344 bytes
-rw-r--r--T/ADskA.HC (renamed from T/BlkDev/DskA.HC)207
-rw-r--r--T/BlkDev/DskCopy.HC27
-rw-r--r--T/BlkDev2/DskATA.HC107
-rw-r--r--T/BlkDev2/DskATAId.HC36
-rw-r--r--T/BlkDev2/DskAddDev.HC215
-rw-r--r--T/BlkDev2/DskBlk.HC110
-rw-r--r--T/BlkDev2/DskBlkDev.HC173
-rw-r--r--T/BlkDev2/DskCDDVD.HC81
-rw-r--r--T/BlkDev2/DskCFile.HC306
-rw-r--r--T/BlkDev2/DskCache.HC145
-rw-r--r--T/BlkDev2/DskClus.HC145
-rw-r--r--T/BlkDev2/DskCopy.HC107
-rw-r--r--T/BlkDev2/DskDirA.HC213
-rw-r--r--T/BlkDev2/DskDirB.HC201
-rw-r--r--T/BlkDev2/DskDirContext.HC87
-rw-r--r--T/BlkDev2/DskDrv.HC367
-rw-r--r--T/BlkDev2/DskFile.HC127
-rw-r--r--T/BlkDev2/DskFind.HC163
-rw-r--r--T/BlkDev2/DskFmt.HC90
-rw-r--r--T/BlkDev2/DskStrA.HC (renamed from T/DSKSTR.HC)162
-rw-r--r--T/BlkDev2/DskStrB.HC95
-rw-r--r--T/BlkDev2/FileSysFAT.HC959
-rw-r--r--T/BlkDev2/FileSysRedSea.HC635
-rw-r--r--T/BlkDev2/FileSysVirt.HC216
-rw-r--r--T/BlkDev2/MakeBlkDev.HC22
-rw-r--r--T/DSKDIRA.HC144
-rw-r--r--T/DSKFIND.HC377
-rw-r--r--T/FILEMGR.HC14
-rw-r--r--T/FULL_PACKAGE.HC23
-rw-r--r--T/HCRT.DBG.Zbin248694 -> 269220 bytes
-rw-r--r--T/HCRT_TOS.HC110
-rw-r--r--T/JOB.HC18
-rw-r--r--T/KERNELA.HH208
-rw-r--r--T/KTASK.HC16
-rw-r--r--runtime.c155
-rw-r--r--vfs.c386
38 files changed, 5205 insertions, 1244 deletions
diff --git a/3d.h b/3d.h
index 749b51e..15e5d63 100644
--- a/3d.h
+++ b/3d.h
@@ -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*);
diff --git a/HCRT.BIN b/HCRT.BIN
index 914b141..9b187a2 100644
--- a/HCRT.BIN
+++ b/HCRT.BIN
Binary files differ
diff --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
index 4137e45..439cccf 100644
--- a/T/HCRT.DBG.Z
+++ b/T/HCRT.DBG.Z
Binary files differ
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
diff --git a/T/JOB.HC b/T/JOB.HC
index 67af36d..a55cf7c 100644
--- a/T/JOB.HC
+++ b/T/JOB.HC
@@ -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);
diff --git a/T/KTASK.HC b/T/KTASK.HC
index 7699fcd..05094fa 100644
--- a/T/KTASK.HC
+++ b/T/KTASK.HC
@@ -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;
diff --git a/runtime.c b/runtime.c
index 03a70cb..81ca2f1 100644
--- a/runtime.c
+++ b/runtime.c
@@ -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);
diff --git a/vfs.c b/vfs.c
index 06448b0..8a83847 100644
--- a/vfs.c
+++ b/vfs.c
@@ -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;
}