TempleOSCDV3.11.ISO

This commit is contained in:
Terry A. Davis authored and minexew committed 2018-09-08 21:46:29 +02:00
1 parent f8c05f98f4
commit ed64d7e3b8
549 files changed
+10643 -12855

No files matched your search

+608
View File
@@ -0,0 +1,608 @@
U0 ATABlkSelect(CBlkDev *bd,I64 blk,I64 cnt)
{
if (bd->type!=BDT_ATAPI && bd->base1)
OutU8(bd->base1+ATAR1_CTRL,0x8);
if (bd->flags & BDF_EXT_SIZE) { //48 Bit LBA?
OutU8(bd->base0+ATAR0_NSECT,cnt.u8[1]);
OutU8(bd->base0+ATAR0_SECT,blk.u8[3]);
OutU8(bd->base0+ATAR0_LCYL,blk.u8[4]);
OutU8(bd->base0+ATAR0_HCYL,blk.u8[5]);
OutU8(bd->base0+ATAR0_NSECT,cnt);
OutU8(bd->base0+ATAR0_SECT,blk);
OutU8(bd->base0+ATAR0_LCYL,blk.u8[1]);
OutU8(bd->base0+ATAR0_HCYL,blk.u8[2]);
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
} else { //28 Bit LBA
OutU8(bd->base0+ATAR0_NSECT,cnt);
OutU8(bd->base0+ATAR0_SECT,blk);
OutU8(bd->base0+ATAR0_LCYL,blk.u8[1]);
OutU8(bd->base0+ATAR0_HCYL,blk.u8[2]);
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4|blk.u8[3]);
}
}
Bool ATAWaitNotBUSY(CBlkDev *bd,F64 timeout)
{
I64 i;
do {
for (i=0;i<3;i++)
if (!(InU8(bd->base0+ATAR0_STAT)&ATAS_BSY))
return TRUE;
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
Bool ATAWaitDRQ(CBlkDev *bd,F64 timeout)
{
I64 i;
do {
for (i=0;i<3;i++)
if (InU8(bd->base0+ATAR0_STAT)&ATAS_DRQ)
return TRUE;
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
Bool ATANop(CBlkDev *bd,F64 timeout)
{
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_FEAT,0);
OutU8(bd->base0+ATAR0_CMD,ATA_NOP);
return ATAWaitNotBUSY(bd,timeout);
}
U0 ATACmd(CBlkDev *bd,U8 cmd)
{
OutU8(bd->base0+ATAR0_FEAT,0);
OutU8(bd->base0+ATAR0_CMD,cmd);
bd->last_time=tS;
PortNop;
}
Bool ATAGetResult(CBlkDev *bd,F64 timeout,U8 *buf,I64 cnt,
I64 _avail,Bool one_read)
{
I64 avail,overflow;
bd->flags&=~BDF_LAST_WAS_WRITE;
MemSet(buf,0,cnt);
while (cnt>0) {
if (!ATAWaitDRQ(bd,timeout))
return FALSE;
if (_avail)
avail=_avail;
else
avail=InU8(bd->base0+ATAR0_HCYL)<<8+InU8(bd->base0+ATAR0_LCYL);
if (avail) {
if (avail>cnt) {
overflow=avail-cnt;
avail=cnt;
} else
overflow=0;
if (avail&2)
RepInU16(buf,avail>>1,bd->base0+ATAR0_DATA);
else
RepInU32(buf,avail>>2,bd->base0+ATAR0_DATA);
cnt-=avail;
buf+=avail;
while (overflow>0) {
InU16(bd->base0+ATAR0_DATA);
overflow-=2;
if (0<timeout<tS)
return FALSE;
}
if (one_read)
break;
} else
Yield;
}
return ATAWaitNotBUSY(bd,timeout);
}
Bool ATAPIWritePktWord(CBlkDev *bd,F64 timeout,...)
{
I64 i;
for (i=0;i<argc;i++) {
if (!ATAWaitDRQ(bd,timeout))
return FALSE;
OutU16(bd->base0+ATAR0_DATA,EndianU16(argv[i]));
bd->last_time=tS;
}
return TRUE;
}
Bool ATAPISetMaxSpeed(CBlkDev *bd)
{
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_LCYL,0);
OutU8(bd->base0+ATAR0_HCYL,0);
ATACmd(bd,ATA_PACKET);
ATAPIWritePktWord(bd,0,0xBB00,0xFFFF,0xFFFF,0,0,0);
return ATAWaitNotBUSY(bd,0);
}
Bool ATAPISeek(CBlkDev *bd,I64 native_blk)
{
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_LCYL,0);
OutU8(bd->base0+ATAR0_HCYL,0);
ATACmd(bd,ATA_PACKET);
ATAPIWritePktWord(bd,0,0x2B00,native_blk>>16,native_blk,0,0,0);
return ATAWaitNotBUSY(bd,0);
}
Bool ATAPIStartStop(CBlkDev *bd,F64 timeout,Bool start)
{
I64 i;
if (start)
i=0x100;
else
i=0;
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
ATACmd(bd,ATA_PACKET);
//Start/Stop
if (ATAPIWritePktWord(bd,timeout,0x1B00,0,i,0,0,0))
return ATAWaitNotBUSY(bd,timeout);
else
return FALSE;
}
I64 ATAGetDevId(CBlkDev *bd,F64 timeout,U16 **_id_record)
{
U16 *id_record;
if (_id_record) *_id_record=NULL;
if (bd->type!=BDT_ATAPI && bd->base1)
OutU8(bd->base1+ATAR1_CTRL,0x8);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
ATACmd(bd,ATA_ID_DEV);
if (!ATAWaitNotBUSY(bd,timeout))
return BDT_NULL;
if (InU8(bd->base0+ATAR0_STAT)&ATAS_ERR)
return BDT_ATAPI;
id_record=ACAlloc(512);
if (!ATAGetResult(bd,timeout,id_record,512,512,FALSE)) {
Free(id_record);
return BDT_NULL;
}
if (_id_record) *_id_record=id_record;
return BDT_ATA;
}
I64 ATAReadNativeMax(CBlkDev *bd,F64 timeout)
{//Returns zero on err
I64 result=0;
Bool okay=TRUE;
if (bd->type==BDT_ATAPI) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
ATACmd(bd,ATA_DEV_RST);
if (!ATAWaitNotBUSY(bd,0))
okay=FALSE;
} else {
while (InU8(bd->base0+ATAR0_STAT) & ATAS_BSY) {
if (bd->flags&BDF_LAST_WAS_WRITE)
OutU16(bd->base0+ATAR0_DATA,0);
else
InU16(bd->base0+ATAR0_DATA);
Yield;
if (0<timeout<tS)
return FALSE;
}
Free(bd->dev_id_record);
if (ATAGetDevId(bd,timeout,&bd->dev_id_record)==BDT_NULL)
okay=FALSE;
else
BEqu(&bd->flags,BDf_EXT_SIZE,Bt(&bd->dev_id_record[86],10));
}
if (okay) {
if (bd->flags & BDF_EXT_SIZE && bd->base1) {
OutU8(bd->base1+ATAR1_CTRL,0x8);
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
ATACmd(bd,ATA_READ_NATIVE_MAX_EXT);
if (ATAWaitNotBUSY(bd,timeout)) {
result.u8[0]=InU8(bd->base0+ATAR0_SECT);
result.u8[1]=InU8(bd->base0+ATAR0_LCYL);
result.u8[2]=InU8(bd->base0+ATAR0_HCYL);
OutU8(bd->base1+ATAR1_CTRL,0x80);
result.u8[3]=InU8(bd->base0+ATAR0_SECT);
result.u8[4]=InU8(bd->base0+ATAR0_LCYL);
result.u8[5]=InU8(bd->base0+ATAR0_HCYL);
if (result>>24==result&0xFFFFFF) {//Kludge to make qemu-kvm work
bd->flags&=~BDF_EXT_SIZE;
result&=0xFFFFFF;
}
}
} else {
if (bd->type!=BDT_ATAPI && bd->base1)
OutU8(bd->base1+ATAR1_CTRL,0x8);
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
ATACmd(bd,ATA_READ_NATIVE_MAX);
if (ATAWaitNotBUSY(bd,timeout)) {
result.u8[0]=InU8(bd->base0+ATAR0_SECT);
result.u8[1]=InU8(bd->base0+ATAR0_LCYL);
result.u8[2]=InU8(bd->base0+ATAR0_HCYL);
result.u8[3]=InU8(bd->base0+ATAR0_SELECT) & 0xF;
}
}
}
return bd->max_blk=result;
}
I64 ATAPIReadCapacity(CBlkDev *bd,I64 *_blk_size=NULL)
{//Supposedly this can return a result +/- 75 sects.
//Error might just be for music.
Bool unlock=BlkDevLock(bd);
U32 buf[2];
if (ATAWaitNotBUSY(bd,0)) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_LCYL,8);
OutU8(bd->base0+ATAR0_HCYL,0);
ATACmd(bd,ATA_PACKET);
ATAPIWritePktWord(bd,0,0x2500,0,0,0,0,0);
if (!ATAGetResult(bd,0,buf,8,0,TRUE))
buf[0]=buf[1]=0;
} else
buf[0]=buf[1]=0;
if (unlock) BlkDevUnlock(bd);
if (_blk_size) *_blk_size=EndianU32(buf[1]);
return EndianU32(buf[0]);
}
CATAPITrack *ATAPIReadTrackInfo(CBlkDev *bd,I64 blk)
{
CATAPITrack *result=CAlloc(sizeof(CATAPITrack));
Bool unlock=BlkDevLock(bd);
if (ATAWaitNotBUSY(bd,0)) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_LCYL,sizeof(CATAPITrack)&0xFF);
OutU8(bd->base0+ATAR0_HCYL,sizeof(CATAPITrack)>>8);
ATACmd(bd,ATA_PACKET);
ATAPIWritePktWord(bd,0,0x5200,blk.u16[1],blk.u16[0],
(sizeof(CATAPITrack)&0xFF00)>>8,(sizeof(CATAPITrack)&0x00FF)<<8,0);
if (!ATAGetResult(bd,0,result,sizeof(CATAPITrack),0,TRUE)) {
Free(result);
result=NULL;
}
} else {
Free(result);
result=NULL;
}
if (unlock) BlkDevUnlock(bd);
return result;
}
Bool ATAInit(CBlkDev *bd)
{
Bool unlock=BlkDevLock(bd),okay=FALSE;
if (bd->type==BDT_ATAPI)
bd->flags&=~BDF_EXT_SIZE;
else
bd->flags|=BDF_EXT_SIZE;
if (ATAReadNativeMax(bd,tS+0.1)) {
ATABlkSelect(bd,bd->max_blk,0);
if (bd->flags&BDF_EXT_SIZE)
ATACmd(bd,ATA_SET_MAX_EXT);
else
ATACmd(bd,ATA_SET_MAX);
if (ATAWaitNotBUSY(bd,0)) {
okay=TRUE;
if (bd->type==BDT_ATAPI) {
if (ATAPIStartStop(bd,0,TRUE)) {
if(!ATAPISetMaxSpeed(bd))
okay=FALSE;
} else
okay=FALSE;
}
}
}
if (unlock) BlkDevUnlock(bd);
return okay;
}
Bool ATAPIWaitReady(CBlkDev *bd,F64 timeout)
{
do {
if (!ATAWaitNotBUSY(bd,timeout) ||
!ATANop(bd,timeout) ||
!ATAPIStartStop(bd,timeout,TRUE))
return FALSE;
if (InU8(bd->base0+ATAR0_STAT) & ATAS_DRDY &&
!InU8(bd->base0+ATAR0_FEAT));
return TRUE;
ATAInit(bd);
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
U0 ATAReadBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 cnt)
{
I64 retries=3;
Bool unlock=BlkDevLock(bd);
retry:
ATABlkSelect(bd,blk,cnt);
if (bd->flags & BDF_EXT_SIZE)
ATACmd(bd,ATA_READ_MULTI_EXT);
else
ATACmd(bd,ATA_READ_MULTI);
if (!ATAGetResult(bd,tS+1.0,buf,cnt*bd->blk_size,BLK_SIZE,FALSE)) {
if (retries--) {
ATAWaitNotBUSY(bd,0);
goto retry;
} else
throw('BlkDev');
}
blkdev.read_cnt+=(cnt*bd->blk_size)>>BLK_SIZE_BITS;
if (unlock) BlkDevUnlock(bd);
}
I64 ATAProbe(I64 base0,I64 base1,I64 unit)
{
CBlkDev bd;
MemSet(&bd,0,sizeof(CBlkDev));
bd.type=BDT_ATAPI;
bd.base0=base0;
bd.base1=base1;
bd.unit=unit;
bd.blk_size=DVD_BLK_SIZE;
return ATAGetDevId(&bd,tS+0.1,NULL);
}
Bool ATAPIReadBlks2(CBlkDev *bd,F64 timeout,U8 *buf,
I64 native_blk, I64 cnt,Bool lock)
{
Bool result=FALSE,unlock;
if (cnt<=0)
return FALSE;
if (lock)
unlock=BlkDevLock(bd);
if (ATAPIWaitReady(bd,timeout)) {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_LCYL,bd->blk_size);
OutU8(bd->base0+ATAR0_HCYL,bd->blk_size.u8[1]);
ATACmd(bd,ATA_PACKET);
if (ATAPIWritePktWord(bd,timeout,0xA800,
native_blk.u16[1],native_blk,cnt.u16[1],cnt,0) &&
ATAGetResult(bd,timeout,buf,cnt*bd->blk_size,0,FALSE)) {
blkdev.read_cnt+=(cnt*bd->blk_size)>>BLK_SIZE_BITS;
result=TRUE;
}
}
// ATAPIStartStop(bd,0,FALSE);
if (lock && unlock) BlkDevUnlock(bd);
return result;
}
U0 ATAPIReadBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 cnt)
{
CDrv *dv=Let2Drv(bd->first_drv_let);
I64 retry,spc=bd->blk_size>>BLK_SIZE_BITS,n,blk2,
l2=bd->max_reads<<1+spc<<1;
U8 *dvd_buf=MAlloc(l2<<BLK_SIZE_BITS);
if (cnt>0) {
if (blk<=bd->max_reads)
blk2=0;
else
blk2=FloorU64(blk-bd->max_reads,spc);
if (blk2+l2>dv->size)
l2=dv->size-blk2;
n=(l2+spc-1)/spc;
retry=4;
while (--retry)
if (ATAPIReadBlks2(bd,tS+7.0+0.004*n,dvd_buf,blk2/spc,n,TRUE))
//n is 0x800 if max_reads. Up to 8 additional seconds
break;
if (!retry)
ATAPIReadBlks2(bd,0,dvd_buf,blk2/spc,n,TRUE);
if (bd->flags & BDF_READ_CACHE)
DskCacheAdd(dv,dvd_buf,blk2,n*spc);
MemCpy(buf,dvd_buf+(blk-blk2)<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
}
Free(dvd_buf);
}
Bool ATARBlks(CDrv *dv,U8 *buf, I64 blk, I64 cnt)
{
I64 n;
CBlkDev *bd=dv->bd;
while (cnt>0) {
n=cnt;
if (n>bd->max_reads)
n=bd->max_reads;
if (bd->type==BDT_ATAPI)
ATAPIReadBlks(bd,buf,blk,n);
else
ATAReadBlks(bd,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
}
return TRUE;
}
U0 ATAWriteBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 cnt)
{//For low level disk access.
//Use WBlks() instead.
I64 i,U32s_avail,sects_avail,retries=3;
F64 timeout;
Bool unlock=BlkDevLock(bd);
retry:
ATABlkSelect(bd,blk,cnt);
if (bd->flags&BDF_EXT_SIZE)
ATACmd(bd,ATA_WRITE_MULTI_EXT);
else
ATACmd(bd,ATA_WRITE_MULTI);
bd->flags|=BDF_LAST_WAS_WRITE;
while (cnt>0) {
timeout=tS+1.0;
while (TRUE) {
i=InU8(bd->base0+ATAR0_STAT);
if (!(i & ATAS_DRDY)||!(i & ATAS_DRQ)) {
Yield;
} else
break;
if (/* i&ATAS_ERR||*/ tS>timeout) {
if (retries--) {
ATAWaitNotBUSY(bd,0);
goto retry;
} else
throw('BlkDev');
}
}
sects_avail=1;
U32s_avail=sects_avail<<BLK_SIZE_BITS>>2;
RepOutU32(buf,U32s_avail,bd->base0+ATAR0_DATA);
buf+=U32s_avail<<2;
cnt-=sects_avail;
retries=3;
}
ATAWaitNotBUSY(bd,0);
if (unlock) BlkDevUnlock(bd);
}
Bool ATAPISync(CBlkDev *bd)
{
Bool okay=TRUE;
if (!ATAWaitNotBUSY(bd,0))
okay=FALSE;
else {
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_LCYL,0);
OutU8(bd->base0+ATAR0_HCYL,0);
ATACmd(bd,ATA_PACKET);
ATAPIWritePktWord(bd,0,0x3500,0,0,0,0,0);
if (!ATAWaitNotBUSY(bd,0))
okay=FALSE;
}
return okay;
}
U0 ATAPIClose(CBlkDev *bd,I64 close_field=0x200,I64 track=0)
{//0x200 CD/DVD part 1
// 0x300 DVD part 2
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_LCYL,0);
OutU8(bd->base0+ATAR0_HCYL,0);
ATACmd(bd,ATA_PACKET);
ATAPIWritePktWord(bd,0,0x5B00,close_field,track,0,0,0);
ATAWaitNotBUSY(bd,0);
}
U0 ATAPIWriteBlks(CBlkDev *bd,U8 *buf, I64 native_blk, I64 cnt)
{
I64 U32s_avail;
U8 *buf2;
ATAWaitNotBUSY(bd,0);
ATAPISeek(bd,native_blk);
OutU8(bd->base0+ATAR0_FEAT,0);
OutU8(bd->base0+ATAR0_LCYL,bd->blk_size);
OutU8(bd->base0+ATAR0_HCYL,bd->blk_size.u8[1]);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_CMD,ATA_PACKET);
ATAPIWritePktWord(bd,0,0x0400,native_blk.u16[1],native_blk,cnt.u16[1],cnt,0);
bd->flags|=BDF_LAST_WAS_WRITE;
ATAWaitNotBUSY(bd,0);
ATAPISeek(bd,native_blk);
if (bd->flags & BDF_EXT_SIZE)
OutU8(bd->base0+ATAR0_SELECT,0xEF|bd->unit<<4);
else
OutU8(bd->base0+ATAR0_SELECT,0xE0|bd->unit<<4);
OutU8(bd->base0+ATAR0_LCYL,bd->blk_size);
OutU8(bd->base0+ATAR0_HCYL,bd->blk_size.u8[1]);
ATACmd(bd,ATA_PACKET);
ATAPIWritePktWord(bd,0,0xAA00,native_blk.u16[1],native_blk,cnt.u16[1],cnt,0);
buf2=buf+bd->blk_size*cnt;
while (buf<buf2) {
ATAWaitDRQ(bd,0);
U32s_avail=(InU8(bd->base0+ATAR0_HCYL)<<8+InU8(bd->base0+ATAR0_LCYL))>>2;
if (buf+U32s_avail<<2>buf2)
U32s_avail=(buf2-buf)>>2;
if (U32s_avail) {
RepOutU32(buf,U32s_avail,bd->base0+ATAR0_DATA);
buf+=U32s_avail<<2;
blkdev.write_cnt+=U32s_avail>>(BLK_SIZE_BITS-2);
}
}
ATAWaitNotBUSY(bd,0);
}
Bool ATAWBlks(CDrv *dv,U8 *buf, I64 blk, I64 cnt)
{
I64 n,spc;
CBlkDev *bd=dv->bd;
Bool unlock;
spc=bd->blk_size>>BLK_SIZE_BITS;
if (bd->type==BDT_ATAPI) {
unlock=BlkDevLock(bd);
ATAPIWaitReady(bd,0);
}
while (cnt>0) {
n=cnt;
if (n>bd->max_writes)
n=bd->max_writes;
if (bd->type==BDT_ATAPI)
ATAPIWriteBlks(bd,buf,blk/spc,(n+spc-1)/spc);
else
ATAWriteBlks(bd,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
blkdev.write_cnt+=n;
}
if (bd->type==BDT_ATAPI) {
ATAPISync(bd);
// ATAPIStartStop(bd,0,FALSE);
if (unlock) BlkDevUnlock(bd);
}
return TRUE;
}
+279
View File
@@ -0,0 +1,279 @@
Bool BootDVDProve(CBlkDev *bd)
{
CKernel *img=CAlloc(DVD_BLK_SIZE);
I64 i;
Bool result=FALSE;
"Port: %04X,%04X Unit: %02X ",bd->base0,bd->base1,bd->unit;
if (ATAProbe(bd->base0,bd->base1,bd->unit)==BDT_ATAPI) {
" ATAPI";
if (ATAPIStartStop(bd,tS+5.0,TRUE)) {
" Started";
for (i=0;i<2;i++) {//Retry
if (ATAPIReadBlks2(bd,tS+7.0,img,sys_boot_src.u16[1],1,FALSE)) {
if (img->compile_time==sys_compile_time) {
" Found";
return TRUE;
} else
" Read";
} else
" NoRead";
}
}
}
" Nope\n";
Free(img);
return result;
}
Bool BootDVDProbeAll(CBlkDev *bd)
{
I64 d1,d2,i,j,k;
bd->base1=0;
for (k=0;k<256;k++) {
i=-1;
while (TRUE) {
j=PCIClassFind(0x010100+k,++i);
if (j<0)
break;
"Subcode:0x%X Bus:0x%X Dev:0x%X Fun:0x%X\n",k,j.u8[2],j.u8[1],j.u8[0];
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x10);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x14);
if (d1&1 && d2&1) {
if (bd->base0=d1&~7) {
bd->unit=0;
if (BootDVDProve(bd))
return TRUE;
bd->unit=1;
if (BootDVDProve(bd))
return TRUE;
}
}
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x18);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x1C);
if (d1&1 && d2&1) {
if (bd->base0=d1&~7) {
bd->unit=0;
if (BootDVDProve(bd))
return TRUE;
bd->unit=1;
if (BootDVDProve(bd))
return TRUE;
}
}
}
}
d1=0x1F0;
d2=0x3F6;
if (bd->base0=d1&~7) {
bd->unit=0;
if (BootDVDProve(bd))
return TRUE;
bd->unit=1;
if (BootDVDProve(bd))
return TRUE;
}
d1=0x170;
d2=0x376;
if (bd->base0=d1&~7) {
bd->unit=0;
if (BootDVDProve(bd))
return TRUE;
bd->unit=1;
if (BootDVDProve(bd))
return TRUE;
}
}
U0 ATARepEntry(I64 base0,I64 base1,I64 unit,I64 irq,U8 *msg,
CATARep **_root,I64 *num_hints)
{
I64 type;
base0&=-8;
base1&=-4;
CATARep *tempha;
if (type=ATAProbe(base0,base1,unit)) {
*num_hints+=1;
"\n\n$$PURPLE$$ $$BT+X,\"%d\",LM=\"%d\\n\"$$$$FG$$$$LM,4$$",*num_hints,*num_hints;
if (type==BDT_ATA)
"$$RED$$ATA ";
else
"$$RED$$ATAPI ";
"$$LTBLUE$$%s$$FG$$\nBase0:0x%04X Base1:0x%04X\nIrq:0x%02X Unit:%d$$LM,0$$\n",
msg,base0,base1,irq,unit;
if (_root) {
tempha=CAlloc(sizeof(CATARep));
tempha->next=*_root;
*_root=tempha;
tempha->num=*num_hints;
tempha->type=type;
tempha->base0=base0;
tempha->base1=base1;
tempha->unit=unit;
}
}
}
Bool ATARepExitAllApplications()
{
"\nWe're going to probe hardware.\n"
"$$RED$$Exit all other applications.$$FG$$\n"
"Press '$$PURPLE$$p$$FG$$' to probe or '$$PURPLE$$s$$FG$$' to skip.\n";
if (ToUpper(GetChar(,FALSE))=='S')
return TRUE;
else
return FALSE;
}
public I64 ATARep(Bool pmt=TRUE,Bool just_ide=FALSE,CATARep **_root=NULL)
{//Report possible ATA devices by probing. Hard disks and CD/DVDs.
I64 d1,d2,d3,i,j,k,cnt=0,unlock_flags=0,num_hints=0;
#assert NUM_BLKDEVS<=64
if (_root) *_root=NULL;
if (pmt && ATARepExitAllApplications)
return 0;
for (i=0;i<NUM_BLKDEVS;i++)
if (blkdev.blkdevs[i].bd_signature==BD_SIGNATURE_VAL)
BEqu(&unlock_flags,i,
BlkDevLock(&blkdev.blkdevs[i]));
if (!just_ide)
for (k=0;k<256;k++) {
i=-1;
while (TRUE) {
j=PCIClassFind(0x010100+k,++i);
if (j<0)
break;
"\nSubcode:0x%X Bus:0x%X Dev:0x%X Fun:0x%X\n",k,j.u8[2],j.u8[1],j.u8[0];
cnt++;
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x10);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x14);
d3=PCIReadU8(j.u8[2],j.u8[1],j.u8[0],0x3C);
if (d1&1 && d2&1) {
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
} else {
d1=0x1F0; d2=0x3F6; d3=14;
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
}
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x18);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x1C);
if (d1&1 && d2&1) {
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
} else {
d1=0x170; d2=0x376; d3=15;
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
}
}
}
if (!cnt) {
d1=0x1F0; d2=0x3F6; d3=14;
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
d1=0x170; d2=0x376; d3=15;
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
}
'\n\n';
for (i=0;i<NUM_BLKDEVS;i++)
if (Bt(&unlock_flags,i))
BlkDevUnlock(&blkdev.blkdevs[i]);
return num_hints;
}
CATARep *ATAIDDrvs(CATARep *root,I64 _sys_boot_drv,
CATARep **_ata_drv,CATARep **_atapi_drv)
{//This is for when trying to sort-out main hard drives and CD/DVD drives.
CATARep *result=NULL,*tempha=root,*ata_drv=NULL,*atapi_drv=NULL;
CBlkDev *bd;
Bool was_silent=Silent;
try
bd=Let2BlkDev(_sys_boot_drv);
catch {
Fs->catch_except=TRUE;
bd=NULL;
}
Silent(was_silent);
while (tempha) {
if (!result && bd && bd->type==tempha->type) {
if (bd->type==BDT_ATAPI &&
bd->base0==tempha->base0 && bd->unit==tempha->unit)
result=atapi_drv=tempha;
else if (bd->type==BDT_ATA && bd->base0==tempha->base0 &&
bd->base1==tempha->base1 && bd->unit==tempha->unit)
result=ata_drv=tempha;
}
if (!result || result->type!=tempha->type) {
if (tempha->type==BDT_ATA) {
if (!ata_drv || tempha->unit<ata_drv->unit ||
tempha->unit==ata_drv->unit && tempha->num<ata_drv->num)
ata_drv=tempha;
} else if (tempha->type==BDT_ATAPI) {
if (!atapi_drv || tempha->unit<atapi_drv->unit ||
tempha->unit==atapi_drv->unit && tempha->num<atapi_drv->num)
atapi_drv=tempha;
}
}
tempha=tempha->next;
}
if (_ata_drv) *_ata_drv =ata_drv;
if (_atapi_drv) *_atapi_drv=atapi_drv;
return result;
}
CBlkDev *ATAMount(U8 first_drv_let,I64 type,I64 base0,I64 base1,I64 unit)
{
CBlkDev *result;
if (0<=first_drv_let-'A'<NUM_DRVS && (type==BDT_ATA || type==BDT_ATAPI) &&
0<=unit<=1) {
result=BlkDevNextFree(first_drv_let,type);
result->unit=unit;
result->base0=base0;
result->base1=base1;
if (BlkDevAdd(result,FALSE,FALSE))
return result;
}
return NULL;
}
I64 AutoMountIDE()
{//Try to mount hard drive and CD/DVD, automatically. (Kernel.Cfg option).
//It uses 'C' and 'T' as first drive letters or whatever you set
//in config when compiling Kernel.BIN.
I64 result=0;
CATARep *root=NULL,*ata_drv=NULL,*atapi_drv=NULL,*tempha;
ATARep(FALSE,TRUE,&root);
ATAIDDrvs(root,blkdev.boot_drv_let,&ata_drv,&atapi_drv);
if (ata_drv && ATAMount(blkdev.first_hd_drv_let,BDT_ATA,
ata_drv->base0,ata_drv->base1,ata_drv->unit))
result++;
if (atapi_drv && ATAMount(blkdev.first_dvd_drv_let,BDT_ATAPI,
atapi_drv->base0,atapi_drv->base1,atapi_drv->unit))
result++;
tempha=root;
while (tempha) {
if (tempha!=ata_drv && tempha!=atapi_drv) {
if (tempha->type==BDT_ATA && ATAMount(blkdev.first_hd_drv_let,BDT_ATA,
tempha->base0,tempha->base1,tempha->unit))
result++;
else if (tempha->type==BDT_ATAPI &&
ATAMount(blkdev.first_dvd_drv_let,BDT_ATAPI,
tempha->base0,tempha->base1,tempha->unit))
result++;
}
tempha=tempha->next;
}
LinkedLstDel(root);
blkdev.auto_mount_ide_cnt=result;
return result;
}
+333
View File
@@ -0,0 +1,333 @@
U0 BlkDevLockFwdingSet(CBlkDev *bd)
{ //If two blkdevs on same controller, use just one lock
CBlkDev *bd1;
I64 i;
switch (bd->type) {
case BDT_RAM:
break;
case BDT_ATA:
case BDT_ATAPI:
for (i=0;i<NUM_BLKDEVS;i++) {
bd1=&blkdev.blkdevs[i];
if (bd1->bd_signature==BD_SIGNATURE_VAL && bd!=bd1 &&
(bd1->type==BDT_ATAPI || bd1->type==BDT_ATA) &&
bd1->base0==bd->base0) {
bd->lock_fwding=bd1;
break;
}
}
break;
}
}
I64 BlkDevAdd(CBlkDev *bd,Bool one_drv,Bool make_free)
{
I64 i,j,ext_base,offset,result=0;
CDrv *dv;
CRedSeaBoot br;
CMasterBoot mbr;
bd->bd_signature=BD_SIGNATURE_VAL;
if (make_free)
dv=DrvMakeFree(bd->first_drv_let+result);
else
dv=DrvNextFree(bd->first_drv_let+result);
dv->bd=bd;
dv->size=bd->max_blk+1;
switch (bd->type) {
case BDT_RAM:
dv->dv_signature=DRV_SIGNATURE_VAL;
dv->type=DVT_REDSEA;
//This is to force creation of a RAM
//drive during boot, so it is probably
//MAlloced to the same addr and can
//be assumed to be already formatted.
//If this line is removed, RAM Drives
//will be alloced on a just-in-time
//basis.
if (BlkDevInit(bd))
result++;
else
dv->dv_signature=0;
break;
case BDT_ATA:
dv->dv_signature=DRV_SIGNATURE_VAL; //Temporarily validate
if (!BlkDevInit(bd))
dv->dv_signature=0; //Revoke validation
else {
dv->dv_signature=0; //Revoke validation
if (one_drv) {
dv->dv_signature=DRV_SIGNATURE_VAL;
result++;
dv->type=DVT_REDSEA;
dv->size=bd->max_blk+1;
//The following read is a test read.
//if it hangs, the drive is not supported.
ATAReadBlks(bd,&mbr,0,1);
break;
}
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bd,&mbr,offset,1);
if (mbr.signature!=0xAA55)
break;
j=-1;
for (i=0;i<4;i++) {
if (mbr.p[i].type) {
if (make_free)
dv=DrvMakeFree(bd->first_drv_let+result);
else
dv=DrvNextFree(bd->first_drv_let+result);
dv->bd=bd;
dv->base_offset=mbr.p[i].offset+offset;
dv->size =mbr.p[i].size;
switch (mbr.p[i].type) {
case MBR_PT_REDSEA:
dv->dv_signature=DRV_SIGNATURE_VAL;
result++;
dv->type=DVT_REDSEA;
RedSeaDrvInit(dv);
break;
case MBR_PT_FAT32a:
case MBR_PT_FAT32b:
case MBR_PT_FAT32c:
case MBR_PT_FAT32d:
case MBR_PT_FAT32e:
case MBR_PT_FAT32f:
ATAReadBlks(bd,&br,dv->base_offset,1);
dv->dv_signature=DRV_SIGNATURE_VAL;
result++;
if (br.signature==MBR_PT_REDSEA) {
dv->type=DVT_REDSEA;
RedSeaDrvInit(dv);
} else {
dv->type=DVT_FAT32;
FAT32DrvInit(dv);
}
break;
case MBR_PT_NTFS:
dv->dv_signature=DRV_SIGNATURE_VAL;
result++;
dv->type=DVT_NTFS;
break;
case 5:
case 15:
j=i;
break;
default:
dv->dv_signature=DRV_SIGNATURE_VAL;
result++;
dv->type=DVT_UNKNOWN;
}
}
}
if (j<0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
}
break;
case BDT_ATAPI:
dv->dv_signature=DRV_SIGNATURE_VAL;
result++;
dv->type=DVT_ISO9660; //Start with this
dv->size =0;
break;
}
if (result)
BlkDevLockFwdingSet(bd);
else
MemSet(bd,0,sizeof(CBlkDev));
return result;
}
Bool DrvEnable(U8 drv_let,Bool val)
{//Can unmount or remount, but not mount the first time.
CDrv *dv;
Bool result=FALSE;
try {
dv=Let2Drv(drv_let);
result=!LBEqu(&dv->type,DVTf_DISABLE,!val);
} catch
Fs->catch_except=TRUE;
return result;
}
CATARep *ATARepFind(CATARep *haystack_root,I64 needle_num)
{
while (haystack_root) {
if (haystack_root->num==needle_num)
return haystack_root;
haystack_root=haystack_root->next;
}
return NULL;
}
U0 Mount(Bool repartition=FALSE)
{//Mount a drive.
CBlkDev *bd;
I64 first_drv_num,type,unit,num_hints;
U8 blks_buf[STR_LEN],addr_buf[STR_LEN],base0_buf[STR_LEN],base1_buf[STR_LEN];
Bool add;
CATARep *root,*tempha;
do {
DrvRep;
"\n****** Mount Drives ******\n"
"The first drive letter is the letter\n"
"of the first partition. If adding\n"
"a hard drive, you should pick 'C'.\n"
"If more than one partition is present\n"
"they will be lettered in sequence.\n"
"\nFirst Drive Letter ($$PURPLE$$<ENTER>$$FG$$ to exit):";
first_drv_num=ToUpper(GetChar)-'A';
'\n';
if (0<=first_drv_num<NUM_DRVS) {
"\t$$PURPLE$$1$$FG$$=RAM\n\t$$PURPLE$$2$$FG$$=ATA(Harddisk)\n"
"\t$$PURPLE$$3$$FG$$=ATAPI(CD/DVD)\nType:";
type=GetChar-'0';
'\n';
unit=0;
if (type==BDT_ATA || type==BDT_ATAPI) {
num_hints=ATARep(,,&root);
do {
if (num_hints)
"Enter dev number or\nport with $$PURPLE$$0x$$FG$$ prefix.\n"
"I/O Port Base0:\n";
else
"Include $$PURPLE$$0x$$FG$$ prefix.\nI/O Port Base0:\n";
GetS(base0_buf,STR_LEN);
} while (!Str2I64(base0_buf));
if (1<=Str2I64(base0_buf)<=num_hints) {
tempha=ATARepFind(root,Str2I64(base0_buf));
StrPrint(base0_buf,"0x%X",tempha->base0);
StrPrint(base1_buf,"0x%X",tempha->base1);
unit=tempha->unit;
} else {
if (type==BDT_ATAPI)
StrCpy(base1_buf,"0");
else
do {
"I/O Port Base1:\n";
GetS(base1_buf,STR_LEN);
} while (!Str2I64(base1_buf));
do {
"\t$$PURPLE$$0$$FG$$=Master\n\t$$PURPLE$$1$$FG$$=Slave\nUnit:";
unit=GetChar-'0';
} while (!(0<=unit<=1));
'\n';
}
LinkedLstDel(root);
}
if (type==BDT_RAM) {
"Addr of RAM disk ($$PURPLE$$<ENTER>$$FG$$ to MAlloc):";
GetS(addr_buf,STR_LEN);
"Blks of 512 bytes:";
GetS(blks_buf,STR_LEN);
}
if (BDT_NULL<type<BDT_NUM_TYPES && 0<=unit<=1) {
bd=BlkDevNextFree(first_drv_num+'A',type);
bd->unit=unit;
if (type==BDT_RAM) {
if (!*addr_buf) StrCpy(addr_buf,"0");
bd->RAM_dsk=Str2I64(addr_buf);
bd->max_blk=Str2I64(blks_buf)-1;
}
if (type==BDT_ATA ||
type==BDT_ATAPI) {
bd->base0=Str2I64(base0_buf);
bd->base1=Str2I64(base1_buf);
}
add=TRUE;
if (type==BDT_ATA && repartition) {
"\nReformat WHOLE drive!";
if (YorN) {
if (!BlkDevAdd(bd,TRUE,TRUE))
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
else
CallExtStr("PrtDsk",bd->first_drv_let);
add=FALSE;
}
}
if (add && !BlkDevAdd(bd,FALSE,TRUE))
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
} else
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
}
} while (0<=first_drv_num<NUM_DRVS);
}
I64 SysGetI64()
{
U8 st[STR_LEN];
GetS(st,STR_LEN,FALSE);
return Str2I64(st,16);
}
Bool GetBaseUnit(CBlkDev *bd)
{
I64 ch;
Bool probe;
" TempleOS\n\n\n";
#exe {
if (kernel_cfg->opts[CFG_DONT_PROBE])
StreamPrint("probe=FALSE;");
else
StreamPrint("probe=TRUE;");
};
if (!probe || !BootDVDProbeAll(bd)) {
"\nDon't worry. This is not a product\n"
"registration. TempleOS just needs the\n"
"I/O port numbers for the CD/DVD.\n"
"\nRetry the ports above or check Windows\n"
"system information under I/O ports for\n"
"'IDE', 'ATA' or 'SATA'.\n"
"In Linux, use 'lspci -v' for ports.\n"
"\n\nEnter 4-digit hex I/O Port number.\n"
"CD/DVD I/O Port Base0: 0x";
bd->base0=SysGetI64;
bd->base1=0;
bd->unit =0;
if (bd->base0) {
"\nUnit (0 or 1): ";
do ch=GetChar(,FALSE);
while (!('0'<=ch<='1'));
'' ch;
bd->unit=ch-'0';
blkdev.dvd_boot_is_good=BootDVDProve(bd);
return TRUE;
} else {
blkdev.dvd_boot_is_good=FALSE;
return FALSE;
}
}
return FALSE;
}
U0 BlkDevsInitAll()
{
CBlkDev *bd;
I64 i;
blkdev.blkdevs=CAlloc(sizeof(CBlkDev)*NUM_BLKDEVS);
blkdev.drvs=CAlloc(sizeof(CDrv)*NUM_DRVS);
for (i=0;i<NUM_DRVS;i++)
blkdev.let_to_drv[i]=&blkdev.drvs[i];
text.raw_col=0;
#exe {
if (kernel_cfg->opts[CFG_AUTO_MOUNT_IDE])
StreamPrint("AutoMountIDE;");
StreamPrint("#exe {Option(OPTf_WARN_PAREN,OFF);}");
StreamDoc(kernel_cfg->add_dev);
StreamPrint("#exe {Option(OPTf_WARN_PAREN,ON);}");
};
DrvRep;
}
+102
View File
@@ -0,0 +1,102 @@
#define ZERO_BUF_SIZE 2048
U0 WZeroBlks(CDrv *dv,I64 blk,I64 cnt)
{//Fill blk cnt with zeros in Drv.
I64 n;
U8 *z=CAlloc(ZERO_BUF_SIZE<<BLK_SIZE_BITS);
Bool show_progress;
if (cnt>ZERO_BUF_SIZE && dv->bd->type!=BDT_RAM) {
progress1=0; progress1_max=cnt;
StrCpy(progress1_desc,"Zeroing");
show_progress=TRUE;
} else
show_progress=FALSE;
while (cnt>0) {
n=cnt;
if (n>ZERO_BUF_SIZE)
n=ZERO_BUF_SIZE;
WBlks(dv,z,blk,n);
blk+=n;
cnt-=n;
if (show_progress)
progress1+=n;
Yield; //Prevent locking
}
Free(z);
if (show_progress) {
*progress1_desc=0;
progress1=progress1_max=0;
}
}
Bool RBlks(CDrv *dv,U8 *buf, I64 blk, I64 cnt)
{//Read blk cnt from Drv to buf.
Bool result=TRUE,unlock;
CBlkDev *bd=dv->bd;
if (cnt<=0) return TRUE;
DrvChk(dv);
try {
unlock=DrvLock(dv);
BlkDevInit(bd);
if (dv->base_offset && blk<dv->base_offset ||
blk+cnt>dv->base_offset+dv->size)
throw('Drv');
if (bd->flags & BDF_READ_CACHE)
RCache(dv,&buf,&blk,&cnt);
if (cnt>0) {
switch (bd->type) {
case BDT_RAM:
MemCpy(buf,bd->RAM_dsk+blk<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
break;
case BDT_ATA:
case BDT_ATAPI:
result=ATARBlks(dv,buf,blk,cnt);
break;
}
bd->last_time=tS;
if (bd->flags & BDF_READ_CACHE)
DskCacheAdd(dv,buf,blk,cnt);
}
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
return result;
}
Bool WBlks(CDrv *dv,U8 *buf, I64 blk, I64 cnt)
{//Write blk cnt from buf to Drv.
Bool result=TRUE,unlock;
CBlkDev *bd=dv->bd;
if (cnt<=0) return TRUE;
DrvChk(dv);
try {
unlock=DrvLock(dv);
BlkDevInit(bd);
if (bd->flags&BDF_READ_ONLY && !(bd->flags & BDF_READ_ONLY_OVERRIDE))
throw('BlkDev');
if (dv->base_offset && blk<dv->base_offset ||
blk+cnt>dv->base_offset+dv->size)
throw('Drv');
if (cnt>0) {
switch (bd->type) {
case BDT_RAM:
MemCpy(bd->RAM_dsk+blk<<BLK_SIZE_BITS,buf,cnt<<BLK_SIZE_BITS);
break;
case BDT_ATA:
case BDT_ATAPI:
result=ATAWBlks(dv,buf,blk,cnt);
break;
}
bd->last_time=tS;
if (bd->flags & BDF_READ_CACHE)
DskCacheAdd(dv,buf,blk,cnt);
}
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
return result;
}
+132
View File
@@ -0,0 +1,132 @@
Bool BlkDevLock(CBlkDev *bd)
{//Make this task have exclusive access to BlkDev.
BlkDevChk(bd);
while (bd->lock_fwding)
bd=bd->lock_fwding; //If two blkdevs on same controller, use just one lock
if (!Bt(&bd->locked_flags,BDlf_LOCKED) || bd->owning_task!=Fs) {
while (LBts(&bd->locked_flags,BDlf_LOCKED))
Yield;
bd->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool BlkDevUnlock(CBlkDev *bd,Bool rst=FALSE)
{//Release exclusive lock on access to BlkDev.
BlkDevChk(bd);
while (bd->lock_fwding)
bd=bd->lock_fwding; //If two blkdevs on same controller, use just one lock
if (Bt(&bd->locked_flags,BDlf_LOCKED) && bd->owning_task==Fs) {
if (rst)
bd->flags&=~(BDF_INITIALIZED|BDF_INIT_IN_PROGRESS);
bd->owning_task=NULL;
LBtr(&bd->locked_flags,BDlf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
Bool BlkDevInit(CBlkDev *bd)
{
CDrv *dv=Let2Drv(bd->first_drv_let);
Bool result=FALSE;
if (!LBts(&bd->flags,BDf_INITIALIZED)) {
bd->flags|=BDF_INIT_IN_PROGRESS;
switch(bd->type) {
case BDT_RAM:
if (!bd->RAM_dsk) {
bd->RAM_dsk=AMAlloc((bd->max_blk+1)<<BLK_SIZE_BITS);
bd->max_blk=MSize(bd->RAM_dsk)>>BLK_SIZE_BITS-1;
}
dv->type=DVT_REDSEA;
dv->size=bd->max_blk+1;
if (RedSeaDrvValidate(bd->first_drv_let))
RedSeaDrvInit(dv);
else
RedSeaFmt(bd->first_drv_let);
result=TRUE;
break;
case BDT_ATA:
bd->max_reads=128;
bd->max_writes=1;
result=ATAInit(bd);
break;
case BDT_ATAPI:
//0xFFFF*4 is too big for my taste
bd->max_reads=0x800*4;
//max of maybe a quarter of disk cache
if (bd->max_reads>blkdev.cache_size/BLK_SIZE/4)
bd->max_reads=blkdev.cache_size/BLK_SIZE/4 & ~3;
if (bd->max_reads<128)
bd->max_reads=128;
bd->max_writes=0xFFFF*4;
if (result=ATAInit(bd))
dv->size=bd->max_blk+1;
break;
}
if (result && bd->flags & BDF_READ_CACHE)
DskCacheInvalidate(dv);
bd->flags&=~BDF_INIT_IN_PROGRESS;
} else
result=TRUE;
return result;
}
U0 BlkDevsRelease()
{//When task dies, release all owned BlkDevs.
I64 i;
CBlkDev *bd;
for (i=0;i<NUM_BLKDEVS;i++) {
bd=&blkdev.blkdevs[i];
if (bd->owning_task==Fs && bd->bd_signature==BD_SIGNATURE_VAL)
BlkDevUnlock(bd,TRUE);
}
}
CBlkDev *BlkDevNextFree(U8 first_drv_let,I64 type)
{//Locate free slot for new BlkDev, like during $LK,"Mount",A="MN:Mount"$().
I64 i=0;
CBlkDev *result;
do {
result=&blkdev.blkdevs[i];
if (result->bd_signature!=BD_SIGNATURE_VAL) {
MemSet(result,0,sizeof(CBlkDev));
result->first_drv_let=first_drv_let;
result->type=type;
if (type==BDT_ATAPI)
result->flags=BDF_REMOVABLE;
else
result->flags=0;
if (type!=BDT_RAM)
result->flags|=BDF_READ_CACHE;
if (type==BDT_ATAPI) {
result->blk_size=DVD_BLK_SIZE;
result->flags|=BDF_READ_ONLY;
} else
result->blk_size=BLK_SIZE;
result->max_blk=0xEFFFFFFF;
return result;
}
} while (++i<NUM_BLKDEVS);
throw('BlkDev');
return NULL; //never gets here
}
U0 BlkDevChk(CBlkDev *bd)
{//Check for valid BlkDev. Throw exception.
if (!bd || bd->bd_signature!=BD_SIGNATURE_VAL ||
!(BDT_NULL<bd->type<BDT_NUM_TYPES))
throw('BlkDev');
}
CBlkDev *Let2BlkDev(U8 drv_let=0)
{//Drv letter to BlkDev ptr.
CDrv *dv=Let2Drv(drv_let);
CBlkDev *bd=dv->bd;
BlkDevChk(bd);
return bd;
}
+179
View File
@@ -0,0 +1,179 @@
U0 DVDImageRead(U8 dvd_drv_let,U8 *out_name)
{//Read entire CD/DVD image into ISO file.
CBlkDev *bd=Let2BlkDev(dvd_drv_let);
CDrv *dv=Let2Drv(dvd_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=bd->blk_size>>BLK_SIZE_BITS,blk=0,cnt,retry;
BlkDevInit(bd);
if (bd->type!=BDT_ATAPI)
throw('BlkDev');
if (!out_name)
out_name=blkdev.dft_iso_filename;
cnt=CeilU64(dv->size,spc);
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bd->max_reads)
n=bd->max_reads;
retry=4;
while (--retry)
if (ATAPIReadBlks2(bd,tS+7.0+0.004*n/spc,buf,blk/spc,n/spc,TRUE))
//n is 0x800 if max_reads. Up to 8 additional seconds
break;
if (!retry)
ATAPIReadBlks2(bd,0,buf,blk/spc,n/spc,TRUE);
FWBlks(f,buf,blk,n);
cnt-=n;
blk+=n;
}
FClose(f);
Free(buf);
Free(out_name2);
}
class CDualBuf
{
U8 *buf0,*buf1;
I64 in_buf,out_buf,cnt;
U8 *filename;
CBlkDev *dvd_bd;
};
U0 DVDImageWriteTask(CDualBuf *d)
{
U8 *buf;
I64 n,blk=0,cnt=d->cnt;
CFile *f;
if (FileAttr(d->filename)&RS_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->dvd_bd->max_writes)
n=d->dvd_bd->max_writes;
if (d->in_buf&1)
buf=d->buf1;
else
buf=d->buf0;
while (d->in_buf>d->out_buf+1)
Yield;
FRBlks(f,buf,blk,n);
d->in_buf++;
cnt-=n;
blk+=n;
}
FClose(f);
}
U0 DVDImageWrite(U8 dvd_drv_let,U8 *in_name=NULL,I64 media_type=MT_DVD)
{//Write CD/DVD ISO file to disk.
CDualBuf *d=CAlloc(sizeof(CDualBuf));
U8 *buf,*in_name2,*in_name3;
I64 i,n,spc,blk=0,cnt;
CDrv *dv=Let2Drv(dvd_drv_let);
CBlkDev *bd=dv->bd,*bd2;
CTask *task;
CFile *f;
if (!in_name)
in_name=blkdev.dft_iso_filename;
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 (bd->type!=BDT_ATAPI)
throw('BlkDev');
bd2=Let2BlkDev(*in_name2);
while (bd2->lock_fwding)
bd2=bd2->lock_fwding; //If two blkdevs on same controller, use one lock
if ((bd2->type==BDT_ATA || bd2->type==BDT_ATAPI) &&
bd2->base0==bd->base0) {
PrintErr("Can't burn CD/DVD on same ATA controller as file.\n\n");
throw('BlkDev');
}
bd->flags|=BDF_READ_ONLY_OVERRIDE;
BlkDevInit(bd);
spc=bd->blk_size>>BLK_SIZE_BITS;
if (dv->size<cnt)
dv->size=cnt;
d->filename=in_name2;
d->dvd_bd=bd;
d->buf0=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->buf1=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->cnt=cnt;
task=Spawn(&DVDImageWriteTask,d,"Write CD/DVD");
while (d->in_buf<=d->out_buf)
Yield;
BlkDevLock(bd);
ATAPIWaitReady(bd,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>bd->max_writes)
n=bd->max_writes;
if (d->out_buf&1)
buf=d->buf1;
else
buf=d->buf0;
while (d->in_buf<=d->out_buf)
Yield;
ATAPIWriteBlks(bd,buf,blk/spc,(n+spc-1)/spc);
d->out_buf++;
cnt-=n;
blk+=n;
progress1+=n;
}
ATAPISync(bd);
progress1=0; progress1_max=2;
StrCpy(progress1_desc,"Closing");
for (i=0;i<2;i++) {
ATAPIClose(bd,0x100,i); //Close tracks
progress1++;
}
ATAPISync(bd);
ATAPIClose(bd,0x200); //close disk
ATAPISync(bd);
if (media_type==MT_DVD) {
ATAPIClose(bd,0x300);
ATAPISync(bd);
}
*progress1_desc=0;
progress1=progress1_max=0;
bd->flags&=~BDF_READ_ONLY_OVERRIDE;
BlkDevUnlock(bd);
Free(d->buf0);
Free(d->buf1);
Free(in_name2);
Free(in_name3);
Free(d);
}
+265
View File
@@ -0,0 +1,265 @@
I64 FSize(CFile *f)
{//Report size of opened file in bytes.
if (f)
return f->de.size;
else
return 0;
}
CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0)
{//Allows flags "r","w","w+". "c" for contiguous.
//(It uses $LK,"StrOcc",A="MN:StrOcc"$() for 'w', 'r', '+', 'c')
CFile *f=CAlloc(sizeof(CFile));
CDirContext *dirc;
U8 *full_name;
Bool contiguous=StrOcc(flags,'c');
f->cluster=INVALID_CLUSTER;
f->fblk_num=0;
if (cnt>0)
f->max_blk=cnt-1;
else
f->max_blk=MAX_I64;
f->file_cluster_num=INVALID_CLUSTER;
full_name=FileNameAbs(filename);
f->dv=Let2Drv(*full_name);
if (f->dv->type==DVT_REDSEA)
contiguous=TRUE;
if (contiguous) {
f->flags|=FF_CONTIGUOUS;
if (f->dv->type!=DVT_REDSEA && !(FileAttr(filename) & RS_ATTR_CONTIGUOUS))
throw('File');
}
f->cluster_buf=CAlloc(f->dv->spc<<BLK_SIZE_BITS);
if (StrOcc(flags,'w')) {
f->flags=f->flags|FF_WRITE|FF_NEEDS_WRITE;
if (StrOcc(flags,'+')) {
if (FileFind(full_name,&f->de,FUF_JUST_FILES)) {
Free(full_name);
if (contiguous)
f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;
return f;
}
} else
Del(full_name,,,FALSE);
f->de.full_name=full_name;
f->flags|=FF_NEW_FILE;
if (dirc=DirContextNew(full_name)) {
StrCpy(f->de.name,dirc->mask);
if (cnt>0) {//We pre-alloc the whole thing.
f->de.cluster=ClustersAlloc(f->dv,0,
(cnt+f->dv->spc-1)/f->dv->spc,contiguous);
f->de.size=cnt<<BLK_SIZE_BITS;
DirNew(dirc->dv,Fs->cur_dir,&f->de,TRUE);
f->flags&=~FF_NEW_FILE;
}
DirContextDel(dirc);
if (!contiguous || cnt>0)
return f;
}
} else {
if (FileFind(full_name,&f->de,FUF_JUST_FILES)) {
Free(full_name);
f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;
return f;
}
}
Free(f->cluster_buf);
Free(full_name);
Free(f);
return NULL;
}
U0 FClose(CFile *f)
{//Close CFile, updating directory.
CDirContext *dirc;
if (f) {
if (f->flags & FF_BUF_DIRTY) {
WClusters(f->dv,f->cluster_buf,f->cluster,1);
f->flags&=~FF_BUF_DIRTY;
}
if (f->flags & FF_NEEDS_WRITE) {
if (dirc=DirContextNew(f->de.full_name)) {
if (!(f->flags & FF_USE_OLD_DATETIME))
f->de.datetime=Now;
if (f->flags & FF_NEW_FILE)
DirNew(dirc->dv,Fs->cur_dir,&f->de,TRUE);
else
DirNew(dirc->dv,Fs->cur_dir,&f->de,FALSE);
DirContextDel(dirc);
} else
throw('File');
}
Free(f->cluster_buf);
Free(f->de.full_name);
Free(f);
}
}
I64 FSetCluster(CFile *f,I64 c,I64 blk,Bool read)
{
CDrv *dv=f->dv;
I64 i;
if (f->cluster!=c) {
if (f->flags & FF_BUF_DIRTY) {
i=dv->spc;
if (f->max_blk!=MAX_I64) {
i=f->max_blk+1-f->file_cluster_num*dv->spc;
if (i>dv->spc)
i=dv->spc;
}
WClustersBlks(dv,f->cluster_buf,f->cluster,i);
f->flags=f->flags & ~FF_BUF_DIRTY;
}
f->cluster=c;
f->file_cluster_num=blk/dv->spc;
if (read) {
i=dv->spc;
if (f->max_blk!=MAX_I64) {
i=f->max_blk+1-f->file_cluster_num*dv->spc;
if (i>dv->spc)
i=dv->spc;
}
c=RClustersBlks(dv,f->cluster_buf,c,i);
}
}
return c;
}
Bool FRBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)
{//Read [nth,n+cnt) blks of file.
CDrv *dv=f->dv;
I64 spc=dv->spc,i,j,c=f->de.cluster;
if (!f || !dv) return FALSE;
if (blk==FFB_NEXT_BLK)
blk=f->fblk_num;
if (blk+cnt-1>f->max_blk)
return FALSE;
if (cnt<=0) return TRUE;
if (f->flags & FF_CONTIGUOUS) {
RBlks(dv,buf,Cluster2Blk(dv,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(dv,c,i);
if (i=blk%spc) {
c=FSetCluster(f,c,blk,TRUE);
if (cnt<spc-i)
j=cnt;
else
j=spc-i;
MemCpy(buf,f->cluster_buf+i<<BLK_SIZE_BITS,j<<BLK_SIZE_BITS);
buf+=j<<BLK_SIZE_BITS;
cnt-=j;
blk+=j;
}
while (cnt>=spc) {
c=FSetCluster(f,c,blk,TRUE);
MemCpy(buf,f->cluster_buf,spc<<BLK_SIZE_BITS);
buf+=spc<<BLK_SIZE_BITS;
cnt-=spc;
blk+=spc;
}
if (cnt>0) {
c=FSetCluster(f,c,blk,TRUE);
MemCpy(buf,f->cluster_buf,cnt<<BLK_SIZE_BITS);
buf+=cnt<<BLK_SIZE_BITS;
blk+=cnt;
}
}
f->fblk_num=blk;
return TRUE;
}
Bool FWBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)
{//Write [nth,n+cnt) blks of file.
CDrv *dv=f->dv;
I64 spc=dv->spc,i,j,c=f->de.cluster,c1;
if (!f || !dv) return FALSE;
if (blk==FFB_NEXT_BLK)
blk=f->fblk_num;
if (blk+cnt-1>f->max_blk)
return FALSE;
if (!(f->flags & FF_WRITE))
return FALSE;
if (cnt<=0) return TRUE;
if (f->flags & FF_CONTIGUOUS) {
WBlks(dv,buf,Cluster2Blk(dv,c)+blk,cnt);
blk+=cnt;
} else {
if (!c) {
c=ClustersAlloc(dv,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(dv,c1,1);
if (c==INVALID_CLUSTER) {
c=ClustersAlloc(dv,c1,i,FALSE);
if (i>1)
c=ClusterNumNext(dv,c,i-1);
break;
} else
i--;
}
if (i=blk%spc) {
FSetCluster(f,c,blk,TRUE);
if (cnt<spc-i)
j=cnt;
else
j=spc-i;
MemCpy(f->cluster_buf+BLK_SIZE*i,buf,j<<BLK_SIZE_BITS);
f->flags|=FF_BUF_DIRTY;
buf+=j<<BLK_SIZE_BITS;
cnt-=j;
blk+=j;
if (cnt>0) {
c1=c;
c=ClusterNumNext(dv,c1,1);
if (c==INVALID_CLUSTER)
c=ClustersAlloc(dv,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(dv,c1,1);
if (c==INVALID_CLUSTER)
c=ClustersAlloc(dv,c1,1,FALSE);
}
}
if (cnt>0) {
FSetCluster(f,c,blk,TRUE);
MemCpy(f->cluster_buf,buf,cnt<<BLK_SIZE_BITS);
f->flags|=FF_BUF_DIRTY;
buf+=cnt<<BLK_SIZE_BITS;
blk+=cnt;
}
if (f->de.size<blk<<BLK_SIZE_BITS)
f->de.size=blk<<BLK_SIZE_BITS;
}
f->fblk_num=blk;
return TRUE;
}
+145
View File
@@ -0,0 +1,145 @@
U0 DskCacheInit(I64 size_in_U8s)
{
CCacheBlk *tempc;
I64 i,cnt;
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
Free(blkdev.cache_ctrl);
Free(blkdev.cache_base);
Free(blkdev.cache_hash_table);
if (size_in_U8s<0x2000) {
blkdev.cache_ctrl=NULL;
blkdev.cache_base=NULL;
blkdev.cache_hash_table=NULL;
} else {
blkdev.cache_ctrl=ACAlloc(offset(CCacheBlk.body));
blkdev.cache_base=AMAlloc(size_in_U8s);
QueInit(blkdev.cache_ctrl);
cnt=MSize(blkdev.cache_base)/sizeof(CCacheBlk);
blkdev.cache_size=cnt*BLK_SIZE;
for (i=0;i<cnt;i++) {
tempc=blkdev.cache_base+i;
QueIns(tempc,blkdev.cache_ctrl->last_lru);
tempc->next_hash=tempc->last_hash=tempc;
tempc->dv=NULL;
tempc->blk=0;
}
blkdev.cache_hash_table=AMAlloc(DSK_CACHE_HASH_SIZE*sizeof(U8 *)*2);
for (i=0;i<DSK_CACHE_HASH_SIZE;i++) {
tempc=blkdev.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 blkdev.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,blkdev.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(CDrv *dv,I64 blk)
{
CCacheBlk *tempc,*tempc1=DskCacheHash(blk);
tempc=tempc1->next_hash;
while (tempc!=tempc1) {
if (tempc->dv==dv && tempc->blk==blk)
return tempc;
tempc=tempc->next_hash;
}
return NULL;
}
U0 DskCacheAdd(CDrv *dv,U8 *buf, I64 blk, I64 cnt)
{
CCacheBlk *tempc;
if (blkdev.cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
while (cnt-->0) {
if (!(tempc=DskCacheFind(dv,blk)))
tempc=blkdev.cache_ctrl->next_lru;
DskCacheQueRem(tempc);
MemCpy(&tempc->body,buf,BLK_SIZE);
tempc->dv=dv;
tempc->blk=blk;
DskCacheQueIns(tempc);
blk++;
buf+=BLK_SIZE;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
U0 DskCacheInvalidate2(CDrv *dv)
{
CCacheBlk *tempc,*tempc1;
if (blkdev.cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
tempc=blkdev.cache_ctrl->last_lru;
while (tempc!=blkdev.cache_ctrl) {
tempc1=tempc->last_lru;
if (tempc->dv==dv) {
DskCacheQueRem(tempc);
tempc->dv=NULL;
tempc->blk=0;
tempc->next_hash=tempc->last_hash=tempc;
QueIns(tempc,blkdev.cache_ctrl->last_lru);
}
tempc=tempc1;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
U0 RCache(CDrv *dv,U8 **_buf, I64 *_blk, I64 *_cnt)
{
CCacheBlk *tempc;
if (blkdev.cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
//fetch leading blks from cache
while (*_cnt>0) {
if (tempc=DskCacheFind(dv,*_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(dv,*_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);
}
}
+151
View File
@@ -0,0 +1,151 @@
I64 ClusterNumNext(CDrv *dv,I64 c,I64 cnt=1)
{//Return next cnt'th cluster in chain.
Bool unlock;
DrvChk(dv);
if (cnt<=0) return c;
try {
unlock=DrvLock(dv);
switch (dv->type) {
case DVT_ISO9660:
case DVT_REDSEA:
c+=cnt;
break;
case DVT_FAT32:
while (cnt-->0 && 0<c<0x0FFFFFF8) {
DrvFATBlkSet(dv,c);
c=dv->cur_fat_blk[c & (BLK_SIZE/4-1)];
}
if (!(0<c<0x0FFFFFF8))
c=INVALID_CLUSTER;
break;
default:
throw('Drv');
}
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
return c;
}
I64 Cluster2Blk(CDrv *dv,I64 c)
{//Drv cluster num to blk num.
DrvChk(dv);
switch (dv->type) {
case DVT_REDSEA:
return c;
case DVT_ISO9660:
case DVT_FAT32:
return dv->data_area+c*dv->spc;
default:
throw('Drv');
}
}
I64 RClustersBlks(CDrv *dv,U8 *buf,I64 c,I64 blks)
{//Accepts blk count, so padding on last cluster is not read.
I64 i;
Bool unlock;
DrvChk(dv);
if (blks<=0) return c;
try {
unlock=DrvLock(dv);
switch (dv->type) {
case DVT_ISO9660:
RBlks(dv,buf,dv->data_area+c*dv->spc,blks);
c+=(blks+dv->spc-1)/dv->spc;
break;
case DVT_REDSEA:
RBlks(dv,buf,c,blks);
c+=blks;
break;
case DVT_FAT32:
while (blks && 0<c<0x0FFFFFF8) {
i=blks;
if (i>dv->spc)
i=dv->spc;
RBlks(dv,buf,dv->data_area+c*dv->spc,i);
buf+=i<<BLK_SIZE_BITS;
c=ClusterNumNext(dv,c,1);
blks-=i;
}
if (blks)
throw('Drv');
break;
default:
throw('Drv');
}
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
return c;
}
I64 RClusters(CDrv *dv,U8 *buf,I64 c,I64 cnt)
{//Read cluster cnt from drv to buf.
return RClustersBlks(dv,buf,c,cnt*dv->spc);
}
I64 WClustersBlks(CDrv *dv,U8 *buf,I64 c,I64 blks)
{//Accepts blk count, so padding on last cluster is not written.
I64 i;
Bool unlock;
DrvChk(dv);
if (blks<=0) return c;
try {
unlock=DrvLock(dv);
switch (dv->type) {
case DVT_REDSEA:
WBlks(dv,buf,c,blks);
c=0;
break;
case DVT_FAT32:
while (blks) {
if (!(0<c<0x0FFFFFF8))
throw('Drv');
i=blks;
if (i>dv->spc)
i=dv->spc;
WBlks(dv,buf,dv->data_area+c*dv->spc,i);
buf+=i<<BLK_SIZE_BITS;
c=ClusterNumNext(dv,c);
blks-=i;
}
break;
default:
throw('Drv');
}
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
return c;
}
I64 WClusters(CDrv *dv,U8 *buf,I64 c,I64 cnt)
{//Write cluster cnt from buf to drv.
return WClustersBlks(dv,buf,c,cnt*dv->spc);
}
I64 ClustersAlloc(CDrv *dv,I64 c=0,I64 cnt=1,Bool contiguous=FALSE)
{//Alloc cluster cnt into chain.
//c=0 means first cluster in chain
DrvChk(dv);
if (cnt<=0) return c;
switch (dv->type) {
case DVT_REDSEA:
return RedSeaAllocClusters(dv,cnt);
case DVT_FAT32:
if (contiguous) {
if (c) throw('File');
return FAT32AllocContiguousClusters(dv,cnt);
} else
return FAT32AllocClusters(dv,c,cnt);
default:
throw('Drv');
}
}
+106
View File
@@ -0,0 +1,106 @@
Bool CopySingleZ(U8 *f1,U8 *f2) //Just one file
{
U8 *file_buf=NULL;
I64 size,attr=0,c;
CDirEntry de;
if (FileFind(f1,&de,FUF_JUST_FILES)) {
Free(de.full_name);
file_buf=FileRead(f1,&size,&attr);
attr=FileAttr(f2,attr);
if (file_buf) {
"Copying %s to %s\n",f1,f2;
c=FileWrite(f2,file_buf,size,de.datetime,attr);
Free(file_buf);
return ToBool(c);
} else
PrintErr("File not found.\n");
} else
PrintErr("File not found.\n");
return FALSE;
}
#define COPY_BUF_BLKS 0x80
Bool CopySingle(U8 *f1,U8 *f2) //Just one file
{
U8 *absf1=FileNameAbs(f1),*absf2=FileNameAbs(f2),*buf;
I64 cnt,n,size,attr1=FileAttr(f1),attr2=FileAttr(f2),i,j;
CFile *in_file=NULL,*out_file=NULL;
if (!StrCmp(absf1,absf2)) {//onto self?
Free(absf1);
Free(absf2);
return FALSE;
}
Free(absf1);
Free(absf2);
if (attr1!=attr2)
return CopySingleZ(f1,f2);
buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
if (attr1 & RS_ATTR_CONTIGUOUS)
in_file=FOpen(f1,"rc");
else
in_file=FOpen(f1,"r");
if (in_file) {
size=FSize(in_file);
cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS;
if (attr2 & RS_ATTR_CONTIGUOUS)
out_file=FOpen(f2,"wc",cnt);
else
out_file=FOpen(f2,"w",cnt);
if (out_file) {
"Copying %s to %s\n",f1,f2;
j=size;
while (cnt>0) {
if (cnt>COPY_BUF_BLKS) {
n=COPY_BUF_BLKS;
i=n<<BLK_SIZE_BITS;
} else {
n=cnt;
i=j;
}
FRBlks(in_file, buf,FFB_NEXT_BLK,n);
FWBlks(out_file,buf,FFB_NEXT_BLK,n);
cnt-=n;
j-=n<<BLK_SIZE_BITS;
}
out_file->flags|=FF_USE_OLD_DATETIME;
out_file->de.datetime=in_file->de.datetime;
out_file->de.size=size;
out_file->de.attr=FileAttr(f2,in_file->de.attr);
FClose(out_file);
FClose(in_file);
Free(buf);
return TRUE;
} else
PrintErr("File not found.\n");
FClose(in_file);
} else
PrintErr("File not found.\n");
Free(buf);
return FALSE;
}
I64 Del(U8 *files_find_mask,Bool make_mask=FALSE,
Bool del_dir=FALSE,Bool print_msg=TRUE)
{//Delete files.
I64 result=0;
CDirContext *dirc;
if (dirc=DirContextNew(files_find_mask,make_mask)) {
switch (dirc->dv->type) {
case DVT_REDSEA:
result=RedSeaFilesDel(dirc->dv,Fs->cur_dir,dirc->mask,
0,del_dir,print_msg);
break;
case DVT_FAT32:
result=FAT32FilesDel(dirc->dv,Fs->cur_dir,dirc->mask,
0,del_dir,print_msg);
break;
case DVT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
DirContextDel(dirc);
}
return result;
}
+212
View File
@@ -0,0 +1,212 @@
Bool DirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tempde,Bool free_old_chain=TRUE)
{//Makes a directory entry in the directory from a $LK,"CDirEntry",A="MN:CDirEntry"$ node.
switch (dv->type) {
case DVT_REDSEA:
return RedSeaDirNew(dv,cur_dir,tempde,free_old_chain);
case DVT_FAT32:
return FAT32DirNew(dv,cur_dir,tempde,free_old_chain);
case DVT_ISO9660:
PrintErr("Not Writable\n");
return FALSE;
default:
PrintErr("File System Not Supported\n");
return FALSE;
}
}
U0 DirEntryDel(CDirEntry *tempde)
{//Free node returned from $LK,"FilesFind",A="MN:FilesFind"$(). Doesn't Free user_data.
//Does not change the directory on disk.
if (tempde) {
Free(tempde->full_name);
Free(tempde);
}
}
U0 DirEntryDel2(CDirEntry *tempde)
{//Free node returned from $LK,"FilesFind",A="MN:FilesFind"$(). Frees user_data
//Does not change the directory on disk.
if (tempde) {
Free(tempde->full_name);
Free(tempde->user_data);
Free(tempde);
}
}
U0 DirTreeDel(CDirEntry *tempde)
{//Free tree returned from $LK,"FilesFind",A="MN:FilesFind"$(). Doesn't Free user_data.
//Does not change the directory on disk.
CDirEntry *tempde2;
while (tempde) {
tempde2=tempde->next;
if (tempde->sub)
DirTreeDel(tempde->sub);
DirEntryDel(tempde);
tempde=tempde2;
}
}
U0 DirTreeDel2(CDirEntry *tempde)
{//Free tree returned from $LK,"FilesFind",A="MN:FilesFind"$(). Frees user_data
//Does not change the directory on disk.
CDirEntry *tempde2;
while (tempde) {
tempde2=tempde->next;
if (tempde->sub)
DirTreeDel2(tempde->sub);
DirEntryDel2(tempde);
tempde=tempde2;
}
}
I64 DirEntryCompareName(CDirEntry *e1,CDirEntry *e2)
{
U8 buf1[CDIR_FILENAME_LEN],buf2[CDIR_FILENAME_LEN],
buf3[CDIR_FILENAME_LEN],buf4[CDIR_FILENAME_LEN];
I64 d1=0,d2=0;
if (e1->attr & RS_ATTR_DIR)
d1=1;
if (e2->attr & RS_ATTR_DIR)
d2=1;
if (d1!=d2)
return d2-d1;
else {
StrCpy(buf1,e1->name);
StrCpy(buf2,e2->name);
FileExtRem(buf1,buf3);
FileExtRem(buf2,buf4);
if (d1=StrCmp(buf3,buf4))
return d1;
return StrCmp(buf1,buf2);
}
}
I64 DirEntryCompareCluster(CDirEntry *e1,CDirEntry *e2)
{
return e1->cluster-e2->cluster;
}
#define SK_NAME 0
#define SK_CLUSTER 1
U0 DirFilesSort(CDirEntry **_tempde,I64 key)
{
I64 i,cnt=0;
CDirEntry *tempde=*_tempde,*tempde1,**sort_buf;
if (tempde) {
tempde1=tempde;
while (tempde1) {
cnt++;
tempde1=tempde1->next;
}
if (cnt>1) {
sort_buf=MAlloc(cnt*sizeof(U8 *));
i=0;
tempde1=tempde;
while (tempde1) {
sort_buf[i++]=tempde1;
tempde1=tempde1->next;
}
nobound_switch(key) {
case SK_NAME:
QSortI64(sort_buf,cnt,&DirEntryCompareName);
break;
case SK_CLUSTER:
QSortI64(sort_buf,cnt,&DirEntryCompareCluster);
break;
}
tempde=sort_buf[0];
*_tempde=tempde;
for (i=0;i<cnt-1;i++) {
tempde1=sort_buf[i];
tempde1->next=sort_buf[i+1];
}
tempde1=sort_buf[i];
tempde1->next=NULL;
Free(sort_buf);
tempde1=tempde;
while (tempde1) {
if (tempde1->sub)
DirFilesSort(&tempde1->sub,key);
tempde1=tempde1->next;
}
} else
if (tempde->sub)
DirFilesSort(&tempde->sub,key);
}
}
CDirEntry *DirFilesFlatten(CDirEntry *tempde,CDirEntry **_result,I64 fuf_flags)
{//Returns last node
CDirEntry *tempde1;
Bool del;
if (tempde)
while (TRUE) {
tempde1=tempde->next;
if (!(tempde->attr&RS_ATTR_DIR)||!(fuf_flags&FUF_JUST_FILES)) {
_result=*_result=tempde;
del=FALSE;
} else
del=TRUE;
if (tempde->sub) {
_result=DirFilesFlatten(tempde->sub,_result,fuf_flags);
tempde->sub=NULL;
}
if (del)
DirEntryDel(tempde);
if (tempde1)
tempde=tempde1;
else
break;
}
*_result=NULL;
return _result;
}
U0 PutFileLink(U8 *filename,I64 line=0,Bool plain_text=FALSE)
{//Put $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.TXT"$ file,line link to StdOut, $LK,"DocPut",A="MN:DocPut"$.
U8 *buf;
if (!filename) return;
if (IsRaw) {
if (line)
"%s,%04d",filename,line;
else
"%s",filename;
} else {
//LK_DOC,LK_DOC_ANCHOR,LK_DOC_FIND,LK_DOC_LINE
if (filename[0]=='A'&&filename[2]==':') {
if (line) //See $LK,"SpriteEdText",A="MN:SpriteEdText"$()
"$$LK,\"%s,%04d\",A=\"AL:%s,%d\"$$",filename+3,line,filename+3,line;
else
"$$LK,\"%s\",A=\"AI:%s\"$$",filename+3,filename+3;
} else {
buf=FileNameAbs(filename);
if (plain_text) {
if (line)
"$$LK,\"%s,%04d\",A=\"PL:%s,%d\"$$",filename,line,buf,line;
else
"$$LK,\"%s\",A=\"PI:%s\"$$",filename,buf;
} else {
if (line)
"$$LK,\"%s,%04d\",A=\"FL:%s,%d\"$$",filename,line,buf,line;
else
"$$LK,\"%s\",A=\"FI:%s\"$$",filename,buf;
}
Free(buf);
}
}
}
U0 PutDirLink(U8 *dirname)
{//Put $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.TXT"$ dir macro to StdOut, $LK,"DocPut",A="MN:DocPut"$.
U8 *buf;
if (!dirname) return;
if (IsRaw)
"%s",dirname;
else {
buf=DirNameAbs(dirname);
"$$MA,T=\"%s\",LM=\"Cd(\\\"%s\\\");Dir;\n\"$$",dirname,buf;
Free(buf);
}
}
+180
View File
@@ -0,0 +1,180 @@
Bool Cd(U8 *dirname=NULL,Bool make_dirs=FALSE)
{//Change directory. Optionally, make directories, too.
I64 maxlen,cur_dir_cluster=0;
U8 *chg_to_buf,*new_cur_dir,*buf;
CDrv *dv;
Bool result=TRUE;
if (!dirname)
dirname="::/Home";
else if (!*dirname)
return TRUE;
if (dirname[1]==':') {
if (*dirname==':') {
if (Fs->cur_dv!=Let2Drv(':') && !Drv(*dirname))
return FALSE;
} else if (Fs->cur_dv!=Let2Drv(*dirname) && !Drv(*dirname))
return FALSE;
dirname+=2;
}
if (*dirname=='/' || !*dirname || !Fs->cur_dir) {
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
if (*dirname=='/')
dirname++;
}
chg_to_buf=MStrUtil(dirname,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
maxlen=StrLen(Fs->cur_dir)+1+StrLen(chg_to_buf)+1;
new_cur_dir=MAlloc(maxlen);
buf=MAlloc(maxlen);
StrCpy(new_cur_dir,Fs->cur_dir);
while (*chg_to_buf && result) {
StrFirstRem(chg_to_buf,"/",buf);
if (!*buf)
StrCpy(new_cur_dir,"/");
else if (!StrCmp(buf,"..")) {
StrLastRem(new_cur_dir,"/");
if (!*new_cur_dir)
StrCpy(new_cur_dir,"/");
} else if (StrCmp(buf,".") && *buf) {
dv=Fs->cur_dv;
cur_dir_cluster=Name2DirCluster(dv,new_cur_dir);
switch (dv->type) {
case DVT_REDSEA:
result=RedSeaCd(buf,cur_dir_cluster);
break;
case DVT_FAT32:
result=FAT32Cd(buf,cur_dir_cluster);
break;
case DVT_ISO9660:
result=ISO1Cd(buf,cur_dir_cluster);
break;
default:
PrintErr("File System Not Supported\n");
result=FALSE;
}
if (!result && make_dirs) {
Free(Fs->cur_dir);
Fs->cur_dir=StrNew(new_cur_dir);
result=MkDir(buf);
}
if (result) {
if (StrCmp(new_cur_dir,"/"))
CatPrint(new_cur_dir,"/");
CatPrint(new_cur_dir,buf);
}
}
}
Free(Fs->cur_dir);
Fs->cur_dir=StrNew(new_cur_dir);
Free(buf);
Free(chg_to_buf);
Free(new_cur_dir);
return result;
}
Bool IsDir(U8 *dir_name)
{//Is a str a valid, existing Dir?
U8 *mask=MStrPrint("%s/*",dir_name);
Bool result,old_silent=Silent;
CDirContext *dirc;
if (dirc=DirContextNew(mask)) {
DirContextDel(dirc);
result=TRUE;
} else
result=FALSE;
Free(mask);
Silent(old_silent);
return result;
}
I64 Dir(U8 *files_find_mask,Bool full)
{//List directory.
CDirEntry *tempde1=NULL,*tempde2;
U8 *st;
CDateStruct ds;
I64 csize=0xFFFF,c=0xFFFF,result=0;
tempde1=FilesFind(files_find_mask);
if (!(st=CurDir))
PrintErr("Invalid Drive\n");
else {
if (tempde1) {
//Find max columns
tempde2=tempde1;
while (tempde2) {
if (tempde2->size>csize)
csize=tempde2->size;
if (tempde2->cluster>c)
c=tempde2->cluster;
tempde2=tempde2->next;
}
csize=Bsr(csize)/4+1;
c=Bsr(c)/4+1;
"$$MA,T=\"Directory\",LM=\"PopUpCd;Dir;\n\"$$ of %s\n",st;
if (full)
"__DATE__ __TIME__ %*ts %*ts\n",
csize,"SIZE",c,"CLUSTER";
else
"DATE_ TIME_ %*ts\n",csize,"SIZE";
while (tempde1) {
tempde2=tempde1->next;
result++;
if (full)
"%D %T %0*tX %0*tX ",tempde1->datetime,tempde1->datetime,
csize,tempde1->size,c,tempde1->cluster;
else {
Date2Struct(&ds,tempde1->datetime+local_time_offset);
"%02d/%02d %02d:%02d %0*tX ",ds.mon,ds.day_of_mon,ds.hour,ds.min,
csize,tempde1->size;
}
if (tempde1->attr & RS_ATTR_DIR)
PutDirLink(tempde1->name);
else
PutFileLink(tempde1->name);
'\n';
DirEntryDel(tempde1);
tempde1=tempde2;
}
} else
"No matching entries\n";
Free(st);
}
return result;
}
Bool MkDir(U8 *filename)
{//Make directory. $LK,"Cd",A="MN:Cd"$() can also make directories.
U8 *name;
CDirContext *dirc;
Bool result=FALSE;
if (FileFind(filename,,FUF_JUST_DIRS))
return FALSE;
if (dirc=DirContextNew(filename)) {
if (*dirc->mask) {
if (!FileNameChk(dirc->mask))
PrintErr("Invalid FileName.\n");
else {
"Make Directory:%s\n",filename;
name=MStrUtil(dirc->mask,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
switch (dirc->dv->type) {
case DVT_REDSEA:
result=RedSeaMkDir(dirc->dv,Fs->cur_dir,name);
break;
case DVT_FAT32:
result=FAT32MkDir(dirc->dv,Fs->cur_dir,name);
break;
case DVT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
Free(name);
}
}
DirContextDel(dirc);
}
return result;
}
+73
View File
@@ -0,0 +1,73 @@
U0 DirContextDel(CDirContext *dirc)
{//Change back to old cur_dir and drv.
CBlkDev *bd;
if (!dirc) return;
bd=dirc->old_dv->bd;
if (!(bd->flags & BDF_INIT_IN_PROGRESS)) {
if (dirc->old_dir) {
Drv(Drv2Let(dirc->old_dv));
Cd(dirc->old_dir);
}
} else {
Fs->cur_dv=dirc->old_dv;
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
}
Free(dirc->old_dir);
Free(dirc->mask);
Free(dirc);
}
CDirContext *DirContextNew(U8 *_mask,Bool make_mask=FALSE,
Bool make_dirs=FALSE,Bool no_mask=FALSE)
{//Save cur_dir and drv. Change to new dir.
Bool valid=TRUE,old_silent;
U8 *buf,*mask,*temp_mask;
CDirContext *dirc=CAlloc(sizeof(CDirContext));
mask=MStrUtil(_mask,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_mask=mask;
dirc->old_dir=StrNew(Fs->cur_dir);
dirc->old_dv=Fs->cur_dv;
if (*mask && mask[1]==':') {
if (Fs->cur_dv!=Let2Drv(*mask) && !Drv(*mask))
valid=FALSE;
mask+=2;
}
dirc->dv=Fs->cur_dv;
DrvChk(dirc->dv);
buf=MAlloc(StrLen(mask)+2);
StrCpy(buf,mask);
dirc->mask=MAlloc(StrLen(mask)+2);
if (no_mask)
*dirc->mask=0;
else
StrLastRem(buf,"/",dirc->mask);
if (*mask=='/' && !*buf)
StrCpy(buf,"/");
//If began with Dir, change to Dir.
if (*buf && !Cd(buf,make_dirs))
valid=FALSE;
if (valid && make_mask) {
if (!*dirc->mask) {
Free(dirc->mask);
dirc->mask=StrNew("*");
} else {
if (!make_dirs || FileNameChk(dirc->mask)) {
old_silent=Silent;
//Try mask to see if Dir. If Dir, change to dir and set to "*".
if (Cd(dirc->mask,make_dirs)) {
Free(dirc->mask);
dirc->mask=StrNew("*");
}
Silent(old_silent);
}
}
}
Free(buf);
Free(temp_mask);
if (!valid) {
DirContextDel(dirc);
dirc=NULL;
}
return dirc;
}
+287
View File
@@ -0,0 +1,287 @@
Bool DrvLock(CDrv *dv)
{//Make this task have exclusive access to drv & BlkDev.
DrvChk(dv);
BlkDevLock(dv->bd);
if (!Bt(&dv->locked_flags,DVlf_LOCKED) || dv->owning_task!=Fs) {
while (LBts(&dv->locked_flags,DVlf_LOCKED))
Yield;
dv->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool DrvUnlock(CDrv *dv,Bool rst=FALSE)
{//Release exclusive lock on access to drv & BlkDev.
DrvChk(dv);
if (Bt(&dv->locked_flags,DVlf_LOCKED) && dv->owning_task==Fs) {
BlkDevUnlock(dv->bd,rst);
dv->owning_task=NULL;
LBtr(&dv->locked_flags,DVlf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
U0 DrvsRelease()
{//When task dies, release all owned drvs.
I64 i;
CDrv *dv;
for (i=0;i<NUM_DRVS;i++) {
dv=&blkdev.drvs[i];
if (dv->owning_task==Fs && dv->dv_signature==DRV_SIGNATURE_VAL)
DrvUnlock(dv,TRUE);
}
}
CDrv *DrvMakeFree(U8 drv_let)
{//Make a slot free for a new drv, like during $LK,"Mount",A="MN:Mount"$().
//!!! drv_let is not a $LK,"remapped",A="MN:MapDrv"$ drv.
I64 i=ToUpper(drv_let)-'A';
CDrv *result;
if (!(0<=i<NUM_DRVS))
throw('Drv');
result=&blkdev.drvs[i];
MemSet(result,0,sizeof(CDrv));
result->drv_let='A'+i;
return result;
}
CDrv *DrvNextFree(U8 first_drv_let='C')
{//Locate free slot for new drv, like during $LK,"Mount",A="MN:Mount"$().
//!!! first_drv_let is not a $LK,"remapped",A="MN:MapDrv"$ drv.
I64 i=ToUpper(first_drv_let)-'A';
if (!(0<=i<NUM_DRVS))
throw('Drv');
do
if (blkdev.drvs[i].dv_signature!=DRV_SIGNATURE_VAL)
return DrvMakeFree(i+'A');
while (++i<NUM_DRVS);
throw('Drv');
return NULL; //never gets here
}
U0 DrvFATBlkAlloc(CDrv *dv)
{
DrvChk(dv);
Free(dv->cur_fat_blk);
dv->cur_fat_blk=AMAlloc(BLK_SIZE);
dv->cur_fat_blk_num=0;
dv->fat_blk_dirty=0;
RBlks(dv,dv->cur_fat_blk,dv->fat1,1);
}
U0 DrvFATBlkClean(CDrv *dv,I64 fat_select=3)
{
if ((dv->type==DVT_FAT32 || dv->type==DVT_REDSEA)&&Bt(&dv->fat_blk_dirty,0)) {
if (dv->fat1==dv->fat2) {
WBlks(dv,dv->cur_fat_blk,dv->fat1+dv->cur_fat_blk_num,1);
LBtr(&dv->fat_blk_dirty,0);
} else {
if (fat_select==3 || !fat_select)
WBlks(dv,dv->cur_fat_blk,dv->fat1+dv->cur_fat_blk_num,1);
if (fat_select==3 || fat_select==1) {
WBlks(dv,dv->cur_fat_blk,dv->fat2+dv->cur_fat_blk_num,1);
LBtr(&dv->fat_blk_dirty,0);
}
}
}
}
U0 DrvFATBlkSet(CDrv *dv,I64 c,I64 fat_select=3)
{
I64 fat_blk_num;
if (c==INVALID_CLUSTER)
throw('Drv');
switch (dv->type) {
case DVT_FAT32:
fat_blk_num=c>>(BLK_SIZE_BITS-2);
break;
case DVT_REDSEA:
fat_blk_num=(c-dv->data_area)>>(BLK_SIZE_BITS+3);
break;
default:
throw('Drv');
}
if (fat_blk_num!=dv->cur_fat_blk_num) {
DrvFATBlkClean(dv,fat_select);
dv->cur_fat_blk_num=fat_blk_num;
if (fat_select==3 || !fat_select)
RBlks(dv,dv->cur_fat_blk,dv->fat1+dv->cur_fat_blk_num,1);
else
RBlks(dv,dv->cur_fat_blk,dv->fat2+dv->cur_fat_blk_num,1);
}
}
U0 DrvChk(CDrv *dv)
{//Check for valid drv. Throw exception.
if (!dv || dv->dv_signature!=DRV_SIGNATURE_VAL)
throw('Drv');
}
U8 Drv2Let(CDrv *dv=NULL)
{//Drv ptr to Drv letter.
if (!dv)
dv=Fs->cur_dv;
DrvChk(dv);
return dv->drv_let;
}
CDrv *Let2Drv(U8 drv_let=0)
{//Drv letter to Drv ptr.
CDrv *dv;
if (!drv_let)
dv=Fs->cur_dv;
else {
if (drv_let==':')
drv_let=blkdev.boot_drv_let;
drv_let=ToUpper(drv_let);
if (!('A'<=drv_let<='Z'))
throw('Drv');
dv=blkdev.let_to_drv[drv_let-'A'];
}
DrvChk(dv);
return dv;
}
Bool DrvIsWritable(U8 drv_let=0)
{//Is drive writable?
CBlkDev *bd=Let2BlkDev(drv_let);
if (bd->flags & BDF_READ_ONLY)
return FALSE;
else
return TRUE;
}
U0 DskCacheInvalidate(CDrv *dv)
{//Needed for removable media. Called by $LK,"ChgDsk",A="MN:ChgDsk"$().
Bool unlock;
CBlkDev *bd=dv->bd;
DrvChk(dv);
try {
unlock=DrvLock(dv);
BlkDevInit(bd);
if (bd->flags & BDF_READ_CACHE)
DskCacheInvalidate2(dv);
if (dv->type==DVT_ISO9660 && !(bd->flags & BDF_READ_ONLY_OVERRIDE))
ISODrvInit(dv,(32767/bd->blk_size+1)*bd->blk_size>>BLK_SIZE_BITS);
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
}
U0 ChgDsk(U8 drv_let=0)
{//Change disk. (Needed for removable media.)
CDrv *dv=Let2Drv(drv_let);
CBlkDev *bd=dv->bd;
if (!(bd->flags&BDF_INITIALIZED))
BlkDevInit(bd);
else if (bd->flags&BDF_REMOVABLE)
DskCacheInvalidate(dv);
Drv(drv_let);
RedSeaFreeFreeLst(dv);
}
Bool MapDrv(U8 drv_let,CDrv *dv)
{//Make drive letter map to another.
drv_let=ToUpper(drv_let);
if ('A'<=drv_let<='Z') {
blkdev.let_to_drv[drv_let-'A']=dv;
dv->drv_let=drv_let;
return TRUE;
} else
return FALSE;
}
Bool Drv(U8 drv_let)
{//Set drive. You can set drive with $LK,"Cd",A="MN:Cd"$() as well.
CDrv *dv=Let2Drv(drv_let);
CBlkDev *bd=dv->bd;
BlkDevChk(bd);
if (dv!=Fs->cur_dv) {
if (bd->flags & BDF_REMOVABLE && !(bd->flags & BDF_INITIALIZED))
ChgDsk(Drv2Let(dv));
if (bd->type==BDT_RAM)
BlkDevInit(bd);
}
Fs->cur_dv=dv;
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
switch (dv->type) {
case DVT_REDSEA:
case DVT_FAT32:
case DVT_ISO9660:
return TRUE;
default:
PrintErr("File System Not Supported\n");
return FALSE;
}
}
U8 *DrvSerialNum(U8 drv_let=0)
{//20 bytes max.
CBlkDev *bd=Let2BlkDev(drv_let);
U16 *st,*result=NULL;
I64 i;
if (bd->dev_id_record) {
st=CAlloc(20+1);
for (i=0;i<10;i++)
st[i]=EndianU16(bd->dev_id_record[10+i]);
result=MStrUtil(st,SUF_REM_LEADING|SUF_REM_TRAILING);
Free(st);
}
return result;
}
U8 *DrvModelNum(U8 drv_let=0)
{//40 bytes max.
CBlkDev *bd=Let2BlkDev(drv_let);
U16 *st,*result=NULL;
I64 i;
if (bd->dev_id_record) {
st=CAlloc(40+1);
for (i=0;i<20;i++)
st[i]=EndianU16(bd->dev_id_record[27+i]);
result=MStrUtil(st,SUF_REM_LEADING|SUF_REM_TRAILING);
Free(st);
}
return result;
}
U0 DrvRep()
{//Drive report.
CDrv *dv;
CBlkDev *bd;
I64 i,drv_let;
U8 *st;
"\nDefined Drives:\n\n";
for (i=0,dv=blkdev.drvs;i<NUM_DRVS;i++,dv++) {
if (dv->dv_signature==DRV_SIGNATURE_VAL) {
bd=dv->bd;
drv_let=Drv2Let(dv);
if (Bt(&dv->type,DVTf_DISABLE))
"$$RED$$X";
else if (drv_let==blkdev.boot_drv_let)
"$$GREEN$$:";
else
'' CH_SPACE;
"$$PURPLE$$%C %-8Z %-9Z %04X %04X %02X$$FG$$\n",
drv_let,dv->type.u16[0],"ST_DRV_TYPES",
bd->type,"ST_BLKDEV_TYPES",bd->base0,bd->base1,bd->unit;
if (st=DrvModelNum(drv_let)) {
" $$CYAN$$Model# :%s$$FG$$\n",st;
Free(st);
}
if (st=DrvSerialNum(drv_let)) {
" $$CYAN$$Serial#:%s$$FG$$\n",st;
Free(st);
}
" %016X-%016X\n",
dv->base_offset,dv->base_offset+dv->size-1;
dv->base_offset,dv->base_offset+dv->size-1;
}
}
}
+138
View File
@@ -0,0 +1,138 @@
U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL)
{//Read whole file from disk.
CHashGeneric *temph;
U8 *absname,*altname,*curname,*result=NULL;
I64 i,size=0,attr=0;
CDirContext *dirc;
CArcCompress *arc;
absname=FileNameAbs(filename);
altname=ToggleZorNotZ(absname);
if ((temph=HashFind(absname,adam_task->hash_table,HTT_FILE))||
(temph=HashFind(altname,adam_task->hash_table,HTT_FILE))) {
size=temph->user_data1;
result=MAlloc(size+1);
MemCpy(result,temph->user_data0,size);
result[size]=0; //Terminate
attr=FileAttr(temph->str,attr);
} else {
for (i=0;i<2 && !result;i++) {//Try name, then altname
if (!i)
curname=absname;
else
curname=altname;
if (dirc=DirContextNew(curname)) {
switch (dirc->dv->type) {
case DVT_REDSEA:
result=RedSeaFileRead(dirc->dv,Fs->cur_dir,dirc->mask,
&size,&attr);
break;
case DVT_FAT32:
result=FAT32FileRead(dirc->dv,Fs->cur_dir,dirc->mask,
&size,&attr);
break;
case DVT_ISO9660:
result=ISO1FileRead(dirc->dv,Fs->cur_dir,dirc->mask,
&size,&attr);
break;
default:
PrintErr("File System Not Supported\n");
}
DirContextDel(dirc);
}
}
//Search parent directories.
for (i=0;i<2 && !result;i++) {//Try name, then altname
if (!i)
curname=absname;
else
curname=altname;
if (dirc=DirContextNew(curname)) {
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
switch (Fs->cur_dv->type) {
case DVT_REDSEA:
result=RedSeaFileRead(dirc->dv,Fs->cur_dir,dirc->mask,
&size,&attr);
break;
case DVT_FAT32:
result=FAT32FileRead(dirc->dv,Fs->cur_dir,dirc->mask,
&size,&attr);
break;
case DVT_ISO9660:
result=ISO1FileRead(dirc->dv,Fs->cur_dir,dirc->mask,
&size,&attr);
break;
default:
PrintErr("File System Not Supported\n");
}
}
DirContextDel(dirc);
}
}
if (!result) {
"%s ",filename;
PrintErr("File not found.\n");
}
if (result && attr & RS_ATTR_RESIDENT)
HashGenericAdd(curname,HTT_FILE,
AMAllocIdentical(result),size,0,adam_task);
}
if (result && attr & RS_ATTR_COMPRESSED) {
arc=result;
size=arc->expanded_size;
result=ExpandBuf(arc);
Free(arc);
}
if (_attr) *_attr=attr;
if (_size) *_size=size;
Free(absname);
Free(altname);
return result;
}
I64 FileWrite(U8 *filename,U8 *fbuf,I64 size,CDate cdt=0,I64 attr=0)
{//Write whole file to disk.
I64 c=0;
CHashGeneric *temph;
CDirContext *dirc;
U8 *fbuf2,*absname=FileNameAbs(filename);
if (dirc=DirContextNew(filename,FALSE,TRUE)) {
attr=FileAttr(dirc->mask,attr);
if (attr&RS_ATTR_COMPRESSED) {
fbuf=CompressBuf(fbuf,size);
size=fbuf(CArcCompress *)->compressed_size;
fbuf2=fbuf;
} else
fbuf2=NULL;
if (!cdt) cdt=Now;
switch (dirc->dv->type) {
case DVT_REDSEA:
c=RedSeaFileWrite(dirc->dv,Fs->cur_dir,dirc->mask,fbuf,
size,cdt,attr);
break;
case DVT_FAT32:
c=FAT32FileWrite(dirc->dv,Fs->cur_dir,dirc->mask,fbuf,
size,cdt,attr);
break;
case DVT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
if (temph=HashFind(absname,adam_task->hash_table,HTT_FILE)) {
if (attr & RS_ATTR_RESIDENT) {
Free(temph->user_data0);
temph->user_data0=AMAllocIdentical(fbuf);
temph->user_data1=size;
} else
HashRemDel(temph,adam_task->hash_table);
} else if (attr & RS_ATTR_RESIDENT)
HashGenericAdd(absname,HTT_FILE,AMAllocIdentical(fbuf),size,0,adam_task);
Free(fbuf2);
DirContextDel(dirc);
}
Free(absname);
return c;
}
+161
View File
@@ -0,0 +1,161 @@
CDirEntry *FilesFind2(U8 *files_find_mask,I64 fuf_flags)
{
CDrv *dv=Fs->cur_dv;
CDirEntry *result=NULL;
DrvChk(dv);
switch (dv->type) {
case DVT_REDSEA:
result=RedSeaFilesFind(files_find_mask,fuf_flags);
break;
case DVT_FAT32:
result=FAT32FilesFind(files_find_mask,fuf_flags);
break;
case DVT_ISO9660:
result=ISO1FilesFind(files_find_mask,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
result=NULL;
}
if (result) {
DirFilesSort(&result,SK_NAME);
if (fuf_flags&(FUF_FLATTEN_TREE|FUF_JUST_FILES))
DirFilesFlatten(result,&result,fuf_flags);
if (fuf_flags&FUF_CLUSTER_ORDER)
DirFilesSort(&result,SK_CLUSTER);
}
return result;
}
CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0)
{/* See $LK,"::/Doc/FileUtils.TXT"$.
Find files and make a directory tree in memory.
When done, you free with $LK,"DirEntryDel",A="MN:DirEntryDel"$(),$LK,"DirEntryDel2",A="MN:DirEntryDel2"$(),
$LK,"DirTreeDel",A="MN:DirTreeDel"$() or $LK,"DirTreeDel2",A="MN:DirTreeDel2"$().
*/
CDirEntry *result;
CDirContext *dirc;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
if (fuf_flags&FUF_SINGLE) {
result=MAlloc(sizeof(CDirEntry));
if (!FileFind(files_find_mask,result)) {
Free(result);
return NULL;
}
} else if (dirc=DirContextNew(files_find_mask,TRUE)) {
result=FilesFind2(dirc->mask,fuf_flags);
DirContextDel(dirc);
} else
return NULL;
return result;
}
Bool FileFind(U8 *filename,CDirEntry *_de=NULL,I64 fuf_flags=0)
{//$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$, $LK,"FUF_Z_OR_NOT_Z",A="MN:FUF_Z_OR_NOT_Z"$, $LK,"FUF_SCAN_PARENTS",A="MN:FUF_SCAN_PARENTS"$
//If you pass _de, you must Free(_de->full_name);
I64 i,j,cur_dir_cluster;
U8 *altname,*curname,*full_name=NULL;
CDirEntry de;
CDirContext *dirc;
Bool result=FALSE,old_silent;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
if (!filename) return FALSE;
altname=ToggleZorNotZ(filename);
if (fuf_flags&FUF_Z_OR_NOT_Z)
j=2;
else
j=1;
for (i=0;i<j && !result;i++) {
if (!i)
curname=filename;
else
curname=altname;
old_silent=Silent;
if (!(dirc=DirContextNew(curname)))
Silent(old_silent);
else {
Silent(old_silent);
cur_dir_cluster=Name2DirCluster(dirc->dv,Fs->cur_dir);
switch (dirc->dv->type) {
case DVT_REDSEA:
result=RedSeaFileFind(dirc->dv,cur_dir_cluster,dirc->mask,
&de,fuf_flags);
break;
case DVT_FAT32:
result=FAT32FileFind(dirc->dv,cur_dir_cluster,dirc->mask,
&de,fuf_flags);
break;
case DVT_ISO9660:
result=ISO1FileFind(dirc->dv,cur_dir_cluster,dirc->mask,
&de,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
}
if (result && _de) {
if (StrCmp(Fs->cur_dir,"/"))
full_name=MStrPrint("%C:%s/%s",
Drv2Let(Fs->cur_dv),Fs->cur_dir,de.name);
else
full_name=MStrPrint("%C:/%s",Drv2Let(Fs->cur_dv),de.name);
}
DirContextDel(dirc);
}
}
for (i=0;i<j && !result && fuf_flags&FUF_SCAN_PARENTS;i++) {
if (!i)
curname=filename;
else
curname=altname;
old_silent=Silent;
if (!(dirc=DirContextNew(curname)))
Silent(old_silent);
else {
Silent(old_silent);
cur_dir_cluster=Name2DirCluster(dirc->dv,Fs->cur_dir);
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
cur_dir_cluster=Name2DirCluster(dirc->dv,Fs->cur_dir);
switch (dirc->dv->type) {
case DVT_REDSEA:
result=RedSeaFileFind(dirc->dv,cur_dir_cluster,
dirc->mask,&de,fuf_flags);
break;
case DVT_FAT32:
result=FAT32FileFind(dirc->dv,cur_dir_cluster,
dirc->mask,&de,fuf_flags);
break;
case DVT_ISO9660:
result=ISO1FileFind(dirc->dv,cur_dir_cluster,
dirc->mask,&de,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
}
}
if (result && _de) {
if (StrCmp(Fs->cur_dir,"/"))
full_name=MStrPrint("%C:%s/%s",
Drv2Let(Fs->cur_dv),Fs->cur_dir,de.name);
else
full_name=MStrPrint("%C:/%s",
Drv2Let(Fs->cur_dv),de.name);
}
DirContextDel(dirc);
}
}
if (_de) {
if (result) {
MemCpy(_de,&de,sizeof(CDirEntry));
_de->full_name=full_name;
} else
MemSet(_de,0,sizeof(CDirEntry));
}
Free(altname);
return result;
}
+90
View File
@@ -0,0 +1,90 @@
Bool DrvTypeSet(U8 drv_let,I64 type=DVT_REDSEA)
{//Very dangerous
I64 i,j,ext_base,drv_num,offset,cur_type;
CMasterBoot mbr;
CBlkDev *bd=Let2BlkDev(drv_let);
drv_num=bd->first_drv_let-'A';
switch (bd->type) {
case BDT_ATA:
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bd,&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 (drv_num+'A'==ToUpper(drv_let)) {
switch (type) {
case DVT_REDSEA:
mbr.p[i].type=MBR_PT_REDSEA;
break;
case DVT_FAT32:
mbr.p[i].type=MBR_PT_FAT32a;
break;
default:
throw('Drv');
}
mbr.p[i].active=0x80;
ATAWriteBlks(bd,&mbr,offset,1);
return TRUE;
}
drv_num++;
}
}
}
if (j<0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
break;
}
}
U0 Fmt(I64 drv_let,Bool quick=TRUE,Bool confirm=TRUE,I64 type=DVT_FAT32)
{//Format hard drive or RAM drive.
//$BK,1$Warning:$BK,0$ Destroys all previous info.
//quick=FALSE means fill entire drive with zeros.
//Choose $LK,"DVT_FAT32",A="MN:DVT_FAT32"$ or $LK,"DVT_REDSEA",A="MN:DVT_REDSEA"$.
//You don't format a CD/DVD with this.
CDrv *dv=Let2Drv(drv_let);
Bool old_silent=IsSilent;
if (confirm && !AreYouSure)
return;
if (!dv) {
PrintErr("Invalid Drive\n");
return;
}
switch (type) {
case DVT_REDSEA:
Silent;
Drv(drv_let);
Silent(old_silent);
RedSeaFmt(drv_let,quick);
DskCacheInvalidate(Let2Drv(drv_let));
Drv(drv_let);
break;
case DVT_FAT32:
Silent;
Drv(drv_let);
Silent(old_silent);
FAT32Fmt(drv_let,quick);
DskCacheInvalidate(Let2Drv(drv_let));
Drv(drv_let);
break;
case DVT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
}
+316
View File
@@ -0,0 +1,316 @@
U8 *FileExtDot(U8 *src)
{//Find dot char in name.
I64 ch;
while (ch=*src++)
if (ch=='.' && *src!='/' && *src!='.')
return src-1;
return NULL;
}
U8 *FileExtRem(U8 *src,U8 *dst=NULL)
{//Remove filename extension from str.
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)
{//Does name end in .Z?
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)
{//Does name end in .C?
I64 i=StrLen(filename);
if (i>6 && filename[i-1]=='C' && filename[i-2]=='.' && filename[i-6]=='.')
return TRUE;
else
return FALSE;
}
Bool FilesFindMatch(U8 *test_filename,U8 *files_find_mask,I64 fuf_flags=0)
{//Does filename meet $LK,"Files Find",A="FI:::/Doc/FileUtils.TXT"$ mask?
U8 *st1=StrNew(files_find_mask),
*st2=MAlloc(StrLen(files_find_mask)+1);
Bool result=FALSE;
while (TRUE) {
StrFirstRem(st1,";",st2);
if (*st2) {
if (*st2=='~') {
if (WildMatch(test_filename,st2+1)) {
result=FALSE;
break;
}
} else {
if (WildMatch(test_filename,st2)) {
if (Bt(&fuf_flags,FUf_JUST_TXT) &&
!FilesFindMatch(test_filename,FILEMASK_TXT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_SRC) &&
!FilesFindMatch(test_filename,FILEMASK_SRC)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_AOT) &&
!FilesFindMatch(test_filename,FILEMASK_AOT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_JIT) &&
!FilesFindMatch(test_filename,FILEMASK_JIT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_GRA) &&
!FilesFindMatch(test_filename,FILEMASK_GRA)) {
result=FALSE;
break;
} else
result=TRUE;
}
}
} else
break;
}
Free(st1);
Free(st2);
return result;
}
U8 *DirNameAbs(U8 *_dirname)
{//MAlloc absolute dir string with drv letter.
I64 maxlen;
U8 drv[3],*result,*buf,*buf2,*buf3,*buf4,*dirname,*free_dirname;
if (!Fs->cur_dir || !*Fs->cur_dir)
return StrNew(_dirname);
free_dirname=dirname=MStrUtil(_dirname,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
*drv=Drv2Let;
drv[1]=':';
drv[2]=0;
if (*dirname && dirname[1]==':') {
if (*dirname==':')
*drv=blkdev.boot_drv_let;
else
*drv=*dirname;
dirname=dirname+2;
buf=StrNew("/");
} else
buf=StrNew(Fs->cur_dir);
if (*dirname=='/') {
Free(buf);
buf=StrNew("/");
dirname++;
}
buf2=StrNew(dirname);
maxlen=StrLen(buf)+1+StrLen(buf2)+1;
buf3=MAlloc(maxlen);
buf4=MAlloc(maxlen);
StrCpy(buf3,buf);
while (*buf2) {
StrFirstRem(buf2,"/",buf4);
if (!*buf4)
StrCpy(buf3,"/");
else if (!StrCmp(buf4,"..")) {
StrLastRem(buf3,"/");
if (!*buf3)
StrCpy(buf3,"/");
} else if (!StrCmp(buf4,".")) {
;
} else if (*buf4) {
if (StrCmp(buf3,"/"))
CatPrint(buf3,"/");
CatPrint(buf3,buf4);
}
}
Free(buf);
result=MAlloc(StrLen(buf3)+3);
StrCpy(result,drv);
StrCpy(result+2,buf3);
Free(buf2);
Free(buf3);
Free(buf4);
Free(free_dirname);
return result;
}
U8 *FileNameAbs(U8 *_filename,I64 fuf_flags=0)
{//Absolute filename. Accepts $LK,"FUF_Z_OR_NOT_Z",A="MN:FUF_Z_OR_NOT_Z"$, $LK,"FUF_SCAN_PARENTS",A="MN:FUF_SCAN_PARENTS"$.
U8 *result,*filename,*buf,*buf_file,*buf_dir,*free_filename,*free_buf;
CDirEntry de;
free_filename=filename=MStrUtil(_filename,
SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
free_buf=buf=StrNew(filename);
if (*buf && buf[1]==':') {
buf+=2;
filename+=2;
}
buf_file=MAlloc(StrLen(free_filename)+1);
StrLastRem(buf,"/",buf_file);
if (*filename=='/' && !*buf)
StrCpy(buf,"/");
buf_dir=DirNameAbs(free_buf);
Free(free_buf);
result=MAlloc(StrLen(buf_dir)+1+StrLen(buf_file)+1);
StrCpy(result,buf_dir);
if (result[StrLen(result)-1]!='/')
CatPrint(result,"/");
CatPrint(result,buf_file);
Free(buf_file);
Free(buf_dir);
Free(free_filename);
if (fuf_flags && FileFind(result,&de,fuf_flags|FUF_JUST_FILES)) {
Free(result);
result=de.full_name;
}
return result;
}
U8 *ChgExt(U8 *filename,U8 *extension)
{//Change filename extension.
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
StrCpy(result,filename);
if (FileExtDot(filename))
FileExtRem(result);
return CatPrint(result,".%s",extension);
}
U8 *DftExt(U8 *filename,U8 *extension)
{//Give extension if has none.
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
StrCpy(result,filename);
if (!FileExtDot(filename))
CatPrint(result,".%s",extension);
return result;
}
CDirEntry *Cd2DirEntry(CDirEntry *tempde,U8 *abs_name)
{
I64 i;
while (tempde) {
i=StrLen(tempde->full_name);
if (StrNCmp(tempde->full_name,abs_name,i)||
i && tempde->full_name[i-1]!='/' && abs_name[i] && abs_name[i]!='/')
tempde=tempde->next;
else
if (StrLen(abs_name)==i)
return tempde;
else
return Cd2DirEntry(tempde->sub,abs_name);
}
return NULL;
}
I64 FileAttr(U8 *name,I64 attr=0)
{
if (IsDotZ(name))
attr|=RS_ATTR_COMPRESSED;
else
attr&=~RS_ATTR_COMPRESSED;
if (IsDotC(name))
attr|=RS_ATTR_CONTIGUOUS;
return attr;
}
Bool FileNameChk(U8 *filename)
{//Return check for valid filename, not checking existence.
U8 *ptr=filename;
if (!filename) return FALSE;
if (!*ptr) return FALSE;
if (*ptr=='.') {
if (!ptr[1]) return TRUE;
if (ptr[1]=='.' && !ptr[2]) return TRUE;
}
if (StrLen(filename)>=CDIR_FILENAME_LEN) return FALSE;
while (*ptr)
if (!Bt(chars_bmp_filename,*ptr++))
return FALSE;
return TRUE;
}
U8 *ToggleZorNotZ(U8 *name)
{//MAlloc name with Z if not Z or vice versa.
U8 *result;
if (IsDotZ(name)) {
result=StrNew(name);
result[StrLen(name)-2]=0;
} else
result=MStrPrint("%s.Z",name);
return result;
}
U8 *FileNameTempTxt()
{//Make pretty-safe temp filename in home dir.
return MStrPrint("::/Home/SysTemp%X.TXT.Z",GetTSC>>8&0xFFFFFFFF);
}
U8 *CurDir(CTask *task=NULL,CTask *mem_task=NULL)
{//MAlloc copy of cur dir with drv letter.
U8 *st;
if (!task) task=Fs;
if (!task->cur_dir)
return NULL;
st=MAlloc(StrLen(task->cur_dir)+3,mem_task);
*st=Drv2Let(task->cur_dv);
st[1]=':';
StrCpy(st+2,task->cur_dir);
return st;
}
U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL)
{/*Strips file from dirname, scans for file upward until found or
returns default.
("/Kernel/KHashA.CPP.Z",NULL,NULL) returns "D:/Kernel"
("/Kernel",NULL,"PRJ.Z") returns "D:/Kernel/Kernel.PRJ.Z"
("/Kernel/BlkDev",NULL,"PRJ.Z") returns "D:/Kernel/Kernel.PRJ.Z"
("/Apps/Psalmody","Load","CPP.Z") returns "D:/Apps/Psalmody/Load.CPP.Z"
*/
U8 *st=DirNameAbs(dirname),*st2,*st3,*result,*dft=NULL,*ext;
if (_extension && *_extension) {
if (*_extension=='.')
ext=StrNew(_extension);
else
ext=MStrPrint(".%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=MStrPrint("%s/%s%s",st,name,ext);
else {
if (*ext)
result=MStrPrint("%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;
}
+97
View File
@@ -0,0 +1,97 @@
Bool CFileNameTo(U8 *dst,U8 *src)
{
MemSet(dst,0,CDIR_FILENAME_LEN);
if (!FileNameChk(src))
return FALSE;
StrCpy(dst,src);
return TRUE;
}
I64 Name2DirCluster(CDrv *dv,U8 *dirname)
{
Bool cont=TRUE,unlock;
I64 cur_dir_cluster;
CDirEntry de;
U8 *buf=StrNew(dirname),*buf2=StrNew(dirname);
DrvChk(dv);
try {
unlock=DrvLock(dv);
cur_dir_cluster=dv->root_cluster;
while (*buf && cont) {
StrFirstRem(buf,"/",buf2);
if (*buf2) {
switch (dv->type) {
case DVT_REDSEA:
cont=RedSeaFileFind(dv,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case DVT_FAT32:
cont=FAT32FileFind(dv,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case DVT_ISO9660:
cont=ISO1FileFind(dv,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
default:
throw('Drv');
}
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
"%s ",dirname;
PrintErr("File not found.\n");
cur_dir_cluster=0;
}
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
Free(buf);
Free(buf2);
return cur_dir_cluster;
}
I64 Name2ParentDirCluster(CDrv *dv,U8 *dirname)
{
Bool cont=TRUE,unlock;
I64 cur_dir_cluster,cur_dir_cluster2;
CDirEntry de;
U8 *buf=StrNew(dirname),*buf2=StrNew(dirname);
DrvChk(dv);
try {
unlock=DrvLock(dv);
cur_dir_cluster=cur_dir_cluster2=dv->root_cluster;
while (*buf && cont) {
cur_dir_cluster2=cur_dir_cluster;
StrFirstRem(buf,"/",buf2);
if (*buf2) {
switch (dv->type) {
case DVT_REDSEA:
cont=RedSeaFileFind(dv,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case DVT_FAT32:
cont=FAT32FileFind(dv,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case DVT_ISO9660:
cont=ISO1FileFind(dv,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
default:
throw('Drv');
}
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
"%s ",dirname;
PrintErr("File not found.\n");
cur_dir_cluster2=0;
}
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
Free(buf);
Free(buf2);
return cur_dir_cluster2;
}
+974
View File
@@ -0,0 +1,974 @@
U0 CDate2Dos(U16 *t,U16 *d,CDate cdt)
{
CDateStruct ds;
Date2Struct(&ds,cdt);
*d=ds.day_of_mon+(ds.mon+(ds.year-1980)<<4)<<5;
*t=ds.sec>>1+(ds.min+ds.hour<<6)<<5;
}
CDate Dos2CDate(U16 t,U16 d)
{
CDateStruct ds;
MemSet(&ds,0,sizeof(CDateStruct));
ds.day_of_mon=d&0x1F; d=d>>5;
ds.mon=d&0xF;
ds.year=d>>4+1980;
ds.sec=(t&0x1F)*2; t=t>>5;
ds.min=t&0x3F;
ds.hour=t>>6;
return Struct2Date(&ds);
}
U0 FAT32DrvInit(CDrv *dv)
{
CFAT32Boot br32;
Bool unlock;
try {
unlock=DrvLock(dv);
dv->type=DVT_FAT32;
RBlks(dv,&br32,dv->base_offset,1);
dv->file_system_info_sect=dv->base_offset+br32.file_system_info_sect;
dv->fat1=dv->base_offset+br32.reserved_sects;
dv->fat2=dv->fat1+br32.sects_per_fat;
dv->data_area=dv->fat2+br32.sects_per_fat
-2*br32.sects_per_cluster; //Starts at Cluster 2
dv->spc=br32.sects_per_cluster;
dv->root_cluster=br32.root_cluster;
DrvFATBlkAlloc(dv);
Free(dv->fis);
dv->fis=AMAlloc(BLK_SIZE);
RBlks(dv,dv->fis,dv->file_system_info_sect,1);
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
}
Bool FAT32DrvValidate(U8 drv_let)
{
CDrv *dv;
CFAT32Boot br;
Bool result=FALSE;
try {
dv=Let2Drv(drv_let);
if (dv->type==DVT_FAT32 &&
RBlks(dv,&br,dv->base_offset,1) &&
br.signature==0xAA55 &&
br.sects==dv->size)
result=TRUE;
} catch
Fs->catch_except=TRUE;
return result;
}
U0 FAT32Fmt(U8 drv_let,Bool quick=TRUE)
{
CFAT32Boot *br=CAlloc(BLK_SIZE);
CFAT32FileInfoSect *fis=CAlloc(BLK_SIZE);
CDrv *dv=Let2Drv(drv_let);
I64 i,l;
try {
DrvLock(dv);
DrvTypeSet(drv_let,DVT_FAT32);
dv->type=DVT_FAT32;
br->jump_and_nop[0]=OC_JMP_REL8;
br->jump_and_nop[1]=offset(CFAT32Boot.code)-2;
br->jump_and_nop[2]=OC_NOP;
br->oem_name[0](I64)='MSWIN4.1';
br->bytes_per_sect=BLK_SIZE;
if (dv->size<= 500000)
br->sects_per_cluster=1;
else if (dv->size<=2000000)
br->sects_per_cluster=2;
else if (dv->size<=6000000)
br->sects_per_cluster=4;
else if (dv->size<=12000000)
br->sects_per_cluster=8;
else if (dv->size<=33000000)
br->sects_per_cluster=16;
else if (dv->size<=67000000)
br->sects_per_cluster=32;
else
br->sects_per_cluster=64;
br->reserved_sects=32;
br->copies_of_fat=2;
br->media_desc=0xF8;
br->sects=dv->size;
l=(br->sects/br->sects_per_cluster)>>(BLK_SIZE_BITS-2)+1;
br->sects_per_fat=l;
br->root_cluster=2;
br->file_system_info_sect=1;
br->log_drv_num=0x80;
br->ext_signature=0x29;
br->serial_num=RandU32;
MemCpy(br->vol_name,"NO NAME ",11);
br->fat_name[0](I64)='FAT32 ';
br->signature=0xAA55;
fis->signature1='RRaA';
fis->signature2='rrAa';
fis->free_clusters=-1;
fis->most_recently_alloced=0;
fis->signature3=0xAA550000;
if (quick)
i=br->reserved_sects+2*l+4*br->sects_per_cluster;
else
i=dv->size;
WZeroBlks(dv,dv->base_offset,i);
WBlks(dv,fis,dv->base_offset+br->file_system_info_sect,1);
WBlks(dv,br,dv->base_offset,1);
FAT32DrvInit(dv);
ClustersAlloc(dv,0,1,FALSE); //Alloc #1
br->root_cluster=ClustersAlloc(dv,0,1,FALSE);
WBlks(dv,br,dv->base_offset,1);
FAT32DrvInit(dv);
DrvUnlock(dv);
} catch
DrvUnlock(dv);
Free(br);
Free(fis);
}
Bool FATNameTo(U8 *dst,U8 *src)
{
I64 i;
MemSet(dst,CH_SPACE,11);
if (!FileNameChk(src))
return FALSE;
if (!StrCmp(src,"..")) {
*dst='.';
dst[1]='.';
return TRUE;
} else if (!StrCmp(src,".")) {
*dst='.';
return TRUE;
}
i=0;
while (i<8 && *src && *src!='.')
dst[i++]=ToUpper(*src++);
i=8;
if (*src=='.') src++;
while (*src)
if (*src!='.')
dst[i++]=ToUpper(*src++);
else
src++;
return TRUE;
}
I64 FATNameXSum(U8 *src)
{
I64 i,result=0;
for (i=0;i<11;i++)
if (result&1)
result.u8[0]=0x80+result>>1+*src++;
else
result.u8[0]=result>>1+*src++;
return result;
}
Bool FATFromName(U8 *dst,U8 *src)
{
I64 i,j,k=0;
for (j=7;j>=0 && src[j]==CH_SPACE;j--);
for(i=0;i<=j;i++)
dst[k++]=src[i];
for (j=10;j>=8 && src[j]==CH_SPACE;j--);
if (*src!='.' && j!=7)
dst[k++]='.';
for(i=8;i<=j;i++)
dst[k++]=src[i];
dst[k++]=0;
return FileNameChk(dst);
}
U8 fat_long_name_map[13]={
offset(CFAT32DirEntryLong.name1),
offset(CFAT32DirEntryLong.name1)+2,
offset(CFAT32DirEntryLong.name1)+4,
offset(CFAT32DirEntryLong.name1)+6,
offset(CFAT32DirEntryLong.name1)+8,
offset(CFAT32DirEntryLong.name2),
offset(CFAT32DirEntryLong.name2)+2,
offset(CFAT32DirEntryLong.name2)+4,
offset(CFAT32DirEntryLong.name2)+6,
offset(CFAT32DirEntryLong.name2)+8,
offset(CFAT32DirEntryLong.name2)+10,
offset(CFAT32DirEntryLong.name3),
offset(CFAT32DirEntryLong.name3)+2
};
Bool DirLongNameFill(CDirEntry *tempde,CFAT32DirEntryLong *de,I64 *xsum)
{
I64 i;
U8 *ptr=de;
if (de->ord&0x40) {
MemSet(tempde,0,sizeof(CDirEntry));
*xsum=de->xsum;
} else if (de->type || de->zero || de->xsum!=*xsum) {
MemSet(tempde,0,sizeof(CDirEntry));
*xsum=0;
return FALSE;
}
switch (de->ord&0x3F) {
case 1:
for (i=0;i<13;i++)
if (!(tempde->name[i]=ptr[fat_long_name_map[i]]))
return TRUE;
break;
case 2:
for (i=0;i<12;i++)
if (!(tempde->name[i+13]=ptr[fat_long_name_map[i]]))
return TRUE;
break;
}
return TRUE;
}
Bool FAT32CDirFill(CDirEntry *tempde,
CFAT32DirEntry *de,CDate _local_time_offset)
{
Bool result;
if (*tempde->name)
result=TRUE;
else
result=FATFromName(tempde->name,de->name);
tempde->cluster=de->cluster_lo+de->cluster_hi<<16;
tempde->size=de->size;
tempde->attr=de->attr;
tempde->datetime=Dos2CDate(de->WrtTime,de->WrtDate)-_local_time_offset;
return result;
}
Bool FAT32DirFill(CFAT32DirEntry *de,
CDirEntry *tempde,I64 *_de_cnt,CDate _local_time_offset)
{//Fill up to 3 entries and store cnt of entries.
I64 de_cnt=0,i,l,xsum,ord;
U8 *ptr,dname[16];
CFAT32DirEntryLong *ld=de;
Bool result;
MemSet(de,0,sizeof(CFAT32DirEntry));
result=FATNameTo(de->name,tempde->name);
FATFromName(dname,de->name);
if (StrCmp(dname,tempde->name)) {
ord=0x41;
xsum=FATNameXSum(de->name);
if ((l=StrLen(tempde->name))>13) {
ptr=&ld[de_cnt];
MemSet(ptr,0,sizeof(CFAT32DirEntryLong));
ld[de_cnt].attr=RS_ATTR_LONG_NAME;
ld[de_cnt].xsum=xsum;
ld[de_cnt].ord=0x42;
for (i=13;i<l;i++)
ptr[fat_long_name_map[i-13]]=tempde->name[i];
i++;
for (;i<26;i++)
ptr[fat_long_name_map[i-13]](U16)=0xFFFF;
ord=1;
l=13;
de_cnt++;
}
ptr=&de[de_cnt];
MemSet(ptr,0,sizeof(CFAT32DirEntryLong));
ld[de_cnt].attr=RS_ATTR_LONG_NAME;
ld[de_cnt].xsum=xsum;
ld[de_cnt].ord=ord;
for (i=0;i<l;i++)
ptr[fat_long_name_map[i]]=tempde->name[i];
i++;
for (;i<13;i++)
ptr[fat_long_name_map[i]](U16)=0xFFFF;
de_cnt++;
MemSet(&de[de_cnt],0,sizeof(CFAT32DirEntry));
result=FATNameTo(de[de_cnt].name,tempde->name);
}
de[de_cnt].cluster_lo=tempde->cluster.u16[0];
de[de_cnt].cluster_hi=tempde->cluster.u16[1];
if (!(tempde->attr&RS_ATTR_DIR))
de[de_cnt].size=tempde->size;
de[de_cnt].attr=tempde->attr;
if (!tempde->datetime)
tempde->datetime=Now;
CDate2Dos(&de[de_cnt].WrtTime,&de[de_cnt].WrtDate,
tempde->datetime+_local_time_offset);
if (_de_cnt)
*_de_cnt=de_cnt+1;
return result;
}
Bool FAT32FileFind(CDrv *dv,I64 cur_dir_cluster,
U8 *name,CDirEntry *_result,I64 fuf_flags=0)
{//$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$
Bool result=FALSE,unlock;
CFAT32DirEntry *buf;
I64 xsum=0,attr,cur_dir_entry,entries_per_cluster;
U8 dname[CDIR_FILENAME_LEN],ch;
CDirEntry long_name;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
MemSet(_result,0,sizeof(CDirEntry));
MemSet(&long_name,0,sizeof(CDirEntry));
DrvChk(dv);
if (dv->type!=DVT_FAT32)
PrintErr("Not FAT32 Drv\n");
else if (!CFileNameTo(dname,name))
PrintErr("Invalid FileName.\n");
else
try {
unlock=DrvLock(dv);
buf=MAlloc(BLK_SIZE*dv->spc);
entries_per_cluster=dv->spc<<FAT32_ENTRIES_BITS;
RClusters(dv,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5) {
if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr&RS_ATTR_VOL_ID)) {
if (xsum==FATNameXSum(buf[cur_dir_entry].name))
MemCpy(_result,&long_name,sizeof(CDirEntry));
else
MemSet(_result,0,sizeof(CDirEntry));
if (!(fuf_flags&FUF_JUST_DIRS && !(attr & RS_ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && attr & RS_ATTR_DIR) &&
FAT32CDirFill(_result,&buf[cur_dir_entry],
dv->fat32_local_time_offset) &&
!StrCmp(dname,_result->name)) {
result=TRUE;
goto fff_done;
}
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClusterNumNext(dv,cur_dir_cluster);
if (!(0<cur_dir_cluster<0x0FFFFFF8))
break;
else {
RClusters(dv,buf,cur_dir_cluster,1);
cur_dir_entry=0;
}
}
}
MemSet(_result,0,sizeof(CDirEntry));
fff_done:
Free(buf);
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
return result;
}
U8 *FAT32FileRead(CDrv *dv,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
DrvChk(dv);
*_size=0;
*_attr=0;
if (dv->type!=DVT_FAT32)
PrintErr("Not FAT32 Drv\n");
else
try {
DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,cur_dir);
if (FAT32FileFind(dv,cur_dir_cluster,filename,&de,FUF_JUST_FILES)) {
blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);
c=de.cluster;
if (!(0<c<0x0FFFFFF8))
c=0x0FFFFFFF;
else
c=RClustersBlks(dv,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
DrvUnlock(dv);
} catch
DrvUnlock(dv);
return buf;
}
Bool FAT32Cd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_dv->type!=DVT_FAT32)
PrintErr("Not FAT32 Drv\n");
else if (FAT32FileFind(Fs->cur_dv,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
U0 FAT32FreeClusters(CDrv *dv,I64 c)
{
I64 next,saved_c=c;
Bool unlock,unlock_break;
DrvChk(dv);
if (!(0<c<0x0FFFFFF8)) return;
if (dv->type!=DVT_FAT32)
PrintErr("Not FAT32 Drv\n");
else
try {
unlock_break=BreakLock;
unlock=DrvLock(dv);
DrvFATBlkClean(dv);
do {
DrvFATBlkSet(dv,c,0);
next=dv->cur_fat_blk[c&(BLK_SIZE/4-1)];
dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0;
LBts(&dv->fat_blk_dirty,0);
c=next;
} while (0<c<0x0FFFFFF8);
DrvFATBlkClean(dv,0);
c=saved_c;
do {
DrvFATBlkSet(dv,c,1);
next=dv->cur_fat_blk[c&(BLK_SIZE/4-1)];
dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0;
LBts(&dv->fat_blk_dirty,0);
c=next;
} while (0<c<0x0FFFFFF8);
DrvFATBlkClean(dv,1);
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
}
I64 FAT32AllocClusters(CDrv *dv,I64 c,I64 cnt)
{
Bool wrap_around=FALSE,unlock,unlock_break;
I64 first=INVALID_CLUSTER,j,l;
if (cnt<=0) return 0x0FFFFFFF;
try {
unlock_break=BreakLock;
unlock=DrvLock(dv);
l=(dv->size+dv->base_offset-dv->data_area)/dv->spc-1;
j=dv->fis->most_recently_alloced;
while (cnt-->0) {
while (TRUE) {
j++;
if (j<1) j=1;
if (j>=l) {
if (wrap_around)
throw('Drv');
j=1;
wrap_around=TRUE;
}
DrvFATBlkSet(dv,j);
if (!dv->cur_fat_blk[j&(BLK_SIZE/4-1)])
break;
}
if (!(0<first<0x0FFFFFF8))
first=j;
if (0<c<l) {
DrvFATBlkSet(dv,c);
dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=j;
LBts(&dv->fat_blk_dirty,0);
}
c=j;
}
if (0<c<l) {
DrvFATBlkSet(dv,c);
dv->cur_fat_blk[c&(BLK_SIZE/4-1)]=0x0FFFFFFF;
LBts(&dv->fat_blk_dirty,0);
}
DrvFATBlkClean(dv);
dv->fis->most_recently_alloced=j;
dv->fis->free_clusters=-1;
WBlks(dv,dv->fis,dv->file_system_info_sect,1);
} catch {
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
return first;
}
I64 FAT32AllocContiguousClusters(CDrv *dv,I64 cnt)
{
I64 i,first=1;
Bool cont,unlock,unlock_break;
if (cnt<=0) return 0x0FFFFFFF;
try {
unlock_break=BreakLock;
unlock=DrvLock(dv);
while (TRUE) {
first++;
i=0;
cont=TRUE;
while (cont && i<cnt) {
if ((first+i+1)*dv->spc+dv->data_area>dv->size+dv->base_offset)
throw('Drv');
DrvFATBlkSet(dv,first+i);
if (dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)])
cont=FALSE;
else
i++;
}
if (!cont)
first=first+i;
else {
DrvFATBlkClean(dv);
for (i=0;i<cnt;i++) {
DrvFATBlkSet(dv,first+i,0);
if (i+1==cnt)
dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF;
else
dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1;
LBts(&dv->fat_blk_dirty,0);
}
DrvFATBlkClean(dv,0);
for (i=0;i<cnt;i++) {
DrvFATBlkSet(dv,first+i,1);
if (i+1==cnt)
dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF;
else
dv->cur_fat_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1;
LBts(&dv->fat_blk_dirty,0);
}
DrvFATBlkClean(dv,1);
break;
}
}
} catch {
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
return first;
}
Bool FAT32DirNew(CDrv *dv,U8 *cur_dir,CDirEntry *tempde,Bool free_old_chain)
{
//See $LK,"::/Doc/CutCorners.TXT"$.
CFAT32DirEntry *buf,*last_buf,*temp_buf,de[3];
I64 i,attr,avail_cnt,de_cnt,c,
cur_dir_entry,entries_per_cluster,
cur_dir_cluster,xsum=0,last_dir_cluster=INVALID_CLUSTER;
U8 ch;
Bool written=FALSE,unlock,unlock_break;
CDirEntry long_name;
FAT32DirFill(&de,tempde,&de_cnt,dv->fat32_local_time_offset);
MemSet(&long_name,0,sizeof(CDirEntry));
try {
unlock_break=BreakLock;
unlock=DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,cur_dir);
buf =MAlloc(BLK_SIZE*dv->spc);
last_buf=CAlloc(BLK_SIZE*dv->spc);
entries_per_cluster=dv->spc<<FAT32_ENTRIES_BITS;
RClusters(dv,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5 && attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
avail_cnt=FAT32_ENTRIES_PER_BLK-cur_dir_entry
&(FAT32_ENTRIES_PER_BLK-1);
for (i=0;i<avail_cnt;i++)
if (*buf[cur_dir_entry+i].name!=0xE5) {
if (*buf[cur_dir_entry+i].name)
avail_cnt=i;
break;
}
if (ch==0xE5 && !written && avail_cnt>=de_cnt) {
MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry));
WBlks(dv,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK],
dv->data_area+cur_dir_cluster*dv->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=de_cnt-1; //gets inc'ed
written=TRUE;
} else if (ch!=0xE5 && !(attr&RS_ATTR_VOL_ID)) {
if (xsum!=FATNameXSum(buf[cur_dir_entry].name))
MemSet(&long_name,0,sizeof(CDirEntry));
if (!*long_name.name)
FATFromName(long_name.name,buf[cur_dir_entry].name);
//Del old entry with same name
if (!StrCmp(long_name.name,tempde->name)) {
if (free_old_chain)
FAT32FreeClusters(dv,buf[cur_dir_entry].cluster_lo+
buf[cur_dir_entry].cluster_hi<<16);
if (!written) {
MemCpy(&buf[cur_dir_entry],&de[de_cnt-1],sizeof(CFAT32DirEntry));
WBlks(dv,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK],
dv->data_area+cur_dir_cluster*dv->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
written=TRUE;
} else {
*buf[cur_dir_entry].name=0xE5;
i=1;
while (i<=cur_dir_entry &&
buf[cur_dir_entry-i].attr&RS_ATTR_LONG_NAME_MASK
==RS_ATTR_LONG_NAME)
*buf[cur_dir_entry-i++].name=0xE5;
i--;
WBlks(dv,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK],
dv->data_area+cur_dir_cluster*dv->spc
+(cur_dir_entry-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS);
if (i==cur_dir_entry && 0<last_dir_cluster<0x0FFFFFF8) {
i=1;
while (i<=entries_per_cluster &&
last_buf[entries_per_cluster-i].attr
&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)
*last_buf[entries_per_cluster-i++].name=0xE5;
if (--i>0)
WBlks(dv,&buf[(entries_per_cluster-i)&-FAT32_ENTRIES_PER_BLK],
dv->data_area+last_dir_cluster*dv->spc
+(entries_per_cluster-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS);
}
}
break;
}
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
if (++cur_dir_entry==entries_per_cluster) {
last_dir_cluster=cur_dir_cluster;
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
c=ClusterNumNext(dv,cur_dir_cluster);
if (!(0<c<0x0FFFFFF8)) {
c=ClustersAlloc(dv,cur_dir_cluster,1,FALSE);
MemSet(buf,0,BLK_SIZE*dv->spc);
WClusters(dv,buf,c,1);
} else
RClusters(dv,buf,c,1);
cur_dir_cluster=c;
cur_dir_entry=0;
}
}
if (!written) {
avail_cnt=FAT32_ENTRIES_PER_BLK-cur_dir_entry & (FAT32_ENTRIES_PER_BLK-1);
if (avail_cnt<de_cnt) {
for (i=0;i<avail_cnt;i++)
*buf[cur_dir_entry+i].name=0xE5;
WBlks(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
dv->data_area+cur_dir_cluster*dv->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=avail_cnt;
if (cur_dir_entry==entries_per_cluster) {
last_dir_cluster=cur_dir_cluster;
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
cur_dir_cluster=ClustersAlloc(dv,cur_dir_cluster,1);
cur_dir_entry=0;
MemSet(buf,0,BLK_SIZE*dv->spc);
WClusters(dv,buf,cur_dir_cluster,1);
}
}
MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry));
WBlks(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
dv->data_area+cur_dir_cluster*dv->spc+
cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=de_cnt;
if (cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClustersAlloc(dv,cur_dir_cluster,1);
MemSet(buf,0,BLK_SIZE*dv->spc);
WClusters(dv,buf,cur_dir_cluster,1);
} else {
MemSet(&buf[cur_dir_entry],0,sizeof(CFAT32DirEntry));
WBlks(dv,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
dv->data_area+cur_dir_cluster*dv->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
}
}
Free(last_buf);
Free(buf);
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
return FALSE;
}
I64 FAT32FilesDel(CDrv *dv,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,
Bool del_dir,Bool print_msg)
{
CFAT32DirEntry *buf,*last_buf,*temp_buf;
I64 i,result=0,attr,xsum=0,last_dir_cluster=INVALID_CLUSTER,
cur_dir_entry,entries_per_cluster,cur_dir_cluster;
U8 ch;
Bool unlock_break;
CDirEntry long_name;
MemSet(&long_name,0,sizeof(CDirEntry));
try {
unlock_break=BreakLock;
DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,cur_dir);
buf =MAlloc(BLK_SIZE*dv->spc);
last_buf=CAlloc(BLK_SIZE*dv->spc);
entries_per_cluster=dv->spc<<FAT32_ENTRIES_BITS;
RClusters(dv,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5 && ch!='.') {
if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr & RS_ATTR_VOL_ID) &&
(del_dir || !(attr & RS_ATTR_DIR))) {
if (xsum!=FATNameXSum(buf[cur_dir_entry].name))
MemSet(&long_name,0,sizeof(CDirEntry));
if (!*long_name.name)
FATFromName(long_name.name,buf[cur_dir_entry].name);
if (FilesFindMatch(long_name.name,files_find_mask,fuf_flags)) {
if (!(attr & RS_ATTR_DIR)) result++;
if (print_msg)
"Del %s\n",long_name.name;
*buf[cur_dir_entry].name=0xE5;
i=1;
while (i<=cur_dir_entry &&
buf[cur_dir_entry-i].attr&RS_ATTR_LONG_NAME_MASK
==RS_ATTR_LONG_NAME)
*buf[cur_dir_entry-i++].name=0xE5;
i--;
WBlks(dv,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK],
dv->data_area+cur_dir_cluster*dv->spc
+(cur_dir_entry-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS);
if (i==cur_dir_entry && last_dir_cluster!=INVALID_CLUSTER) {
i=1;
while (i<=entries_per_cluster &&
last_buf[entries_per_cluster-i].attr
&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)
*last_buf[entries_per_cluster-i++].name=0xE5;
if (--i>0)
WBlks(dv,&buf[(entries_per_cluster-i)&-FAT32_ENTRIES_PER_BLK],
dv->data_area+last_dir_cluster*dv->spc
+(entries_per_cluster-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS);
}
FAT32FreeClusters(dv,buf[cur_dir_entry].cluster_lo+
buf[cur_dir_entry].cluster_hi<<16);
}
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
last_dir_cluster=cur_dir_cluster;
cur_dir_cluster=ClusterNumNext(dv,cur_dir_cluster,1);
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
RClusters(dv,buf,cur_dir_cluster,1);
cur_dir_entry=0;
}
}
Free(buf);
Free(last_buf);
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
} catch {
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
return result;
}
I64 FAT32FileWrite(CDrv *dv,U8 *cur_dir,U8 *name,U8 *buf,I64 size,
CDate cdt,I64 attr)
{
CDirEntry de;
I64 c=0,blk_cnt;
Bool contiguous;
MemSet(&de,0,sizeof(CDirEntry));
if (size<0) size=0;
if (dv->type!=DVT_FAT32)
PrintErr("Not FAT32 Drv\n");
else if (!CFileNameTo(de.name,name))
PrintErr("Invalid FileName.\n");
else {
FAT32FilesDel(dv,cur_dir,de.name,0,FALSE,FALSE);
if (attr & RS_ATTR_CONTIGUOUS)
contiguous=TRUE;
else
contiguous=FALSE;
de.size=size;
if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)
c=ClustersAlloc(dv,0,(blk_cnt+dv->spc-1)/dv->spc,contiguous);
else
c=0x0FFFFFFF;
de.cluster=c;
de.attr=attr;
de.datetime=cdt;
if (blk_cnt)
WClustersBlks(dv,buf,c,blk_cnt);
FAT32DirNew(dv,cur_dir,&de,TRUE);
}
return c;
}
CDirEntry *FAT32FilesFind(U8 *files_find_mask,
I64 fuf_flags,CDirEntry *parent=NULL,I64 *_dir_size=NULL)
{
CDrv *dv=Fs->cur_dv;
CFAT32DirEntry *buf;
I64 attr,xsum=0,dir_size=0,sub_dir_size,
cur_dir_cluster,cur_dir_entry,entries_per_cluster;
U8 ch;
CDirEntry *result=NULL,*tempde,long_name;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
try {
MemSet(&long_name,0,sizeof(CDirEntry));
DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,Fs->cur_dir);
buf=MAlloc(BLK_SIZE*dv->spc);
entries_per_cluster=dv->spc<<FAT32_ENTRIES_BITS;
RClusters(dv,buf,cur_dir_cluster,1);
dir_size+=dv->spc*BLK_SIZE;
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5) {
if (attr&RS_ATTR_LONG_NAME_MASK==RS_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr&RS_ATTR_VOL_ID)) {
tempde=MAlloc(sizeof(CDirEntry));
if (xsum==FATNameXSum(buf[cur_dir_entry].name))
MemCpy(tempde,&long_name,sizeof(CDirEntry));
else
MemSet(tempde,0,sizeof(CDirEntry));
if (FAT32CDirFill(tempde,&buf[cur_dir_entry],
dv->fat32_local_time_offset)) {
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && attr&RS_ATTR_DIR &&
*tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
DrvUnlock(dv);
if (Cd(tempde->name)) {
tempde->sub=FAT32FilesFind(files_find_mask,fuf_flags,
tempde,&sub_dir_size);
tempde->size=sub_dir_size;
Cd("..");
}
DrvLock(dv);
} else if ((attr&RS_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) &&
*tempde->name=='.' && attr&RS_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
} else
DirEntryDel(tempde);
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClusterNumNext(dv,cur_dir_cluster);
if (cur_dir_cluster==INVALID_CLUSTER)
break;
else {
RClusters(dv,buf,cur_dir_cluster,1);
dir_size+=dv->spc*BLK_SIZE;
cur_dir_entry=0;
}
}
}
Free(buf);
DrvUnlock(dv);
} catch
DrvUnlock(dv);
if (_dir_size)
*_dir_size=dir_size;
return result;
}
Bool FAT32MkDir(CDrv *dv,U8 *cur_dir,U8 *name)
{
I64 size=dv->spc<<BLK_SIZE_BITS,c,
cur_dir_cluster=Name2DirCluster(dv,cur_dir);
U8 *buf=CAlloc(size);
CDirEntry d_native;
CFAT32DirEntry *dFAT=buf;
Bool unlock_break;
try {
unlock_break=BreakLock;
c=FileWrite(name,buf,size,0,RS_ATTR_DIR);
MemSet(&d_native,0,sizeof(CDirEntry));
d_native.attr=RS_ATTR_DIR;
*d_native.name='.';
d_native.name[1]=0;
d_native.cluster=c;
d_native.size=0;
d_native.datetime=Now;
FAT32DirFill(dFAT,&d_native,NULL,dv->fat32_local_time_offset);
dFAT++;
MemSet(&d_native,0,sizeof(CDirEntry));
d_native.attr=RS_ATTR_DIR;
*d_native.name='.';
d_native.name[1]='.';
d_native.name[2]=0;
d_native.cluster=cur_dir_cluster;
d_native.size=0;
d_native.datetime=Now;
FAT32DirFill(dFAT,&d_native,NULL,dv->fat32_local_time_offset);
WClusters(dv,buf,c,1);
Free(buf);
if (unlock_break)
BreakUnlock;
} catch
if (unlock_break)
BreakUnlock;
return TRUE;
}
+290
View File
@@ -0,0 +1,290 @@
//ISO1 is ISO9660
//ISO2 is ISO13490
//ISO3 is ISO13346
Bool ISODrvInit(CDrv *dv,I64 blk)
{
CBlkDev *bd=dv->bd;
I64 spc=bd->blk_size>>BLK_SIZE_BITS,i=blk/spc;
CISO1PriDesc *iso=MAlloc(bd->blk_size);
CISO1DirEntry *de;
Bool unlock,result=FALSE;
U8 buf[8];
try {
unlock=DrvLock(dv);
dv->type=DVT_ISO9660; //default
dv->spc=spc;
dv->base_offset=dv->data_area=dv->root_cluster=dv->size=0;
while (TRUE) {
dv->size=MaxI64(dv->size,(i+1)*spc);
RBlks(dv,iso,i*spc,spc);
buf[0](U32)=iso->id[0](U32);
buf[4](U16)=iso->id[4](U8);
switch (LstMatch(buf,"CD001\0CDW02\0BEA01\0BOOT2\0NSR02\0NSR03\0TEA01\0",
LMF_EXACT)) {
case 0:
dv->type=DVT_ISO9660;
switch (iso->type) {
case ISO1T_SUPPLEMENTARY_DESC:
dv->data_area=0;
de=&iso->root_dir_record;
dv->root_cluster=de->loc.little;
dv->size=iso->vol_space_size.little*bd->blk_size>>BLK_SIZE_BITS;
result=TRUE;
goto ipi_done;
case ISO1T_TERMINATOR:
throw('Drv');
}
break;
default: //Its normal for ISO13346 to read NULL blk as terminator
PrintErr("File System Not Supported\n");
throw('Drv');
}
i++;
}
ipi_done:
Free(iso);
if (unlock)
DrvUnlock(dv);
} catch {
dv->type=DVT_ISO9660;
dv->spc=spc;
dv->base_offset=dv->data_area=dv->root_cluster=0;
Free(iso);
if (unlock)
DrvUnlock(dv);
}
return result;
}
U0 Date2ISO1(CISO1Date *dst,CDate cdt)
{
CDateStruct ds;
Date2Struct(&ds,cdt);
dst->year=ds.year-ISO1_BASE_YEAR;
dst->mon=ds.mon;
dst->day=ds.day_of_mon;
dst->hour=ds.hour;
dst->min=ds.min;
dst->sec=ds.sec;
dst->sec100=ds.sec100;
}
CDate ISO1DateStruct2CDate(CISO1Date *dt)
{
CDateStruct ds;
MemSet(&ds,0,sizeof(CDateStruct));
ds.day_of_mon=dt->day;
ds.mon=dt->mon;
ds.year=dt->year+ISO1_BASE_YEAR;
ds.sec100=dt->sec100;
ds.sec=dt->sec;
ds.min=dt->min;
ds.hour=dt->hour;
return Struct2Date(&ds);
}
Bool ISO1FromName(U8 *dst,U8 *src)
{
I64 i,j,n;
MemSet(dst,0,CDIR_FILENAME_LEN);
n=*src++;
if (n==1 && !*src) {
*dst='.';
} else if (n==1 && *src==1) {
*dst='.';
dst[1]='.';
} else {
n>>=1;
j=0;
for (i=0;i<n;i++) {
src++;
if (*src==';')
break;
if (Bt(chars_bmp_filename,*src)) {
if (j>=CDIR_FILENAME_LEN-1)
return FALSE;
dst[j++]=*src++;
} else
return FALSE;
}
}
return FileNameChk(dst);
}
Bool ISO1CDirFill(CDirEntry *tempde,CISO1DirEntry *de)
{
Bool result;
MemSet(tempde,0,sizeof(CDirEntry));
result=ISO1FromName(tempde->name,&de->name_len);
tempde->cluster=de->loc.little;
tempde->size=de->size.little;
tempde->attr=FileAttr(tempde->name);
if (de->flags & ISO1_ATTR_DIR)
tempde->attr|=RS_ATTR_DIR;
tempde->datetime=ISO1DateStruct2CDate(&de->date);
return result;
}
Bool ISO1FileFind(CDrv *dv,I64 cur_dir_cluster,U8 *name,
CDirEntry *_result,I64 fuf_flags=0)
{//$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$
CISO1DirEntry *isoptr,*buf;
U8 dname[CDIR_FILENAME_LEN];
Bool result=FALSE,unlock;
I64 i;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
DrvChk(dv);
if (dv->type!=DVT_ISO9660)
PrintErr("Not ISO9660 Drv\n");
else
try {
unlock=DrvLock(dv);
isoptr=MAlloc(dv->spc<<BLK_SIZE_BITS);
RClusters(dv,isoptr,cur_dir_cluster,1);
if (isoptr->name_len==1 && !isoptr->name) {//curdir
i=(isoptr->size.little+dv->spc<<BLK_SIZE_BITS-1)/dv->spc<<BLK_SIZE_BITS;
buf=MAlloc(dv->spc<<BLK_SIZE_BITS*i);
RClusters(dv,buf,cur_dir_cluster,i);
Free(isoptr);
} else {
buf=isoptr;
i=1;
}
i*=dv->spc<<BLK_SIZE_BITS;
isoptr=buf;
while (i>0) {
if (!isoptr->len) {
isoptr(U8 *)++;
i--;
} else {
ISO1FromName(dname,&isoptr->name_len);
if (*dname) {
if (!StrCmp(name,dname)) {
result=ISO1CDirFill(_result,isoptr);
if (result &&
!(fuf_flags&FUF_JUST_DIRS &&
!(_result->attr & RS_ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && _result->attr & RS_ATTR_DIR) )
goto iff_done;
else
result=FALSE;
}
}
i-=isoptr->len;
isoptr(U8 *)+=isoptr->len;
}
}
iff_done:
Free(buf);
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
return result;
}
U8 *ISO1FileRead(CDrv *dv,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
DrvChk(dv);
*_size=0;
*_attr=0;
if (dv->type!=DVT_ISO9660)
PrintErr("Not ISO9660 Drv\n");
else
try {
DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,cur_dir);
if (ISO1FileFind(dv,cur_dir_cluster,filename,&de,FUF_JUST_FILES)) {
blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);
c=de.cluster;
c=RClustersBlks(dv,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
DrvUnlock(dv);
} catch
DrvUnlock(dv);
return buf;
}
Bool ISO1Cd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_dv->type!=DVT_ISO9660)
PrintErr("Not ISO9660 Drv\n");
else if (ISO1FileFind(Fs->cur_dv,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
CDirEntry *ISO1FilesFind(U8 *files_find_mask,
I64 fuf_flags,CDirEntry *parent=NULL)
{
CDrv *dv=Fs->cur_dv;
CISO1DirEntry *buf,*buf2,*isoptr;
I64 i,cur_dir_cluster=Name2DirCluster(dv,Fs->cur_dir);
CDirEntry *result=NULL,*tempde;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
isoptr=MAlloc(dv->spc<<BLK_SIZE_BITS);
RClusters(dv,isoptr,cur_dir_cluster,1);
if (isoptr->name_len==1 && !isoptr->name) {//curdir
i=(isoptr->size.little+dv->spc<<BLK_SIZE_BITS-1)/dv->spc<<BLK_SIZE_BITS;
buf=MAlloc(dv->spc<<BLK_SIZE_BITS*i);
RClusters(dv,buf,cur_dir_cluster,i);
Free(isoptr);
} else {
buf=isoptr;
i=1;
}
buf2=buf;
i*=dv->spc<<BLK_SIZE_BITS;
while (i>0) {
if (!buf->len) {
buf(U8 *)++;
i--;
} else {
tempde=MAlloc(sizeof(CDirEntry));
if (ISO1CDirFill(tempde,buf)) {
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempde->attr&RS_ATTR_DIR &&
*tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
if (Cd(tempde->name)) {
tempde->sub=ISO1FilesFind(files_find_mask,fuf_flags,tempde);
Cd("..");
}
} else if ((tempde->attr & RS_ATTR_DIR ||
!Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) &&
*tempde->name=='.' && tempde->attr&RS_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
} else
DirEntryDel(tempde);
i-=buf->len;
buf(U8 *)+=buf->len;
}
}
Free(buf2);
return result;
}
+636
View File
@@ -0,0 +1,636 @@
// See $LK,"RedSea File System",A="FI:::/Doc/RedSea.TXT"$
U0 RedSeaFreeFreeLst(CDrv *dv)
{
CFreeLst *tempf,*tempf1;
Bool unlock;
try {
unlock=DrvLock(dv);
if (tempf=dv->next_free) {
while (tempf!=&dv->next_free) {
tempf1=tempf->next;
Free(tempf);
tempf=tempf1;
}
}
dv->next_free=NULL;
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
}
U0 RedSeaFreeLstBuild(CDrv *dv)
{
Bool unlock;
CFreeLst *tempf;
I64 i,first=dv->data_area,max_blk=dv->size+dv->base_offset;
try {
unlock=DrvLock(dv);
if (dv->next_free)
RedSeaFreeFreeLst(dv);
QueInit(&dv->next_free);
while (first<max_blk) {
i=0; //count free clusters
while (first+i<max_blk) {
DrvFATBlkSet(dv,first+i);
if (Bt(dv->cur_fat_blk,(first+i-dv->data_area)&(BLK_SIZE<<3-1)))
break;
else
i++;
}
if (i) {
tempf=AMAlloc(sizeof(CFreeLst));
tempf->size=i;
tempf->start=first;
QueIns(tempf,dv->last_free);
}
first+=i+1;
}
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
}
U0 RedSeaDrvInit(CDrv *dv)
{
CRedSeaBoot br;
Bool unlock;
try {
unlock=DrvLock(dv);
RBlks(dv,&br,dv->base_offset,1);
if (br.signature!=MBR_PT_REDSEA || br.signature2!=0xAA55)
throw('Drv');
dv->type=DVT_REDSEA;
RedSeaFreeFreeLst(dv);
dv->spc=1;
dv->size=br.sects;
dv->data_area=dv->base_offset+br.bitmap_sects;
dv->root_cluster=br.root_cluster;
dv->fat1=dv->fat2=dv->base_offset+1;
DrvFATBlkAlloc(dv);
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
}
Bool RedSeaDrvValidate(U8 drv_let)
{
CDrv *dv;
CRedSeaBoot br;
Bool result=FALSE;
try {
dv=Let2Drv(drv_let);
if (dv->type==DVT_REDSEA && RBlks(dv,&br,dv->base_offset,1) &&
br.signature==MBR_PT_REDSEA && br.signature2==0xAA55 &&
br.sects==dv->size)
result=TRUE;
} catch
Fs->catch_except=TRUE;
return result;
}
U0 RedSeaFmt(U8 drv_let,Bool quick=TRUE)
{
U8 *root_dir;
CDirEntry *d_native;
CRedSeaBoot *br=CAlloc(BLK_SIZE);
CDrv *dv=Let2Drv(drv_let);
I64 i,n;
try {
DrvLock(dv);
// DrvTypeSet(drv_let,DVT_REDSEA);
DrvTypeSet(drv_let,DVT_FAT32);
dv->type=DVT_REDSEA;
br->signature=MBR_PT_REDSEA;
br->signature2=0xAA55;
br->base_offset=dv->base_offset; //For CD/DVD image copy.
br->sects=dv->size;
n=(br->sects+BLK_SIZE<<3-1)/BLK_SIZE<<3;
br->bitmap_sects=n;
br->unique_id=GetTSC^Now()(U64);
br->root_cluster=0;
if (quick)
i=n+1;
else
i=dv->size;
WZeroBlks(dv,dv->base_offset,i);
WBlks(dv,br,dv->base_offset,1);
RedSeaDrvInit(dv);
ClustersAlloc(dv,0,1,FALSE); //Alloc #1
br->root_cluster=ClustersAlloc(dv,0,1,FALSE);
WBlks(dv,br,dv->base_offset,1);
root_dir=CAlloc(BLK_SIZE);
d_native=root_dir-offset(CDirEntry.start);
d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS;
*d_native->name='.';
d_native->cluster=br->root_cluster;
d_native->size=BLK_SIZE;
d_native->datetime=Now;
d_native(U8 *)+=CDIR_SIZE;
*d_native->name='.';
d_native->name[1]='.';
d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS;
d_native->cluster=br->root_cluster;
d_native->datetime=Now;
WBlks(dv,root_dir,br->root_cluster,1);
RedSeaDrvInit(dv);
DrvUnlock(dv);
} catch
DrvUnlock(dv);
Free(br);
Free(root_dir);
}
Bool RedSeaFileFind(CDrv *dv,I64 cur_dir_cluster,U8 *name,
CDirEntry *_result,I64 fuf_flags=0)
{//$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$
CDirEntry *buf,*buf2,*ptr;
U8 dname[CDIR_FILENAME_LEN];
I64 ch;
Bool result=FALSE,unlock;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
MemSet(_result,0,sizeof(CDirEntry));
DrvChk(dv);
if (dv->type!=DVT_REDSEA)
PrintErr("Not RedSea Drv\n");
else if (!CFileNameTo(dname,name))
PrintErr("Invalid FileName.\n");
else
try {
unlock=DrvLock(dv);
buf2=MAlloc(BLK_SIZE);
RBlks(dv,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RBlks(dv,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 & RS_ATTR_DELETED) &&
!(fuf_flags&FUF_JUST_DIRS && !(ptr->attr & RS_ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && ptr->attr & RS_ATTR_DIR) &&
!StrCmp(dname,ptr->name)) {
MemCpy(&_result->attr,&ptr->attr,CDIR_SIZE);
result=TRUE;
goto rsff_done;
}
ptr(U8 *)+=CDIR_SIZE;
}
rsff_done:
Free(buf);
if (unlock)
DrvUnlock(dv);
} catch
if (unlock)
DrvUnlock(dv);
return result;
}
U8 *RedSeaFileRead(CDrv *dv,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
DrvChk(dv);
*_size=0;
*_attr=0;
if (dv->type!=DVT_REDSEA)
PrintErr("Not RedSea Drv\n");
else
try {
DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,cur_dir);
if (RedSeaFileFind(dv,cur_dir_cluster,filename,&de,FUF_JUST_FILES)) {
blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);
c=de.cluster;
c=RBlks(dv,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
DrvUnlock(dv);
} catch
DrvUnlock(dv);
return buf;
}
Bool RedSeaCd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_dv->type!=DVT_REDSEA)
PrintErr("Not RedSea Drv\n");
else if (RedSeaFileFind(Fs->cur_dv,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
U0 RedSeaFreeClusters(CDrv *dv,I64 c,I64 cnt)
{
CFreeLst *tempf;
Bool found=FALSE,unlock,unlock_break;
DrvChk(dv);
if (!c) return;
if (dv->type!=DVT_REDSEA)
PrintErr("Not RedSea Drv\n");
else
try {
unlock_break=BreakLock;
unlock=DrvLock(dv);
if (!dv->next_free)
RedSeaFreeLstBuild(dv);
tempf=dv->next_free;
while (!found && tempf!=&dv->next_free) {
if (tempf->start+tempf->size==c) {
tempf->size+=cnt;
found=TRUE;
} else if (c+cnt==tempf->start) {
tempf->size+=cnt;
tempf->start=c;
found=TRUE;
}
tempf=tempf->next;
}
if (!found) {
tempf=AMAlloc(sizeof(CFreeLst));
tempf->size=cnt;
tempf->start=c;
QueIns(tempf,dv->last_free);
}
while (cnt-->0) {
DrvFATBlkSet(dv,c);
LBtr(dv->cur_fat_blk,(c-dv->data_area)&(BLK_SIZE<<3-1));
LBts(&dv->fat_blk_dirty,0);
c++;
}
DrvFATBlkClean(dv);
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
}
I64 RedSeaAllocClusters(CDrv *dv,I64 cnt)
{
CFreeLst *tempf,*best_free=NULL;
I64 i,first,best_size=MAX_I64;
Bool unlock,unlock_break;
if (cnt<=0)
throw('Drv');
try {
unlock_break=BreakLock;
unlock=DrvLock(dv);
if (!dv->next_free)
RedSeaFreeLstBuild(dv);
tempf=dv->next_free;
while (tempf!=&dv->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)
throw('Drv');
first=best_free->start;
for (i=0;i<cnt;i++) {
DrvFATBlkSet(dv,first+i);
LBts(dv->cur_fat_blk,(first+i-dv->data_area)&(BLK_SIZE<<3-1));
LBts(&dv->fat_blk_dirty,0);
}
DrvFATBlkClean(dv);
if (best_free->size-=cnt)
best_free->start+=cnt;
else {
QueRem(best_free);
Free(best_free);
}
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
return first;
}
Bool RedSeaDirNew(CDrv *dv,U8 *cur_dir,CDirEntry *de,Bool free_old_chain)
{
CDirEntry *buf,*buf2,*ptr,de2;
CRedSeaBoot *br;
I64 c,ch,i=1,j=0,n=BLK_SIZE/CDIR_SIZE,dir_size,cur_dir_cluster;
Bool written=FALSE,unlock,unlock_break;
U8 *temp,*parent_dir;
try {
unlock_break=BreakLock;
de->attr|=RS_ATTR_CONTIGUOUS;
unlock=DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,cur_dir);
buf2=MAlloc(BLK_SIZE);
RBlks(dv,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RBlks(dv,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(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_cluster+j,1);
else {
buf2=CAlloc(dir_size+BLK_SIZE);
MemCpy(buf2,buf,dir_size);
RedSeaFreeClusters(dv,cur_dir_cluster,dir_size>>BLK_SIZE_BITS);
dir_size+=BLK_SIZE;
c=ClustersAlloc(dv,0,dir_size>>BLK_SIZE_BITS,TRUE);
Free(buf);
buf=buf2;
ptr=buf(U8 *)-offset(CDirEntry.start);
ptr->size=dir_size;
ptr->cluster=c;
WBlks(dv,buf,c,dir_size>>BLK_SIZE_BITS);
if (cur_dir_cluster==dv->root_cluster) {
br=CAlloc(BLK_SIZE);
RBlks(dv,br,dv->base_offset,1);
br->root_cluster=c;
WBlks(dv,br,dv->base_offset,1);
Free(br);
dv->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 (RedSeaFileFind(dv,Name2DirCluster(dv,parent_dir),
temp,&de2,FUF_JUST_DIRS)) {
de2.cluster=c;
de2.size=dir_size;
RedSeaDirNew(dv,parent_dir,&de2,FALSE);
} else
throw('Drv');
Free(temp);
Free(parent_dir);
}
}
break;
} else if (ptr->attr & RS_ATTR_DELETED) {
if (!written) {
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
WBlks(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_cluster+j,1);
written=TRUE;
}
} else {
if (!StrCmp(de->name,ptr->name)) {
if (free_old_chain)
RedSeaFreeClusters(dv,ptr->cluster,
(ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS);
if (!written)
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
else
ptr->attr|=RS_ATTR_DELETED;
WBlks(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_cluster+j,1);
break;
}
}
ptr(U8 *)+=CDIR_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
return FALSE;
}
I64 RedSeaFilesDel(CDrv *dv,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,
Bool del_dir,Bool print_msg)
{
CDirEntry *buf,*buf2,*ptr;
I64 i=0,result=0,ch,j=0,n=BLK_SIZE/CDIR_SIZE,cur_dir_cluster;
Bool unlock_break;
try {
unlock_break=BreakLock;
DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,cur_dir);
buf2=MAlloc(BLK_SIZE);
RBlks(dv,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RBlks(dv,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 & RS_ATTR_DELETED) && ch!='.' && (del_dir ||
!(ptr->attr & RS_ATTR_DIR)) &&
FilesFindMatch(ptr->name,files_find_mask,fuf_flags)) {
if (!(ptr->attr & RS_ATTR_DIR)) result++;
if (print_msg)
"Del %s\n",ptr->name;
ptr->attr|=RS_ATTR_DELETED;
WBlks(dv,buf(U8 *)+j<<BLK_SIZE_BITS,cur_dir_cluster+j,1);
RedSeaFreeClusters(dv,ptr->cluster,
(ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS);
}
ptr(U8 *)+=CDIR_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
} catch {
DrvUnlock(dv);
if (unlock_break)
BreakUnlock;
}
return result;
}
I64 RedSeaFileWrite(CDrv *dv,U8 *cur_dir,U8 *name,U8 *buf,I64 size,
CDate cdt,I64 attr)
{
CDirEntry de;
I64 c=0,blk_cnt;
MemSet(&de,0,sizeof(CDirEntry));
if (size<0) size=0;
if (dv->type!=DVT_REDSEA)
PrintErr("Not RedSea Drv\n");
else if (!CFileNameTo(de.name,name))
PrintErr("Invalid FileName.\n");
else {
RedSeaFilesDel(dv,cur_dir,de.name,0,FALSE,FALSE);
de.size=size;
if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)
c=ClustersAlloc(dv,0,blk_cnt,TRUE); //Always contiguous
else
c=INVALID_CLUSTER;
de.cluster=c;
de.attr=attr|RS_ATTR_CONTIGUOUS;
de.datetime=cdt;
if (blk_cnt)
WBlks(dv,buf,c,blk_cnt);
RedSeaDirNew(dv,cur_dir,&de,TRUE);
}
return c;
}
CDirEntry *RedSeaFilesFind(U8 *files_find_mask,I64 fuf_flags,
CDirEntry *parent=NULL)
{
CDrv *dv=Fs->cur_dv;
CDirEntry *buf,*buf2,*ptr,*result=NULL,*tempde;
I64 ch,cur_dir_cluster;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
try {
DrvLock(dv);
cur_dir_cluster=Name2DirCluster(dv,Fs->cur_dir);
buf2=MAlloc(BLK_SIZE);
RBlks(dv,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RBlks(dv,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(dv,Fs->cur_dir);
ptr(U8 *)-=CDIR_SIZE;
while (TRUE) {
if (!(ch=*ptr->name))
break;
else if (!(ptr->attr & RS_ATTR_DELETED)) {
tempde=CAlloc(sizeof(CDirEntry));
MemCpy(&tempde->start,&ptr->start,CDIR_SIZE);
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempde->attr&RS_ATTR_DIR &&
*tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
DrvUnlock(dv);
if (Cd(tempde->name)) {
tempde->sub=RedSeaFilesFind(files_find_mask,fuf_flags,tempde);
Cd("..");
}
DrvLock(dv);
} else if ((tempde->attr&RS_ATTR_DIR ||
!Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempde->name=='.' &&
tempde->attr&RS_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
}
ptr(U8 *)+=CDIR_SIZE;
}
Free(buf);
DrvUnlock(dv);
} catch
DrvUnlock(dv);
return result;
}
Bool RedSeaMkDir(CDrv *dv,U8 *cur_dir,U8 *name)
{
I64 size=BLK_SIZE,c,cur_dir_cluster=Name2DirCluster(dv,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,RS_ATTR_DIR);
d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS;
StrCpy(d_native->name,name);
d_native->cluster=c;
d_native->size=size;
d_native->datetime=Now;
d_native(U8 *)+=CDIR_SIZE;
d_native->attr=RS_ATTR_DIR|RS_ATTR_CONTIGUOUS;
*d_native->name='.';
d_native->name[1]='.';
d_native->name[2]=0;
d_native->cluster=cur_dir_cluster;
d_native->size=0;
d_native->datetime=Now;
WBlks(dv,buf,c,1);
Free(buf);
if (unlock_break)
BreakUnlock;
} catch
if (unlock_break)
BreakUnlock;
return TRUE;
}
+24
View File
@@ -0,0 +1,24 @@
#exe {Cd(__DIR__);};
#include "DskStrA"
#include "DskCache"
#include "DskATA"
#include "DskATAId"
#include "DskBlkDev"
#include "DskDrv"
#include "DskBlk"
#include "DskCluster"
#include "DskStrB"
#include "DskAddDev"
#include "DskDirA"
#include "FileSysISO"
#include "FileSysRedSea"
#include "FileSysFAT"
#include "DskDirContext"
#include "DskFind"
#include "DskDirB"
#include "DskFile"
#include "DskCFile"
#include "DskCopy"
#include "DskCDDVD"
#include "DskFmt"
#exe {Cd("..");};