TempleOSTS_140317.ISO

This commit is contained in:
Terry A. Davis authored and minexew committed 2018-09-08 21:46:02 +02:00
1 parent 2d2a65d572
commit 7ef616a20e
1416 files changed
+223873 -53917

No files matched your search

+31
View File
@@ -0,0 +1,31 @@
//See $LK,"::/Doc/Acknowledgements.TXT"$.
#define ATA_NOP 0x00
#define ATA_DEV_RST 0x08
#define ATA_PACKET 0xA0
#define ATA_READ_NATIVE_MAX 0xF8
#define ATA_READ_NATIVE_MAX_EXT 0x27
#define ATA_SET_MAX 0xF9
#define ATA_SET_MAX_EXT 0x37
#define ATA_READ_MULTI 0xC4
#define ATA_READ_MULTI_EXT 0x29
#define ATA_WRITE_MULTI 0xC5
#define ATA_WRITE_MULTI_EXT 0x39
#define ATA_ID_DEV 0xEC
#define ATAS_ERR 0x01
#define ATAS_DRQ 0x08
#define ATAS_DF 0x20
#define ATAS_DRDY 0x40
#define ATAS_BSY 0x80
#define ATAR0_DATA 0
#define ATAR0_FEAT 1
#define ATAR0_NSECT 2
#define ATAR0_SECT 3
#define ATAR0_LCYL 4
#define ATAR0_HCYL 5
#define ATAR0_SELECT 6
#define ATAR0_STAT 7
#define ATAR0_CMD 7
#define ATAR1_CTRL 2
+726
View File
@@ -0,0 +1,726 @@
Bool BlkDevLock(CBlkDev *bdev)
{
BlkDevChk(bdev);
while (bdev->lock_fwding)
bdev=bdev->lock_fwding;
if (!Bt(&bdev->locked_flags,BDlf_LOCKED) || bdev->owning_task!=Fs) {
while (LBts(&bdev->locked_flags,BDlf_LOCKED))
Yield;
bdev->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool PrtLock(CPrt *p)
{
PrtChk(p);
BlkDevLock(p->bdev);
if (!Bt(&p->locked_flags,Plf_LOCKED) || p->owning_task!=Fs) {
while (LBts(&p->locked_flags,Plf_LOCKED))
Yield;
p->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool BlkDevUnlock(CBlkDev *bdev,Bool rst=FALSE)
{
BlkDevChk(bdev);
while (bdev->lock_fwding)
bdev=bdev->lock_fwding;
if (Bt(&bdev->locked_flags,BDlf_LOCKED) && bdev->owning_task==Fs) {
if (rst)
bdev->flags&=~(BDF_INITIALIZED|BDF_INIT_IN_PROGRESS);
bdev->owning_task=NULL;
LBtr(&bdev->locked_flags,BDlf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
Bool PrtUnlock(CPrt *p,Bool rst=FALSE)
{
PrtChk(p);
if (Bt(&p->locked_flags,Plf_LOCKED) && p->owning_task==Fs) {
BlkDevUnlock(p->bdev,rst);
p->owning_task=NULL;
LBtr(&p->locked_flags,Plf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
Bool BlkDevInit(CBlkDev *bdev)
{
CPrt *p=Drv2Prt(bdev->first_drv_let);
Bool old_preempt=Preempt(OFF),result=FALSE;
if (!LBts(&bdev->flags,BDf_INITIALIZED)) {
bdev->flags|=BDF_INIT_IN_PROGRESS;
switch(bdev->type) {
case BDT_RAM:
if (!bdev->RAM_dsk) {
bdev->RAM_dsk=AMAlloc((bdev->max_blk+1)<<BLK_SIZE_BITS);
bdev->max_blk=MSize(bdev->RAM_dsk)>>BLK_SIZE_BITS-1;
}
p->type=PT_REDSEA;
p->size=bdev->max_blk+1;
if (RedSeaFSDrvValidate(bdev->first_drv_let))
RedSeaFSPrtInit(p);
else
RedSeaFSFmt(bdev->first_drv_let);
result=TRUE;
break;
case BDT_ATA:
bdev->max_reads=128;
bdev->max_writes=1;
result=ATAInit(bdev);
break;
case BDT_ATAPI:
//0xFFFF*4 is too big for my taste
bdev->max_reads=0x800*4;
//max of maybe a quarter of disk cache
if (bdev->max_reads>sys_dsk_cache_size/BLK_SIZE/4)
bdev->max_reads=sys_dsk_cache_size/BLK_SIZE/4 & ~3;
if (bdev->max_reads<128)
bdev->max_reads=128;
bdev->max_writes=0xFFFF*4;
if (result=ATAInit(bdev))
p->size=bdev->max_blk+1;
break;
}
if (result && bdev->flags & BDF_READ_CACHE)
DskCacheInvalidate(p);
bdev->flags&=~BDF_INIT_IN_PROGRESS;
} else
result=TRUE;
Preempt(old_preempt);
return result;
}
U0 BlkDevsRelease()
{
I64 i;
CBlkDev *bdev;
for (i=0;i<NUM_BLKDEVS;i++) {
bdev=&sys_blkdevs[i];
if (bdev->owning_task==Fs && bdev->bd_signature==BD_SIGNATURE_VAL)
BlkDevUnlock(bdev,TRUE);
}
}
U0 PrtsRelease()
{
I64 i;
CPrt *p;
for (i=0;i<NUM_PRTS;i++) {
p=&sys_prts[i];
if (p->owning_task==Fs && p->pt_signature==PRT_SIGNATURE_VAL)
PrtUnlock(p,TRUE);
}
}
CPrt *PrtMakeFree(U8 drv_let)
{//!!! drv is not a remapped prt.
I64 i=ToUpper(drv_let)-'A';
CPrt *result;
if (!(0<=i<NUM_PRTS))
throw('Prt');
result=&sys_prts[i];
MemSet(result,0,sizeof(CPrt));
result->drv_let='A'+i;
return result;
}
CPrt *PrtNextFree(U8 first_drv_let='C')
{//!!! first_drv_let is not a remapped prt.
I64 i=ToUpper(first_drv_let)-'A';
if (!(0<=i<NUM_PRTS))
throw('Prt');
do
if (sys_prts[i].pt_signature!=PRT_SIGNATURE_VAL)
return PrtMakeFree(i+'A');
while (++i<NUM_PRTS);
throw('Prt');
return NULL; //never gets here
}
CBlkDev *BlkDevNextFree(U8 first_drv_let,I64 type)
{
I64 i=0;
CBlkDev *result;
do {
result=&sys_blkdevs[i];
if (result->bd_signature!=BD_SIGNATURE_VAL) {
MemSet(result,0,sizeof(CBlkDev));
result->first_drv_let=first_drv_let;
result->type=type;
if (type==BDT_ATAPI)
result->flags=BDF_REMOVABLE;
else
result->flags=0;
if (type!=BDT_RAM)
result->flags|=BDF_READ_CACHE;
if (type==BDT_ATAPI) {
result->blk_size=CD_BLK_SIZE;
result->flags|=BDF_READ_ONLY;
} else
result->blk_size=BLK_SIZE;
result->max_blk=0xEFFFFFFF;
return result;
}
} while (++i<NUM_BLKDEVS);
throw('BlkDev');
return NULL; //never gets here
}
U0 MapBufAlloc(CPrt *p,I64 num_blks)
{
PrtChk(p);
Free(p->cur_map_blk);
Free(p->buffered_map_dirty_bits);
p->num_buffered_map_blks=num_blks;
p->cur_map_blk=AMAlloc(num_blks<<BLK_SIZE_BITS);
p->buffered_map_dirty_bits=ACAlloc((num_blks+7)>>3);
p->cur_map_blk_num=0;
RBlks(p,p->cur_map_blk,p->map1,p->num_buffered_map_blks);
}
U0 CleanMAPBuf(CPrt *p,I64 MAP_select=-1)
{
I64 i;
if ((MAP_select==-1 || !MAP_select) && p->map1!=p->map2)
for (i=0;i<p->num_buffered_map_blks;i++)
if (Bt(p->buffered_map_dirty_bits,i))
WBlks(p,p->cur_map_blk(I64)+i<<BLK_SIZE_BITS,p->map1+i+p->cur_map_blk_num,1);
if (MAP_select==-1 || MAP_select==1 || p->map1==p->map2)
for (i=0;i<p->num_buffered_map_blks;i++)
if (LBtr(p->buffered_map_dirty_bits,i))
WBlks(p,p->cur_map_blk(I64)+i<<BLK_SIZE_BITS,p->map2+i+p->cur_map_blk_num,1);
}
U0 SetFSBuf(CPrt *p,I64 c,I64 map_select=-1)
{
I64 MAP_blk_num;
if (c==INVALID_CLUSTER)
throw('Prt');
if (p->type==PT_FAT32)
MAP_blk_num=c>>(BLK_SIZE_BITS-2);
else
MAP_blk_num=c>>(BLK_SIZE_BITS+3);
if (MAP_blk_num!=p->cur_map_blk_num) {
CleanMAPBuf(p,map_select);
p->cur_map_blk_num=MAP_blk_num;
if (map_select==-1 || !map_select)
RBlks(p,p->cur_map_blk,p->map1+p->cur_map_blk_num,1);
else
RBlks(p,p->cur_map_blk,p->map2+p->cur_map_blk_num,1);
}
}
#define ZERO_BUF_SIZE 2048
U0 WZeroBlks(CPrt *p,I64 blk,I64 cnt)
{
I64 n;
U8 *z=CAlloc(ZERO_BUF_SIZE<<BLK_SIZE_BITS);
Bool show_progress;
if (cnt>ZERO_BUF_SIZE && p->bdev->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;
WBlks(p,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;
}
}
//Very dangerous
Bool SetDrvType(U8 drv_let,I64 type=PT_REDSEA)
{
I64 i,j,ext_base,prt_num,offset,cur_type;
CMasterBoot mbr;
CBlkDev *bdev=Drv2BlkDev(drv_let);
prt_num=bdev->first_drv_let-'A';
switch (bdev->type) {
case BDT_ATA:
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bdev,&mbr,offset,1);
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 (prt_num+'A'==ToUpper(drv_let)) {
switch (type) {
case PT_REDSEA:
mbr.p[i].type=MBR_PT_REDSEA;
break;
case PT_FAT32:
mbr.p[i].type=MBR_PT_FAT32a;
break;
default:
Dbg;
}
mbr.p[i].active=0x80;
ATAWriteBlks(bdev,&mbr,offset,1);
return TRUE;
}
prt_num++;
}
}
}
if (j<0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
break;
}
}
Bool RBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
Bool result=TRUE,unlock;
CBlkDev *bdev=p->bdev;
if (cnt<=0) return TRUE;
PrtChk(p);
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (p->offset && blk<p->offset || blk+cnt>p->offset+p->size)
throw('Prt');
blk+=bdev->offset;
if (bdev->flags & BDF_READ_CACHE)
RCache(p,&buf,&blk,&cnt);
if (cnt>0) {
switch (bdev->type) {
case BDT_RAM:
MemCpy(buf,bdev->RAM_dsk+blk<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
break;
case BDT_ATA:
case BDT_ATAPI:
result=ATARBlks(p,buf,blk,cnt);
break;
}
bdev->last_time=tS;
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,buf,blk,cnt);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
Bool WBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
Bool result=TRUE,unlock;
CBlkDev *bdev=p->bdev;
if (cnt<=0) return TRUE;
PrtChk(p);
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (bdev->flags&BDF_READ_ONLY &&
!(bdev->flags & BDF_READ_ONLY_OVERRIDE))
throw('BlkDev');
if (p->offset && blk<p->offset || blk+cnt>p->offset+p->size)
throw('Prt');
blk+=bdev->offset;
if (cnt>0) {
switch (bdev->type) {
case BDT_RAM:
MemCpy(bdev->RAM_dsk+blk<<BLK_SIZE_BITS,buf,cnt<<BLK_SIZE_BITS);
break;
case BDT_ATA:
case BDT_ATAPI:
result=ATAWBlks(p,buf,blk,cnt);
break;
}
bdev->last_time=tS;
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,buf,blk,cnt);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U0 DskCacheInvalidate(CPrt *p)
{
Bool unlock;
CBlkDev *bdev=p->bdev;
PrtChk(p);
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (bdev->flags & BDF_READ_CACHE)
DskCacheInvalidate2(p);
if (p->type==PT_ISO9660) {
if (!(bdev->flags & BDF_READ_ONLY_OVERRIDE))
ISOPrtInit(p,(32767/bdev->blk_size+1)*
bdev->blk_size>>BLK_SIZE_BITS);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 ChgDsk(U8 drv_let=0)
{ //This is needed for removable media
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
Bool old_preempt=Preempt(OFF);
if (!(bdev->flags&BDF_INITIALIZED))
BlkDevInit(bdev);
else if (bdev->flags&BDF_REMOVABLE)
DskCacheInvalidate(p);
Drv(drv_let);
RedSeaFSFreeFreeLst(p);
Preempt(old_preempt);
}
U8 *DrvSerialNum(U8 drv_let=0)
{ //20 bytes max.
CBlkDev *bdev=Drv2BlkDev(drv_let);
U16 *st,*result=NULL;
I64 i;
if (bdev->dev_id_record) {
st=CAlloc(20+1);
for (i=0;i<10;i++)
st[i]=EndianU16(bdev->dev_id_record[10+i]);
result=MStrUtil(st,SUF_REM_LEADING|SUF_REM_TRAILING);
Free(st);
}
return result;
}
U8 *DrvModelNum(U8 drv_let=0)
{ //40 bytes max.
CBlkDev *bdev=Drv2BlkDev(drv_let);
U16 *st,*result=NULL;
I64 i;
if (bdev->dev_id_record) {
st=CAlloc(40+1);
for (i=0;i<20;i++)
st[i]=EndianU16(bdev->dev_id_record[27+i]);
result=MStrUtil(st,SUF_REM_LEADING|SUF_REM_TRAILING);
Free(st);
}
return result;
}
U0 PrtRep()
{ //Partition report
CPrt *p;
CBlkDev *bdev;
I64 i,drv_let;
U8 *st;
"\nDefined Partitions:\n\n";
for (i=0,p=sys_prts;i<NUM_PRTS;i++,p++) {
if (p->pt_signature==PRT_SIGNATURE_VAL) {
bdev=p->bdev;
drv_let=Prt2Drv(p);
if (Bt(&p->type,PTf_DISABLE))
"$$RED$$X";
else if (drv_let==*sys_acct)
"$$GREEN$$:";
else
'' CH_SPACE;
"$$PURPLE$$%C %-8Z %-9Z %04X %04X %02X$$FG$$\n",
drv_let,p->type.u16[0],"ST_PRT_TYPES",
bdev->type,"ST_BLKDEV_TYPES",bdev->base0,bdev->base1,bdev->unit;
if (st=DrvModelNum(drv_let)) {
" $$CYAN$$Model# :%s$$FG$$\n",st;
Free(st);
}
if (st=DrvSerialNum(drv_let)) {
" $$CYAN$$Serial#:%s$$FG$$\n",st;
Free(st);
}
" %016X-%016X\n",
p->offset,p->offset+p->size-1;
p->offset,p->offset+p->size-1;
}
}
}
I64 ClusterNumNext(CPrt *p,I64 c,I64 cnt=1)
{
Bool unlock;
PrtChk(p);
if (cnt<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_ISO9660:
case PT_REDSEA:
c+=cnt;
break;
case PT_FAT32:
while (cnt-->0 && 0<c<0x0FFFFFF8) {
SetFSBuf(p,c);
c=p->cur_map_blk[c & (BLK_SIZE/4-1)];
}
if (!(0<c<0x0FFFFFF8))
c=INVALID_CLUSTER;
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 Cluster2Blk(CPrt *p,I64 c)
{
PrtChk(p);
return p->data+c*p->spc;
}
I64 RClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks)
{ //This accepts blk count, so padding on last cluster is not read.
I64 i;
Bool unlock;
PrtChk(p);
if (blks<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_ISO9660:
case PT_REDSEA:
RBlks(p,buf,p->data+c*p->spc,blks);
c+=(blks+p->spc-1)/p->spc;
break;
case PT_FAT32:
while (blks && 0<c<0x0FFFFFF8) {
i=blks;
if (i>p->spc)
i=p->spc;
RBlks(p,buf,p->data+c*p->spc,i);
buf+=i<<BLK_SIZE_BITS;
c=ClusterNumNext(p,c,1);
blks-=i;
}
if (blks)
Dbg;
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 RClusters(CPrt *p,U8 *buf,I64 c,I64 cnt)
{
return RClustersBlks(p,buf,c,cnt*p->spc);
}
Bool CFileNameTo(U8 *dst,U8 *src)
{
MemSet(dst,0,CDIR_FILENAME_LEN);
if (!FileNameChk(src))
return FALSE;
StrCpy(dst,src);
return TRUE;
}
I64 Name2DirCluster(CPrt *p,U8 *dirname)
{
Bool cont=TRUE,unlock;
I64 cur_dir_cluster;
CDirEntry de;
U8 *buf=StrNew(dirname),*buf2=StrNew(dirname);
PrtChk(p);
try {
unlock=PrtLock(p);
cur_dir_cluster=p->root_cluster;
while (*buf && cont) {
StrFirstRem(buf,"/",buf2);
if (*buf2) {
switch (p->type) {
case PT_REDSEA:
cont=RedSeaFSFileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case PT_FAT32:
cont=FAT32FileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case PT_ISO9660:
cont=ISO1FileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
default:
Dbg;
}
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
"%s ",dirname;
PrintErr("File not found.\n");
cur_dir_cluster=0;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
Free(buf);
Free(buf2);
return cur_dir_cluster;
}
I64 Name2ParentDirCluster(CPrt *p,U8 *dirname)
{
Bool cont=TRUE,unlock;
I64 cur_dir_cluster,cur_dir_cluster2;
CDirEntry de;
U8 *buf=StrNew(dirname),*buf2=StrNew(dirname);
PrtChk(p);
try {
unlock=PrtLock(p);
cur_dir_cluster=cur_dir_cluster2=p->root_cluster;
while (*buf && cont) {
cur_dir_cluster2=cur_dir_cluster;
StrFirstRem(buf,"/",buf2);
if (*buf2) {
switch (p->type) {
case PT_REDSEA:
cont=RedSeaFSFileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case PT_FAT32:
cont=FAT32FileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case PT_ISO9660:
cont=ISO1FileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
default:
Dbg;
}
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
"%s ",dirname;
PrintErr("File not found.\n");
cur_dir_cluster2=0;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
Free(buf);
Free(buf2);
return cur_dir_cluster2;
}
I64 WClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks)
{ //This accepts blk count, so padding on last cluster is not written.
I64 i;
Bool unlock;
PrtChk(p);
if (blks<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_REDSEA:
WBlks(p,buf,p->data+c*p->spc,blks);
c=0;
break;
case PT_FAT32:
while (blks) {
if (!(0<c<0x0FFFFFF8))
Dbg;
i=blks;
if (i>p->spc)
i=p->spc;
WBlks(p,buf,p->data+c*p->spc,i);
buf+=i<<BLK_SIZE_BITS;
c=ClusterNumNext(p,c);
blks-=i;
}
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 WClusters(CPrt *p,U8 *buf,I64 c,I64 cnt)
{
return WClustersBlks(p,buf,c,cnt*p->spc);
}
//c=0 means first cluster in chain
I64 ClustersAlloc(CPrt *p,I64 c=0,I64 cnt=1,Bool contiguous=FALSE)
{
PrtChk(p);
if (cnt<=0) return c;
switch (p->type) {
case PT_REDSEA:
return RedSeaFSAllocClusters(p,cnt);
case PT_FAT32:
if (contiguous) {
if (c) throw('File');
return FAT32AllocContiguousClusters(p,cnt);
} else
return FAT32AllocClusters(p,c,cnt);
default:
Dbg;
}
}
+489
View File
@@ -0,0 +1,489 @@
Bool MapDrv(U8 drv_let,CPrt *p)
{
drv_let=ToUpper(drv_let);
if ('A'<=drv_let<='Z') {
drv_to_prt[drv_let-'A']=p;
p->drv_let=drv_let;
return TRUE;
} else
return FALSE;
}
Bool Drv(U8 drv_let)
{
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
if (p!=Fs->cur_prt) {
if (bdev->flags & BDF_REMOVABLE && !(bdev->flags & BDF_INITIALIZED))
ChgDsk(Prt2Drv(p));
if (bdev->type==BDT_RAM)
BlkDevInit(bdev);
}
Fs->cur_prt=p;
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
switch (p->type) {
case PT_REDSEA:
case PT_FAT32:
case PT_ISO9660:
return TRUE;
default:
PrintErr("File System Not Supported\n");
return FALSE;
}
}
Bool Cd(U8 *dirname,Bool make_dirs=FALSE)
{//Optionally, will create the directories if they don't exist.
I64 maxlen,cur_dir_cluster=0;
U8 *chg_to_buf,*new_cur_dir,*buf;
CPrt *p;
Bool result=TRUE;
if (!*dirname)
return TRUE;
if (dirname[1]==':') {
if (*dirname==':') {
if (Fs->cur_prt->drv_let!=*sys_acct && !Drv(*dirname))
return FALSE;
} else if (Fs->cur_prt!=Drv2Prt(*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 && result) {
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,".") && *buf) {
if (!StrCmp(buf,"HOME")) {
result=Cd(sys_acct);
Free(new_cur_dir);
new_cur_dir=MAlloc(maxlen+StrLen(sys_acct));
StrCpy(new_cur_dir,sys_acct+2);
} else {
p=Fs->cur_prt;
cur_dir_cluster=Name2DirCluster(p,new_cur_dir);
switch (p->type) {
case PT_REDSEA:
result=RedSeaFSCd(buf,cur_dir_cluster);
break;
case PT_FAT32:
result=FAT32Cd(buf,cur_dir_cluster);
break;
case PT_ISO9660:
result=ISO1Cd(buf,cur_dir_cluster);
break;
default:
PrintErr("File System Not Supported\n");
result=FALSE;
}
if (!result && make_dirs) {
Free(Fs->cur_dir);
Fs->cur_dir=StrNew(new_cur_dir);
result=MkDir(buf);
}
if (result) {
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 result;
}
U0 FileAccessDel(CFileAccess *fa)
{
CBlkDev *bdev;
if (!fa) return;
bdev=fa->old_prt->bdev;
if (!(bdev->flags & BDF_INIT_IN_PROGRESS)) {
if (fa->old_dir) {
Drv(Prt2Drv(fa->old_prt));
Cd(fa->old_dir);
}
} else {
Fs->cur_prt=fa->old_prt;
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
}
Free(fa->old_dir);
Free(fa->mask);
Free(fa);
}
CFileAccess *FileAccessNew(U8 *_mask,Bool make_mask=FALSE,Bool make_dirs=FALSE,Bool no_mask=FALSE)
{
Bool valid=TRUE,old_silent;
U8 *buf,*mask,*temp_mask;
CFileAccess *fa=CAlloc(sizeof(CFileAccess));
mask=MStrUtil(_mask,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_mask=mask;
fa->old_dir=StrNew(Fs->cur_dir);
fa->old_prt=Fs->cur_prt;
if (*mask && mask[1]==':') {
if (Fs->cur_prt!=Drv2Prt(*mask) && !Drv(*mask))
valid=FALSE;
mask+=2;
}
if (StrMatch("HOME",mask) && Fs->cur_prt!=Drv2Prt(*sys_acct))
Drv(*sys_acct);
fa->p=Fs->cur_prt;
PrtChk(fa->p);
buf=MAlloc(StrLen(mask)+2);
StrCpy(buf,mask);
fa->mask=MAlloc(StrLen(mask)+2);
if (no_mask)
*fa->mask=0;
else
StrLastRem(buf,"/",fa->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 (!*fa->mask) {
Free(fa->mask);
fa->mask=StrNew("*");
} else {
if (!make_dirs || FileNameChk(fa->mask)) {
old_silent=Silent(ON);
//Try mask to see if Dir. If Dir, change to dir and set to "*".
if (Cd(fa->mask,make_dirs)) {
Free(fa->mask);
fa->mask=StrNew("*");
}
Silent(old_silent);
}
}
}
Free(buf);
Free(temp_mask);
if (!valid) {
FileAccessDel(fa);
fa=NULL;
// throw('File');
}
return fa;
}
CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0)
{
/*
Flags:
$LK,"FUF_RECURSE",A="MN:FUF_RECURSE"$ +r Recurse
$LK,"FUF_SINGLE",A="MN:FUF_SINGLE"$ +s Single File (Optimization for one file in mask.)
$LK,"FUF_FLATTEN_TREE",A="MN:FUF_FLATTEN_TREE"$ +f $BK,1$use with '+F'$BK,0$. Just use +F, probably.
$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$ +D just directories
$LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$ +F just files (Flattens trees)
$LK,"FUF_CLUSTER_ORDER",A="MN:FUF_CLUSTER_ORDER"$ +O sort by cluster (move head one direction)
$LK,"FUF_JUST_TXT",A="MN:FUF_JUST_TXT"$ +T just text files : $LK,"FILEMASK_TXT",A="MN:FILEMASK_TXT"$
$LK,"FUF_JUST_SRC",A="MN:FUF_JUST_SRC"$ +S just src files : $LK,"FILEMASK_SRC",A="MN:FILEMASK_SRC"$
$LK,"FUF_JUST_AOT",A="MN:FUF_JUST_AOT"$ +A just aot files : $LK,"FILEMASK_AOT",A="MN:FILEMASK_AOT"$
$LK,"FUF_JUST_JIT",A="MN:FUF_JUST_JIT"$ +J just jit files : $LK,"FILEMASK_JIT",A="MN:FILEMASK_JIT"$
$LK,"FUF_JUST_GRA",A="MN:FUF_JUST_GRA"$ +G just graphic files : $LK,"FILEMASK_GRA",A="MN:FILEMASK_GRA"$
See $LK,"ST_FILE_UTIL_FLAGS",A="MN:ST_FILE_UTIL_FLAGS"$ when used in calling program taking text flags.
*/
CDirEntry *result;
CFileAccess *fa;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
if (fuf_flags&FUF_SINGLE) {
result=MAlloc(sizeof(CDirEntry));
if (!FileFind(files_find_mask,result)) {
Free(result);
return NULL;
}
} else if (fa=FileAccessNew(files_find_mask,TRUE)) {
result=SysFilesFind(fa->mask,fuf_flags);
FileAccessDel(fa);
} else
return NULL;
return result;
}
Bool IsDir(U8 *dir_name)
{
U8 *mask=MPrint("%s/*",dir_name);
Bool result,old_silent=Silent(ON);
CFileAccess *fa;
if (fa=FileAccessNew(mask)) {
FileAccessDel(fa);
result=TRUE;
} else
result=FALSE;
Free(mask);
Silent(old_silent);
return result;
}
I64 Dir(U8 *files_find_mask="*",Bool full=FALSE)
{
I64 result;
CFileAccess *fa;
if (fa=FileAccessNew(files_find_mask,TRUE)) {
result=Dir2(fa->mask,0,full);
FileAccessDel(fa);
return result;
} else
return 0;
}
I64 Del(U8 *files_find_mask,Bool print_msg=TRUE)
{
I64 result=0;
CFileAccess *fa;
if (fa=FileAccessNew(files_find_mask)) {
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFilesDel(fa->p,Fs->cur_dir,fa->mask,0,FALSE,print_msg);
break;
case PT_FAT32:
result=FAT32FilesDel(fa->p,Fs->cur_dir,fa->mask,0,FALSE,print_msg);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
FileAccessDel(fa);
}
return result;
}
U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL,Bool raw=FALSE)
{
CHashGeneric *temph;
U8 *absname,*altname,*curname,*result=NULL;
I64 i,size=0,attr=0;
CFileAccess *fa;
CArcCompress *ac;
absname=FileNameAbs(filename);
altname=ToggleZorNotZ(absname);
if (!raw && ((temph=HashFind(absname,adam_task->hash_table,HTT_FILE))||
(temph=HashFind(altname,adam_task->hash_table,HTT_FILE)))) {
size=temph->user_data1;
result=MAlloc(size+1);
MemCpy(result,temph->user_data0,size);
result[size]=0; //Terminate
attr=FileAttr(temph->str,attr);
} else {
for (i=0;i<2 && !result;i++) {//Try name, then altname
if (!i)
curname=absname;
else
curname=altname;
if (fa=FileAccessNew(curname)) {
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
case PT_FAT32:
result=FAT32FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
case PT_ISO9660:
result=ISO1FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
default:
PrintErr("File System Not Supported\n");
}
FileAccessDel(fa);
}
}
//Search parent directories.
for (i=0;i<2 && !result;i++) {//Try name, then altname
if (!i)
curname=absname;
else
curname=altname;
if (fa=FileAccessNew(curname)) {
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
switch (Fs->cur_prt->type) {
case PT_REDSEA:
result=RedSeaFSFileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
case PT_FAT32:
result=FAT32FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
case PT_ISO9660:
result=ISO1FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
default:
PrintErr("File System Not Supported\n");
}
}
FileAccessDel(fa);
}
}
if (!result) {
"%s ",filename;
PrintErr("File not found.\n");
}
if (result && !raw && attr & _ATTR_RESIDENT)
HashGenericAdd(curname,HTT_FILE,AMAllocIdentical(result),size,0,adam_task);
}
if (result && !raw && attr & _ATTR_COMPRESSED) {
ac=result;
size=ac->expanded_size;
result=ExpandBuf(ac);
Free(ac);
}
if (_attr) *_attr=attr;
if (_size) *_size=size;
Free(absname);
Free(altname);
return result;
}
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_cluster;
U8 *altname,*curname,*full_name=NULL;
CDirEntry de;
CFileAccess *fa;
Bool result=FALSE;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
if (!filename) return FALSE;
altname=ToggleZorNotZ(filename);
if (fuf_flags&FUF_Z_OR_NOT_Z)
j=2;
else
j=1;
for (i=0;i<j && !result;i++) {
if (!i)
curname=filename;
else
curname=altname;
if (fa=FileAccessNew(curname)) {
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
case PT_FAT32:
result=FAT32FileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
case PT_ISO9660:
result=ISO1FileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
}
if (result && _de)
full_name=MPrint("%C:%s/%s",Fs->cur_prt->drv_let,Fs->cur_dir,de.name);
FileAccessDel(fa);
}
}
for (i=0;i<j && !result && fuf_flags&FUF_SCAN_PARENTS;i++) {
if (!i)
curname=filename;
else
curname=altname;
if (fa=FileAccessNew(curname)) {
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
case PT_FAT32:
result=FAT32FileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
case PT_ISO9660:
result=ISO1FileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
}
}
if (result && _de)
full_name=MPrint("%C:%s/%s",Fs->cur_prt->drv_let,Fs->cur_dir,de.name);
FileAccessDel(fa);
}
}
if (_de) {
if (result) {
MemCpy(_de,&de,sizeof(CDirEntry));
_de->full_name=full_name;
} else
MemSet(_de,0,sizeof(CDirEntry));
}
Free(altname);
return result;
}
I64 FileWrite(U8 *filename,U8 *fbuf,
I64 size,CDate cdt=0,I64 attr=0,Bool raw=FALSE)
{
I64 c=0;
CHashGeneric *temph;
CFileAccess *fa;
U8 *fbuf2,*absname=FileNameAbs(filename);
if (fa=FileAccessNew(filename,FALSE,TRUE)) {
attr=FileAttr(fa->mask,attr);
if (attr&_ATTR_COMPRESSED && !raw) {
fbuf=CompressBuf(fbuf,size);
size=fbuf(CArcCompress *)->compressed_size;
fbuf2=fbuf;
} else
fbuf2=NULL;
if (!cdt) cdt=Now;
switch (fa->p->type) {
case PT_REDSEA:
c=RedSeaFSFileWrite(fa->p,Fs->cur_dir,fa->mask,fbuf,size,cdt,attr);
break;
case PT_FAT32:
c=FAT32FileWrite(fa->p,Fs->cur_dir,fa->mask,fbuf,size,cdt,attr);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
if (temph=HashFind(absname,adam_task->hash_table,HTT_FILE)) {
if (!raw && attr & _ATTR_RESIDENT) {
Free(temph->user_data0);
temph->user_data0=AMAllocIdentical(fbuf);
temph->user_data1=size;
} else
HashRemDel(temph,adam_task->hash_table);
} else if (!raw && attr & _ATTR_RESIDENT)
HashGenericAdd(absname,HTT_FILE,AMAllocIdentical(fbuf),size,0,adam_task);
Free(fbuf2);
FileAccessDel(fa);
}
Free(absname);
return c;
}
+361
View File
@@ -0,0 +1,361 @@
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.\n");
} else
PrintErr("File not found.\n");
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 & _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 & _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;
}
FRBlks(in_file, buf,FFB_NEXT_BLK,n);
FWBlks(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.\n");
FClose(in_file);
} else
PrintErr("File not found.\n");
Free(buf);
return FALSE;
}
Bool MkDir(U8 *filename)
{
U8 *name;
CFileAccess *fa;
Bool result=FALSE;
if (FileFind(filename,,FUF_JUST_DIRS))
return FALSE;
if (fa=FileAccessNew(filename)) {
if (*fa->mask) {
if (!FileNameChk(fa->mask))
PrintErr("Invalid FileName.\n");
else {
"Make Directory:%s\n",filename;
name=MStrUtil(fa->mask,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSMkDir(fa->p,Fs->cur_dir,name);
break;
case PT_FAT32:
result=FAT32MkDir(fa->p,Fs->cur_dir,name);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
Free(name);
}
}
FileAccessDel(fa);
}
return result;
}
I64 SysDel(U8 *wild,Bool make_mask) //this is dangerous
{
I64 result=0;
CFileAccess *fa;
if (fa=FileAccessNew(wild,make_mask)) {
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFilesDel(fa->p,Fs->cur_dir,fa->mask,0,TRUE,TRUE);
break;
case PT_FAT32:
result=FAT32FilesDel(fa->p,Fs->cur_dir,fa->mask,0,TRUE,TRUE);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
FileAccessDel(fa);
}
return result;
}
U0 Fmt(I64 drv_let,Bool quick=TRUE,Bool confirm=TRUE,I64 type=PT_FAT32)
{//See $LK,"PT_FAT32",A="MN:PT_FAT32"$ for a lst of supported file system types.
CPrt *p=Drv2Prt(drv_let);
Bool old_silent=IsSilent;
if (confirm && !AreYouSure)
return;
if (!p) {
PrintErr("Invalid Drive\n");
return;
}
switch (type) {
case PT_REDSEA:
Silent(ON);
Drv(drv_let);
Silent(old_silent);
RedSeaFSFmt(drv_let,quick);
DskCacheInvalidate(Drv2Prt(drv_let));
Drv(drv_let);
break;
case PT_FAT32:
Silent(ON);
Drv(drv_let);
Silent(old_silent);
FAT32Fmt(drv_let,quick);
DskCacheInvalidate(Drv2Prt(drv_let));
Drv(drv_let);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
}
U0 CDImageRead(U8 cd_drv_let,U8 *out_name)
{
CBlkDev *bdev=Drv2BlkDev(cd_drv_let);
CPrt *p=Drv2Prt(cd_drv_let);
U8 *buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS),
*out_name2=DftExt(out_name,"ISO");
CFile *f=FOpen(out_name2,"w");
I64 n,spc=bdev->blk_size>>BLK_SIZE_BITS,blk=0,cnt,retry;
BlkDevInit(bdev);
if (bdev->type!=BDT_ATAPI)
throw('BlkDev');
if (!out_name)
out_name=sys_dft_iso_name;
cnt=CeilU64(p->size,spc);
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
retry=4;
while (--retry)
if (ATAPIReadBlks2(bdev,tS+7.0+0.004*n/spc,buf,blk/spc,n/spc,TRUE))
//n is 0x800 if max_reads. Up to 8 additional seconds
break;
if (!retry)
ATAPIReadBlks2(bdev,0,buf,blk/spc,n/spc,TRUE);
FWBlks(f,buf,blk,n);
cnt-=n;
blk+=n;
}
FClose(f);
Free(buf);
Free(out_name2);
}
class CDualBuf
{
U8 *buf0,*buf1;
I64 in_buf,out_buf,cnt;
U8 *filename;
CBlkDev *CD_bdev;
};
U0 CDImageWriteTask(CDualBuf *d)
{
U8 *buf;
I64 n,blk=0,cnt=d->cnt;
CFile *f;
Preempt(ON);
if (FileAttr(d->filename)&_ATTR_CONTIGUOUS)
f=FOpen(d->filename,"rc");
else
f=FOpen(d->filename,"r");
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>d->CD_bdev->max_writes)
n=d->CD_bdev->max_writes;
if (d->in_buf&1)
buf=d->buf1;
else
buf=d->buf0;
while (d->in_buf>d->out_buf+1)
Yield;
FRBlks(f,buf,blk,n);
d->in_buf++;
cnt-=n;
blk+=n;
}
FClose(f);
}
U0 CDImageWrite(U8 cd_drv_let,U8 *in_name=NULL,I64 media_type=MT_CD)
{
CDualBuf *d=CAlloc(sizeof(CDualBuf));
U8 *buf,*in_name2,*in_name3;
I64 i,n,spc,blk=0,cnt;
CPrt *p=Drv2Prt(cd_drv_let);
CBlkDev *bdev=p->bdev,*bdev2;
CTask *task;
Bool old_preempt;
CFile *f;
if (!in_name)
in_name=sys_dft_iso_name;
in_name3=DftExt(in_name,"ISO");
in_name2=FileNameAbs(in_name3);
f=FOpen(in_name2,"r");
if (!f) {
Free(d);
return;
}
cnt=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS;
FClose(f);
if (bdev->type!=BDT_ATAPI)
throw('BlkDev');
bdev2=Drv2BlkDev(*in_name2);
while (bdev2->lock_fwding)
bdev2=bdev2->lock_fwding;
if ((bdev2->type==BDT_ATA || bdev2->type==BDT_ATAPI) &&
bdev2->base0==bdev->base0) {
"Can't Burn CD on same ATA ctrller as File.\n\n";
throw('BlkDev');
}
bdev->flags|=BDF_READ_ONLY_OVERRIDE;
BlkDevInit(bdev);
spc=bdev->blk_size>>BLK_SIZE_BITS;
if (p->size<cnt)
p->size=cnt;
d->filename=in_name2;
d->CD_bdev=bdev;
d->buf0=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->buf1=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->cnt=cnt;
old_preempt=Preempt(OFF);
task=Spawn(&CDImageWriteTask,d,"Write CD");
while (d->in_buf<=d->out_buf)
Yield;
BlkDevLock(bdev);
ATAPIWaitReady(bdev,0);
progress1=0; progress1_max=cnt;
StrCpy(progress1_desc,"Writing");
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
if (d->out_buf&1)
buf=d->buf1;
else
buf=d->buf0;
while (d->in_buf<=d->out_buf)
Yield;
ATAPIWriteBlks(bdev,buf,blk/spc,(n+spc-1)/spc);
d->out_buf++;
cnt-=n;
blk+=n;
progress1+=n;
}
ATAPISync(bdev);
progress1=0; progress1_max=2;
StrCpy(progress1_desc,"Closing");
for (i=0;i<2;i++) {
ATAPIClose(bdev,0x100,i); //Close tracks
progress1++;
}
ATAPISync(bdev);
ATAPIClose(bdev,0x200); //close disk
ATAPISync(bdev);
if (media_type==MT_DVD) {
ATAPIClose(bdev,0x300);
ATAPISync(bdev);
}
*progress1_desc=0;
progress1=progress1_max=0;
bdev->flags&=~BDF_READ_ONLY_OVERRIDE;
BlkDevUnlock(bdev);
Free(d->buf0);
Free(d->buf1);
Free(in_name2);
Free(in_name3);
Preempt(old_preempt);
Free(d);
}
+887
View File
@@ -0,0 +1,887 @@
U0 ATABlkSelect(CBlkDev *bdev,I64 blk,I64 cnt)
{
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
if (bdev->flags & BDF_EXT_SIZE) {
OutU8(bdev->base0+ATAR0_NSECT,cnt.u8[1]);
OutU8(bdev->base0+ATAR0_SECT,blk.u8[3]);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[4]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[5]);
OutU8(bdev->base0+ATAR0_NSECT,cnt);
OutU8(bdev->base0+ATAR0_SECT,blk);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[1]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[2]);
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
} else {
OutU8(bdev->base0+ATAR0_NSECT,cnt);
OutU8(bdev->base0+ATAR0_SECT,blk);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[1]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[2]);
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4|blk.u8[3]);
}
}
Bool ATAWaitNotBUSY(CBlkDev *bdev,F64 timeout)
{
I64 i;
do {
for (i=0;i<3;i++)
if (!(InU8(bdev->base0+ATAR0_STAT)&ATAS_BSY))
return TRUE;
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
Bool ATAWaitDRQ(CBlkDev *bdev,F64 timeout)
{
I64 i;
do {
for (i=0;i<3;i++)
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_DRQ)
return TRUE;
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
Bool ATANop(CBlkDev *bdev,F64 timeout)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_CMD,ATA_NOP);
return ATAWaitNotBUSY(bdev,timeout);
}
U0 ATACmd(CBlkDev *bdev,U8 cmd)
{
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_CMD,cmd);
bdev->last_time=tS;
PortNop;
}
Bool ATAGetResult(CBlkDev *bdev,F64 timeout,U8 *buf,I64 cnt,I64 _avail,Bool one_read)
{
I64 avail,overflow;
bdev->flags&=~BDF_LAST_WAS_WRITE;
MemSet(buf,0,cnt);
while (cnt>0) {
if (!ATAWaitDRQ(bdev,timeout))
return FALSE;
if (_avail)
avail=_avail;
else
avail=InU8(bdev->base0+ATAR0_HCYL)<<8+InU8(bdev->base0+ATAR0_LCYL);
if (avail) {
if (avail>cnt) {
overflow=avail-cnt;
avail=cnt;
} else
overflow=0;
if (avail&2)
RepInU16(buf,avail>>1,bdev->base0+ATAR0_DATA);
else
RepInU32(buf,avail>>2,bdev->base0+ATAR0_DATA);
cnt-=avail;
buf+=avail;
while (overflow>0) {
InU16(bdev->base0+ATAR0_DATA);
overflow-=2;
if (0<timeout<tS)
return FALSE;
}
if (one_read)
break;
} else
Yield;
}
return ATAWaitNotBUSY(bdev,timeout);
}
Bool ATAPIWritePktWord(CBlkDev *bdev,F64 timeout,...)
{
I64 i;
for (i=0;i<argc;i++) {
if (!ATAWaitDRQ(bdev,timeout))
return FALSE;
OutU16(bdev->base0+ATAR0_DATA,EndianU16(argv[i]));
bdev->last_time=tS;
}
return TRUE;
}
Bool ATAPISetMaxSpeed(CBlkDev *bdev)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0xBB00,0xFFFF,0xFFFF,0,0,0);
return ATAWaitNotBUSY(bdev,0);
}
Bool ATAPISeek(CBlkDev *bdev,I64 native_blk)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x2B00,native_blk>>16,native_blk,0,0,0);
return ATAWaitNotBUSY(bdev,0);
}
Bool ATAPIStartStop(CBlkDev *bdev,F64 timeout,Bool start)
{
I64 i;
if (start)
i=0x100;
else
i=0;
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_PACKET);
//Start/Stop
if (ATAPIWritePktWord(bdev,timeout,0x1B00,0,i,0,0,0))
return ATAWaitNotBUSY(bdev,timeout);
else
return FALSE;
}
I64 ATAGetDevId(CBlkDev *bdev,F64 timeout,U16 **_id_record)
{
U16 *id_record;
if (_id_record) *_id_record=NULL;
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_ID_DEV);
if (!ATAWaitNotBUSY(bdev,timeout))
return BDT_NULL;
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_ERR)
return BDT_ATAPI;
id_record=ACAlloc(512);
if (!ATAGetResult(bdev,timeout,id_record,512,512,FALSE)) {
Free(id_record);
return BDT_NULL;
}
if (_id_record) *_id_record=id_record;
return BDT_ATA;
}
I64 ATAReadNativeMax(CBlkDev *bdev,F64 timeout)
{ //returns zero on err
I64 result=0;
Bool okay=TRUE;
if (bdev->type==BDT_ATAPI) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_DEV_RST);
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
} else {
while (InU8(bdev->base0+ATAR0_STAT) & ATAS_BSY) {
if (bdev->flags&BDF_LAST_WAS_WRITE)
OutU16(bdev->base0+ATAR0_DATA,0);
else
InU16(bdev->base0+ATAR0_DATA);
Yield;
if (0<timeout<tS)
return FALSE;
}
Free(bdev->dev_id_record);
if (ATAGetDevId(bdev,timeout,&bdev->dev_id_record)==BDT_NULL)
okay=FALSE;
else
BEqu(&bdev->flags,BDf_EXT_SIZE,Bt(&bdev->dev_id_record[86],10));
}
if (okay) {
if (bdev->flags & BDF_EXT_SIZE && bdev->base1) {
OutU8(bdev->base1+ATAR1_CTRL,0x8);
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
ATACmd(bdev,ATA_READ_NATIVE_MAX_EXT);
if (ATAWaitNotBUSY(bdev,timeout)) {
result.u8[0]=InU8(bdev->base0+ATAR0_SECT);
result.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
result.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
OutU8(bdev->base1+ATAR1_CTRL,0x80);
result.u8[3]=InU8(bdev->base0+ATAR0_SECT);
result.u8[4]=InU8(bdev->base0+ATAR0_LCYL);
result.u8[5]=InU8(bdev->base0+ATAR0_HCYL);
if (result>>24==result&0xFFFFFF) {//Kludge to make qemu-kvm work
bdev->flags&=~BDF_EXT_SIZE;
result&=0xFFFFFF;
}
}
} else {
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_READ_NATIVE_MAX);
if (ATAWaitNotBUSY(bdev,timeout)) {
result.u8[0]=InU8(bdev->base0+ATAR0_SECT);
result.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
result.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
result.u8[3]=InU8(bdev->base0+ATAR0_SELECT) & 0xF;
}
}
}
return bdev->max_blk=result;
}
I64 ATAPIReadCapacity(CBlkDev *bdev,I64 *_blk_size=NULL)
{ //Supposedly this can return a result +/- 75 sects.
//Error might just be for music.
Bool unlock=BlkDevLock(bdev);
U32 buf[2];
if (ATAWaitNotBUSY(bdev,0)) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,8);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x2500,0,0,0,0,0);
if (!ATAGetResult(bdev,0,buf,8,0,TRUE))
buf[0]=buf[1]=0;
} else
buf[0]=buf[1]=0;
if (unlock) BlkDevUnlock(bdev);
if (_blk_size) *_blk_size=EndianU32(buf[1]);
return EndianU32(buf[0]);
}
CATAPITrack *ATAPIReadTrackInfo(CBlkDev *bdev,I64 blk)
{
CATAPITrack *result=CAlloc(sizeof(CATAPITrack));
Bool unlock=BlkDevLock(bdev);
if (ATAWaitNotBUSY(bdev,0)) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,sizeof(CATAPITrack)&0xFF);
OutU8(bdev->base0+ATAR0_HCYL,sizeof(CATAPITrack)>>8);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x5200,blk.u16[1],blk.u16[0],
(sizeof(CATAPITrack)&0xFF00)>>8,(sizeof(CATAPITrack)&0x00FF)<<8,0);
if (!ATAGetResult(bdev,0,result,sizeof(CATAPITrack),0,TRUE)) {
Free(result);
result=NULL;
}
} else {
Free(result);
result=NULL;
}
if (unlock) BlkDevUnlock(bdev);
return result;
}
Bool ATAInit(CBlkDev *bdev)
{
Bool unlock=BlkDevLock(bdev),okay=FALSE;
if (bdev->type==BDT_ATAPI)
bdev->flags&=~BDF_EXT_SIZE;
else
bdev->flags|=BDF_EXT_SIZE;
if (ATAReadNativeMax(bdev,tS+0.1)) {
ATABlkSelect(bdev,bdev->max_blk,0);
if (bdev->flags&BDF_EXT_SIZE)
ATACmd(bdev,ATA_SET_MAX_EXT);
else
ATACmd(bdev,ATA_SET_MAX);
if (ATAWaitNotBUSY(bdev,0)) {
okay=TRUE;
if (bdev->type==BDT_ATAPI) {
if (ATAPIStartStop(bdev,0,TRUE)) {
if(!ATAPISetMaxSpeed(bdev))
okay=FALSE;
} else
okay=FALSE;
}
}
}
if (unlock) BlkDevUnlock(bdev);
return okay;
}
Bool ATAPIWaitReady(CBlkDev *bdev,F64 timeout)
{
do {
if (!ATAWaitNotBUSY(bdev,timeout) ||
!ATANop(bdev,timeout) ||
!ATAPIStartStop(bdev,timeout,TRUE))
return FALSE;
if (InU8(bdev->base0+ATAR0_STAT) & ATAS_DRDY &&
!InU8(bdev->base0+ATAR0_FEAT));
return TRUE;
ATAInit(bdev);
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
U0 ATAReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
I64 retries=3;
Bool unlock=BlkDevLock(bdev);
retry:
ATABlkSelect(bdev,blk,cnt);
if (bdev->flags & BDF_EXT_SIZE)
ATACmd(bdev,ATA_READ_MULTI_EXT);
else
ATACmd(bdev,ATA_READ_MULTI);
if (!ATAGetResult(bdev,tS+1.0,buf,cnt*bdev->blk_size,BLK_SIZE,FALSE)) {
if (retries--) {
ATAWaitNotBUSY(bdev,0);
goto retry;
} else
throw('BlkDev');
}
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
if (unlock) BlkDevUnlock(bdev);
}
I64 ATAProbe(I64 base0,I64 base1,I64 unit)
{
CBlkDev bdev;
MemSet(&bdev,0,sizeof(CBlkDev));
bdev.type=BDT_ATAPI;
bdev.base0=base0;
bdev.base1=base1;
bdev.unit=unit;
bdev.blk_size=CD_BLK_SIZE;
return ATAGetDevId(&bdev,tS+0.1,NULL);
}
Bool ATAPIReadBlks2(CBlkDev *bdev,F64 timeout,U8 *buf, I64 native_blk, I64 cnt,Bool lock)
{
Bool result=FALSE,unlock;
if (cnt<=0)
return FALSE;
if (lock)
unlock=BlkDevLock(bdev);
if (ATAPIWaitReady(bdev,timeout)) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
ATACmd(bdev,ATA_PACKET);
if (ATAPIWritePktWord(bdev,timeout,0xA800,
native_blk.u16[1],native_blk,cnt.u16[1],cnt,0) &&
ATAGetResult(bdev,timeout,buf,cnt*bdev->blk_size,0,FALSE)) {
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
result=TRUE;
}
}
// ATAPIStartStop(bdev,0,FALSE);
if (lock && unlock) BlkDevUnlock(bdev);
return result;
}
U0 ATAPIReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
CPrt *p=Drv2Prt(bdev->first_drv_let);
I64 retry,spc=bdev->blk_size>>BLK_SIZE_BITS,n,blk2,
l2=bdev->max_reads<<1+spc<<1;
U8 *cd_buf=MAlloc(l2<<BLK_SIZE_BITS);
if (cnt>0) {
if (blk<=bdev->max_reads)
blk2=0;
else
blk2=FloorU64(blk-bdev->max_reads,spc);
if (blk2+l2>p->size)
l2=p->size-blk2;
n=(l2+spc-1)/spc;
retry=4;
while (--retry)
if (ATAPIReadBlks2(bdev,tS+7.0+0.004*n,cd_buf,blk2/spc,n,TRUE))
//n is 0x800 if max_reads. Up to 8 additional seconds
break;
if (!retry)
ATAPIReadBlks2(bdev,0,cd_buf,blk2/spc,n,TRUE);
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,cd_buf,blk2,n*spc);
MemCpy(buf,cd_buf+(blk-blk2)<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
}
Free(cd_buf);
}
Bool ATARBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
I64 n;
CBlkDev *bdev=p->bdev;
while (cnt>0) {
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
if (bdev->type==BDT_ATAPI)
ATAPIReadBlks(bdev,buf,blk,n);
else
ATAReadBlks(bdev,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
}
return TRUE;
}
//This is for low level disk access
//Call WBlks() instead
U0 ATAWriteBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
I64 i,U32s_avail,sects_avail,retries=3;
F64 timeout;
Bool unlock=BlkDevLock(bdev);
retry:
ATABlkSelect(bdev,blk,cnt);
if (bdev->flags&BDF_EXT_SIZE)
ATACmd(bdev,ATA_WRITE_MULTI_EXT);
else
ATACmd(bdev,ATA_WRITE_MULTI);
bdev->flags|=BDF_LAST_WAS_WRITE;
while (cnt>0) {
timeout=tS+1.0;
while (TRUE) {
i=InU8(bdev->base0+ATAR0_STAT);
if (!(i & ATAS_DRDY)||!(i & ATAS_DRQ)) {
Yield;
} else
break;
if (/* i&ATAS_ERR||*/ tS>timeout) {
if (retries--) {
ATAWaitNotBUSY(bdev,0);
goto retry;
} else
throw('BlkDev');
}
}
sects_avail=1;
U32s_avail=sects_avail<<BLK_SIZE_BITS>>2;
RepOutU32(buf,U32s_avail,bdev->base0+ATAR0_DATA);
buf+=U32s_avail<<2;
cnt-=sects_avail;
retries=3;
}
ATAWaitNotBUSY(bdev,0);
if (unlock) BlkDevUnlock(bdev);
}
Bool ATAPISync(CBlkDev *bdev)
{
Bool okay=TRUE;
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
else {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x3500,0,0,0,0,0);
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
}
return okay;
}
U0 ATAPIClose(CBlkDev *bdev,I64 close_field=0x200,I64 track=0)
{
//0x200 CD/DVD part 1
//0x300 DVD part 2
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x5B00,close_field,track,0,0,0);
ATAWaitNotBUSY(bdev,0);
}
U0 ATAPIWriteBlks(CBlkDev *bdev,U8 *buf, I64 native_blk, I64 cnt)
{
I64 U32s_avail;
U8 *buf2;
ATAWaitNotBUSY(bdev,0);
ATAPISeek(bdev,native_blk);
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_CMD,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x0400,native_blk.u16[1],native_blk,cnt.u16[1],cnt,0);
bdev->flags|=BDF_LAST_WAS_WRITE;
ATAWaitNotBUSY(bdev,0);
ATAPISeek(bdev,native_blk);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0xAA00,native_blk.u16[1],native_blk,cnt.u16[1],cnt,0);
buf2=buf+bdev->blk_size*cnt;
while (buf<buf2) {
ATAWaitDRQ(bdev,0);
U32s_avail=(InU8(bdev->base0+ATAR0_HCYL)<<8+InU8(bdev->base0+ATAR0_LCYL))>>2;
if (buf+U32s_avail<<2>buf2)
U32s_avail=(buf2-buf)>>2;
if (U32s_avail) {
RepOutU32(buf,U32s_avail,bdev->base0+ATAR0_DATA);
buf+=U32s_avail<<2;
sys_dsk_writes+=U32s_avail>>(BLK_SIZE_BITS-2);
}
}
ATAWaitNotBUSY(bdev,0);
}
Bool ATAWBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
I64 n,spc;
CBlkDev *bdev=p->bdev;
Bool unlock;
spc=bdev->blk_size>>BLK_SIZE_BITS;
if (bdev->type==BDT_ATAPI) {
unlock=BlkDevLock(bdev);
ATAPIWaitReady(bdev,0);
}
while (cnt>0) {
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
if (bdev->type==BDT_ATAPI)
ATAPIWriteBlks(bdev,buf,blk/spc,(n+spc-1)/spc);
else
ATAWriteBlks(bdev,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
sys_dsk_writes+=n;
}
if (bdev->type==BDT_ATAPI) {
ATAPISync(bdev);
// ATAPIStartStop(bdev,0,FALSE);
if (unlock) BlkDevUnlock(bdev);
}
return TRUE;
}
Bool BootCdProbe(CBlkDev *bdev)
{
CKernel *img=CAlloc(CD_BLK_SIZE);
I64 i;
Bool result=FALSE;
"Port: %04X,%04X Unit: %02X ",bdev->base0,bdev->base1,bdev->unit;
if (ATAProbe(bdev->base0,bdev->base1,bdev->unit)==BDT_ATAPI) {
" ATAPI";
if (ATAPIStartStop(bdev,tS+5.0,TRUE)) {
" Started";
for (i=0;i<2;i++) { //Retry
if (ATAPIReadBlks2(bdev,tS+7.0,img,sys_boot_code.u16[1],1,FALSE)) {
if (img->compile_time==sys_compile_time) {
" Found";
return TRUE;
} else
" Read";
} else
" NoRead";
}
}
}
" Nope\n";
Free(img);
return result;
}
Bool BootCdProbeAll(CBlkDev *bdev)
{
I64 d1,d2,i,j,k;
bdev->base1=0;
for (k=0;k<256;k++) {
i=-1;
while (TRUE) {
j=PCIClassFind(0x010100+k,++i);
if (j<0)
break;
"Subcode:0x%X Bus:0x%X Dev:0x%X Fun:0x%X\n",k,j.u8[2],j.u8[1],j.u8[0];
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x10);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x14);
if (d1&1 && d2&1) {
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x18);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x1C);
if (d1&1 && d2&1) {
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
}
}
d1=0x1F0;
d2=0x3F6;
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
d1=0x170;
d2=0x376;
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
U0 ATARepEntry(I64 base0,I64 base1,I64 unit,I64 irq,U8 *msg,CATARep **_root,I64 *num_hints)
{
I64 type;
base0&=-8;
base1&=-4;
CATARep *tempha;
if (type=ATAProbe(base0,base1,unit)) {
*num_hints+=1;
"\n\n$$PURPLE$$ $$BT+X,\"%d\",LM=\"%d\\n\"$$$$FG$$$$LM,4$$",*num_hints,*num_hints;
if (type==BDT_ATA)
"$$RED$$ATA ";
else
"$$RED$$ATAPI ";
"$$LTBLUE$$%s$$FG$$\nBase0:0x%04X Base1:0x%04X\nIrq:0x%02X Unit:%d$$LM,0$$\n",msg,base0,base1,irq,unit;
if (_root) {
tempha=CAlloc(sizeof(CATARep));
tempha->next=*_root;
*_root=tempha;
tempha->num=*num_hints;
tempha->type=type;
tempha->base0=base0;
tempha->base1=base1;
tempha->unit=unit;
}
}
}
Bool ATARepExitAllApplications()
{
"\nWe're going to probe hardware.\n"
"$$RED$$Exit all other applications.$$FG$$\n"
"Press '$$PURPLE$$p$$FG$$' to probe or '$$PURPLE$$s$$FG$$' to skip.\n";
if (ToUpper(GetChar(,FALSE))=='S')
return TRUE;
else
return FALSE;
}
public I64 ATARep(Bool pmt=TRUE,Bool just_ide=FALSE,CATARep **_root=NULL)
{
I64 d1,d2,d3,i,j,k,cnt=0,unlock_flags=0,num_hints=0;
#assert NUM_BLKDEVS<=64
Bool old_preempt;
if (_root) *_root=NULL;
if (pmt && ATARepExitAllApplications)
return 0;
old_preempt=Preempt(OFF);
for (i=0;i<NUM_BLKDEVS;i++)
if (sys_blkdevs[i].bd_signature==BD_SIGNATURE_VAL)
BEqu(&unlock_flags,i,
BlkDevLock(&sys_blkdevs[i]));
if (!just_ide)
for (k=0;k<256;k++) {
i=-1;
while (TRUE) {
j=PCIClassFind(0x010100+k,++i);
if (j<0)
break;
"\nSubcode:0x%X Bus:0x%X Dev:0x%X Fun:0x%X\n",k,j.u8[2],j.u8[1],j.u8[0];
cnt++;
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x10);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x14);
d3=PCIReadU8(j.u8[2],j.u8[1],j.u8[0],0x3C);
if (d1&1 && d2&1) {
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
} else {
d1=0x1F0; d2=0x3F6; d3=14;
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
}
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x18);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x1C);
if (d1&1 && d2&1) {
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
} else {
d1=0x170; d2=0x376; d3=15;
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
}
}
}
if (!cnt) {
d1=0x1F0; d2=0x3F6; d3=14;
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
d1=0x170; d2=0x376; d3=15;
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
}
NewLine(2);
for (i=0;i<NUM_BLKDEVS;i++)
if (Bt(&unlock_flags,i))
BlkDevUnlock(&sys_blkdevs[i]);
Preempt(old_preempt);
return num_hints;
}
CATARep *ATAIDDrvs(CATARep *root,U8 _sys_acct_drv,CATARep **_ata_drv,CATARep **_atapi_drv)
{
CATARep *result=NULL,*tempha=root,*ata_drv=NULL,*atapi_drv=NULL;
CBlkDev *bdev;
Bool was_silent=Silent(ON);
try
bdev=Drv2BlkDev(_sys_acct_drv);
catch {
Fs->catch_except=TRUE;
bdev=NULL;
}
Silent(was_silent);
while (tempha) {
if (!result && bdev && bdev->type==tempha->type) {
if (bdev->type==BDT_ATAPI &&
bdev->base0==tempha->base0 && bdev->unit==tempha->unit)
result=atapi_drv=tempha;
else if (bdev->type==BDT_ATA && bdev->base0==tempha->base0 &&
bdev->base1==tempha->base1 && bdev->unit==tempha->unit)
result=ata_drv=tempha;
}
if (!result || result->type!=tempha->type) {
if (tempha->type==BDT_ATA) {
if (!ata_drv || tempha->unit<ata_drv->unit ||
tempha->unit==ata_drv->unit && tempha->num<ata_drv->num)
ata_drv=tempha;
} else if (tempha->type==BDT_ATAPI) {
if (!atapi_drv || tempha->unit<atapi_drv->unit ||
tempha->unit==atapi_drv->unit && tempha->num<atapi_drv->num)
atapi_drv=tempha;
}
}
tempha=tempha->next;
}
if (_ata_drv) *_ata_drv =ata_drv;
if (_atapi_drv) *_atapi_drv=atapi_drv;
return result;
}
CBlkDev *ATAMount(U8 first_drv_let,I64 type,I64 base0,I64 base1,I64 unit)
{
CBlkDev *result;
if (0<=first_drv_let-'A'<NUM_PRTS && (type==BDT_ATA || type==BDT_ATAPI) &&
0<=unit<=1) {
result=BlkDevNextFree(first_drv_let,type);
result->unit=unit;
result->base0=base0;
result->base1=base1;
if (BlkDevAdd(result,FALSE,FALSE))
return result;
}
return NULL;
}
I64 AutoMountIDE()
{
I64 result=0;
CATARep *root=NULL,*ata_drv=NULL,*atapi_drv=NULL,*tempha;
ATARep(FALSE,TRUE,&root);
ATAIDDrvs(root,*sys_acct,&ata_drv,&atapi_drv);
if (ata_drv && ATAMount(sys_first_hd_drv_let,BDT_ATA,
ata_drv->base0,ata_drv->base1,ata_drv->unit))
result++;
if (atapi_drv && ATAMount(sys_first_cd_drv_let,BDT_ATAPI,
atapi_drv->base0,atapi_drv->base1,atapi_drv->unit))
result++;
tempha=root;
while (tempha) {
if (tempha!=ata_drv && tempha!=atapi_drv) {
if (tempha->type==BDT_ATA && ATAMount(sys_first_hd_drv_let,BDT_ATA,
tempha->base0,tempha->base1,tempha->unit))
result++;
else if (tempha->type==BDT_ATAPI && ATAMount(sys_first_cd_drv_let,BDT_ATAPI,
tempha->base0,tempha->base1,tempha->unit))
result++;
}
tempha=tempha->next;
}
LinkedLstDel(root);
sys_auto_mount_ide_cnt=result;
return result;
}
+339
View File
@@ -0,0 +1,339 @@
U0 SetBlkDevLockFwding(CBlkDev *bdev)
{
CBlkDev *bdev1;
I64 i;
switch (bdev->type) {
case BDT_RAM:
break;
case BDT_ATA:
case BDT_ATAPI:
for (i=0;i<NUM_BLKDEVS;i++) {
bdev1=&sys_blkdevs[i];
if (bdev1->bd_signature==BD_SIGNATURE_VAL && bdev!=bdev1 &&
(bdev1->type==BDT_ATAPI || bdev1->type==BDT_ATA) &&
bdev1->base0==bdev->base0) {
bdev->lock_fwding=bdev1;
break;
}
}
break;
}
}
I64 BlkDevAdd(CBlkDev *bdev,Bool one_prt,Bool make_free)
{
I64 i,j,ext_base,offset,result=0;
CPrt *p;
CBootStruct br;
CMasterBoot mbr;
bdev->bd_signature=BD_SIGNATURE_VAL;
if (make_free)
p=PrtMakeFree(bdev->first_drv_let+result);
else
p=PrtNextFree(bdev->first_drv_let+result);
p->bdev=bdev;
p->size=bdev->max_blk+1;
switch (bdev->type) {
case BDT_RAM:
p->pt_signature=PRT_SIGNATURE_VAL;
p->type=PT_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 allocated on a just-in-time
//basis.
if (BlkDevInit(bdev))
result++;
else
p->pt_signature=0;
break;
case BDT_ATA:
p->pt_signature=PRT_SIGNATURE_VAL; //Temporarily validate
if (!BlkDevInit(bdev))
p->pt_signature=0; //Revoke validation
else {
p->pt_signature=0; //Revoke validation
if (one_prt) {
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_REDSEA;
p->size=bdev->max_blk+1;
//The following read is a test read.
//if it hangs, the drive is not supported.
ATAReadBlks(bdev,&mbr,0,1);
break;
}
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bdev,&mbr,offset,1);
if (mbr.signature!=0xAA55)
break;
j=-1;
for (i=0;i<4;i++) {
if (mbr.p[i].type) {
if (make_free)
p=PrtMakeFree(bdev->first_drv_let+result);
else
p=PrtNextFree(bdev->first_drv_let+result);
p->bdev=bdev;
p->offset=mbr.p[i].offset+offset;
p->size =mbr.p[i].size;
switch (mbr.p[i].type) {
case MBR_PT_REDSEA:
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_REDSEA;
RedSeaFSPrtInit(p);
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:
ATAReadBlks(bdev,&br,p->offset,1);
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
if (br.signature==MBR_PT_REDSEA) {
p->type=PT_REDSEA;
RedSeaFSPrtInit(p);
} else {
p->type=PT_FAT32;
FAT32PrtInit(p);
}
break;
case MBR_PT_NTFS:
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_NTFS;
break;
case 5:
case 15:
j=i;
break;
default:
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_UNKNOWN;
}
}
}
if (j<0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
}
break;
case BDT_ATAPI:
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_ISO9660; //Start with this
p->size =0;
break;
}
if (result)
SetBlkDevLockFwding(bdev);
else
MemSet(bdev,0,sizeof(CBlkDev));
return result;
}
Bool DrvEnable(U8 drv_let,Bool val)
{//This can be used to unmount a drive or remount,
//but not mount the first time.
CPrt *p;
Bool result=FALSE;
try {
p=Drv2Prt(drv_let);
result=!LBEqu(&p->type,PTf_DISABLE,!val);
} catch
Fs->catch_except=TRUE;
return result;
}
CATARep *ATARepFind(CATARep *haystack_root,I64 needle_num)
{
while (haystack_root) {
if (haystack_root->num==needle_num)
return haystack_root;
haystack_root=haystack_root->next;
}
return NULL;
}
U0 Mount(Bool repartition=FALSE)
{
CBlkDev *bdev;
I64 first_prt_num,type,unit,num_hints;
U8 blks_buf[128],addr_buf[128],base0_buf[128],base1_buf[128];
Bool add;
CATARep *root,*tempha;
do {
PrtRep;
"\n****** Mount Drives ******\n"
"The first drive letter is the letter\n"
"of the first partition. If adding\n"
"a hard drive, you should pick 'C'.\n"
"If more than one partition is present\n"
"they will be lettered in sequence.\n"
"\nFirst Drive Letter ($$PURPLE$$<ENTER>$$FG$$ to exit):";
first_prt_num=ToUpper(GetChar)-'A';
NewLine;
if (0<=first_prt_num<NUM_PRTS) {
"\t$$PURPLE$$1$$FG$$=RAM\n\t$$PURPLE$$2$$FG$$=ATA(Harddisk)\n"
"\t$$PURPLE$$3$$FG$$=ATAPI(CD-ROM)\nType:";
type=GetChar-'0';
NewLine;
unit=0;
if (type==BDT_ATA || type==BDT_ATAPI) {
num_hints=ATARep(,,&root);
do {
if (num_hints)
"Enter dev number or\nport with $$PURPLE$$0x$$FG$$ prefix.\n"
"I/O Port Base0:\n";
else
"Include $$PURPLE$$0x$$FG$$ prefix.\nI/O Port Base0:\n";
GetS(base0_buf,128);
} while (!A2I64(base0_buf));
if (1<=A2I64(base0_buf)<=num_hints) {
tempha=ATARepFind(root,A2I64(base0_buf));
SPrint(base0_buf,"0x%X",tempha->base0);
SPrint(base1_buf,"0x%X",tempha->base1);
unit=tempha->unit;
} else {
if (type==BDT_ATAPI)
StrCpy(base1_buf,"0");
else
do {
"I/O Port Base1:\n";
GetS(base1_buf,128);
} while (!A2I64(base1_buf));
do {
"\t$$PURPLE$$0$$FG$$=Master\n\t$$PURPLE$$1$$FG$$=Slave\nUnit:";
unit=GetChar-'0';
} while (!(0<=unit<=1));
NewLine;
}
LinkedLstDel(root);
}
if (type==BDT_RAM) {
"Addr of RAM disk ($$PURPLE$$<ENTER>$$FG$$ to MAlloc):";
GetS(addr_buf,128);
"Blks of 512 bytes:";
GetS(blks_buf,128);
}
if (BDT_NULL<type<BDT_NUM_TYPES && 0<=unit<=1) {
bdev=BlkDevNextFree(first_prt_num+'A',type);
bdev->unit=unit;
if (type==BDT_RAM) {
if (!*addr_buf) StrCpy(addr_buf,"0");
bdev->RAM_dsk=A2I64(addr_buf);
bdev->max_blk=A2I64(blks_buf)-1;
}
if (type==BDT_ATA ||
type==BDT_ATAPI) {
bdev->base0=A2I64(base0_buf);
bdev->base1=A2I64(base1_buf);
}
add=TRUE;
if (type==BDT_ATA && repartition) {
"\nReformat WHOLE drive!";
if (YorN) {
if (!BlkDevAdd(bdev,TRUE,TRUE))
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
else
CallExtStr("PrtDsk",bdev->first_drv_let);
add=FALSE;
}
}
if (add && !BlkDevAdd(bdev,FALSE,TRUE))
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
} else
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
}
} while (0<=first_prt_num<NUM_PRTS);
}
I64 SysPmtI64()
{
U8 st[136];
StrCpy(st,"0x");
GetS(st+2,134,FALSE);
if (!st[2])
return 0;
else
return A2I64(st);
}
Bool PmtBaseUnit(CBlkDev *bdev)
{
I64 ch;
Bool probe;
" TempleOS\n\n\n";
#exe {
if (kernel_cfg->opts[CFG_DONT_PROBE])
StreamPrint("probe=FALSE;");
else
StreamPrint("probe=TRUE;");
};
if (!probe || !BootCdProbeAll(bdev)) {
"\nDon't worry. This is not a product\n"
"registration. TempleOS just needs the\n"
"I/O port numbers for the CD-ROM.\n"
"\nRetry the ports above or check Windows\n"
"system information under I/O ports for\n"
"'IDE', 'ATA' or 'SATA'.\n"
"\n\nEnter 4-digit hex I/O Port number.\n"
"CD-ROM I/O Port Base0: 0x";
bdev->base0=SysPmtI64;
bdev->base1=0;
bdev->unit =0;
if (bdev->base0) {
"\nUnit (0 or 1): ";
do ch=GetChar(,FALSE);
while (!('0'<=ch<='1'));
'' ch;
bdev->unit=ch-'0';
cdrom_boot_is_good=BootCdProbe(bdev);
return TRUE;
} else {
cdrom_boot_is_good=FALSE;
return FALSE;
}
}
return FALSE;
}
U0 BlkDevsInitAll()
{
CBlkDev *bdev;
I64 i;
sys_blkdevs=CAlloc(sizeof(CBlkDev)*NUM_BLKDEVS);
sys_prts=CAlloc(sizeof(CPrt)*NUM_PRTS);
for (i=0;i<NUM_PRTS;i++)
drv_to_prt[i]=&sys_prts[i];
sys_raw_col=0;
#exe {
if (kernel_cfg->opts[CFG_AUTO_MOUNT_IDE])
StreamPrint("AutoMountIDE;");
StreamPrint("#exe {OptOff(OPTf_WARN_PAREN);}");
StreamDoc(kernel_cfg->add_dev);
StreamPrint("#exe {OptOn(OPTf_WARN_PAREN);}");
};
PrtRep;
}
+265
View File
@@ -0,0 +1,265 @@
I64 FSize(CFile *f)
{
if (f)
return f->de.size;
else
return 0;
}
CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0)
{ //allows flags "r","w","w+". Include a "c" for contiguous.
//(It uses $LK,"StrOcc",A="MN:StrOcc"$() for 'w', 'r', '+', 'c')
CFile *f=CAlloc(sizeof(CFile));
CFileAccess *fa;
U8 *full_name;
Bool contiguous=StrOcc(flags,'c');
f->cluster=INVALID_CLUSTER;
f->fblk_num=0;
if (cnt>0)
f->max_blk=cnt-1;
else
f->max_blk=MAX_I64;
f->file_cluster_num=INVALID_CLUSTER;
full_name=FileNameAbs(filename);
f->p=Drv2Prt(*full_name);
if (f->p->type==PT_REDSEA)
contiguous=TRUE;
if (contiguous) {
f->flags|=FF_CONTIGUOUS;
if (f->p->type!=PT_REDSEA && !(FileAttr(filename) & _ATTR_CONTIGUOUS))
throw('File');
}
f->cluster_buf=CAlloc(f->p->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)) {
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 (fa=FileAccessNew(full_name)) {
StrCpy(f->de.name,fa->mask);
if (cnt>0) { //We pre-alloc the whole thing.
f->de.cluster=ClustersAlloc(f->p,0,
(cnt+f->p->spc-1)/f->p->spc,contiguous);
f->de.size=cnt<<BLK_SIZE_BITS;
DirNew(fa->p,Fs->cur_dir,&f->de,TRUE);
f->flags&=~FF_NEW_FILE;
}
FileAccessDel(fa);
if (!contiguous || cnt>0)
return f;
}
} else {
if (FileFind(full_name,&f->de,FUF_JUST_FILES)) {
Free(full_name);
f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;
return f;
}
}
Free(f->cluster_buf);
Free(full_name);
Free(f);
return NULL;
}
U0 FClose(CFile *f)
{
CFileAccess *fa;
if (f) {
if (f->flags & FF_BUF_DIRTY) {
WClusters(f->p,f->cluster_buf,f->cluster,1);
f->flags&=~FF_BUF_DIRTY;
}
if (f->flags & FF_NEEDS_WRITE) {
if (fa=FileAccessNew(f->de.full_name)) {
if (!(f->flags & FF_USE_OLD_DATETIME))
f->de.datetime=Now;
if (f->flags & FF_NEW_FILE)
DirNew(fa->p,Fs->cur_dir,&f->de,TRUE);
else
DirNew(fa->p,Fs->cur_dir,&f->de,FALSE);
FileAccessDel(fa);
} else
throw('File');
}
Free(f->cluster_buf);
Free(f->de.full_name);
Free(f);
}
}
I64 FSetCluster(CFile *f,I64 c,I64 blk,Bool read)
{
CPrt *p=f->p;
I64 i;
if (f->cluster!=c) {
if (f->flags & FF_BUF_DIRTY) {
i=p->spc;
if (f->max_blk!=MAX_I64) {
i=f->max_blk+1-f->file_cluster_num*p->spc;
if (i>p->spc)
i=p->spc;
}
WClustersBlks(p,f->cluster_buf,f->cluster,i);
f->flags=f->flags & ~FF_BUF_DIRTY;
}
f->cluster=c;
f->file_cluster_num=blk/p->spc;
if (read) {
i=p->spc;
if (f->max_blk!=MAX_I64) {
i=f->max_blk+1-f->file_cluster_num*p->spc;
if (i>p->spc)
i=p->spc;
}
c=RClustersBlks(p,f->cluster_buf,c,i);
}
}
return c;
}
Bool FRBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)
{
CPrt *p=f->p;
I64 spc=p->spc,i,j,c=f->de.cluster;
if (!f || !p) 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) {
RBlks(p,buf,Cluster2Blk(p,c)+blk,cnt);
blk+=cnt;
} else {
i=blk/spc;
if (0<=f->file_cluster_num<=i) {
c=f->cluster;
i-=f->file_cluster_num;
}
if (i>0)
c=ClusterNumNext(p,c,i);
if (i=blk%spc) {
c=FSetCluster(f,c,blk,TRUE);
if (cnt<spc-i)
j=cnt;
else
j=spc-i;
MemCpy(buf,f->cluster_buf+i<<BLK_SIZE_BITS,j<<BLK_SIZE_BITS);
buf+=j<<BLK_SIZE_BITS;
cnt-=j;
blk+=j;
}
while (cnt>=spc) {
c=FSetCluster(f,c,blk,TRUE);
MemCpy(buf,f->cluster_buf,spc<<BLK_SIZE_BITS);
buf+=spc<<BLK_SIZE_BITS;
cnt-=spc;
blk+=spc;
}
if (cnt>0) {
c=FSetCluster(f,c,blk,TRUE);
MemCpy(buf,f->cluster_buf,cnt<<BLK_SIZE_BITS);
buf+=cnt<<BLK_SIZE_BITS;
blk+=cnt;
}
}
f->fblk_num=blk;
return TRUE;
}
Bool FWBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)
{
CPrt *p=f->p;
I64 spc=p->spc,i,j,c=f->de.cluster,c1;
if (!f || !p) 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) {
WBlks(p,buf,Cluster2Blk(p,c)+blk,cnt);
blk+=cnt;
} else {
if (!c) {
c=ClustersAlloc(p,0,1,FALSE);
f->file_cluster_num=0;
f->cluster=c;
f->de.cluster=c;
f->flags|=FF_NEEDS_WRITE|FF_NEW_FILE;
}
i=blk/spc;
if (0<=f->file_cluster_num<=i) {
c=f->cluster;
i-=f->file_cluster_num;
}
while (i>0) {
c1=c;
c=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER) {
c=ClustersAlloc(p,c1,i,FALSE);
if (i>1)
c=ClusterNumNext(p,c,i-1);
break;
} else
i--;
}
if (i=blk%spc) {
FSetCluster(f,c,blk,TRUE);
if (cnt<spc-i)
j=cnt;
else
j=spc-i;
MemCpy(f->cluster_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=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER)
c=ClustersAlloc(p,c1,1,FALSE);
}
}
while (cnt>=spc) {
FSetCluster(f,c,blk,FALSE);
MemCpy(f->cluster_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=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER)
c=ClustersAlloc(p,c1,1,FALSE);
}
}
if (cnt>0) {
FSetCluster(f,c,blk,TRUE);
MemCpy(f->cluster_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;
}
+144
View File
@@ -0,0 +1,144 @@
U0 DskCacheInit(I64 size_in_U8s)
{
CCacheBlk *tempc;
I64 i,cnt;
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
Free(sys_dsk_cache_ctrl);
Free(sys_dsk_cache_base);
Free(sys_dsk_cache_hash_table);
if (size_in_U8s<0x2000) {
sys_dsk_cache_ctrl=NULL;
sys_dsk_cache_base=NULL;
sys_dsk_cache_hash_table=NULL;
} else {
sys_dsk_cache_ctrl=ACAlloc(offset(CCacheBlk.body));
sys_dsk_cache_base=AMAlloc(size_in_U8s);
QueInit(sys_dsk_cache_ctrl);
cnt=MSize(sys_dsk_cache_base)/sizeof(CCacheBlk);
sys_dsk_cache_size=cnt*BLK_SIZE;
for (i=0;i<cnt;i++) {
tempc=sys_dsk_cache_base+i;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
tempc->next_hash=tempc->last_hash=tempc;
tempc->p=NULL;
tempc->blk=0;
}
sys_dsk_cache_hash_table=AMAlloc(DSK_CACHE_HASH_SIZE*sizeof(U8 *)*2);
for (i=0;i<DSK_CACHE_HASH_SIZE;i++) {
tempc=sys_dsk_cache_hash_table(U8 *)+i*sizeof(U8 *)*2-offset(CCacheBlk.next_hash);
tempc->next_hash=tempc->last_hash=tempc;
}
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
I64 DskCacheHash(I64 blk)
{
I64 i=blk & (DSK_CACHE_HASH_SIZE-1);
return sys_dsk_cache_hash_table(U8 *)+i<<4-offset(CCacheBlk.next_hash);
}
U0 DskCacheQueRem(CCacheBlk *tempc)
{
QueRem(tempc);
tempc->next_hash->last_hash=tempc->last_hash;
tempc->last_hash->next_hash=tempc->next_hash;
}
U0 DskCacheQueIns(CCacheBlk *tempc)
{
CCacheBlk *temp_n,*temp_l;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
temp_l=DskCacheHash(tempc->blk);
temp_n=temp_l->next_hash;
tempc->last_hash=temp_l;
tempc->next_hash=temp_n;
temp_l->next_hash=temp_n->last_hash=tempc;
}
CCacheBlk *DskCacheFind(CPrt *p,I64 blk)
{
CCacheBlk *tempc,*tempc1=DskCacheHash(blk);
tempc=tempc1->next_hash;
while (tempc!=tempc1) {
if (tempc->p==p && tempc->blk==blk)
return tempc;
tempc=tempc->next_hash;
}
return NULL;
}
U0 DskCacheAdd(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
CCacheBlk *tempc;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
while (cnt-->0) {
if (!(tempc=DskCacheFind(p,blk)))
tempc=sys_dsk_cache_ctrl->next_lru;
DskCacheQueRem(tempc);
MemCpy(&tempc->body,buf,BLK_SIZE);
tempc->p=p;
tempc->blk=blk;
DskCacheQueIns(tempc);
blk++;
buf+=BLK_SIZE;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
U0 DskCacheInvalidate2(CPrt *p)
{
CCacheBlk *tempc,*tempc1;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
tempc=sys_dsk_cache_ctrl->last_lru;
while (tempc!=sys_dsk_cache_ctrl) {
tempc1=tempc->last_lru;
if (tempc->p==p) {
DskCacheQueRem(tempc);
tempc->p=NULL;
tempc->blk=0;
tempc->next_hash=tempc->last_hash=tempc;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
}
tempc=tempc1;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
U0 RCache(CPrt *p,U8 **_buf, I64 *_blk, I64 *_cnt)
{
CCacheBlk *tempc;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
//fetch leading blks from cache
while (*_cnt>0) {
if (tempc=DskCacheFind(p,*_blk)) {
MemCpy(*_buf,&tempc->body,BLK_SIZE);
*_cnt-=1;
*_buf+=BLK_SIZE;
*_blk+=1;
} else
break;
}
//fetch trailing blks from cache
while (*_cnt>0) {
if (tempc=DskCacheFind(p,*_blk+*_cnt-1)) {
MemCpy(*_buf+(*_cnt-1)<<BLK_SIZE_BITS,&tempc->body,BLK_SIZE);
*_cnt-=1;
} else
break;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
+283
View File
@@ -0,0 +1,283 @@
Bool DirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempde,Bool free_old_chain=TRUE)
{
switch (p->type) {
case PT_REDSEA:
return RedSeaFSDirNew(p,cur_dir,tempde,free_old_chain);
case PT_FAT32:
return FAT32DirNew(p,cur_dir,tempde,free_old_chain);
case PT_ISO9660:
PrintErr("Not Writable\n");
return FALSE;
default:
PrintErr("File System Not Supported\n");
return FALSE;
}
}
U0 DirEntryDel(CDirEntry *tempde)
{ //Doesn't Free user_data
if (tempde) {
Free(tempde->full_name);
Free(tempde);
}
}
U0 DirEntryDel2(CDirEntry *tempde)
{ //Frees user_data
if (tempde) {
Free(tempde->full_name);
Free(tempde->user_data);
Free(tempde);
}
}
U0 DirLstDel(CDirEntry *tempde)
{ //Doesn't Free user_data
CDirEntry *tempde2;
while (tempde) {
tempde2=tempde->next;
if (tempde->sub)
DirLstDel(tempde->sub);
DirEntryDel(tempde);
tempde=tempde2;
}
}
U0 DirLstDel2(CDirEntry *tempde)
{ //Frees user_data
CDirEntry *tempde2;
while (tempde) {
tempde2=tempde->next;
if (tempde->sub)
DirLstDel2(tempde->sub);
DirEntryDel2(tempde);
tempde=tempde2;
}
}
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 & _ATTR_DIR)
d1=1;
if (e2->attr & _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 DirEntryCompareCluster(CDirEntry *e1,CDirEntry *e2)
{
return e1->cluster-e2->cluster;
}
#define SK_NAME 0
#define SK_CLUSTER 1
U0 DirFilesSort(CDirEntry **_tempde,I64 key)
{
I64 i,cnt=0;
CDirEntry *tempde=*_tempde,*tempde1,**sort_buf;
if (tempde) {
tempde1=tempde;
while (tempde1) {
cnt++;
tempde1=tempde1->next;
}
if (cnt>1) {
sort_buf=MAlloc(cnt*sizeof(U8 *));
i=0;
tempde1=tempde;
while (tempde1) {
sort_buf[i++]=tempde1;
tempde1=tempde1->next;
}
nobound_switch(key) {
case SK_NAME:
QSortI64(sort_buf,cnt,&DirEntryCompareName);
break;
case SK_CLUSTER:
QSortI64(sort_buf,cnt,&DirEntryCompareCluster);
break;
}
tempde=sort_buf[0];
*_tempde=tempde;
for (i=0;i<cnt-1;i++) {
tempde1=sort_buf[i];
tempde1->next=sort_buf[i+1];
}
tempde1=sort_buf[i];
tempde1->next=NULL;
Free(sort_buf);
tempde1=tempde;
while (tempde1) {
if (tempde1->sub)
DirFilesSort(&tempde1->sub,key);
tempde1=tempde1->next;
}
} else
if (tempde->sub)
DirFilesSort(&tempde->sub,key);
}
}
CDirEntry *DirFilesFlatten(CDirEntry *tempde,CDirEntry **_result,I64 fuf_flags)
{ //returns last node
CDirEntry *tempde1;
Bool del;
if (tempde)
while (TRUE) {
tempde1=tempde->next;
if (!(tempde->attr&_ATTR_DIR)||!(fuf_flags&FUF_JUST_FILES)) {
_result=*_result=tempde;
del=FALSE;
} else
del=TRUE;
if (tempde->sub) {
_result=DirFilesFlatten(tempde->sub,_result,fuf_flags);
tempde->sub=NULL;
}
if (del)
DirEntryDel(tempde);
if (tempde1)
tempde=tempde1;
else
break;
}
*_result=NULL;
return _result;
}
CDirEntry *SysFilesFind(U8 *files_find_mask,I64 fuf_flags)
{
CPrt *p=Fs->cur_prt;
CDirEntry *result=NULL;
PrtChk(p);
switch (p->type) {
case PT_REDSEA:
result=RedSeaFSFilesFind(files_find_mask,fuf_flags);
break;
case PT_FAT32:
result=FAT32FilesFind(files_find_mask,fuf_flags);
break;
case PT_ISO9660:
result=ISO1FilesFind(files_find_mask,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
result=NULL;
}
if (result) {
DirFilesSort(&result,SK_NAME);
if (fuf_flags&(FUF_FLATTEN_TREE|FUF_JUST_FILES))
DirFilesFlatten(result,&result,fuf_flags);
if (fuf_flags&FUF_CLUSTER_ORDER)
DirFilesSort(&result,SK_CLUSTER);
}
return result;
}
U0 PutFileLink(U8 *filename,I64 line=0,Bool plain_text=FALSE)
{
U8 *buf;
if (!filename) return;
if (IsRaw) {
if (line)
"%s,%04d",filename,line;
else
"%s",filename;
} else {
buf=FileNameAbs(filename);
if (plain_text) {
if (line)
"$$LK,\"%s,%04d\",A=\"PL:%s,%d\"$$",filename,line,buf,line;
else
"$$LK,\"%s\",A=\"PI:%s\"$$",filename,buf;
} else {
if (line)
"$$LK,\"%s,%04d\",A=\"FL:%s,%d\"$$",filename,line,buf,line;
else
"$$LK,\"%s\",A=\"FI:%s\"$$",filename,buf;
}
Free(buf);
}
}
U0 PutDirLink(U8 *dirname)
{
U8 *buf;
if (!dirname) return;
if (IsRaw)
"%s",dirname;
else {
buf=DirNameAbs(dirname);
"$$MA,T=\"%s\",LM=\"Cd(\\\"%s\\\");Dir;\n\"$$",dirname,buf;
Free(buf);
}
}
I64 Dir2(U8 *files_find_mask,I64 fuf_flags,Bool full)
{
CDirEntry *tempde1=NULL,*tempde2;
U8 *st;
I64 csize=0xFFFF,c=0xFFFF,result=0;
tempde1=SysFilesFind(files_find_mask,fuf_flags);
if (!(st=CurDir))
PrintErr("Invalid Drive\n");
else {
if (tempde1) {
//Find max columns
tempde2=tempde1;
while (tempde2) {
if (tempde2->size>csize)
csize=tempde2->size;
if (tempde2->cluster>c)
c=tempde2->cluster;
tempde2=tempde2->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,"CLUSTER";
else
"DATE_ TIME_ %*ts\n",csize,"SIZE";
while (tempde1) {
tempde2=tempde1->next;
result++;
if (full)
"%D %T %0*tX %0*tX ",tempde1->datetime,tempde1->datetime,
csize,tempde1->size,c,tempde1->cluster;
else
"%02d/%02d %02d:%02d %0*tX ",Month(tempde1->datetime),Day(tempde1->datetime),
Hour24(tempde1->datetime),Minute(tempde1->datetime),
csize,tempde1->size;
if (tempde1->attr & _ATTR_DIR)
PutDirLink(tempde1->name);
else
PutFileLink(tempde1->name);
NewLine;
DirEntryDel(tempde1);
tempde1=tempde2;
}
} else
"No matching entries\n";
Free(st);
}
return result;
}
+367
View File
@@ -0,0 +1,367 @@
U8 *FileExtDot(U8 *src)
{
I64 ch;
while (ch=*src++)
if (ch=='.' && *src!='/' && *src!='.')
return src-1;
return NULL;
}
U8 *FileExtRem(U8 *src,U8 *dst=NULL)
{
U8 *ptr;
if (ptr=FileExtDot(src)) {
if (dst)
StrCpy(dst,ptr+1);
*ptr=0;
} else if (dst)
*dst=0;
return dst;
}
Bool IsDotZ(U8 *filename)
{
I64 i=StrLen(filename);
if (i>6 && filename[i-1]=='Z' && filename[i-2]=='.' && filename[i-6]=='.')
return TRUE;
else
return FALSE;
}
Bool IsDotC(U8 *filename)
{
I64 i=StrLen(filename);
if (i>6 && filename[i-1]=='C' && filename[i-2]=='.' && filename[i-6]=='.')
return TRUE;
else
return FALSE;
}
Bool FilesFindMatch(U8 *test_filename,U8 *files_find_mask,I64 fuf_flags=0)
{
U8 *st1=StrNew(files_find_mask),
*st2=MAlloc(StrLen(files_find_mask)+1);
Bool result=FALSE;
while (TRUE) {
StrFirstRem(st1,";",st2);
if (*st2) {
if (*st2=='~') {
if (WildMatch(test_filename,st2+1)) {
result=FALSE;
break;
}
} else {
if (WildMatch(test_filename,st2)) {
if (Bt(&fuf_flags,FUf_JUST_TXT) && !FilesFindMatch(test_filename,FILEMASK_TXT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_SRC) && !FilesFindMatch(test_filename,FILEMASK_SRC)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_AOT) && !FilesFindMatch(test_filename,FILEMASK_AOT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_JIT) && !FilesFindMatch(test_filename,FILEMASK_JIT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_GRA) && !FilesFindMatch(test_filename,FILEMASK_GRA)) {
result=FALSE;
break;
} else
result=TRUE;
}
}
} else
break;
}
Free(st1);
Free(st2);
return result;
}
U0 PrtChk(CPrt *p)
{
if (!p || p->pt_signature!=PRT_SIGNATURE_VAL)
throw('Prt');
}
U8 Prt2Drv(CPrt *p=NULL)
{
if (!p)
p=Fs->cur_prt;
PrtChk(p);
return p->drv_let;
}
CPrt *Drv2Prt(U8 drv_let=0)
{
CPrt *p;
if (!drv_let)
p=Fs->cur_prt;
else {
if (drv_let==':')
drv_let=*sys_acct;
p=drv_to_prt[ToUpper(drv_let)-'A'];
}
PrtChk(p);
return p;
}
U0 BlkDevChk(CBlkDev *bdev)
{
if (!bdev || bdev->bd_signature!=BD_SIGNATURE_VAL ||
!(BDT_NULL<bdev->type<BDT_NUM_TYPES))
throw('BlkDev');
}
CBlkDev *Drv2BlkDev(U8 drv_let=0)
{
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
return bdev;
}
Bool IsDrvWritable(U8 drv_let=0)
{
CBlkDev *bdev=Drv2BlkDev(drv_let);
if (bdev->flags & BDF_READ_ONLY)
return FALSE;
else
return TRUE;
}
U8 *CurDir(CTask *task=NULL,CTask *mem_task=NULL)
{
U8 *st;
if (!task) task=Fs;
if (!task->cur_dir)
return NULL;
st=MAlloc(StrLen(task->cur_dir)+3,mem_task);
*st=Prt2Drv;
st[1]=':';
StrCpy(st+2,task->cur_dir);
return st;
}
U8 *DirNameAbs(U8 *_dirname)
{
I64 maxlen;
U8 drv[3],*cur_dir,*buf2,*buf3,*buf,*dirname,*temp_name;
if (!Fs->cur_dir || !*Fs->cur_dir)
return StrNew(_dirname);
dirname=MStrUtil(_dirname,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_name=dirname;
*drv=Prt2Drv;
drv[1]=':';
drv[2]=0;
if (*dirname && dirname[1]==':') {
if (*dirname==':')
*drv=*sys_acct;
else
*drv=*dirname;
dirname=dirname+2;
cur_dir=StrNew("/");
} else
cur_dir=StrNew(Fs->cur_dir);
if (*dirname=='/') {
Free(cur_dir);
cur_dir=StrNew("/");
dirname++;
}
buf2=StrNew(dirname);
maxlen=StrLen(cur_dir)+1+StrLen(buf2)+1;
buf3=MAlloc(maxlen);
buf =MAlloc(maxlen);
StrCpy(buf3,cur_dir);
while (*buf2) {
StrFirstRem(buf2,"/",buf);
if (!*buf)
StrCpy(buf3,"/");
else if (!StrCmp(buf,"..")) {
StrLastRem(buf3,"/");
if (!*buf3)
StrCpy(buf3,"/");
} else if (!StrCmp(buf,".")) {
;
} else if (*buf) {
if (!StrCmp(buf,"HOME")) {
Free(buf3);
buf3=MAlloc(maxlen+StrLen(sys_acct));
StrCpy(buf3,sys_acct+2);
*drv=*sys_acct;
} else {
if (StrCmp(buf3,"/"))
CatPrint(buf3,"/");
CatPrint(buf3,buf);
}
}
}
Free(cur_dir);
cur_dir=MAlloc(StrLen(buf3)+3);
StrCpy(cur_dir,drv);
StrCpy(cur_dir+2,buf3);
Free(buf);
Free(buf2);
Free(buf3);
Free(temp_name);
return cur_dir;
}
U8 *FileNameAbs(U8 *_filename,I64 fuf_flags=0)
{//$LK,"FUF_Z_OR_NOT_Z",A="MN:FUF_Z_OR_NOT_Z"$, $LK,"FUF_SCAN_PARENTS",A="MN:FUF_SCAN_PARENTS"$
U8 *buf,*buf2,*buf3,*filename,*temp_name,*temp_buf;
CDirEntry de;
filename=MStrUtil(_filename,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_name=filename;
buf=StrNew(filename);
temp_buf=buf;
if (*buf && buf[1]==':') {
buf+=2;
filename+=2;
}
buf2=MAlloc(StrLen(temp_name)+1);
StrLastRem(buf,"/",buf2);
if (*filename=='/' && !*buf)
StrCpy(buf,"/");
buf3=DirNameAbs(temp_buf);
Free(temp_buf);
buf=MAlloc(StrLen(buf3)+1+StrLen(buf2)+1);
StrCpy(buf,buf3);
if (buf[StrLen(buf)-1]!='/')
CatPrint(buf,"/");
CatPrint(buf,buf2);
Free(buf2);
Free(buf3);
Free(temp_name);
if (fuf_flags&&FileFind(buf,&de,fuf_flags|FUF_JUST_FILES)) {
Free(buf);
buf=de.full_name;
}
return buf;
}
U8 *ChgExt(U8 *filename,U8 *extension)
{//Change filename extension
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
StrCpy(result,filename);
if (FileExtDot(filename))
FileExtRem(result);
return CatPrint(result,".%s",extension);
}
U8 *DftExt(U8 *filename,U8 *extension)
{//Give extension if has none.
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
StrCpy(result,filename);
if (!FileExtDot(filename))
CatPrint(result,".%s",extension);
return result;
}
CDirEntry *Cd2DirEntry(CDirEntry *tempde,U8 *abs_name)
{
I64 i;
while (tempde) {
i=StrLen(tempde->full_name);
if (StrNCmp(tempde->full_name,abs_name,i)||
i && tempde->full_name[i-1]!='/' && abs_name[i] && abs_name[i]!='/')
tempde=tempde->next;
else
if (StrLen(abs_name)==i)
return tempde;
else
return Cd2DirEntry(tempde->sub,abs_name);
}
return NULL;
}
I64 FileAttr(U8 *name,I64 attr=0)
{
if (IsDotZ(name))
attr|=_ATTR_COMPRESSED;
else
attr&=~_ATTR_COMPRESSED;
if (IsDotC(name))
attr|=_ATTR_CONTIGUOUS;
return attr;
}
Bool FileNameChk(U8 *filename)
{
U8 *ptr=filename;
if (!filename) return FALSE;
if (!*ptr) return FALSE;
if (*ptr=='.') {
if (!ptr[1]) return TRUE;
if (ptr[1]=='.' && !ptr[2]) return TRUE;
}
if (StrLen(filename)>=CDIR_FILENAME_LEN) return FALSE;
while (*ptr)
if (!Bt(chars_bitmap_filename,*ptr++))
return FALSE;
return TRUE;
}
U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL)
{/*
Strips file from dirname, scans for file upward until found or returns default.
("/Kernel/Hash1a.CPP.Z",NULL,NULL) returns "D:/Kernel"
("/Kernel",NULL,"PRJ.Z") returns "D:/Kernel/Kernel.PRJ.Z"
("/Kernel/Dsk",NULL,"PRJ.Z") returns "D:/Kernel/Kernel.PRJ.Z"
("/Apps/MusicOrgan","Load","CPP.Z") returns "D:/Apps/MusicOrgan/Load.CPP.Z"
*/
U8 *st=DirNameAbs(dirname),*st2,*st3,*result,*dft=NULL,*ext;
if (_extension && *_extension) {
if (*_extension=='.')
ext=StrNew(_extension);
else
ext=MPrint(".%s",_extension);
} else
ext=StrNew("");
while (StrOcc(st,'/')&&!IsDir(st))
StrLastRem(st,"/");
while (StrOcc(st,'/')) {
st2=StrNew(st);
st3=StrNew(st);
StrLastRem(st2,"/",st3);
if (name)
result=MPrint("%s/%s%s",st,name,ext);
else {
if (*ext)
result=MPrint("%s/%s%s",st,st3,ext);
else
result=StrNew(st);
}
if (!dft)
dft=StrNew(result);
if (!*ext&&(!name||!*name)||FileFind(result)) {
Free(st3);
Free(st2);
Free(st);
Free(dft);
Free(ext);
return result;
}
Free(st);
st=st2;
Free(st3);
}
Free(st);
Free(ext);
return dft;
}
U8 *ToggleZorNotZ(U8 *name)
{
U8 *result;
if (IsDotZ(name)) {
result=StrNew(name);
result[StrLen(name)-2]=0;
} else
result=MPrint("%s.Z",name);
return result;
}
+964
View File
@@ -0,0 +1,964 @@
U0 CDate2Dos(U16 *t,U16 *d,CDate cdt)
{
CDateStruct ds;
Date2Struct(&ds,cdt+local_time_offset);
*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)-local_time_offset;
}
U0 FAT32PrtInit(CPrt *p)
{
CFAT32Boot br32;
Bool unlock;
try {
unlock=PrtLock(p);
p->type=PT_FAT32;
RBlks(p,&br32,p->offset,1);
p->file_system_info_sect=p->offset+br32.file_system_info_sect;
p->map1=p->offset+br32.reserved_sects;
p->map2=p->map1+br32.sects_per_fat;
p->data=p->map2+br32.sects_per_fat-2*br32.sects_per_cluster; //Starts at Cluster 2
p->spc=br32.sects_per_cluster;
p->root_cluster=br32.root_cluster;
MapBufAlloc(p,1);
Free(p->fis);
p->fis=AMAlloc(BLK_SIZE);
RBlks(p,p->fis,p->file_system_info_sect,1);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
Bool FAT32DrvValidate(U8 drv_let)
{
CPrt *p;
CFAT32Boot br;
Bool result=FALSE;
try {
p=Drv2Prt(drv_let);
if (p->type==PT_FAT32 &&
RBlks(p,&br,p->offset,1) &&
br.signature==0xAA55 &&
br.sects==p->size)
result=TRUE;
} catch
Fs->catch_except=TRUE;
return result;
}
U0 FAT32Fmt(U8 drv_let,Bool quick=TRUE)
{
CFAT32Boot *br=CAlloc(BLK_SIZE);
CFAT32FileInfoSect *fis=CAlloc(BLK_SIZE);
CPrt *p=Drv2Prt(drv_let);
I64 i,l;
try {
PrtLock(p);
SetDrvType(drv_let,PT_FAT32);
p->type=PT_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;
MemCpy(br->oem_name,"MSWIN4.1",8);
br->bytes_per_sect=BLK_SIZE;
if (p->size<= 500000)
br->sects_per_cluster=1;
else if (p->size<=2000000)
br->sects_per_cluster=2;
else if (p->size<=6000000)
br->sects_per_cluster=4;
else if (p->size<=12000000)
br->sects_per_cluster=8;
else if (p->size<=33000000)
br->sects_per_cluster=16;
else if (p->size<=67000000)
br->sects_per_cluster=32;
else
br->sects_per_cluster=64;
br->reserved_sects=32;
br->copies_of_fat=2;
br->media_desc=0xF8;
br->sects=p->size;
l=(br->sects/br->sects_per_cluster)>>(BLK_SIZE_BITS-2)+1;
br->sects_per_fat=l;
br->root_cluster=2;
br->file_system_info_sect=1;
br->log_drv_num=0x80;
br->ext_signature=0x29;
br->serial_num=RandU32;
MemCpy(br->vol_name,"NO NAME ",11);
MemCpy(br->fat_name,"FAT32 ",8);
br->signature=0xAA55;
fis->signature1=0x41615252;
fis->signature2=0x61417272;
fis->free_clusters=-1;
fis->most_recently_allocated=0;
fis->signature3=0xAA550000;
if (quick)
i=br->reserved_sects+2*l+4*br->sects_per_cluster;
else
i=p->size;
WZeroBlks(p,p->offset,i);
WBlks(p,fis,p->offset+br->file_system_info_sect,1);
WBlks(p,br,p->offset,1);
FAT32PrtInit(p);
ClustersAlloc(p,0,1,FALSE); //Allocate #1
br->root_cluster=ClustersAlloc(p,0,1,FALSE);
WBlks(p,br,p->offset,1);
FAT32PrtInit(p);
PrtUnlock(p);
} catch
PrtUnlock(p);
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,result=0;
for (i=0;i<11;i++)
if (result&1)
result.u8[0]=0x80+result>>1+*src++;
else
result.u8[0]=result>>1+*src++;
return result;
}
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 *tempde,CFAT32DirEntryLong *de,I64 *xsum)
{
I64 i;
U8 *ptr=de;
if (de->ord&0x40) {
MemSet(tempde,0,sizeof(CDirEntry));
*xsum=de->xsum;
} else if (de->type || de->zero || de->xsum!=*xsum) {
MemSet(tempde,0,sizeof(CDirEntry));
*xsum=0;
return FALSE;
}
switch (de->ord&0x3F) {
case 1:
for (i=0;i<13;i++)
if (!(tempde->name[i]=ptr[fat_long_name_map[i]]))
return TRUE;
break;
case 2:
for (i=0;i<12;i++)
if (!(tempde->name[i+13]=ptr[fat_long_name_map[i]]))
return TRUE;
break;
}
return TRUE;
}
Bool FAT32CDirFill(CDirEntry *tempde,CFAT32DirEntry *de)
{
Bool result;
if (*tempde->name)
result=TRUE;
else
result=FATFromName(tempde->name,de->name);
tempde->cluster=de->cluster_lo+de->cluster_hi<<16;
tempde->size=de->size;
tempde->attr=de->attr;
tempde->datetime=Dos2CDate(de->WrtTime,de->WrtDate);
return result;
}
Bool FAT32DirFill(CFAT32DirEntry *de,CDirEntry *tempde,I64 *_de_cnt=NULL)
{ //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 result;
MemSet(de,0,sizeof(CFAT32DirEntry));
result=FATNameTo(de->name,tempde->name);
FATFromName(dname,de->name);
if (StrCmp(dname,tempde->name)) {
ord=0x41;
xsum=FATNameXSum(de->name);
if ((l=StrLen(tempde->name))>13) {
ptr=&ld[de_cnt];
MemSet(ptr,0,sizeof(CFAT32DirEntryLong));
ld[de_cnt].attr=_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]]=tempde->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=_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]]=tempde->name[i];
i++;
for (;i<13;i++)
ptr[fat_long_name_map[i]](U16)=0xFFFF;
de_cnt++;
MemSet(&de[de_cnt],0,sizeof(CFAT32DirEntry));
result=FATNameTo(de[de_cnt].name,tempde->name);
}
de[de_cnt].cluster_lo=tempde->cluster.u16[0];
de[de_cnt].cluster_hi=tempde->cluster.u16[1];
if (!(tempde->attr&_ATTR_DIR))
de[de_cnt].size=tempde->size;
de[de_cnt].attr=tempde->attr;
if (!tempde->datetime)
tempde->datetime=Now;
CDate2Dos(&de[de_cnt].WrtTime,&de[de_cnt].WrtDate,tempde->datetime);
if (_de_cnt)
*_de_cnt=de_cnt+1;
return result;
}
Bool FAT32FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,I64 fuf_flags=0)
{ //$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$
Bool result=FALSE,unlock;
CFAT32DirEntry *buf;
I64 xsum=0,attr,cur_dir_entry,entries_per_cluster;
U8 dname[CDIR_FILENAME_LEN],ch;
CDirEntry long_name;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
MemSet(_result,0,sizeof(CDirEntry));
MemSet(&long_name,0,sizeof(CDirEntry));
PrtChk(p);
if (p->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else if (!CFileNameTo(dname,name))
PrintErr("Invalid FileName.\n");
else
try {
unlock=PrtLock(p);
buf=MAlloc(BLK_SIZE*p->spc);
entries_per_cluster=p->spc<<FAT32_ENTRIES_BITS;
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5) {
if (attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr&_ATTR_VOL_ID)) {
if (xsum==FATNameXSum(buf[cur_dir_entry].name))
MemCpy(_result,&long_name,sizeof(CDirEntry));
else
MemSet(_result,0,sizeof(CDirEntry));
if (!(fuf_flags&FUF_JUST_DIRS && !(attr & _ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && attr & _ATTR_DIR) &&
FAT32CDirFill(_result,&buf[cur_dir_entry]) &&
!StrCmp(dname,_result->name)) {
result=TRUE;
goto exit_this;
}
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClusterNumNext(p,cur_dir_cluster);
if (!(0<cur_dir_cluster<0x0FFFFFF8))
break;
else {
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
}
}
}
MemSet(_result,0,sizeof(CDirEntry));
exit_this:
Free(buf);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U8 *FAT32FileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
PrtChk(p);
*_size=0;
*_attr=0;
if (p->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
if (FAT32FileFind(p,cur_dir_cluster,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.cluster;
if (!(0<c<0x0FFFFFF8))
c=0x0FFFFFFF;
else
c=RClustersBlks(p,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
PrtUnlock(p);
} catch
PrtUnlock(p);
return buf;
}
Bool FAT32Cd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_prt->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else if (FAT32FileFind(Fs->cur_prt,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
U0 FAT32FreeClusters(CPrt *p,I64 c)
{
I64 next,saved_c=c;
Bool unlock,unlock_break;
PrtChk(p);
if (!(0<c<0x0FFFFFF8)) return;
if (p->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
CleanMAPBuf(p);
do {
SetFSBuf(p,c,0);
next=p->cur_map_blk[c&(BLK_SIZE/4-1)];
p->cur_map_blk[c&(BLK_SIZE/4-1)]=0;
LBts(p->buffered_map_dirty_bits,0);
c=next;
} while (0<c<0x0FFFFFF8);
CleanMAPBuf(p,0);
c=saved_c;
do {
SetFSBuf(p,c,1);
next=p->cur_map_blk[c&(BLK_SIZE/4-1)];
p->cur_map_blk[c&(BLK_SIZE/4-1)]=0;
LBts(p->buffered_map_dirty_bits,0);
c=next;
} while (0<c<0x0FFFFFF8);
CleanMAPBuf(p,1);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
}
I64 FAT32AllocClusters(CPrt *p,I64 c,I64 cnt)
{
Bool wrap_around=FALSE,unlock,unlock_break;
I64 first=INVALID_CLUSTER,j,l;
if (cnt<=0) return 0x0FFFFFFF;
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
l=(p->size+p->offset-p->data)/p->spc-1;
j=p->fis->most_recently_allocated;
while (cnt-->0) {
while (TRUE) {
j++;
if (j<1) j=1;
if (j>=l) {
if (wrap_around)
Dbg;
j=1;
wrap_around=TRUE;
}
SetFSBuf(p,j);
if (!p->cur_map_blk[j&(BLK_SIZE/4-1)])
break;
}
if (!(0<first<0x0FFFFFF8))
first=j;
if (0<c<l) {
SetFSBuf(p,c);
p->cur_map_blk[c&(BLK_SIZE/4-1)]=j;
LBts(p->buffered_map_dirty_bits,0);
}
c=j;
}
if (0<c<l) {
SetFSBuf(p,c);
p->cur_map_blk[c&(BLK_SIZE/4-1)]=0x0FFFFFFF;
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p);
p->fis->most_recently_allocated=j;
p->fis->free_clusters=-1;
WBlks(p,p->fis,p->file_system_info_sect,1);
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
return first;
}
I64 FAT32AllocContiguousClusters(CPrt *p,I64 cnt)
{
I64 i,first=1;
Bool cont,unlock,unlock_break;
if (cnt<=0) return 0x0FFFFFFF;
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
while (TRUE) {
first++;
i=0;
cont=TRUE;
while (cont && i<cnt) {
if ((first+i+1)*p->spc+p->data>p->size+p->offset)
Dbg;
SetFSBuf(p,first+i);
if (p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)])
cont=FALSE;
else
i++;
}
if (!cont)
first=first+i;
else {
CleanMAPBuf(p);
for (i=0;i<cnt;i++) {
SetFSBuf(p,first+i,0);
if (i+1==cnt)
p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF;
else
p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1;
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p,0);
for (i=0;i<cnt;i++) {
SetFSBuf(p,first+i,1);
if (i+1==cnt)
p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF;
else
p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1;
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p,1);
break;
}
}
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
return first;
}
Bool FAT32DirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempde,Bool free_old_chain)
{
//See $LK,"::/Doc/CutCorners.TXT"$.
CFAT32DirEntry *buf,*last_buf,*temp_buf,de[3];
I64 i,attr,avail_cnt,de_cnt,c,
cur_dir_entry,entries_per_cluster,
cur_dir_cluster,xsum=0,last_dir_cluster=INVALID_CLUSTER;
U8 ch;
Bool written=FALSE,unlock,unlock_break;
CDirEntry long_name;
FAT32DirFill(&de,tempde,&de_cnt);
MemSet(&long_name,0,sizeof(CDirEntry));
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf =MAlloc(BLK_SIZE*p->spc);
last_buf=CAlloc(BLK_SIZE*p->spc);
entries_per_cluster=p->spc<<FAT32_ENTRIES_BITS;
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5 && attr&_ATTR_LONG_NAME_MASK==_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));
WBlks(p,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=de_cnt-1; //gets inc'ed
written=TRUE;
} else if (ch!=0xE5 && !(attr&_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,tempde->name)) {
if (free_old_chain)
FAT32FreeClusters(p,buf[cur_dir_entry].cluster_lo+
buf[cur_dir_entry].cluster_hi<<16);
if (!written) {
MemCpy(&buf[cur_dir_entry],&de[de_cnt-1],sizeof(CFAT32DirEntry));
WBlks(p,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->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&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
*buf[cur_dir_entry-i++].name=0xE5;
i--;
WBlks(p,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+(cur_dir_entry-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS);
if (i==cur_dir_entry && 0<last_dir_cluster<0x0FFFFFF8) {
i=1;
while (i<=entries_per_cluster &&
last_buf[entries_per_cluster-i].attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
*last_buf[entries_per_cluster-i++].name=0xE5;
if (--i>0)
WBlks(p,&buf[(entries_per_cluster-i)&-FAT32_ENTRIES_PER_BLK],
p->data+last_dir_cluster*p->spc
+(entries_per_cluster-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_cluster) {
last_dir_cluster=cur_dir_cluster;
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
c=ClusterNumNext(p,cur_dir_cluster);
if (!(0<c<0x0FFFFFF8)) {
c=ClustersAlloc(p,cur_dir_cluster,1,FALSE);
MemSet(buf,0,BLK_SIZE*p->spc);
WClusters(p,buf,c,1);
} else
RClusters(p,buf,c,1);
cur_dir_cluster=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;
WBlks(p,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=avail_cnt;
if (cur_dir_entry==entries_per_cluster) {
last_dir_cluster=cur_dir_cluster;
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
cur_dir_cluster=ClustersAlloc(p,cur_dir_cluster,1);
cur_dir_entry=0;
MemSet(buf,0,BLK_SIZE*p->spc);
WClusters(p,buf,cur_dir_cluster,1);
}
}
MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry));
WBlks(p,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc+
cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=de_cnt;
if (cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClustersAlloc(p,cur_dir_cluster,1);
MemSet(buf,0,BLK_SIZE*p->spc);
WClusters(p,buf,cur_dir_cluster,1);
} else {
MemSet(&buf[cur_dir_entry],0,sizeof(CFAT32DirEntry));
WBlks(p,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
}
}
Free(last_buf);
Free(buf);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return FALSE;
}
I64 FAT32FilesDel(CPrt *p,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,
Bool del_dir,Bool print_msg)
{
CFAT32DirEntry *buf,*last_buf,*temp_buf;
I64 i,result=0,attr,xsum=0,last_dir_cluster=INVALID_CLUSTER,
cur_dir_entry,entries_per_cluster,cur_dir_cluster;
U8 ch;
Bool unlock_break;
CDirEntry long_name;
MemSet(&long_name,0,sizeof(CDirEntry));
try {
unlock_break=BreakLock;
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf =MAlloc(BLK_SIZE*p->spc);
last_buf=CAlloc(BLK_SIZE*p->spc);
entries_per_cluster=p->spc<<FAT32_ENTRIES_BITS;
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5 && ch!='.') {
if (attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr & _ATTR_VOL_ID) &&
(del_dir || !(attr & _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 & _ATTR_DIR)) result++;
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&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
*buf[cur_dir_entry-i++].name=0xE5;
i--;
WBlks(p,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+(cur_dir_entry-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS);
if (i==cur_dir_entry && last_dir_cluster!=INVALID_CLUSTER) {
i=1;
while (i<=entries_per_cluster &&
last_buf[entries_per_cluster-i].attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
*last_buf[entries_per_cluster-i++].name=0xE5;
if (--i>0)
WBlks(p,&buf[(entries_per_cluster-i)&-FAT32_ENTRIES_PER_BLK],
p->data+last_dir_cluster*p->spc
+(entries_per_cluster-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS);
}
FAT32FreeClusters(p,buf[cur_dir_entry].cluster_lo+
buf[cur_dir_entry].cluster_hi<<16);
}
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
last_dir_cluster=cur_dir_cluster;
cur_dir_cluster=ClusterNumNext(p,cur_dir_cluster,1);
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
}
}
Free(buf);
Free(last_buf);
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return result;
}
I64 FAT32FileWrite(CPrt *p,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 (p->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else if (!CFileNameTo(de.name,name))
PrintErr("Invalid FileName.\n");
else {
FAT32FilesDel(p,cur_dir,de.name,0,FALSE,FALSE);
if (attr & _ATTR_CONTIGUOUS)
contiguous=TRUE;
else
contiguous=FALSE;
de.size=size;
if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)
c=ClustersAlloc(p,0,(blk_cnt+p->spc-1)/p->spc,contiguous);
else
c=0x0FFFFFFF;
de.cluster=c;
de.attr=attr;
de.datetime=cdt;
if (blk_cnt)
WClustersBlks(p,buf,c,blk_cnt);
FAT32DirNew(p,cur_dir,&de,TRUE);
}
return c;
}
CDirEntry *FAT32FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL,I64 *_dir_size=NULL)
{
CPrt *p=Fs->cur_prt;
CFAT32DirEntry *buf;
I64 attr,xsum=0,dir_size=0,sub_dir_size,
cur_dir_cluster,cur_dir_entry,entries_per_cluster;
U8 ch;
CDirEntry *result=NULL,*tempde,long_name;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
try {
MemSet(&long_name,0,sizeof(CDirEntry));
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
buf=MAlloc(BLK_SIZE*p->spc);
entries_per_cluster=p->spc<<FAT32_ENTRIES_BITS;
RClusters(Fs->cur_prt,buf,cur_dir_cluster,1);
dir_size+=Fs->cur_prt->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&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr&_ATTR_VOL_ID)) {
tempde=MAlloc(sizeof(CDirEntry));
if (xsum==FATNameXSum(buf[cur_dir_entry].name))
MemCpy(tempde,&long_name,sizeof(CDirEntry));
else
MemSet(tempde,0,sizeof(CDirEntry));
if (FAT32CDirFill(tempde,&buf[cur_dir_entry])) {
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && attr&_ATTR_DIR && *tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
PrtUnlock(p);
if (Cd(tempde->name)) {
tempde->sub=FAT32FilesFind(files_find_mask,fuf_flags,tempde,&sub_dir_size);
tempde->size=sub_dir_size;
Cd("..");
}
PrtLock(p);
} else if ((attr&_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempde->name=='.' && attr&_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
} else
DirEntryDel(tempde);
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClusterNumNext(p,cur_dir_cluster);
if (cur_dir_cluster==INVALID_CLUSTER)
break;
else {
RClusters(p,buf,cur_dir_cluster,1);
dir_size+=Fs->cur_prt->spc*BLK_SIZE;
cur_dir_entry=0;
}
}
}
Free(buf);
PrtUnlock(p);
} catch
PrtUnlock(p);
if (_dir_size)
*_dir_size=dir_size;
return result;
}
Bool FAT32MkDir(CPrt *p,U8 *cur_dir,U8 *name)
{
I64 size=p->spc<<BLK_SIZE_BITS,c,
cur_dir_cluster=Name2DirCluster(p,cur_dir);
U8 *buf=CAlloc(size);
CDirEntry d_native;
CFAT32DirEntry *dFAT=buf;
Bool unlock_break;
try {
unlock_break=BreakLock;
c=FileWrite(name,buf,size,0,_ATTR_DIR,FALSE);
MemSet(&d_native,0,sizeof(CDirEntry));
d_native.attr=_ATTR_DIR;
*d_native.name='.';
d_native.name[1]=0;
d_native.cluster=c;
d_native.size=0;
d_native.datetime=Now;
FAT32DirFill(dFAT,&d_native);
dFAT++;
MemSet(&d_native,0,sizeof(CDirEntry));
d_native.attr=_ATTR_DIR;
*d_native.name='.';
d_native.name[1]='.';
d_native.name[2]=0;
d_native.cluster=cur_dir_cluster;
d_native.size=0;
d_native.datetime=Now;
FAT32DirFill(dFAT,&d_native);
WClusters(p,buf,c,1);
Free(buf);
if (unlock_break)
BreakUnlock;
} catch
if (unlock_break)
BreakUnlock;
return TRUE;
}
+283
View File
@@ -0,0 +1,283 @@
//ISO1 is ISO9660
//ISO2 is ISO13490
//ISO3 is ISO13346
Bool ISOPrtInit(CPrt *p,I64 blk)
{
CBlkDev *bdev=p->bdev;
I64 spc=bdev->blk_size>>BLK_SIZE_BITS,i=blk/spc;
CISO1PriDesc *iso=MAlloc(bdev->blk_size);
CISO1DirEntry *de;
Bool unlock,result=FALSE;
U8 buf[8];
try {
unlock=PrtLock(p);
p->type=PT_ISO9660; //default
p->spc=spc;
p->offset=p->data=p->root_cluster=p->size=0;
while (TRUE) {
p->size=MaxI64(p->size,(i+1)*spc);
RBlks(p,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:
p->type=PT_ISO9660;
switch (iso->type) {
case ISO1T_SUPPLEMENTARY_DESC:
p->data=0;
de=&iso->root_dir_record;
p->root_cluster=de->loc.little;
p->size=iso->vol_space_size.little*bdev->blk_size>>BLK_SIZE_BITS;
result=TRUE;
goto ipi_done;
case ISO1T_TERMINATOR:
throw('Prt');
}
break;
default: //Its normal for ISO13346 to read NULL blk as terminator
PrintErr("File System Not Supported\n");
throw('Prt');
}
i++;
}
ipi_done:
Free(iso);
if (unlock)
PrtUnlock(p);
} catch {
p->type=PT_ISO9660;
p->spc=spc;
p->offset=p->data=p->root_cluster=0;
Free(iso);
if (unlock)
PrtUnlock(p);
}
return result;
}
U0 Date2ISO1(CISO1Date *dst,CDate cdt)
{
CDateStruct ds;
Date2Struct(&ds,cdt);
dst->year=ds.year-ISO1_BASE_YEAR;
dst->mon=ds.mon;
dst->day=ds.day_of_mon;
dst->hour=ds.hour;
dst->min=ds.min;
dst->sec=ds.sec;
dst->sec100=ds.sec100;
}
CDate ISO1DateStruct2CDate(CISO1Date *dt)
{
CDateStruct ds;
MemSet(&ds,0,sizeof(CDateStruct));
ds.day_of_mon=dt->day;
ds.mon=dt->mon;
ds.year=dt->year+ISO1_BASE_YEAR;
ds.sec100=dt->sec100;
ds.sec=dt->sec;
ds.min=dt->min;
ds.hour=dt->hour;
return Struct2Date(&ds);
}
Bool ISO1FromName(U8 *dst,U8 *src)
{
I64 i,j,n;
MemSet(dst,0,CDIR_FILENAME_LEN);
n=*src++;
if (n==1 && !*src) {
*dst='.';
} else if (n==1 && *src==1) {
*dst='.';
dst[1]='.';
} else {
n>>=1;
j=0;
for (i=0;i<n;i++) {
src++;
if (*src==';')
break;
if (Bt(chars_bitmap_filename,*src)) {
if (j>=CDIR_FILENAME_LEN-1)
return FALSE;
dst[j++]=*src++;
} else
return FALSE;
}
}
return FileNameChk(dst);
}
Bool ISO1CDirFill(CDirEntry *tempde,CISO1DirEntry *de)
{
Bool result;
MemSet(tempde,0,sizeof(CDirEntry));
result=ISO1FromName(tempde->name,&de->name_len);
tempde->cluster=de->loc.little;
tempde->size=de->size.little;
tempde->attr=FileAttr(tempde->name);
if (de->flags & ISO1_ATTR_DIR)
tempde->attr|=_ATTR_DIR;
tempde->datetime=ISO1DateStruct2CDate(&de->date);
return result;
}
Bool ISO1FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,I64 fuf_flags=0)
{ //$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$
CISO1DirEntry *isoptr,*buf;
U8 dname[CDIR_FILENAME_LEN];
Bool result=FALSE,unlock;
I64 i;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
PrtChk(p);
if (p->type!=PT_ISO9660)
PrintErr("Not ISO9660 Partition\n");
else
try {
unlock=PrtLock(p);
isoptr=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(Fs->cur_prt,isoptr,cur_dir_cluster,1);
if (isoptr->name_len==1 && !isoptr->name) { //curdir
i=(isoptr->size.little+p->spc<<BLK_SIZE_BITS-1)/p->spc<<BLK_SIZE_BITS;
buf=MAlloc(p->spc<<BLK_SIZE_BITS*i);
RClusters(Fs->cur_prt,buf,cur_dir_cluster,i);
Free(isoptr);
} else {
buf=isoptr;
i=1;
}
i*=p->spc<<BLK_SIZE_BITS;
isoptr=buf;
while (i>0) {
if (!isoptr->len) {
isoptr(U8 *)++;
i--;
} else {
ISO1FromName(dname,&isoptr->name_len);
if (*dname) {
if (!StrCmp(name,dname)) {
result=ISO1CDirFill(_result,isoptr);
if (result &&
!(fuf_flags&FUF_JUST_DIRS && !(_result->attr & _ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && _result->attr & _ATTR_DIR) )
goto exit_this;
else
result=FALSE;
}
}
i-=isoptr->len;
isoptr(U8 *)+=isoptr->len;
}
}
exit_this:
Free(buf);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U8 *ISO1FileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
PrtChk(p);
*_size=0;
*_attr=0;
if (p->type!=PT_ISO9660)
PrintErr("Not ISO9660 Partition\n");
else
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
if (ISO1FileFind(p,cur_dir_cluster,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.cluster;
c=RClustersBlks(p,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
PrtUnlock(p);
} catch
PrtUnlock(p);
return buf;
}
Bool ISO1Cd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_prt->type!=PT_ISO9660)
PrintErr("Not ISO9660 Partition\n");
else if (ISO1FileFind(Fs->cur_prt,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
CDirEntry *ISO1FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL)
{
CPrt *p=Fs->cur_prt;
CISO1DirEntry *buf,*buf2,*isoptr;
I64 i,cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
CDirEntry *result=NULL,*tempde;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
isoptr=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(Fs->cur_prt,isoptr,cur_dir_cluster,1);
if (isoptr->name_len==1 && !isoptr->name) { //curdir
i=(isoptr->size.little+p->spc<<BLK_SIZE_BITS-1)/p->spc<<BLK_SIZE_BITS;
buf=MAlloc(p->spc<<BLK_SIZE_BITS*i);
RClusters(Fs->cur_prt,buf,cur_dir_cluster,i);
Free(isoptr);
} else {
buf=isoptr;
i=1;
}
buf2=buf;
i*=p->spc<<BLK_SIZE_BITS;
while (i>0) {
if (!buf->len) {
buf(U8 *)++;
i--;
} else {
tempde=MAlloc(sizeof(CDirEntry));
if (ISO1CDirFill(tempde,buf)) {
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempde->attr&_ATTR_DIR && *tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
if (Cd(tempde->name)) {
tempde->sub=ISO1FilesFind(files_find_mask,fuf_flags,tempde);
Cd("..");
}
} else if ((tempde->attr & _ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempde->name=='.' && tempde->attr&_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
} else
DirEntryDel(tempde);
i-=buf->len;
buf(U8 *)+=buf->len;
}
}
Free(buf2);
return result;
}
+632
View File
@@ -0,0 +1,632 @@
// See $LK,"RedSea File System",A="FI:::/Doc/RedSea.TXT"$
U0 RedSeaFSFreeFreeLst(CPrt *p)
{
CFreeLst *tempf,*tempf1;
Bool unlock;
try {
unlock=PrtLock(p);
if (tempf=p->next_free) {
while (tempf!=&p->next_free) {
tempf1=tempf->next;
Free(tempf);
tempf=tempf1;
}
}
p->next_free=NULL;
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 RedSeaFSFreeLstBuild(CPrt *p)
{
Bool unlock;
CFreeLst *tempf;
I64 i,first=0,max_cluster=p->size+p->offset-p->data;
try {
unlock=PrtLock(p);
if (p->next_free)
RedSeaFSFreeFreeLst(p);
QueInit(&p->next_free);
while (first<max_cluster) {
i=0; //count free clusters
while (first+i<max_cluster) {
SetFSBuf(p,first+i);
if (Bt(p->cur_map_blk,(first+i)&(BLK_SIZE<<3-1)))
break;
else
i++;
}
if (i) {
tempf=AMAlloc(sizeof(CFreeLst));
tempf->size=i;
tempf->start=first;
QueIns(tempf,p->last_free);
}
first+=i+1;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 RedSeaFSPrtInit(CPrt *p)
{
CBootStruct br;
Bool unlock;
try {
unlock=PrtLock(p);
RBlks(p,&br,p->offset,1);
if (br.signature!=MBR_PT_REDSEA || br.signature2!=0xAA55)
throw('Prt');
p->type=PT_REDSEA;
RedSeaFSFreeFreeLst(p);
p->spc=1;
p->size=br.sects;
p->data=p->offset+br.bitmap_sects;
p->root_cluster=br.root_cluster;
p->map1=p->map2=p->offset+1;
MapBufAlloc(p,1);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
Bool RedSeaFSDrvValidate(U8 drv_let)
{
CPrt *p;
CBootStruct br;
Bool result=FALSE;
try {
p=Drv2Prt(drv_let);
if (p->type==PT_REDSEA && RBlks(p,&br,p->offset,1) &&
br.signature==MBR_PT_REDSEA && br.signature2==0xAA55 &&
br.sects==p->size)
result=TRUE;
} catch
Fs->catch_except=TRUE;
return result;
}
U0 RedSeaFSFmt(U8 drv_let,Bool quick=TRUE)
{
U8 *root_dir;
CDirEntry *d_native;
CBootStruct *br=CAlloc(BLK_SIZE);
CPrt *p=Drv2Prt(drv_let);
I64 i,n;
try {
PrtLock(p);
// SetDrvType(drv_let,PT_REDSEA);
SetDrvType(drv_let,PT_FAT32);
p->type=PT_REDSEA;
br->signature=MBR_PT_REDSEA;
br->signature2=0xAA55;
br->sects=p->size;
n=(br->sects+BLK_SIZE<<3-1)/BLK_SIZE<<3;
br->bitmap_sects=n;
br->unique_id=GetTSC^Now()(U64);
br->root_cluster=0;
if (quick)
i=n+1;
else
i=p->size;
WZeroBlks(p,p->offset,i);
WBlks(p,br,p->offset,1);
RedSeaFSPrtInit(p);
ClustersAlloc(p,0,1,FALSE); //Alloc #1
br->root_cluster=ClustersAlloc(p,0,1,FALSE);
WBlks(p,br,p->offset,1);
root_dir=CAlloc(BLK_SIZE);
d_native=root_dir-offset(CDirEntry.start);
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
*d_native->name='.';
d_native->cluster=br->root_cluster;
d_native->size=BLK_SIZE;
d_native->datetime=Now;
d_native(U8 *)+=CDIR_SIZE;
*d_native->name='.';
d_native->name[1]='.';
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
d_native->cluster=br->root_cluster;
d_native->datetime=Now;
WBlks(p,root_dir,p->data+br->root_cluster,1);
RedSeaFSPrtInit(p);
PrtUnlock(p);
} catch
PrtUnlock(p);
Free(br);
Free(root_dir);
}
Bool RedSeaFSFileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,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 result=FALSE,unlock;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
MemSet(_result,0,sizeof(CDirEntry));
PrtChk(p);
if (p->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else if (!CFileNameTo(dname,name))
PrintErr("Invalid FileName.\n");
else
try {
unlock=PrtLock(p);
buf2=MAlloc(BLK_SIZE);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,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 & _ATTR_DELETED) &&
!(fuf_flags&FUF_JUST_DIRS && !(ptr->attr & _ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && ptr->attr & _ATTR_DIR) &&
!StrCmp(dname,ptr->name)) {
MemCpy(&_result->attr,&ptr->attr,CDIR_SIZE);
result=TRUE;
goto exit_this;
}
ptr(U8 *)+=CDIR_SIZE;
}
exit_this:
Free(buf);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U8 *RedSeaFSFileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
PrtChk(p);
*_size=0;
*_attr=0;
if (p->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
if (RedSeaFSFileFind(p,cur_dir_cluster,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.cluster;
c=RClustersBlks(p,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
PrtUnlock(p);
} catch
PrtUnlock(p);
return buf;
}
Bool RedSeaFSCd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_prt->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else if (RedSeaFSFileFind(Fs->cur_prt,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
U0 RedSeaFSFreeClusters(CPrt *p,I64 c,I64 cnt)
{
CFreeLst *tempf;
Bool found=FALSE,unlock,unlock_break;
PrtChk(p);
if (!c) return;
if (p->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
if (!p->next_free)
RedSeaFSFreeLstBuild(p);
tempf=p->next_free;
while (!found && tempf!=&p->next_free) {
if (tempf->start+tempf->size==c) {
tempf->size+=cnt;
found=TRUE;
} else if (c+cnt==tempf->start) {
tempf->size+=cnt;
tempf->start=c;
found=TRUE;
}
tempf=tempf->next;
}
if (!found) {
tempf=AMAlloc(sizeof(CFreeLst));
tempf->size=cnt;
tempf->start=c;
QueIns(tempf,p->last_free);
}
while (cnt-->0) {
SetFSBuf(p,c);
LBtr(p->cur_map_blk,c&(BLK_SIZE<<3-1));
LBts(p->buffered_map_dirty_bits,0);
c++;
}
CleanMAPBuf(p);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
}
I64 RedSeaFSAllocClusters(CPrt *p,I64 cnt)
{
CFreeLst *tempf,*best_free=NULL;
I64 i,first,best_size=MAX_I64;
Bool unlock,unlock_break;
if (cnt<=0)
Dbg;
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
if (!p->next_free)
RedSeaFSFreeLstBuild(p);
tempf=p->next_free;
while (tempf!=&p->next_free) {
if (tempf->size>=cnt && tempf->size<best_size) {
best_free=tempf;
best_size=tempf->size;
if (tempf->size==cnt)
break;
}
tempf=tempf->next;
}
if (!best_free)
Dbg;
first=best_free->start;
for (i=0;i<cnt;i++) {
SetFSBuf(p,first+i);
LBts(p->cur_map_blk,(first+i)&(BLK_SIZE<<3-1));
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p);
if (best_free->size-=cnt)
best_free->start+=cnt;
else {
QueRem(best_free);
Free(best_free);
}
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return first;
}
Bool RedSeaFSDirNew(CPrt *p,U8 *cur_dir,CDirEntry *de,Bool free_old_chain)
{
CDirEntry *buf,*buf2,*ptr,de2;
CBootStruct *br;
I64 c,ch,i=1,j=0,n=BLK_SIZE/CDIR_SIZE,dir_size,cur_dir_cluster;
Bool written=FALSE,unlock,unlock_break;
U8 *temp,*parent_dir;
try {
unlock_break=BreakLock;
de->attr|=_ATTR_CONTIGUOUS;
unlock=PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf2=MAlloc(BLK_SIZE);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,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,&de->start,CDIR_SIZE);
if ((i+1)*CDIR_SIZE+j<<BLK_SIZE_BITS<dir_size)
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,p->data+cur_dir_cluster+j,1);
else {
buf2=CAlloc(dir_size+BLK_SIZE);
MemCpy(buf2,buf,dir_size);
RedSeaFSFreeClusters(p,cur_dir_cluster,dir_size>>BLK_SIZE_BITS);
dir_size+=BLK_SIZE;
c=ClustersAlloc(p,0,dir_size>>BLK_SIZE_BITS,TRUE);
Free(buf);
buf=buf2;
ptr=buf(U8 *)-offset(CDirEntry.start);
ptr->size=dir_size;
ptr->cluster=c;
WClustersBlks(p,buf,c,dir_size>>BLK_SIZE_BITS);
if (cur_dir_cluster==p->root_cluster) {
br=CAlloc(BLK_SIZE);
RBlks(p,br,p->offset,1);
br->root_cluster=c;
WBlks(p,br,p->offset,1);
Free(br);
p->root_cluster=c;
} else {
temp=StrNew(cur_dir);
parent_dir=StrNew(cur_dir);
StrLastRem(parent_dir,"/",temp);
if (!*parent_dir) {
Free(parent_dir);
parent_dir=StrNew("/");
}
if (RedSeaFSFileFind(p,Name2DirCluster(p,parent_dir),
temp,&de2,FUF_JUST_DIRS)) {
de2.cluster=c;
de2.size=dir_size;
RedSeaFSDirNew(p,parent_dir,&de2,FALSE);
} else
Dbg;
Free(temp);
Free(parent_dir);
}
}
break;
} else if (ptr->attr & _ATTR_DELETED) {
if (!written) {
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,p->data+cur_dir_cluster+j,1);
written=TRUE;
}
} else {
if (!StrCmp(de->name,ptr->name)) {
if (free_old_chain)
RedSeaFSFreeClusters(p,ptr->cluster,
(ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS);
if (!written)
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
else
ptr->attr|=_ATTR_DELETED;
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,p->data+cur_dir_cluster+j,1);
break;
}
}
ptr(U8 *)+=CDIR_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return FALSE;
}
I64 RedSeaFSFilesDel(CPrt *p,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,
Bool del_dir,Bool print_msg)
{
CDirEntry *buf,*buf2,*ptr;
I64 i=0,result=0,ch,j=0,n=BLK_SIZE/CDIR_SIZE,cur_dir_cluster;
Bool unlock_break;
try {
unlock_break=BreakLock;
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf2=MAlloc(BLK_SIZE);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,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 & _ATTR_DELETED) && ch!='.' && (del_dir ||
!(ptr->attr & _ATTR_DIR)) &&
FilesFindMatch(ptr->name,files_find_mask,fuf_flags)) {
if (!(ptr->attr & _ATTR_DIR)) result++;
if (print_msg)
"Del %s\n",ptr->name;
ptr->attr|=_ATTR_DELETED;
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,p->data+cur_dir_cluster+j,1);
RedSeaFSFreeClusters(p,ptr->cluster,(ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS);
}
ptr(U8 *)+=CDIR_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return result;
}
I64 RedSeaFSFileWrite(CPrt *p,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 (p->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else if (!CFileNameTo(de.name,name))
PrintErr("Invalid FileName.\n");
else {
RedSeaFSFilesDel(p,cur_dir,de.name,0,FALSE,FALSE);
de.size=size;
if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)
c=ClustersAlloc(p,0,blk_cnt,TRUE); //Always contiguous
else
c=INVALID_CLUSTER;
de.cluster=c;
de.attr=attr|_ATTR_CONTIGUOUS;
de.datetime=cdt;
if (blk_cnt)
WClustersBlks(p,buf,c,blk_cnt);
RedSeaFSDirNew(p,cur_dir,&de,TRUE);
}
return c;
}
CDirEntry *RedSeaFSFilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL)
{
CPrt *p=Fs->cur_prt;
CDirEntry *buf,*buf2,*ptr,*result=NULL,*tempde;
I64 ch,cur_dir_cluster;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
buf2=MAlloc(BLK_SIZE);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
Free(buf2);
ptr=buf(U8 *)-offset(CDirEntry.start);
*ptr->name='.';
ptr->name[1]=0;
ptr(U8 *)+=CDIR_SIZE;
ptr->cluster=Name2ParentDirCluster(p,Fs->cur_dir);
ptr(U8 *)-=CDIR_SIZE;
while (TRUE) {
if (!(ch=*ptr->name))
break;
else if (!(ptr->attr & _ATTR_DELETED)) {
tempde=CAlloc(sizeof(CDirEntry));
MemCpy(&tempde->start,&ptr->start,CDIR_SIZE);
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempde->attr&_ATTR_DIR && *tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
PrtUnlock(p);
if (Cd(tempde->name)) {
tempde->sub=RedSeaFSFilesFind(files_find_mask,fuf_flags,tempde);
Cd("..");
}
PrtLock(p);
} else if ((tempde->attr&_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempde->name=='.' && tempde->attr&_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
}
ptr(U8 *)+=CDIR_SIZE;
}
Free(buf);
PrtUnlock(p);
} catch
PrtUnlock(p);
return result;
}
Bool RedSeaFSMkDir(CPrt *p,U8 *cur_dir,U8 *name)
{
I64 size=BLK_SIZE,c,cur_dir_cluster=Name2DirCluster(p,cur_dir);
U8 *buf=CAlloc(size);
CDirEntry *d_native=buf-offset(CDirEntry.start);
Bool unlock_break;
try {
unlock_break=BreakLock;
c=FileWrite(name,buf,size,0,_ATTR_DIR,FALSE);
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
StrCpy(d_native->name,name);
d_native->cluster=c;
d_native->size=size;
d_native->datetime=Now;
d_native(U8 *)+=CDIR_SIZE;
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
*d_native->name='.';
d_native->name[1]='.';
d_native->name[2]=0;
d_native->cluster=cur_dir_cluster;
d_native->size=0;
d_native->datetime=Now;
WClusters(p,buf,c,1);
Free(buf);
if (unlock_break)
BreakUnlock;
} catch
if (unlock_break)
BreakUnlock;
return TRUE;
}