SparrowOSTS_121127.ISO
This commit is contained in:
1 parent
0e9364ff4c
commit
e57428affb
1218 files changed
+247142
-165507
No files matched your search
@@ -0,0 +1,31 @@
|
||||
//See $LK,"::/SparrowOS/Doc/Acknowledgements.TXT.Z","FI:::/SparrowOS/Doc/Acknowledgements.TXT.Z"$ (2).
|
||||
|
||||
#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
|
||||
@@ -0,0 +1,652 @@
|
||||
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) {
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(0);
|
||||
bdev->flags&=~(BDF_INITIALIZED|BDF_INIT_IN_PROGRESS);
|
||||
}
|
||||
bdev->owning_task=0;
|
||||
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=0;
|
||||
LBtr(&p->locked_flags,Plf_LOCKED);
|
||||
Yield; //Prevent deadlock
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Bool BlkDevInit(CBlkDev *bdev)
|
||||
{
|
||||
CPrt *p=Drv2Prt(bdev->drv_let_base),*p2;
|
||||
Bool old_preempt=Preempt(OFF),result=FALSE;
|
||||
if (!(bdev->flags & BDF_INITIALIZED)) {
|
||||
bdev->flags|=BDF_INITIALIZED |
|
||||
BDF_INIT_IN_PROGRESS;
|
||||
switch(bdev->type) {
|
||||
case BDT_RAM:
|
||||
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_NATIVE;
|
||||
if (sys_boot_code.u8[0]!=BOOT_CODE_RAM ||
|
||||
!NativeFSDrvValidate(bdev->drv_let_base))
|
||||
NativeFSFmt(bdev->drv_let_base);
|
||||
else {
|
||||
p->size=bdev->max_blk+1;
|
||||
NativeFSPrtInit(p);
|
||||
}
|
||||
break;
|
||||
case BDT_ATA:
|
||||
bdev->max_reads=128;
|
||||
bdev->max_writes=1;
|
||||
bdev->read_freq=2000;
|
||||
bdev->write_freq=500;
|
||||
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;
|
||||
bdev->read_freq=1000;
|
||||
bdev->write_freq=250;
|
||||
ATAInit(bdev);
|
||||
p->size=bdev->max_blk+1;
|
||||
break;
|
||||
case BDT_NON_NATIVE_FILE:
|
||||
bdev->max_reads=128;
|
||||
bdev->max_writes=128;
|
||||
bdev->read_freq=2000;
|
||||
bdev->write_freq=500;
|
||||
if (bdev->flags & BDF_FMT)
|
||||
NativeFSFmt(bdev->drv_let_base,TRUE);
|
||||
else {
|
||||
p2=Drv2Prt(bdev->non_native_drv);
|
||||
bdev->min_blk=p->offset;
|
||||
bdev->max_blk=p2->offset+p2->size-1; //temp
|
||||
p->size=p2->size-(p->offset-p2->offset); //temp
|
||||
NativeFSPrtInit(p);
|
||||
bdev->max_blk=p->offset+p->size-1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (bdev->flags & BDF_READ_CACHE)
|
||||
DskCacheInvalidate(p);
|
||||
bdev->flags&=~BDF_INIT_IN_PROGRESS;
|
||||
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 (Bt(&bdev->locked_flags,BDlf_LOCKED) && bdev->owning_task==Fs)
|
||||
BlkDevUnlock(bdev,TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
U0 PrtsRelease()
|
||||
{
|
||||
I64 i;
|
||||
CPrt *p;
|
||||
for (i=0;i<NUM_PRTS;i++) {
|
||||
p=&sys_prts[i];
|
||||
if (Bt(&p->locked_flags,Plf_LOCKED) && p->owning_task==Fs)
|
||||
PrtUnlock(p,TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
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 SetNativeBuf(CPrt *p,I64 c,I64 map_select=-1)
|
||||
{
|
||||
I64 MAP_blk_num;
|
||||
if (c==INVALID_CLUSTER)
|
||||
throw(EXCEPT_PRT,1);
|
||||
if (p->type==PT_FAT32)
|
||||
MAP_blk_num=c/(BLK_SIZE>>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_NATIVE)
|
||||
{
|
||||
I64 i,j,ext_base,num_prt,offset,cur_type;
|
||||
CMasterBoot mbr;
|
||||
CBlkDev *bdev=Drv2BlkDev(drv_let);
|
||||
num_prt=bdev->drv_let_base-'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 (num_prt+'A'==ToUpper(drv_let)) {
|
||||
switch (type) {
|
||||
case PT_NATIVE:
|
||||
mbr.p[i].type=MBR_PT_NATIVE;
|
||||
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;
|
||||
}
|
||||
num_prt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
PrtChk(p);
|
||||
if (cnt<=0) return result;
|
||||
try {
|
||||
unlock=PrtLock(p);
|
||||
BlkDevInit(bdev);
|
||||
if (p->offset && blk<p->offset || blk+cnt>p->offset+p->size)
|
||||
throw(EXCEPT_PRT,2);
|
||||
blk+=bdev->offset;
|
||||
|
||||
if (bdev->flags & BDF_READ_CACHE)
|
||||
RCache(p,&buf,&blk,&cnt);
|
||||
if (cnt>0) {
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(bdev->read_freq);
|
||||
result=(*p->rblks)(p,buf,blk,cnt);
|
||||
bdev->last_time=tS;
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(0);
|
||||
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;
|
||||
PrtChk(p);
|
||||
if (cnt<=0) return result;
|
||||
try {
|
||||
unlock=PrtLock(p);
|
||||
BlkDevInit(bdev);
|
||||
if (bdev->flags&BDF_READ_ONLY &&
|
||||
!(bdev->flags & BDF_READ_ONLY_OVERRIDE))
|
||||
throw(EXCEPT_BLKDEV,0);
|
||||
if (p->offset && blk<p->offset || blk+cnt>p->offset+p->size)
|
||||
throw(EXCEPT_PRT,3);
|
||||
blk+=bdev->offset;
|
||||
if (cnt>0) {
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(bdev->write_freq);
|
||||
result=(*p->wblks)(p,buf,blk,cnt);
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(0);
|
||||
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 (!BlkDevInit(bdev) && bdev->flags & BDF_REMOVABLE)
|
||||
DskCacheInvalidate(p);
|
||||
Drv(drv_let);
|
||||
NativeFSFreeFreeList(p);
|
||||
Preempt(old_preempt);
|
||||
}
|
||||
|
||||
|
||||
U0 PrtRep()
|
||||
{ //Partition report
|
||||
CPrt *p;
|
||||
CBlkDev *bdev;
|
||||
U16 type_u16;
|
||||
I64 i;
|
||||
"\nDefined Partitions:\n\n";
|
||||
p=sys_prts;
|
||||
for (i=0;i<NUM_PRTS;i++,p++) {
|
||||
bdev=p->bdev;
|
||||
if (type_u16=p->type.u16[0]) {
|
||||
"$$FG,PURPLE$$";
|
||||
if (p==dft_prt)
|
||||
'*';
|
||||
else
|
||||
'' CH_SPACE;
|
||||
if (Bt(&p->type,PTf_DISABLE))
|
||||
"Disabled ";
|
||||
"%C %-8Z %-9Z %04X %04X %02X$$FG$$\n%016X-%016X\n",
|
||||
Prt2Drv(p),type_u16,"ST_PRT_TYPES",
|
||||
bdev->type,"ST_BLKDEV_TYPES",bdev->base0,bdev->base1,bdev->unit,
|
||||
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_NATIVE:
|
||||
c+=cnt;
|
||||
break;
|
||||
case PT_FAT32:
|
||||
while (cnt-->0 && 0<c<0x0FFFFFF8) {
|
||||
SetNativeBuf(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_NATIVE:
|
||||
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_NATIVE:
|
||||
cont=NativeFSFileFind(p,cur_dir_cluster,
|
||||
buf2,&de,TRUE,FALSE);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
cont=FAT32FileFind(p,cur_dir_cluster,
|
||||
buf2,&de,TRUE,FALSE);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
cont=ISO1FileFind(p,cur_dir_cluster,
|
||||
buf2,&de,TRUE,FALSE);
|
||||
break;
|
||||
default:
|
||||
Dbg;
|
||||
}
|
||||
cur_dir_cluster=de.cluster;
|
||||
}
|
||||
}
|
||||
if (!cont) {
|
||||
"%s ",dirname;
|
||||
PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
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=p->root_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_NATIVE:
|
||||
cont=NativeFSFileFind(p,cur_dir_cluster,
|
||||
buf2,&de,TRUE,FALSE);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
cont=FAT32FileFind(p,cur_dir_cluster,
|
||||
buf2,&de,TRUE,FALSE);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
cont=ISO1FileFind(p,cur_dir_cluster,
|
||||
buf2,&de,TRUE,FALSE);
|
||||
break;
|
||||
default:
|
||||
Dbg;
|
||||
}
|
||||
cur_dir_cluster=de.cluster;
|
||||
}
|
||||
}
|
||||
if (!cont) {
|
||||
"%s ",dirname;
|
||||
PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
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_NATIVE:
|
||||
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 ClusersAlloc(CPrt *p,I64 c=0,I64 cnt=1,Bool contiguous=FALSE)
|
||||
{
|
||||
PrtChk(p);
|
||||
if (cnt<=0) return c;
|
||||
switch (p->type) {
|
||||
case PT_NATIVE:
|
||||
return NativeFSAllocClusters(p,cnt);
|
||||
case PT_FAT32:
|
||||
if (contiguous) {
|
||||
if (c) throw(EXCEPT_FILE,3);
|
||||
return FAT32AllocContiguousClusters(p,cnt);
|
||||
} else
|
||||
return FAT32AllocClusters(p,c,cnt);
|
||||
default:
|
||||
Dbg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,468 @@
|
||||
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 ||
|
||||
bdev->type==BDT_NON_NATIVE_FILE)
|
||||
BlkDevInit(bdev);
|
||||
}
|
||||
Fs->cur_prt=p;
|
||||
Free(Fs->cur_dir);
|
||||
Fs->cur_dir=StrNew("/");
|
||||
switch (p->type) {
|
||||
case PT_NATIVE:
|
||||
case PT_FAT32:
|
||||
case PT_ISO9660:
|
||||
return TRUE;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
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!=dft_prt)
|
||||
if (!Drv(*dirname)) return FALSE;
|
||||
} else {
|
||||
if (Fs->cur_prt!=
|
||||
Drv2Prt(*dirname))
|
||||
if (!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,".")) {
|
||||
;
|
||||
} else if (*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_NATIVE:
|
||||
result=NativeFSCd(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:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
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,"/"))
|
||||
StrCat(new_cur_dir,"/");
|
||||
StrCat(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 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))
|
||||
if (!Drv(*mask)) valid=FALSE;
|
||||
mask+=2;
|
||||
}
|
||||
if (StrStr(mask,"HOME") && 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);
|
||||
StrLastRem(buf,"/",fa->mask);
|
||||
if (*mask=='/' && !*buf)
|
||||
StrCpy(buf,"/");
|
||||
if (*buf)
|
||||
if (!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);
|
||||
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(EXCEPT_FILE);
|
||||
}
|
||||
return fa;
|
||||
}
|
||||
|
||||
CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0)
|
||||
{
|
||||
/*
|
||||
Flags:
|
||||
$LK,"FUF_RECURSE","MN:FUF_RECURSE"$ +r Recurse
|
||||
$LK,"FUF_FLATTEN_TREE","MN:FUF_FLATTEN_TREE"$ +f $BK,1$be sure to use this along with '+F'$BK,0$.
|
||||
$LK,"FUF_JUST_DIRS","MN:FUF_JUST_DIRS"$ +D just directories
|
||||
$LK,"FUF_JUST_FILES","MN:FUF_JUST_FILES"$ +F just files
|
||||
$LK,"FUF_JUST_TEXT_FILES","MN:FUF_JUST_TEXT_FILES"$ +t just text files: $LK,"TEXT_FILE_MASK","MN:TEXT_FILE_MASK"$
|
||||
$LK,"FUF_JUST_SRC_FILES","MN:FUF_JUST_SRC_FILES"$ +s just src files : $LK,"SRC_FILE_MASK","MN:SRC_FILE_MASK"$
|
||||
See $LK,"ST_FILE_UTIL_FLAGS","MN:ST_FILE_UTIL_FLAGS"$ when used in calling program taking text flags.
|
||||
*/
|
||||
CDirEntry *result;
|
||||
CFileAccess *fa=FileAccessNew(files_find_mask,TRUE);
|
||||
if (fa) {
|
||||
result=SysFilesFind(fa->mask,fuf_flags);
|
||||
FileAccessDel(fa);
|
||||
} else
|
||||
result=NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
Bool IsDir(U8 *dir_name)
|
||||
{
|
||||
U8 *mask=MSPrintF("%s/*",dir_name);
|
||||
Bool result,old_silent=Silent(ON);
|
||||
CFileAccess *fa=FileAccessNew(mask);
|
||||
if (fa) {
|
||||
FileAccessDel(fa);
|
||||
result=TRUE;
|
||||
} else
|
||||
result=FALSE;
|
||||
Free(mask);
|
||||
Silent(old_silent);
|
||||
return result;
|
||||
}
|
||||
|
||||
U0 Dir(U8 *files_find_mask="*",Bool full=FALSE)
|
||||
{
|
||||
CFileAccess *fa;
|
||||
fa=FileAccessNew(files_find_mask,TRUE);
|
||||
if (fa) {
|
||||
Dir2(fa->mask,0,full);
|
||||
FileAccessDel(fa);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
U0 Del(U8 *files_find_mask,Bool print_msg=TRUE)
|
||||
{
|
||||
CFileAccess *fa=FileAccessNew(files_find_mask);
|
||||
if (fa) {
|
||||
switch (fa->p->type) {
|
||||
case PT_NATIVE:
|
||||
NativeFSFilesDel(fa->p,Fs->cur_dir,fa->mask,0,FALSE,print_msg);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
FAT32FilesDel(fa->p,Fs->cur_dir,fa->mask,0,FALSE,print_msg);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
PutDefineErr("ST_NOT_WRITABLE");
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
FileAccessDel(fa);
|
||||
}
|
||||
}
|
||||
|
||||
U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL,Bool raw=FALSE)
|
||||
{
|
||||
CHashGeneric *temph;
|
||||
U8 *absname,*result=NULL;
|
||||
I64 size=0,attr=0;
|
||||
CFileAccess *fa;
|
||||
CArcCompress *ac=NULL;
|
||||
if (_attr) *_attr=0;
|
||||
absname=FileNameAbs(filename);
|
||||
if (!raw && (temph=HashFind(absname,adam_task->hash_table,HTT_FILE))) {
|
||||
if (FileAttr(absname) & _ATTR_COMPRESSED) {
|
||||
ac=temph->user_data0;
|
||||
if (_size) *_size=ac->expanded_size;
|
||||
if (_attr) *_attr=FileAttr(absname,*_attr);
|
||||
result=ExpandBuf(ac);
|
||||
} else {
|
||||
result=MAlloc(temph->user_data1+1);
|
||||
MemCpy(result,temph->user_data0,temph->user_data1);
|
||||
result[temph->user_data1]=0; //Terminate
|
||||
if (_size) *_size=temph->user_data1;
|
||||
}
|
||||
} else {
|
||||
fa=FileAccessNew(absname);
|
||||
if (fa) {
|
||||
switch (fa->p->type) {
|
||||
case PT_NATIVE:
|
||||
result=NativeFSFileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
result=FAT32FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
result=ISO1FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
while (!result && StrCmp(Fs->cur_dir,"/")) {
|
||||
Cd("..");
|
||||
switch (Fs->cur_prt->type) {
|
||||
case PT_NATIVE:
|
||||
result=NativeFSFileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
result=FAT32FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
result=ISO1FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr,raw,&ac);
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
"%s ",filename;
|
||||
PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
}
|
||||
FileAccessDel(fa);
|
||||
}
|
||||
if (_size) *_size=size;
|
||||
if (_attr) *_attr=attr;
|
||||
if (!raw && attr & _ATTR_RESIDENT)
|
||||
HashGenericAdd(absname,HTT_FILE,AMAllocIdentical(ac),size,0,adam_task);
|
||||
Free(ac);
|
||||
}
|
||||
Free(absname);
|
||||
return result;
|
||||
}
|
||||
|
||||
U8 *TextFileRead(U8 *filename,I64 *_attr=NULL)
|
||||
{
|
||||
return FileRead(filename,NULL,_attr);
|
||||
}
|
||||
|
||||
|
||||
Bool FileFind(U8 *filename,CDirEntry *rde=NULL,
|
||||
Bool dir_only=FALSE,Bool file_only=FALSE,Bool scan_parents=FALSE)
|
||||
{
|
||||
I64 cur_dir_cluster;
|
||||
CDirEntry de;
|
||||
CFileAccess *fa=FileAccessNew(filename);
|
||||
Bool result=FALSE;
|
||||
if (fa) {
|
||||
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
|
||||
switch (fa->p->type) {
|
||||
case PT_NATIVE:
|
||||
result=NativeFSFileFind(fa->p,cur_dir_cluster,fa->mask,
|
||||
&de,dir_only,file_only);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
result=FAT32FileFind(fa->p,cur_dir_cluster,fa->mask,
|
||||
&de,dir_only,file_only);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
result=ISO1FileFind(fa->p,cur_dir_cluster,fa->mask,
|
||||
&de,dir_only,file_only);
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
if (scan_parents) {
|
||||
while (!result && StrCmp(Fs->cur_dir,"/")) {
|
||||
Cd("..");
|
||||
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
|
||||
switch (fa->p->type) {
|
||||
case PT_NATIVE:
|
||||
result=NativeFSFileFind(fa->p,cur_dir_cluster,fa->mask,
|
||||
&de,dir_only,file_only);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
result=FAT32FileFind(fa->p,cur_dir_cluster,fa->mask,
|
||||
&de,dir_only,file_only);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
result=ISO1FileFind(fa->p,cur_dir_cluster,fa->mask,
|
||||
&de,dir_only,file_only);
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
}
|
||||
}
|
||||
FileAccessDel(fa);
|
||||
}
|
||||
if (result && rde)
|
||||
MemCpy(rde,&de,sizeof(CDirEntry));
|
||||
return result;
|
||||
}
|
||||
|
||||
I64 FileSize(U8 *filename)
|
||||
{
|
||||
CDirEntry de;
|
||||
if (FileFind(filename,&de))
|
||||
return de.size;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
I64 FileSizeExpanded(U8 *filename)
|
||||
{
|
||||
U8 buf[BLK_SIZE],*full_name;
|
||||
CPrt *p;
|
||||
CDirEntry de;
|
||||
if (FileFind(filename,&de)) {
|
||||
full_name=FileNameAbs(filename);
|
||||
p=Drv2Prt(*full_name);
|
||||
Free(full_name);
|
||||
if (p->type==PT_NATIVE && de.expanded_size)
|
||||
return de.expanded_size;
|
||||
else {
|
||||
if (de.size && FileAttr(de.name) & _ATTR_COMPRESSED) {
|
||||
RBlks(p,buf,Cluster2Blk(p,de.cluster),1);
|
||||
return (&buf)(CArcCompress *)->expanded_size;
|
||||
} else
|
||||
return de.size;
|
||||
}
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
I64 FileWrite(U8 *filename,U8 *fbuf,
|
||||
I64 size,CDate ltdt=0,I64 attr=0,Bool raw=FALSE)
|
||||
{
|
||||
I64 c=0;
|
||||
CHashGeneric *temph;
|
||||
CFileAccess *fa=FileAccessNew(filename,FALSE,TRUE);
|
||||
CArcCompress *ac=NULL;
|
||||
U8 *absname=FileNameAbs(filename);
|
||||
if (fa) {
|
||||
switch (fa->p->type) {
|
||||
case PT_NATIVE:
|
||||
c=NativeFSFileWrite(fa->p,Fs->cur_dir,fa->mask,
|
||||
fbuf,size,ltdt,attr,raw,&ac);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
c=FAT32FileWrite(fa->p,Fs->cur_dir,fa->mask,
|
||||
fbuf,size,ltdt,attr,raw,&ac);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
PutDefineErr("ST_NOT_WRITABLE");
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
if (temph=HashFind(absname,adam_task->hash_table,HTT_FILE)) {
|
||||
if (!raw && ac && attr & _ATTR_RESIDENT) {
|
||||
Free(temph->user_data0);
|
||||
temph->user_data0=AMAllocIdentical(ac);
|
||||
temph->user_data1=size;
|
||||
} else
|
||||
HashRemDel(temph,adam_task->hash_table);
|
||||
} else if (!raw && ac && attr & _ATTR_RESIDENT)
|
||||
HashGenericAdd(absname,HTT_FILE,AMAllocIdentical(ac),size,0,adam_task);
|
||||
Free(ac);
|
||||
FileAccessDel(fa);
|
||||
}
|
||||
Free(absname);
|
||||
return c;
|
||||
}
|
||||
|
||||
U0 TextFileWrite(U8 *filename,U8 *st,I64 attr=0)
|
||||
{
|
||||
FileWrite(filename,st,StrLen(st),0,attr);
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
U0 DrvDftSelect()
|
||||
{
|
||||
dft_prt=Drv2Prt(dft_drv);
|
||||
Fs->cur_prt=INVALID_PTR; //Null screws-up cache
|
||||
Fs->cur_dir=StrNew("/");
|
||||
ChgDsk(':');
|
||||
}
|
||||
|
||||
Bool CopySingleZ(U8 *f1,U8 *f2) //Just one file
|
||||
{
|
||||
U8 *file_buf=NULL;
|
||||
I64 size,attr=0,c;
|
||||
CDirEntry de;
|
||||
|
||||
if (FileFind(f1,&de,FALSE,TRUE)) {
|
||||
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 PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
} else PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
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),
|
||||
xsum=NATIVE_XSUM,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);
|
||||
xsum^=ArcXSum(buf,i);
|
||||
FWBlks(out_file,buf,FFB_NEXT_BLK,n);
|
||||
cnt-=n;
|
||||
j-=n<<BLK_SIZE_BITS;
|
||||
}
|
||||
if (in_file->de.xsum &&
|
||||
in_file->de.xsum!=xsum)
|
||||
throw(EXCEPT_ARC_XSUM);
|
||||
out_file->de.xsum=xsum;
|
||||
out_file->flags|=FF_USE_OLD_DATETIME;
|
||||
out_file->de.datetime=in_file->de.datetime;
|
||||
out_file->de.size=size;
|
||||
out_file->de.expanded_size=in_file->de.expanded_size;
|
||||
out_file->de.attr=FileAttr(f2,in_file->de.attr);
|
||||
FClose(out_file);
|
||||
FClose(in_file);
|
||||
Free(buf);
|
||||
return TRUE;
|
||||
} else PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
FClose(in_file);
|
||||
} else PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
Free(buf);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Bool MkDir(U8 *filename)
|
||||
{
|
||||
U8 *name;
|
||||
if (FileFind(filename,NULL,TRUE))
|
||||
return FALSE;
|
||||
CFileAccess *fa=FileAccessNew(filename);
|
||||
Bool result=FALSE;
|
||||
if (fa) {
|
||||
if (*fa->mask) {
|
||||
if (!FileNameChk(fa->mask))
|
||||
PutDefineErr("ST_INVALID_FILENAME");
|
||||
else {
|
||||
"Make Directory:";
|
||||
"" filename;
|
||||
NewLine;
|
||||
name=MStrUtil(fa->mask,
|
||||
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
|
||||
switch (fa->p->type) {
|
||||
case PT_NATIVE:
|
||||
result=NativeFSMkDir(fa->p,Fs->cur_dir,name);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
result=FAT32MkDir(fa->p,Fs->cur_dir,name);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
PutDefineErr("ST_NOT_WRITABLE");
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
Free(name);
|
||||
}
|
||||
}
|
||||
FileAccessDel(fa);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
U0 SysDel(U8 *wild,Bool make_mask) //this is dangerous
|
||||
{
|
||||
CFileAccess *fa=FileAccessNew(wild,make_mask);
|
||||
if (fa) {
|
||||
switch (fa->p->type) {
|
||||
case PT_NATIVE:
|
||||
NativeFSFilesDel(fa->p,Fs->cur_dir,fa->mask,0,TRUE,TRUE);
|
||||
break;
|
||||
case PT_FAT32:
|
||||
FAT32FilesDel(fa->p,Fs->cur_dir,fa->mask,0,TRUE,TRUE);
|
||||
break;
|
||||
case PT_ISO9660:
|
||||
PutDefineErr("ST_NOT_WRITABLE");
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
FileAccessDel(fa);
|
||||
}
|
||||
}
|
||||
|
||||
U0 Fmt(I64 drv_let,Bool quick=TRUE,Bool confirm=TRUE,I64 type=PT_FAT32)
|
||||
{//See $LK,"PT_FAT32","MN:PT_FAT32"$ for a list of supported file system types.
|
||||
|
||||
CPrt *p=Drv2Prt(drv_let);
|
||||
Bool old_silent=IsSilent;
|
||||
if (confirm) {
|
||||
if (!AreYouSure)
|
||||
return;
|
||||
}
|
||||
if (!p) {
|
||||
PutDefineErr("ST_INVALID_DRV");
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case PT_NATIVE:
|
||||
Silent(ON);
|
||||
Drv(drv_let);
|
||||
Silent(old_silent);
|
||||
NativeFSFmt(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:
|
||||
PutDefineErr("ST_NOT_WRITABLE");
|
||||
break;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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(EXCEPT_BLKDEV,3);
|
||||
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;
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(bdev->read_freq);
|
||||
|
||||
retry=4;
|
||||
while (--retry)
|
||||
if (ATAPIReadBlks2(bdev,buf,blk/spc,n/spc,TRUE,
|
||||
//n is 0x800 if max_reads. Up to 8 additional seconds
|
||||
tS+7.0+0.004*n/spc))
|
||||
break;
|
||||
|
||||
if (!retry)
|
||||
ATAPIReadBlks2(bdev,buf,blk/spc,n/spc,TRUE,0);
|
||||
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(0);
|
||||
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;
|
||||
if (!IsSysDeterministic)
|
||||
Preempt(ON);
|
||||
TaskInitExt; //needed for disk access
|
||||
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;
|
||||
buf=d->in_buf&1 ? d->buf1:d->buf0;
|
||||
while (d->in_buf>d->out_buf+1)
|
||||
Yield;
|
||||
FRBlks(f,buf,blk,n);
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(d->CD_bdev->write_freq);
|
||||
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(EXCEPT_BLKDEV,4);
|
||||
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(EXCEPT_BLKDEV,5);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(bdev->write_freq);
|
||||
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;
|
||||
buf=d->out_buf&1 ? d->buf1: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;
|
||||
|
||||
if (!Bt(&sys_semas[SYS_SEMA_NO_IO_SND],0))
|
||||
Snd(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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,655 @@
|
||||
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)
|
||||
{
|
||||
while (TRUE) {
|
||||
if (timeout && tS>timeout)
|
||||
return FALSE;
|
||||
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_BSY)
|
||||
Yield;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Bool ATAWaitDRQ(CBlkDev *bdev,F64 timeout)
|
||||
{
|
||||
while (TRUE) {
|
||||
if (timeout && tS>timeout)
|
||||
return FALSE;
|
||||
if (!(InU8(bdev->base0+ATAR0_STAT)&ATAS_DRQ))
|
||||
Yield;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
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,U8 *buf,I64 cnt,I64 _avail,Bool one_read,F64 timeout=0)
|
||||
{
|
||||
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) {
|
||||
if (timeout && tS>timeout)
|
||||
return FALSE;
|
||||
InU16(bdev->base0+ATAR0_DATA);
|
||||
overflow-=2;
|
||||
}
|
||||
if (one_read)
|
||||
break;
|
||||
} else
|
||||
Yield;
|
||||
}
|
||||
return ATAWaitNotBUSY(bdev,timeout);
|
||||
}
|
||||
|
||||
Bool ATAPIWritePktWord(CBlkDev *bdev,U16 w,F64 timeout=0)
|
||||
{
|
||||
if (!ATAWaitDRQ(bdev,timeout))
|
||||
return FALSE;
|
||||
OutU16(bdev->base0+ATAR0_DATA,EndianU16(w));
|
||||
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,0xBB00); //Set speed
|
||||
ATAPIWritePktWord(bdev,0xFFFF); //read at max
|
||||
ATAPIWritePktWord(bdev,0xFFFF); //write at max
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
ATAPIWritePktWord(bdev,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,0x2B00); //Seek
|
||||
ATAPIWritePktWord(bdev,native_blk>>16);
|
||||
ATAPIWritePktWord(bdev,native_blk);
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
ATAPIWritePktWord(bdev,0);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
return ATAWaitNotBUSY(bdev,0);
|
||||
}
|
||||
|
||||
Bool ATAPIStartStop(CBlkDev *bdev,Bool start,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);
|
||||
ATACmd(bdev,ATA_PACKET);
|
||||
|
||||
//Start/Stop
|
||||
if (!ATAPIWritePktWord(bdev,0x1B00,timeout)) return FALSE;
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
if (start) {
|
||||
if (!ATAPIWritePktWord(bdev,0x0100,timeout)) return FALSE;
|
||||
} else {
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
}
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) return FALSE;
|
||||
return ATAWaitNotBUSY(bdev,timeout);
|
||||
}
|
||||
|
||||
I64 ATAGetDevId(CBlkDev *bdev,U16 **_id_record,F64 timeout)
|
||||
{
|
||||
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,id_record,512,512,FALSE,timeout)) {
|
||||
Free(id_record);
|
||||
return BDT_NULL;
|
||||
}
|
||||
if (_id_record) *_id_record=id_record;
|
||||
return BDT_ATA;
|
||||
}
|
||||
|
||||
I64 ATAReadNativeMax(CBlkDev *bdev)
|
||||
{ //returns zero on err
|
||||
I64 blk=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;
|
||||
}
|
||||
|
||||
Free(bdev->dev_id_record);
|
||||
if (ATAGetDevId(bdev,&bdev->dev_id_record,0)==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,0)) {
|
||||
blk.u8[0]=InU8(bdev->base0+ATAR0_SECT);
|
||||
blk.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
|
||||
blk.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
|
||||
|
||||
OutU8(bdev->base1+ATAR1_CTRL,0x80);
|
||||
blk.u8[3]=InU8(bdev->base0+ATAR0_SECT);
|
||||
blk.u8[4]=InU8(bdev->base0+ATAR0_LCYL);
|
||||
blk.u8[5]=InU8(bdev->base0+ATAR0_HCYL);
|
||||
|
||||
if (blk>>24==blk&0xFFFFFF) {//Kludge to make qemu-kvm work
|
||||
Btr(&bdev->flags,BDf_EXT_SIZE);
|
||||
blk&=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,0)) {
|
||||
blk.u8[0]=InU8(bdev->base0+ATAR0_SECT);
|
||||
blk.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
|
||||
blk.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
|
||||
blk.u8[3]=InU8(bdev->base0+ATAR0_SELECT) & 0xF;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bdev->max_blk=blk;
|
||||
}
|
||||
|
||||
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,0x2500); //Read Capacity
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
if (!ATAGetResult(bdev,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,0x5200); //Read Track Info
|
||||
ATAPIWritePktWord(bdev,blk.u16[1]);
|
||||
ATAPIWritePktWord(bdev,blk.u16[0]);
|
||||
ATAPIWritePktWord(bdev,(sizeof(CATAPITrack)&0xFF00)>>8);
|
||||
ATAPIWritePktWord(bdev,(sizeof(CATAPITrack)&0x00FF)<<8);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
if (!ATAGetResult(bdev,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)) {
|
||||
|
||||
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,TRUE,0)) {
|
||||
if(!ATAPISetMaxSpeed(bdev))
|
||||
okay=FALSE;
|
||||
} else
|
||||
okay=FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unlock) BlkDevUnlock(bdev);
|
||||
return okay;
|
||||
}
|
||||
|
||||
Bool ATAPIWaitReady(CBlkDev *bdev,F64 timeout)
|
||||
{
|
||||
while (TRUE) {
|
||||
if (!ATAWaitNotBUSY(bdev,timeout) ||
|
||||
!ATANop(bdev,timeout) ||
|
||||
!ATAPIStartStop(bdev,TRUE,timeout))
|
||||
return FALSE;
|
||||
if (InU8(bdev->base0+ATAR0_STAT) & ATAS_DRDY &&
|
||||
!InU8(bdev->base0+ATAR0_FEAT));
|
||||
return TRUE;
|
||||
if (timeout && tS>timeout)
|
||||
return FALSE;
|
||||
ATAInit(bdev);
|
||||
Yield;
|
||||
}
|
||||
}
|
||||
|
||||
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,buf,cnt*bdev->blk_size,BLK_SIZE,FALSE,tS+1.0)) {
|
||||
if (retries--) {
|
||||
ATAWaitNotBUSY(bdev,0);
|
||||
goto retry;
|
||||
} else
|
||||
throw(EXCEPT_BLKDEV,6);
|
||||
}
|
||||
|
||||
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,NULL,tS+0.1);
|
||||
}
|
||||
|
||||
Bool ATAPIReadBlks2(CBlkDev *bdev,U8 *buf, I64 native_blk, I64 cnt,Bool lock,F64 timeout)
|
||||
{
|
||||
Bool result,unlock;
|
||||
if (cnt<=0)
|
||||
return FALSE;
|
||||
if (lock)
|
||||
unlock=BlkDevLock(bdev);
|
||||
if (!ATAPIWaitReady(bdev,timeout)) goto arb_false_done;
|
||||
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,0xA800,timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,native_blk.u16[1],timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,native_blk,timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,cnt.u16[1],timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,cnt,timeout)) goto arb_false_done;
|
||||
if (!ATAPIWritePktWord(bdev,0x0000,timeout)) goto arb_false_done;
|
||||
if (!ATAGetResult(bdev,buf,cnt*bdev->blk_size,0,FALSE,timeout)) {
|
||||
arb_false_done:
|
||||
result=FALSE;
|
||||
} else {
|
||||
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
|
||||
result=TRUE;
|
||||
}
|
||||
// ATAPIStartStop(bdev,FALSE,0);
|
||||
if (lock && unlock) BlkDevUnlock(bdev);
|
||||
return result;
|
||||
}
|
||||
|
||||
U0 ATAPIReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
|
||||
{
|
||||
CPrt *p=Drv2Prt(bdev->drv_let_base);
|
||||
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,cd_buf,blk2/spc,n,TRUE,
|
||||
//n is 0x800 if max_reads. Up to 8 additional seconds
|
||||
tS+7.0+0.004*n))
|
||||
break;
|
||||
if (!retry)
|
||||
ATAPIReadBlks2(bdev,cd_buf,blk2/spc,n,TRUE,0);
|
||||
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);
|
||||
}
|
||||
|
||||
U0 ATARBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
|
||||
{
|
||||
I64 n;
|
||||
CBlkDev *bdev=p->bdev;
|
||||
BlkDevChk(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;
|
||||
}
|
||||
}
|
||||
|
||||
//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(EXCEPT_BLKDEV,7);
|
||||
}
|
||||
}
|
||||
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,0x3500); //Sync
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
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,0x5B00); //Close
|
||||
ATAPIWritePktWord(bdev,close_field);
|
||||
ATAPIWritePktWord(bdev,track);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
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,0x0400); //FMT
|
||||
ATAPIWritePktWord(bdev,native_blk.u16[1]);
|
||||
ATAPIWritePktWord(bdev,native_blk);
|
||||
ATAPIWritePktWord(bdev,cnt.u16[1]);
|
||||
ATAPIWritePktWord(bdev,cnt);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
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,0xAA00); //Write
|
||||
ATAPIWritePktWord(bdev,native_blk.u16[1]);
|
||||
ATAPIWritePktWord(bdev,native_blk);
|
||||
ATAPIWritePktWord(bdev,cnt.u16[1]);
|
||||
ATAPIWritePktWord(bdev,cnt);
|
||||
ATAPIWritePktWord(bdev,0x0000);
|
||||
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);
|
||||
}
|
||||
|
||||
U0 ATAWBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
|
||||
{
|
||||
I64 n,spc;
|
||||
CBlkDev *bdev=p->bdev;
|
||||
Bool unlock;
|
||||
BlkDevChk(bdev);
|
||||
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,FALSE,0);
|
||||
if (unlock) BlkDevUnlock(bdev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
U0 SetBlkDevLockFwding(CBlkDev *bdev)
|
||||
{
|
||||
CBlkDev *bd1;
|
||||
I64 i;
|
||||
switch (bdev->type) {
|
||||
case BDT_RAM:
|
||||
break;
|
||||
case BDT_ATA:
|
||||
case BDT_ATAPI:
|
||||
for (i=0;i<num_blkdevs;i++) {
|
||||
bd1=&sys_blkdevs[i];
|
||||
if (bdev!=bd1 && (bd1->type==BDT_ATAPI || bd1->type==BDT_ATA) &&
|
||||
bd1->base0==bdev->base0) {
|
||||
bdev->lock_fwding=bd1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BDT_NON_NATIVE_FILE:
|
||||
bdev->lock_fwding=Drv2BlkDev(bdev->non_native_drv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
I64 BlkDevAdd(CBlkDev *bdev,Bool one_prt)
|
||||
{
|
||||
I64 i,j,ext_base,num_prt,offset;
|
||||
CPrt *p;
|
||||
CBootStruct br;
|
||||
CMasterBoot mbr;
|
||||
|
||||
bdev->bd_signature=BD_SIGNATURE_VAL;
|
||||
num_prt=bdev->drv_let_base-'A';
|
||||
p=&sys_prts[num_prt];
|
||||
MemSet(p,0,sizeof(CPrt));
|
||||
p->drv_let=num_prt+'A';
|
||||
p->pt_signature=PRT_SIGNATURE_VAL;
|
||||
p->bdev=bdev;
|
||||
p->size=bdev->max_blk+1;
|
||||
switch (bdev->type) {
|
||||
case BDT_RAM:
|
||||
p->type=PT_NATIVE;
|
||||
p->rblks=&RAMRBlks;
|
||||
p->wblks=&RAMWBlks;
|
||||
num_prt++;
|
||||
|
||||
//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.
|
||||
BlkDevInit(bdev);
|
||||
|
||||
break;
|
||||
case BDT_ATA:
|
||||
BlkDevInit(bdev);
|
||||
if (one_prt) {
|
||||
p->type=PT_NATIVE;
|
||||
p->rblks=&ATARBlks;
|
||||
p->wblks=&ATAWBlks;
|
||||
p->size=bdev->max_blk+1;
|
||||
num_prt++;
|
||||
//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) {
|
||||
p=&sys_prts[num_prt];
|
||||
MemSet(p,0,sizeof(CPrt));
|
||||
p->drv_let=num_prt+'A';
|
||||
p->pt_signature=PRT_SIGNATURE_VAL;
|
||||
p->bdev=bdev;
|
||||
p->rblks=&ATARBlks;
|
||||
p->wblks=&ATAWBlks;
|
||||
p->offset=mbr.p[i].offset+offset;
|
||||
p->size =mbr.p[i].size;
|
||||
p->type=PT_NULL;
|
||||
switch (mbr.p[i].type) {
|
||||
case MBR_PT_NATIVE:
|
||||
p->type=PT_NATIVE;
|
||||
NativeFSPrtInit(p);
|
||||
num_prt++;
|
||||
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);
|
||||
if (br.signature==MBR_PT_NATIVE) {
|
||||
p->type=PT_NATIVE;
|
||||
NativeFSPrtInit(p);
|
||||
} else {
|
||||
p->type=PT_FAT32;
|
||||
FAT32PrtInit(p);
|
||||
}
|
||||
num_prt++;
|
||||
break;
|
||||
case MBR_PT_NTFS:
|
||||
p->type=PT_NTFS;
|
||||
num_prt++;
|
||||
break;
|
||||
case 5:
|
||||
case 15:
|
||||
j=i;
|
||||
break;
|
||||
default:
|
||||
p->type=PT_UNKNOWN;
|
||||
num_prt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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->type=PT_ISO9660; //Start with this
|
||||
p->rblks=&ATARBlks;
|
||||
p->wblks=&ATAWBlks;
|
||||
p->size =0;
|
||||
num_prt++;
|
||||
break;
|
||||
case BDT_NON_NATIVE_FILE:
|
||||
p->type=PT_NATIVE;
|
||||
p->offset=bdev->non_native_offset;
|
||||
p->rblks=&NonNativeFileRBlks;
|
||||
p->wblks=&NonNativeFileWBlks;
|
||||
if (bdev->flags & BDF_FMT)
|
||||
p->size=bdev->max_blk-bdev->min_blk+1;
|
||||
num_prt++;
|
||||
break;
|
||||
}
|
||||
SetBlkDevLockFwding(bdev);
|
||||
return num_prt-(bdev->drv_let_base-'A');
|
||||
}
|
||||
|
||||
|
||||
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->ignore_except=TRUE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CATARep *ATARepFind(CATARep *root,I64 num)
|
||||
{
|
||||
CATARep *tempha=root;
|
||||
while (tempha) {
|
||||
if (tempha->num==num)
|
||||
return tempha;
|
||||
tempha=tempha->next;
|
||||
}
|
||||
return tempha;
|
||||
}
|
||||
|
||||
U0 Mount(Bool repartition=FALSE)
|
||||
{
|
||||
CBlkDev *bdev;
|
||||
I64 drv_let_base,drv_let,type,k,num_hints;
|
||||
U8 buf[32],buf2[128],buf3[128];
|
||||
Bool add;
|
||||
CATARep *root,*tempha;
|
||||
|
||||
do {
|
||||
PrtRep;
|
||||
PutDefine("ST_MOUNT_BASE_LET");
|
||||
drv_let_base=ToUpper(GetChar)-'A';
|
||||
NewLine;
|
||||
if (0<=drv_let_base<NUM_PRTS) {
|
||||
PutDefine("ST_MOUNT_DRV_TYPE");
|
||||
type=GetChar-'0';
|
||||
NewLine;
|
||||
|
||||
k=0;
|
||||
|
||||
if (type==BDT_ATA || type==BDT_ATAPI) {
|
||||
num_hints=CallExtStr("ATARep",TRUE,&root);
|
||||
do {
|
||||
if (num_hints)
|
||||
PutDefine("ST_MOUNT_BASE0_HINT");
|
||||
else
|
||||
PutDefine("ST_MOUNT_BASE0");
|
||||
GetS(buf2,128);
|
||||
} while (!A2I(buf2));
|
||||
if (1<=A2I(buf2)<=num_hints) {
|
||||
tempha=ATARepFind(root,A2I(buf2));
|
||||
SPrintF(buf2,"0x%X",tempha->base0);
|
||||
SPrintF(buf3,"0x%X",tempha->base1);
|
||||
k=tempha->unit;
|
||||
} else {
|
||||
if (type==BDT_ATAPI)
|
||||
StrCpy(buf3,"0");
|
||||
else
|
||||
do {
|
||||
PutDefine("ST_MOUNT_BASE1");
|
||||
GetS(buf3,128);
|
||||
} while (!A2I(buf3));
|
||||
do {
|
||||
PutDefine("ST_MOUNT_UNIT");
|
||||
k=GetChar-'0';
|
||||
} while (!(0<=k<=1));
|
||||
NewLine;
|
||||
}
|
||||
LinkedListDel(root);
|
||||
}
|
||||
if (type==BDT_NON_NATIVE_FILE) {
|
||||
PutDefine("ST_MOUNT_NON_NATIVE_LET");
|
||||
drv_let=GetChar;
|
||||
NewLine;
|
||||
PutDefine("ST_INCLUDE_0X");
|
||||
PutDefine("ST_MOUNT_NON_NATIVE_BLK");
|
||||
GetS(buf2,128);
|
||||
}
|
||||
if (type==BDT_RAM) {
|
||||
PutDefine("ST_MOUNT_BLKS");
|
||||
GetS(buf,32);
|
||||
}
|
||||
|
||||
if (BDT_NULL<type<=BDT_NON_NATIVE_FILE &&
|
||||
0<=k<=1) {
|
||||
bdev=&sys_blkdevs[num_blkdevs++];
|
||||
bdev->drv_let_base=drv_let_base+'A';
|
||||
bdev->unit=k;
|
||||
bdev->type=type;
|
||||
|
||||
if (type==BDT_ATAPI)
|
||||
bdev->flags=BDF_REMOVABLE;
|
||||
else
|
||||
bdev->flags=0;
|
||||
if (type!=BDT_RAM)
|
||||
bdev->flags|=BDF_READ_CACHE;
|
||||
|
||||
if (type==BDT_ATAPI) {
|
||||
bdev->blk_size=CD_BLK_SIZE;
|
||||
bdev->flags|=BDF_READ_ONLY;
|
||||
} else
|
||||
bdev->blk_size=BLK_SIZE;
|
||||
|
||||
if (type==BDT_RAM)
|
||||
bdev->max_blk=A2I(buf)-1;
|
||||
else
|
||||
bdev->max_blk=0xEFFFFFFF;
|
||||
|
||||
if (type==BDT_NON_NATIVE_FILE) {
|
||||
bdev->non_native_drv=drv_let;
|
||||
bdev->non_native_offset=A2I(buf2);
|
||||
} else {
|
||||
bdev->non_native_drv=0;
|
||||
bdev->non_native_offset=0;
|
||||
}
|
||||
|
||||
if (type==BDT_ATA ||
|
||||
type==BDT_ATAPI) {
|
||||
bdev->base0=A2I(buf2);
|
||||
bdev->base1=A2I(buf3);
|
||||
}
|
||||
|
||||
add=TRUE;
|
||||
if (type==BDT_ATA && repartition) {
|
||||
PutDefine("ST_MOUNT_FMT_WHOLE_DRV");
|
||||
if (YorN) {
|
||||
if (!BlkDevAdd(bdev,TRUE))
|
||||
PutDefine("ST_FAILED");
|
||||
else
|
||||
CallExtStr("PrtDsk",bdev->drv_let_base);
|
||||
add=FALSE;
|
||||
}
|
||||
}
|
||||
if (add && !BlkDevAdd(bdev,FALSE))
|
||||
PutDefine("ST_FAILED");
|
||||
} else
|
||||
PutDefine("ST_FAILED");
|
||||
}
|
||||
} while (0<=drv_let_base<NUM_PRTS);
|
||||
}
|
||||
|
||||
I64 SysPmtI64()
|
||||
{
|
||||
U8 st[136];
|
||||
StrCpy(st,"0x");
|
||||
GetS(st+2,134,FALSE);
|
||||
return A2I(st);
|
||||
}
|
||||
|
||||
Bool PmtBaseUnit(CBlkDev *bdev)
|
||||
{
|
||||
I64 ch;
|
||||
Bool probe;
|
||||
" SparrowOS\n\n\n";
|
||||
#exe {
|
||||
if (osmain_cfg->opts[CFG_DONT_PROBE])
|
||||
StreamPutS("probe=FALSE;");
|
||||
else
|
||||
StreamPutS("probe=TRUE;");
|
||||
};
|
||||
if (!probe || !BootCdProbeAll(bdev)) {
|
||||
"\nThis is not a product registration. SparrowOS\n"
|
||||
"needs the I/O port numbers for the CD-ROM.\n"
|
||||
"Retry 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;
|
||||
|
||||
"\nUnit (0 or 1): ";
|
||||
do ch=GetChar(NULL,FALSE);
|
||||
while (!('0'<=ch<='1'));
|
||||
'' ch;
|
||||
bdev->unit=ch-'0';
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
U0 BlkDevsInitAll()
|
||||
{
|
||||
CBlkDev *bdev;
|
||||
I64 i;
|
||||
num_blkdevs=0;
|
||||
sys_blkdevs=ACAlloc(sizeof(CBlkDev)*NUM_BLKDEVS);
|
||||
sys_prts=ACAlloc(sizeof(CPrt)*NUM_PRTS);
|
||||
for (i=0;i<NUM_PRTS;i++)
|
||||
drv_to_prt[i]=&sys_prts[i];
|
||||
sys_raw_dc_col=0;
|
||||
#exe {
|
||||
StreamPutS("#exe {OptOff(OPTf_WARN_PAREN);}");
|
||||
StreamDoc(osmain_cfg->add_dev);
|
||||
StreamPutS("#exe {OptOn(OPTf_WARN_PAREN);}");
|
||||
};
|
||||
PrtRep;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
U0 FAllocFile(CFile *f,I64 cnt,Bool contiguous)
|
||||
{
|
||||
CPrt *fp=f->p;
|
||||
CFileAccess *fa=FileAccessNew(f->de.full_name);
|
||||
f->de.cluster=ClusersAlloc(fp,0,(cnt+fp->spc-1)/fp->spc,contiguous);
|
||||
f->de.size=cnt<<BLK_SIZE_BITS;
|
||||
f->de.expanded_size=f->de.size;
|
||||
if (fa) {
|
||||
CDirNew(fa->p,Fs->cur_dir,&f->de,TRUE);
|
||||
FileAccessDel(fa);
|
||||
}
|
||||
f->flags&=~FF_NEW_FILE;
|
||||
}
|
||||
|
||||
I64 FSize(CFile *f)
|
||||
{
|
||||
if (f)
|
||||
return f->de.size;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
U0 FSync(CFile *f)
|
||||
{
|
||||
if (f->flags & FF_BUF_DIRTY) {
|
||||
WClusters(f->p,f->cluster_buf,f->cluster,1);
|
||||
f->flags&=~FF_BUF_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0)
|
||||
{ //allows flags "r","w","w+" and "c" (contiguous)
|
||||
CFile *f=CAlloc(sizeof(CFile));
|
||||
CFileAccess *fa;
|
||||
U8 *full_name,*full_name2;
|
||||
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_name2=FileNameAbs(filename);
|
||||
full_name=AStrNew(full_name2);
|
||||
Free(full_name2);
|
||||
f->p=Drv2Prt(*full_name);
|
||||
if (f->p->type==PT_NATIVE)
|
||||
contiguous=TRUE;
|
||||
if (contiguous) {
|
||||
f->flags|=FF_CONTIGUOUS;
|
||||
if (f->p->type!=PT_NATIVE) {
|
||||
if (!(FileAttr(filename) & _ATTR_CONTIGUOUS))
|
||||
throw(EXCEPT_FILE,2);
|
||||
}
|
||||
}
|
||||
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,FALSE,TRUE)) {
|
||||
f->de.full_name=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;
|
||||
fa=FileAccessNew(full_name);
|
||||
if (fa) {
|
||||
StrCpy(f->de.name,fa->mask);
|
||||
FileAccessDel(fa);
|
||||
if (cnt>0)
|
||||
FAllocFile(f,cnt,contiguous);
|
||||
if (!contiguous || cnt>0)
|
||||
return f;
|
||||
}
|
||||
} else {
|
||||
if (FileFind(full_name,&f->de,FALSE,TRUE)) {
|
||||
f->de.full_name=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) {
|
||||
FSync(f);
|
||||
if (f->flags & FF_NEEDS_WRITE) {
|
||||
fa=FileAccessNew(f->de.full_name);
|
||||
if (fa) {
|
||||
if (!(f->flags & FF_USE_OLD_DATETIME))
|
||||
f->de.datetime=GetCurTimeCDate;
|
||||
if (f->flags & FF_NEW_FILE)
|
||||
CDirNew(fa->p,Fs->cur_dir,&f->de,TRUE);
|
||||
else
|
||||
CDirNew(fa->p,Fs->cur_dir,&f->de,FALSE);
|
||||
FileAccessDel(fa);
|
||||
} else
|
||||
throw(EXCEPT_FILE,1);
|
||||
}
|
||||
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);
|
||||
j= cnt<spc-i ? cnt: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=ClusersAlloc(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=ClusersAlloc(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);
|
||||
j=cnt<spc-i ? cnt: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=ClusersAlloc(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=ClusersAlloc(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;
|
||||
if (f->de.expanded_size<blk<<BLK_SIZE_BITS)
|
||||
f->de.expanded_size=blk<<BLK_SIZE_BITS;
|
||||
}
|
||||
f->fblk_num=blk;
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Bool RAMRBlks(CPrt *p,U8 *buf,I64 blk,I64 cnt)
|
||||
{
|
||||
CBlkDev *bdev=p->bdev;
|
||||
BlkDevChk(bdev);
|
||||
MemCpy(buf,bdev->RAM_dsk+blk<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool RAMWBlks(CPrt *p,U8 *buf,I64 blk,I64 cnt)
|
||||
{
|
||||
CBlkDev *bdev=p->bdev;
|
||||
BlkDevChk(bdev);
|
||||
MemCpy(bdev->RAM_dsk+blk<<BLK_SIZE_BITS,buf,cnt<<BLK_SIZE_BITS);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool NonNativeFileRBlks(CPrt *p,U8 *buf,I64 blk,I64 cnt)
|
||||
{
|
||||
CBlkDev *bdev=p->bdev;
|
||||
CPrt *bp=Drv2Prt(bdev->non_native_drv);
|
||||
BlkDevChk(bdev);
|
||||
return (*bp->rblks)(bp,buf,blk,cnt);
|
||||
}
|
||||
|
||||
Bool NonNativeFileWBlks(CPrt *p,U8 *buf,I64 blk,I64 cnt)
|
||||
{
|
||||
CBlkDev *bdev=p->bdev;
|
||||
CPrt *bp=Drv2Prt(bdev->non_native_drv);
|
||||
BlkDevChk(bdev);
|
||||
return (*bp->wblks)(bp,buf,blk,cnt);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
Bool CDirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempm,Bool free_old_chain=TRUE)
|
||||
{
|
||||
switch (p->type) {
|
||||
case PT_NATIVE:
|
||||
return NativeFSDirNew(p,cur_dir,tempm,free_old_chain);
|
||||
case PT_FAT32:
|
||||
return FAT32DirNew(p,cur_dir,tempm,free_old_chain);
|
||||
case PT_ISO9660:
|
||||
PutDefineErr("ST_NOT_WRITABLE");
|
||||
return FALSE;
|
||||
default:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
U0 CDirEntryDel(CDirEntry *tempm)
|
||||
{ //Doesn't Free user_data
|
||||
if (tempm) {
|
||||
Free(tempm->full_name);
|
||||
Free(tempm);
|
||||
}
|
||||
}
|
||||
|
||||
U0 CDirEntryDel2(CDirEntry *tempm)
|
||||
{ //Frees user_data
|
||||
if (tempm) {
|
||||
Free(tempm->full_name);
|
||||
Free(tempm->user_data);
|
||||
Free(tempm);
|
||||
}
|
||||
}
|
||||
|
||||
U0 CDirListDel(CDirEntry *tempm)
|
||||
{ //Doesn't Free user_data
|
||||
CDirEntry *tempm2;
|
||||
while (tempm) {
|
||||
tempm2=tempm->next;
|
||||
if (tempm->sub)
|
||||
CDirListDel(tempm->sub);
|
||||
CDirEntryDel(tempm);
|
||||
tempm=tempm2;
|
||||
}
|
||||
}
|
||||
|
||||
U0 CDirListDel2(CDirEntry *tempm)
|
||||
{ //Frees user_data
|
||||
CDirEntry *tempm2;
|
||||
while (tempm) {
|
||||
tempm2=tempm->next;
|
||||
if (tempm->sub)
|
||||
CDirListDel2(tempm->sub);
|
||||
CDirEntryDel2(tempm);
|
||||
tempm=tempm2;
|
||||
}
|
||||
}
|
||||
|
||||
I64 CDirEntryCompare(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);
|
||||
}
|
||||
}
|
||||
|
||||
U0 CDirFilesSort(CDirEntry **_tempm)
|
||||
{
|
||||
I64 i,cnt=0;
|
||||
CDirEntry *tempm=*_tempm,*tempm1,**sort_buf;
|
||||
if (tempm) {
|
||||
tempm1=tempm;
|
||||
while (tempm1) {
|
||||
cnt++;
|
||||
tempm1=tempm1->next;
|
||||
}
|
||||
if (cnt>1) {
|
||||
sort_buf=MAlloc(cnt*sizeof(U8 *));
|
||||
i=0;
|
||||
tempm1=tempm;
|
||||
while (tempm1) {
|
||||
sort_buf[i++]=tempm1;
|
||||
tempm1=tempm1->next;
|
||||
}
|
||||
QSortI64(sort_buf,cnt,&CDirEntryCompare);
|
||||
tempm=sort_buf[0];
|
||||
*_tempm=tempm;
|
||||
for (i=0;i<cnt-1;i++) {
|
||||
tempm1=sort_buf[i];
|
||||
tempm1->next=sort_buf[i+1];
|
||||
}
|
||||
tempm1=sort_buf[i];
|
||||
tempm1->next=NULL;
|
||||
Free(sort_buf);
|
||||
|
||||
tempm1=tempm;
|
||||
while (tempm1) {
|
||||
if (tempm1->sub)
|
||||
CDirFilesSort(&tempm1->sub);
|
||||
tempm1=tempm1->next;
|
||||
}
|
||||
} else
|
||||
if (tempm->sub)
|
||||
CDirFilesSort(&tempm->sub);
|
||||
}
|
||||
}
|
||||
|
||||
CDirEntry *CDirFilesFlatten(CDirEntry *tempm,CDirEntry **_result,I64 fuf_flags)
|
||||
{ //returns last node
|
||||
CDirEntry *tempm1;
|
||||
Bool del;
|
||||
if (tempm)
|
||||
while (TRUE) {
|
||||
tempm1=tempm->next;
|
||||
if (!(tempm->attr&_ATTR_DIR)||!(fuf_flags&FUF_JUST_FILES)) {
|
||||
_result=*_result=tempm;
|
||||
del=FALSE;
|
||||
} else
|
||||
del=TRUE;
|
||||
if (tempm->sub) {
|
||||
_result=CDirFilesFlatten(tempm->sub,_result,fuf_flags);
|
||||
tempm->sub=NULL;
|
||||
}
|
||||
if (del)
|
||||
CDirEntryDel(tempm);
|
||||
if (tempm1)
|
||||
tempm=tempm1;
|
||||
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_NATIVE:
|
||||
result=NativeFSFilesFind(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:
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
result=NULL;
|
||||
}
|
||||
if (result) {
|
||||
CDirFilesSort(&result);
|
||||
if (fuf_flags&(FUF_FLATTEN_TREE|FUF_JUST_FILES))
|
||||
CDirFilesFlatten(result,&result,fuf_flags);
|
||||
}
|
||||
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
|
||||
"" filename;
|
||||
} else {
|
||||
buf=FileNameAbs(filename);
|
||||
if (plain_text) {
|
||||
if (line)
|
||||
"$$LK,\"%s,%04d\",\"PL:%s,%d\"$$",filename,line,buf,line;
|
||||
else
|
||||
"$$LK,\"%s\",\"PI:%s\"$$",filename,buf;
|
||||
} else {
|
||||
if (line)
|
||||
"$$LK,\"%s,%04d\",\"FL:%s,%d\"$$",filename,line,buf,line;
|
||||
else
|
||||
"$$LK,\"%s\",\"FI:%s\"$$",filename,buf;
|
||||
}
|
||||
Free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
U0 PutDirLink(U8 *dirname)
|
||||
{
|
||||
U8 *buf;
|
||||
if (!dirname) return;
|
||||
if (IsRaw)
|
||||
"" dirname;
|
||||
else {
|
||||
buf=DirNameAbs(dirname);
|
||||
"$$MA+A,\"%s\",\"Cd(\\\"%s\\\");Dir;\n\"$$",dirname,buf;
|
||||
Free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
U0 Dir2(U8 *files_find_mask,I64 fuf_flags,Bool full)
|
||||
{
|
||||
CDirEntry *tempm1=NULL,*tempm2;
|
||||
U8 *st;
|
||||
I64 csize=0xFFFF,esize=0xFFFF,c=0xFFFF;
|
||||
tempm1=SysFilesFind(files_find_mask,fuf_flags);
|
||||
|
||||
if (!(st=CurDir))
|
||||
PutDefine("ST_INVALID_DRV");
|
||||
else {
|
||||
if (tempm1) {
|
||||
//Find max columns
|
||||
tempm2=tempm1;
|
||||
while (tempm2) {
|
||||
if (tempm2->size>csize)
|
||||
csize=tempm2->size;
|
||||
if (tempm2->expanded_size>esize)
|
||||
esize=tempm2->expanded_size;
|
||||
if (tempm2->cluster>c)
|
||||
c=tempm2->cluster;
|
||||
tempm2=tempm2->next;
|
||||
}
|
||||
csize=Bsr(csize)/4+1;
|
||||
esize=Bsr(esize)/4+1;
|
||||
c=Bsr(c)/4+1;
|
||||
|
||||
"$$MA+A,\"Directory \",\"PopUpCd;Dir;\n\"$$ of %s\n",st;
|
||||
if (full)
|
||||
"__DATE__ __TIME__ %*ts %*ts %*ts\n",
|
||||
csize,"SIZE",esize,"UNCMPSIZE",c,"CLUSTER";
|
||||
else
|
||||
"DATE_ TIME_ %*ts\n",csize,"SIZE";
|
||||
while (tempm1) {
|
||||
tempm2=tempm1->next;
|
||||
if (full)
|
||||
"%D %T %0*tX %0*tX %0*tX ",tempm1->datetime,tempm1->datetime,
|
||||
csize,tempm1->size,esize,tempm1->expanded_size,
|
||||
c, tempm1->cluster;
|
||||
else
|
||||
"%h1D %h1T %0*tX ",tempm1->datetime,tempm1->datetime,
|
||||
csize,tempm1->size;
|
||||
if (tempm1->attr & _ATTR_DIR)
|
||||
PutDirLink(tempm1->name);
|
||||
else
|
||||
PutFileLink(tempm1->name);
|
||||
|
||||
NewLine;
|
||||
CDirEntryDel(tempm1);
|
||||
tempm1=tempm2;
|
||||
}
|
||||
} else
|
||||
PutDefine("ST_NO_MATCHING_ENTRIES");
|
||||
Free(st);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
U8 *FileExtDot(U8 *src)
|
||||
{
|
||||
U8 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 IsTextFile(U8 *filename)
|
||||
{
|
||||
return FilesFindMatch(TEXT_FILE_MASK,filename);
|
||||
}
|
||||
|
||||
Bool IsSrcFile(U8 *filename)
|
||||
{
|
||||
return FilesFindMatch(SRC_FILE_MASK,filename);
|
||||
}
|
||||
|
||||
Bool FilesFindMatch(U8 *files_find_mask,U8 *filename,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 (WildCardMatch(st2+1,filename)) {
|
||||
result=FALSE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (WildCardMatch(st2,filename)) {
|
||||
if (Bt(&fuf_flags,FUf_JUST_TEXT_FILES) && !IsTextFile(filename)) {
|
||||
result=FALSE;
|
||||
break;
|
||||
} else if (Bt(&fuf_flags,FUf_JUST_SRC_FILES) && !IsSrcFile(filename)) {
|
||||
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(EXCEPT_PRT,4);
|
||||
}
|
||||
|
||||
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==':')
|
||||
p=dft_prt;
|
||||
else
|
||||
p=drv_to_prt[ToUpper(drv_let)-'A'];
|
||||
PrtChk(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
U0 BlkDevChk(CBlkDev *bdev)
|
||||
{
|
||||
if (!bdev || bdev->bd_signature!=BD_SIGNATURE_VAL)
|
||||
throw(EXCEPT_BLKDEV,1);
|
||||
if (bdev->type<=BDT_NULL || bdev->type>BDT_NON_NATIVE_FILE)
|
||||
throw(EXCEPT_BLKDEV,2);
|
||||
}
|
||||
|
||||
CBlkDev *Drv2BlkDev(U8 drv_let=0)
|
||||
{
|
||||
CPrt *p=Drv2Prt(drv_let);
|
||||
CBlkDev *bdev=p->bdev;
|
||||
BlkDevChk(bdev);
|
||||
return bdev;
|
||||
}
|
||||
|
||||
CBlkDev *Drv2BlkDevFwded(U8 drv_let=0)
|
||||
{
|
||||
CBlkDev *bdev=Drv2BlkDev(drv_let);
|
||||
while (bdev && bdev->non_native_drv)
|
||||
bdev=Drv2BlkDev(bdev->non_native_drv);
|
||||
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=dft_drv;
|
||||
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,"/"))
|
||||
StrCat(buf3,"/");
|
||||
StrCat(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)
|
||||
{
|
||||
U8 *buf,*buf2,*buf3,*filename,*temp_name,*temp_buf;
|
||||
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]!='/')
|
||||
StrCat(buf,"/");
|
||||
StrCat(buf,buf2);
|
||||
Free(buf2);
|
||||
Free(buf3);
|
||||
Free(temp_name);
|
||||
return buf;
|
||||
}
|
||||
|
||||
U8 *ChgExt(U8 *filename,U8 *extension)
|
||||
{//Change file name extension
|
||||
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
|
||||
StrCpy(result,filename);
|
||||
if (FileExtDot(filename))
|
||||
FileExtRem(result);
|
||||
StrCat(result,".");
|
||||
StrCat(result,extension);
|
||||
return result;
|
||||
}
|
||||
|
||||
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)) {
|
||||
StrCat(result,".");
|
||||
StrCat(result,extension);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CDirEntry *CdDir(CDirEntry *tempm,U8 *abs_name)
|
||||
{
|
||||
I64 i;
|
||||
while (tempm) {
|
||||
i=StrLen(tempm->full_name);
|
||||
if (StrNCmp(tempm->full_name,abs_name,i))
|
||||
tempm=tempm->next;
|
||||
else
|
||||
if (StrLen(abs_name)==i)
|
||||
return tempm;
|
||||
else
|
||||
return CdDir(tempm->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(filename_chars_bitmap,*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.
|
||||
|
||||
("/SparrowOS/OSMain/Hash1a.CPP.Z",NULL,NULL) returns "D:/SparrowOS/OSMain"
|
||||
("/SparrowOS/OSMain",NULL,"PRJ.Z") returns "D:/SparrowOS/OSMain/OSMain.PRJ.Z"
|
||||
("/SparrowOS/OSMain/Dsk",NULL,"PRJ.Z") returns "D:/SparrowOS/OSMain/OSMain.PRJ.Z"
|
||||
("/SparrowOS/Apps/MusicOrgan","Load","CPP.Z") returns "D:/SparrowOS/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=MSPrintF(".%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=MSPrintF("%s/%s%s",st,name,ext);
|
||||
else {
|
||||
if (*ext)
|
||||
result=MSPrintF("%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 *ZorNotZ(U8 *name)
|
||||
{ //Compressed file name unless only uncompressed is available
|
||||
I64 i;
|
||||
U8 *result=StrNew(name);
|
||||
if (!*result||FileFind(result)||!IsDotZ(name))
|
||||
return result;
|
||||
i=StrLen(name)-2;
|
||||
result[i]=0;
|
||||
if (FileFind(result))
|
||||
return result;
|
||||
result[i]='.';
|
||||
return result;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,312 @@
|
||||
//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 (ListEntryMatch(buf,"CD001\0CDW02\0BEA01\0BOOT2\0NSR02\0NSR03\0TEA01\0",LEF_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(EXCEPT_PRT,5);
|
||||
}
|
||||
break;
|
||||
default: //Its normal for ISO13346 to read NULL blk as terminator
|
||||
PutDefineErr("ST_UNSUPPORTED_FILE_SYSTEM");
|
||||
throw(EXCEPT_PRT,6);
|
||||
}
|
||||
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 CDate2ISO1(CISO1Date *dst,CDate ltdt)
|
||||
{
|
||||
CDateStruct ds;
|
||||
CDate2CDateStruct(&ds,ltdt);
|
||||
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 CDateStruct2CDate(&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(filename_chars_bitmap,*src)) {
|
||||
if (j>=CDIR_FILENAME_LEN-1)
|
||||
return FALSE;
|
||||
dst[j++]=*src++;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return FileNameChk(dst);
|
||||
}
|
||||
|
||||
Bool ISO1CDirFill(CPrt *p,CDirEntry *tempm,CISO1DirEntry *de)
|
||||
{
|
||||
Bool result;
|
||||
CArcCompress *buf;
|
||||
MemSet(tempm,0,sizeof(CDirEntry));
|
||||
result=ISO1FromName(tempm->name,&de->name_len);
|
||||
tempm->cluster=de->loc.little;
|
||||
tempm->size=de->size.little;
|
||||
tempm->attr=FileAttr(tempm->name);
|
||||
if (de->flags & ISO1_ATTR_DIR)
|
||||
tempm->attr|=_ATTR_DIR;
|
||||
tempm->datetime=ISO1DateStruct2CDate(&de->date);
|
||||
if (tempm->attr & _ATTR_COMPRESSED) {
|
||||
buf=MAlloc(BLK_SIZE);
|
||||
RClustersBlks(p,buf,tempm->cluster,1);
|
||||
tempm->expanded_size=buf->expanded_size;
|
||||
Free(buf);
|
||||
} else
|
||||
tempm->expanded_size=tempm->size;
|
||||
return result;
|
||||
}
|
||||
|
||||
Bool ISO1FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,
|
||||
Bool dir_only,Bool file_only)
|
||||
{
|
||||
CISO1DirEntry *isoptr,*buf;
|
||||
U8 dname[CDIR_FILENAME_LEN];
|
||||
Bool result=FALSE,unlock;
|
||||
I64 i;
|
||||
|
||||
PrtChk(p);
|
||||
if (p->type!=PT_ISO9660)
|
||||
PutDefineErr("ST_NOT_ISO9660");
|
||||
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(p,_result,isoptr);
|
||||
if (result &&
|
||||
!(dir_only && !(_result->attr & _ATTR_DIR)) &&
|
||||
!(file_only && _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,Bool raw,CArcCompress **_ac2)
|
||||
{
|
||||
U8 *buf=NULL;
|
||||
CDirEntry de;
|
||||
I64 c,blk_cnt,cur_dir_cluster;
|
||||
CArcCompress *ac;
|
||||
|
||||
PrtChk(p);
|
||||
if (_size) *_size=0;
|
||||
if (_ac2) *_ac2=NULL;
|
||||
if (_attr) *_attr=0;
|
||||
if (p->type!=PT_ISO9660)
|
||||
PutDefineErr("ST_NOT_ISO9660");
|
||||
else {
|
||||
try {
|
||||
PrtLock(p);
|
||||
cur_dir_cluster=Name2DirCluster(p,cur_dir);
|
||||
if (ISO1FileFind(p,cur_dir_cluster,filename,&de,FALSE,TRUE)) {
|
||||
if (_attr) *_attr=de.attr;
|
||||
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);
|
||||
if (FileAttr(de.name)&_ATTR_COMPRESSED && !raw) {
|
||||
ac=buf;
|
||||
if (_attr) *_attr=FileAttr(de.name,*_attr);
|
||||
if (_size) *_size=ac->expanded_size;
|
||||
if (_ac2) {
|
||||
*_ac2=ac;
|
||||
buf=ExpandBuf(ac);
|
||||
} else {
|
||||
buf=ExpandBuf(ac);
|
||||
Free(ac);
|
||||
}
|
||||
} else {
|
||||
buf[de.size]=0; //Terminate
|
||||
if (_size) *_size=de.size;
|
||||
}
|
||||
if (_attr) *_attr=FileAttr(de.name,*_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)
|
||||
PutDefineErr("ST_NOT_ISO9660");
|
||||
else {
|
||||
if (ISO1FileFind(Fs->cur_prt,cur_dir_cluster,name,&de,TRUE,FALSE))
|
||||
return TRUE;
|
||||
else {
|
||||
"%s ",name;
|
||||
PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
}
|
||||
}
|
||||
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,*tempm;
|
||||
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 {
|
||||
tempm=MAlloc(sizeof(CDirEntry));
|
||||
if (ISO1CDirFill(Fs->cur_prt,tempm,buf)) {
|
||||
tempm->parent=parent;
|
||||
if (Bt(&fuf_flags,FUf_RECURSE) && tempm->attr&_ATTR_DIR && *tempm->name!='.') {
|
||||
tempm->next=result;
|
||||
result=tempm;
|
||||
tempm->full_name=DirNameAbs(tempm->name);
|
||||
if (Cd(tempm->name)) {
|
||||
tempm->sub=ISO1FilesFind(files_find_mask,fuf_flags,tempm);
|
||||
Cd("..");
|
||||
}
|
||||
} else if ((tempm->attr & _ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
|
||||
!(Bt(&fuf_flags,FUf_RECURSE) && *tempm->name=='.' && tempm->attr&_ATTR_DIR) &&
|
||||
FilesFindMatch(files_find_mask,tempm->name,fuf_flags)) {
|
||||
tempm->next=result;
|
||||
result=tempm;
|
||||
tempm->full_name=FileNameAbs(tempm->name);
|
||||
} else
|
||||
CDirEntryDel(tempm);
|
||||
} else
|
||||
CDirEntryDel(tempm);
|
||||
i-=buf->len;
|
||||
buf(U8 *)+=buf->len;
|
||||
}
|
||||
}
|
||||
Free(buf2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,715 @@
|
||||
U0 NativeFSFreeFreeList(CPrt *p)
|
||||
{
|
||||
CFreeList *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 NativeFSFreeListBuild(CPrt *p)
|
||||
{
|
||||
Bool unlock;
|
||||
CFreeList *tempf;
|
||||
I64 i,first=0,
|
||||
max_cluster=(p->size+p->offset-p->data)/p->spc;
|
||||
|
||||
try {
|
||||
unlock=PrtLock(p);
|
||||
if (p->next_free)
|
||||
NativeFSFreeFreeList(p);
|
||||
p->next_free=&p->next_free;
|
||||
p->last_free=&p->next_free;
|
||||
while (first<max_cluster) {
|
||||
i=0; //count free clusters
|
||||
while (first+i<max_cluster) {
|
||||
SetNativeBuf(p,first+i);
|
||||
if (Bt(p->cur_map_blk,(first+i)&(BLK_SIZE<<3-1)))
|
||||
break;
|
||||
else
|
||||
i++;
|
||||
}
|
||||
if (i) {
|
||||
tempf=AMAlloc(sizeof(CFreeList));
|
||||
tempf->size=i;
|
||||
tempf->start=first;
|
||||
QueIns(tempf,p->last_free);
|
||||
}
|
||||
first+=i+1;
|
||||
}
|
||||
if (unlock)
|
||||
PrtUnlock(p);
|
||||
} catch
|
||||
if (unlock)
|
||||
PrtUnlock(p);
|
||||
}
|
||||
|
||||
U0 NativeFSPrtInit(CPrt *p)
|
||||
{
|
||||
CBootStruct br;
|
||||
Bool unlock;
|
||||
try {
|
||||
unlock=PrtLock(p);
|
||||
RBlks(p,&br,p->offset,1);
|
||||
if (br.signature!=MBR_PT_NATIVE ||
|
||||
br.signature2!=0xAA55)
|
||||
throw(EXCEPT_PRT,7);
|
||||
p->type=PT_NATIVE;
|
||||
NativeFSFreeFreeList(p);
|
||||
p->spc=br.sects_per_cluster;
|
||||
p->size=br.sects;
|
||||
p->data=p->offset+1+br.bitmap_sects-p->spc;
|
||||
p->root_cluster=br.root_cluster;
|
||||
p->map1=p->offset+1;
|
||||
p->map2=p->offset+1;
|
||||
MapBufAlloc(p,1);
|
||||
if (unlock)
|
||||
PrtUnlock(p);
|
||||
} catch
|
||||
if (unlock)
|
||||
PrtUnlock(p);
|
||||
}
|
||||
|
||||
Bool NativeFSDrvValidate(U8 drv_let)
|
||||
{
|
||||
CPrt *p;
|
||||
CBootStruct br;
|
||||
Bool result=FALSE;
|
||||
try {
|
||||
p=Drv2Prt(drv_let);
|
||||
if (p->type==PT_NATIVE &&
|
||||
RBlks(p,&br,p->offset,1) &&
|
||||
br.signature==MBR_PT_NATIVE &&
|
||||
br.signature2==0xAA55 &&
|
||||
br.sects==p->size)
|
||||
result=TRUE;
|
||||
} catch
|
||||
Fs->catch_except=TRUE;
|
||||
return result;
|
||||
}
|
||||
|
||||
U0 NativeFSFmt(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_NATIVE);
|
||||
SetDrvType(drv_let,PT_FAT32);
|
||||
p->type=PT_NATIVE;
|
||||
br->U8s_per_sect=BLK_SIZE;
|
||||
if (p->size<0x20000)
|
||||
br->sects_per_cluster=1;
|
||||
else if (p->size<0x200000)
|
||||
br->sects_per_cluster=2;
|
||||
else if (p->size<0x2000000)
|
||||
br->sects_per_cluster=4;
|
||||
else if (p->size<0x20000000)
|
||||
br->sects_per_cluster=8;
|
||||
else if (p->size<0x200000000)
|
||||
br->sects_per_cluster=16;
|
||||
else
|
||||
br->sects_per_cluster=32;
|
||||
|
||||
br->signature=MBR_PT_NATIVE;
|
||||
br->signature2=0xAA55;
|
||||
br->sects=p->size;
|
||||
n=br->sects_per_cluster*(BLK_SIZE<<3);
|
||||
n=(br->sects+n-1)/n;
|
||||
br->bitmap_sects=n;
|
||||
br->unique_id=GetTimeStamp>>4;
|
||||
br->root_cluster=0;
|
||||
|
||||
if (quick)
|
||||
i=n+1;
|
||||
else
|
||||
i=p->size;
|
||||
WZeroBlks(p,p->offset,i);
|
||||
|
||||
WBlks(p,br,p->offset,1);
|
||||
NativeFSPrtInit(p);
|
||||
ClusersAlloc(p,0,1,FALSE); //Alloc #1
|
||||
br->root_cluster=ClusersAlloc(p,0,1,FALSE);
|
||||
WBlks(p,br,p->offset,1);
|
||||
root_dir=CAlloc(p->spc<<BLK_SIZE_BITS);
|
||||
|
||||
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=p->spc<<BLK_SIZE_BITS;
|
||||
d_native->expanded_size=d_native->size;
|
||||
d_native->datetime=GetCurTimeCDate;
|
||||
|
||||
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=GetCurTimeCDate;
|
||||
|
||||
WBlks(p,root_dir,p->data+br->root_cluster*p->spc,p->spc);
|
||||
NativeFSPrtInit(p);
|
||||
PrtUnlock(p);
|
||||
} catch
|
||||
PrtUnlock(p);
|
||||
Free(br);
|
||||
Free(root_dir);
|
||||
}
|
||||
|
||||
Bool NativeFSFileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,
|
||||
Bool dir_only,Bool file_only)
|
||||
{
|
||||
CDirEntry *buf,*buf2,*ptr;
|
||||
U8 dname[CDIR_FILENAME_LEN];
|
||||
I64 ch;
|
||||
Bool result=FALSE,unlock;
|
||||
|
||||
MemSet(_result,0,sizeof(CDirEntry));
|
||||
PrtChk(p);
|
||||
if (p->type!=PT_NATIVE)
|
||||
PutDefineErr("ST_NOT_NATIVE");
|
||||
else if (!CFileNameTo(dname,name))
|
||||
PutDefineErr("ST_INVALID_FILENAME");
|
||||
else {
|
||||
try {
|
||||
unlock=PrtLock(p);
|
||||
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
|
||||
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) &&
|
||||
!(dir_only && !(ptr->attr & _ATTR_DIR)) &&
|
||||
!(file_only && 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 *NativeFSFileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,
|
||||
I64 *_attr,Bool raw,CArcCompress **_ac2)
|
||||
{
|
||||
U8 *buf=NULL;
|
||||
CDirEntry de;
|
||||
I64 c,blk_cnt,cur_dir_cluster;
|
||||
CArcCompress *ac;
|
||||
|
||||
PrtChk(p);
|
||||
if (_size) *_size=0;
|
||||
if (_ac2) *_ac2=NULL;
|
||||
if (_attr) *_attr=0;
|
||||
if (p->type!=PT_NATIVE)
|
||||
PutDefineErr("ST_NOT_NATIVE");
|
||||
else {
|
||||
try {
|
||||
PrtLock(p);
|
||||
cur_dir_cluster=Name2DirCluster(p,cur_dir);
|
||||
if (NativeFSFileFind(p,cur_dir_cluster,filename,&de,FALSE,TRUE)) {
|
||||
if (_attr) *_attr=de.attr;
|
||||
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);
|
||||
if (de.xsum) {
|
||||
if (de.xsum^ArcXSum(buf,de.size) !=NATIVE_XSUM)
|
||||
throw(EXCEPT_ARC_XSUM);
|
||||
}
|
||||
if (FileAttr(de.name) & _ATTR_COMPRESSED && !raw) {
|
||||
ac=buf;
|
||||
if (_attr) *_attr=FileAttr(de.name,*_attr);
|
||||
if (_size) *_size=ac->expanded_size;
|
||||
if (_ac2) {
|
||||
*_ac2=ac;
|
||||
buf=ExpandBuf(ac);
|
||||
} else {
|
||||
buf=ExpandBuf(ac);
|
||||
Free(ac);
|
||||
}
|
||||
} else {
|
||||
buf[de.size]=0; //Terminate
|
||||
if (_size) *_size=de.size;
|
||||
}
|
||||
if (_attr) *_attr=FileAttr(de.name,*_attr);
|
||||
}
|
||||
PrtUnlock(p);
|
||||
} catch
|
||||
PrtUnlock(p);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
Bool NativeFSCd(U8 *name,I64 cur_dir_cluster)
|
||||
{
|
||||
CDirEntry de;
|
||||
if (Fs->cur_prt->type!=PT_NATIVE)
|
||||
PutDefineErr("ST_NOT_NATIVE");
|
||||
else {
|
||||
if (NativeFSFileFind(Fs->cur_prt,cur_dir_cluster,
|
||||
name,&de,TRUE,FALSE))
|
||||
return TRUE;
|
||||
else {
|
||||
"%s ",name;
|
||||
PutDefineErr("ST_FILE_NOT_FOUND");
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
U0 NativeFSFreeClusters(CPrt *p,I64 c,I64 cnt)
|
||||
{
|
||||
CFreeList *tempf;
|
||||
Bool found=FALSE,unlock,unlock_break;
|
||||
PrtChk(p);
|
||||
if (!c) return;
|
||||
if (p->type!=PT_NATIVE)
|
||||
PutDefineErr("ST_NOT_NATIVE");
|
||||
else {
|
||||
try {
|
||||
unlock_break=BreakLock;
|
||||
unlock=PrtLock(p);
|
||||
if (!p->next_free)
|
||||
NativeFSFreeListBuild(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(CFreeList));
|
||||
tempf->size=cnt;
|
||||
tempf->start=c;
|
||||
QueIns(tempf,p->last_free);
|
||||
}
|
||||
while (cnt-->0) {
|
||||
SetNativeBuf(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 NativeFSAllocClusters(CPrt *p,I64 cnt)
|
||||
{
|
||||
CFreeList *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)
|
||||
NativeFSFreeListBuild(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++) {
|
||||
SetNativeBuf(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 NativeFSDirNew(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(p->spc<<BLK_SIZE_BITS);
|
||||
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*p->spc+j,1);
|
||||
else {
|
||||
buf2=CAlloc(dir_size+p->spc<<BLK_SIZE_BITS);
|
||||
MemCpy(buf2,buf,dir_size);
|
||||
NativeFSFreeClusters(p,cur_dir_cluster,
|
||||
(dir_size>>BLK_SIZE_BITS+p->spc-1)/p->spc);
|
||||
dir_size+=p->spc<<BLK_SIZE_BITS;
|
||||
c=ClusersAlloc(p,0,(dir_size>>BLK_SIZE_BITS+p->spc-1)/p->spc,TRUE);
|
||||
Free(buf);
|
||||
buf=buf2;
|
||||
ptr=buf(U8 *)-offset(CDirEntry.start);
|
||||
ptr->size=dir_size;
|
||||
ptr->expanded_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 (NativeFSFileFind(p,Name2DirCluster(p,parent_dir),
|
||||
temp,&de2,TRUE,FALSE)) {
|
||||
de2.cluster=c;
|
||||
de2.size=dir_size;
|
||||
de2.expanded_size=dir_size;
|
||||
NativeFSDirNew(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*p->spc+j,1);
|
||||
written=TRUE;
|
||||
}
|
||||
} else {
|
||||
if (!StrCmp(de->name,ptr->name)) {
|
||||
if (free_old_chain)
|
||||
NativeFSFreeClusters(p,ptr->cluster,
|
||||
(ptr->size+p->spc<<BLK_SIZE_BITS-1)/p->spc<<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*p->spc+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;
|
||||
}
|
||||
|
||||
Bool NativeFSFilesDel(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,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(p->spc<<BLK_SIZE_BITS);
|
||||
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(files_find_mask,ptr->name,fuf_flags)) {
|
||||
if (print_msg) {
|
||||
PutDefine("ST_DELETE");
|
||||
"" ptr->name;
|
||||
NewLine;
|
||||
}
|
||||
ptr->attr|=_ATTR_DELETED;
|
||||
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,
|
||||
p->data+cur_dir_cluster*p->spc+j,1);
|
||||
NativeFSFreeClusters(p,ptr->cluster,
|
||||
(ptr->size+p->spc<<BLK_SIZE_BITS-1)/p->spc<<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 FALSE;
|
||||
}
|
||||
|
||||
I64 NativeFSFileWrite(CPrt *p,U8 *cur_dir,U8 *name,U8 *buf,I64 size,
|
||||
CDate ltdt,I64 attr,Bool raw,
|
||||
CArcCompress **_ac2)
|
||||
{
|
||||
CDirEntry de;
|
||||
I64 c=0,flags=0,blk_cnt;
|
||||
CArcCompress *ac=NULL;
|
||||
Bool contiguous;
|
||||
MemSet(&de,0,sizeof(CDirEntry));
|
||||
if (_ac2) *_ac2=NULL;
|
||||
if (size<0) size=0;
|
||||
if (!ltdt)
|
||||
ltdt=GetCurTimeCDate;
|
||||
|
||||
if (p->type!=PT_NATIVE)
|
||||
PutDefineErr("ST_NOT_NATIVE");
|
||||
else if (!CFileNameTo(de.name,name))
|
||||
PutDefineErr("ST_INVALID_FILENAME");
|
||||
else {
|
||||
NativeFSFilesDel(p,cur_dir,de.name,0,FALSE,FALSE);
|
||||
attr=FileAttr(name,attr);
|
||||
attr|=_ATTR_CONTIGUOUS;
|
||||
contiguous=TRUE;
|
||||
de.expanded_size=size;
|
||||
if (attr&_ATTR_COMPRESSED && !raw) {
|
||||
ac=CompressBuf(buf,size,flags);
|
||||
size=ac->compressed_size;
|
||||
buf=ac;
|
||||
}
|
||||
de.size=size;
|
||||
de.xsum=ArcXSum(buf,size)^NATIVE_XSUM;
|
||||
if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)
|
||||
c=ClusersAlloc(p,0,(blk_cnt+p->spc-1)/p->spc,contiguous);
|
||||
else
|
||||
c=INVALID_CLUSTER;
|
||||
de.cluster=c;
|
||||
de.attr=attr;
|
||||
de.datetime=ltdt;
|
||||
if (blk_cnt)
|
||||
WClustersBlks(p,buf,c,blk_cnt);
|
||||
NativeFSDirNew(p,cur_dir,&de,TRUE);
|
||||
if (_ac2)
|
||||
*_ac2=ac;
|
||||
else
|
||||
Free(ac);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
CDirEntry *NativeFSFilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL)
|
||||
{
|
||||
CPrt *p=Fs->cur_prt;
|
||||
CDirEntry *buf,*buf2,*ptr,*result=NULL,*tempm;
|
||||
I64 ch,cur_dir_cluster;
|
||||
try {
|
||||
PrtLock(p);
|
||||
cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
|
||||
buf2=MAlloc(p->spc<<BLK_SIZE_BITS);
|
||||
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)) {
|
||||
tempm=CAlloc(sizeof(CDirEntry));
|
||||
MemCpy(&tempm->start,&ptr->start,CDIR_SIZE);
|
||||
tempm->parent=parent;
|
||||
if (Bt(&fuf_flags,FUf_RECURSE) && tempm->attr&_ATTR_DIR && *tempm->name!='.') {
|
||||
tempm->next=result;
|
||||
result=tempm;
|
||||
tempm->full_name=DirNameAbs(tempm->name);
|
||||
PrtUnlock(p);
|
||||
if (Cd(tempm->name)) {
|
||||
tempm->sub=NativeFSFilesFind(files_find_mask,fuf_flags,tempm);
|
||||
Cd("..");
|
||||
}
|
||||
PrtLock(p);
|
||||
} else if ((tempm->attr&_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
|
||||
!(Bt(&fuf_flags,FUf_RECURSE) && *tempm->name=='.' && tempm->attr&_ATTR_DIR) &&
|
||||
FilesFindMatch(files_find_mask,tempm->name,fuf_flags)) {
|
||||
tempm->next=result;
|
||||
result=tempm;
|
||||
tempm->full_name=FileNameAbs(tempm->name);
|
||||
} else
|
||||
CDirEntryDel(tempm);
|
||||
}
|
||||
ptr(U8 *)+=CDIR_SIZE;
|
||||
}
|
||||
Free(buf);
|
||||
PrtUnlock(p);
|
||||
} catch
|
||||
PrtUnlock(p);
|
||||
return result;
|
||||
}
|
||||
|
||||
Bool NativeFSMkDir(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=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->expanded_size=size;
|
||||
d_native->datetime=GetCurTimeCDate;
|
||||
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->expanded_size=0;
|
||||
d_native->datetime=GetCurTimeCDate;
|
||||
WClusters(p,buf,c,1);
|
||||
Free(buf);
|
||||
if (unlock_break)
|
||||
BreakUnlock;
|
||||
} catch
|
||||
if (unlock_break)
|
||||
BreakUnlock;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user