1984 lines
47 KiB
Plaintext
1984 lines
47 KiB
Plaintext
void LockPartition(LTPartition *p)
|
|
{
|
|
LTBlkDev *bdev=p->bdev;
|
|
CheckLTPartition(p);
|
|
if (p->owning_task!=Fs) {
|
|
while (Bts(&p->flags,MPEf_LOCKED))
|
|
SwapInNext;
|
|
if (bdev->type==LTBDT_FDC)
|
|
FDCGet(bdev);
|
|
p->owning_task=Fs;
|
|
}
|
|
}
|
|
|
|
BoolU4 UnlockPartition(LTPartition *p,BoolU4 reset=FALSE)
|
|
{
|
|
LTBlkDev *bdev=p->bdev;
|
|
BoolU4 old_preempt=Preempt(OFF),result=FALSE;
|
|
CheckLTPartition(p);
|
|
if (p->owning_task==Fs) {
|
|
if (reset) {
|
|
bdev->flags&=~(LTBDF_INITIALIZED|LTBDF_INIT_IN_PROGRESS);
|
|
if (bdev->irq)
|
|
Btr(&sys_irq_busy_flags,bdev->irq);
|
|
}
|
|
p->owning_task=0;
|
|
if (bdev->type==LTBDT_FDC)
|
|
FDCFree(bdev);
|
|
Btr(&p->flags,MPEf_LOCKED);
|
|
result=TRUE;
|
|
}
|
|
Preempt(old_preempt);
|
|
return result;
|
|
}
|
|
|
|
|
|
void AllocMAPBuf(LTPartition *p,U8 num_blks)
|
|
{
|
|
CheckLTPartition(p);
|
|
AFree(p->cur_MAP_blk);
|
|
AFree(p->buffered_MAP_dirty_bits);
|
|
p->num_buffered_MAP_blks=num_blks;
|
|
p->cur_MAP_blk=AMAlloc(BLK_SIZE*num_blks);
|
|
p->buffered_MAP_dirty_bits=AMAllocZ((num_blks+7)>>3);
|
|
p->cur_MAP_blk_num=0;
|
|
RBlks(p,p->cur_MAP_blk,p->MAP1,p->num_buffered_MAP_blks,FALSE);
|
|
}
|
|
|
|
|
|
void CleanMAPBuf(LTPartition *p,I8 MAP_select=-1)
|
|
{
|
|
U8 i;
|
|
if (MAP_select==-1 || MAP_select==0) {
|
|
for (i=0;i<p->num_buffered_MAP_blks;i++)
|
|
if (Bt(p->buffered_MAP_dirty_bits,i))
|
|
WBlks(p,p->cur_MAP_blk+i*BLK_SIZE,p->MAP1+i+p->cur_MAP_blk_num,1,FALSE);
|
|
}
|
|
if (MAP_select==-1 || MAP_select==1) {
|
|
for (i=0;i<p->num_buffered_MAP_blks;i++)
|
|
if (Btr(p->buffered_MAP_dirty_bits,i))
|
|
WBlks(p,p->cur_MAP_blk+i*BLK_SIZE,p->MAP2+i+p->cur_MAP_blk_num,1,FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
void SetLTBuf(LTPartition *p,U8 c)
|
|
{
|
|
U8 MAP_blk_num=c/(BLK_SIZE<<3);
|
|
if (MAP_blk_num!=p->cur_MAP_blk_num) {
|
|
CleanMAPBuf(p);
|
|
p->cur_MAP_blk_num=MAP_blk_num;
|
|
RBlks(p,p->cur_MAP_blk,p->MAP1+p->cur_MAP_blk_num,1,FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
void FreeLTFreeList(LTPartition *p,BoolU4 unlock)
|
|
{
|
|
LTFreeList *tempf,*tempf1;
|
|
try {
|
|
LockPartition(p);
|
|
|
|
if (tempf=p->next_free) {
|
|
while (tempf!=&p->next_free) {
|
|
tempf1=tempf->next;
|
|
AFree(tempf);
|
|
tempf=tempf1;
|
|
}
|
|
}
|
|
p->next_free=NULL;
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
|
|
void BuildLTFreeList(LTPartition *p,BoolU4 unlock)
|
|
{
|
|
LTFreeList *tempf;
|
|
U8 i,first=0,
|
|
max_cluster=(p->size+p->offset-p->data)/p->spc;
|
|
|
|
try {
|
|
LockPartition(p);
|
|
|
|
if (p->next_free)
|
|
FreeLTFreeList(p,FALSE);
|
|
p->next_free=&p->next_free;
|
|
p->last_free=&p->next_free;
|
|
while (first<max_cluster) {
|
|
i=0; //count free clusters
|
|
while (first+i<max_cluster) {
|
|
SetLTBuf(p,first+i);
|
|
if (Bt(p->cur_MAP_blk,(first+i)&(BLK_SIZE<<3-1)))
|
|
break;
|
|
else
|
|
i++;
|
|
}
|
|
if (i) {
|
|
tempf=AMAlloc(sizeof(LTFreeList));
|
|
tempf->size=i;
|
|
tempf->start=first;
|
|
InsQue(tempf,p->last_free);
|
|
}
|
|
first+=i+1;
|
|
}
|
|
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
|
|
void InitLTPartition(LTPartition *p,BoolU4 unlock)
|
|
{
|
|
LTBootStruct br;
|
|
try {
|
|
LockPartition(p);
|
|
p->type=PT_LT;
|
|
FreeLTFreeList(p,FALSE);
|
|
RBlks(p,&br,p->offset,1,FALSE);
|
|
p->spc=br.sectors_per_cluster;
|
|
p->data=p->offset+1+br.bitmap_sectors-1*p->spc;
|
|
p->root_cluster=br.root_cluster;
|
|
p->MAP1=p->offset+1;
|
|
p->MAP2=p->offset+1;
|
|
AllocMAPBuf(p,1);
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
|
|
void InitISOPartition(LTPartition *p,BoolU4 unlock)
|
|
{
|
|
U8 i=16;
|
|
ISOPrimaryDescriptor *iso=MAlloc(CD_BLK_SIZE);
|
|
ISODirEntry *de;
|
|
|
|
try {
|
|
LockPartition(p);
|
|
p->type=PT_ISO9660;
|
|
p->spc=CD_BLK_SIZE/BLK_SIZE;
|
|
p->size=CD_FILE_OFFSET;
|
|
while (TRUE) {
|
|
RBlks(p,iso,i*p->spc,p->spc,FALSE);
|
|
if (iso->type==ISOT_SUPPLEMENTARY_DESC)
|
|
break;
|
|
else if (iso->type==ISOT_TERMINATOR)
|
|
throw(EXCEPT_PARTITION,0);
|
|
else
|
|
i++;
|
|
}
|
|
p->data=0;
|
|
de=&iso->root_directory_record;
|
|
p->root_cluster=de->location.little;
|
|
p->size=iso->volume_space_size.little*CD_BLK_SIZE/BLK_SIZE;
|
|
Free(iso);
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
|
|
#define ZERO_BUF_SIZE 2048
|
|
void WZeroBlks(LTPartition *p,U8 blk,U8 cnt,BoolU4 unlock)
|
|
{
|
|
U8 l;
|
|
U1 *z=MAllocZ(BLK_SIZE*ZERO_BUF_SIZE);
|
|
while (cnt) {
|
|
l=cnt;
|
|
if (l>ZERO_BUF_SIZE)
|
|
l=ZERO_BUF_SIZE;
|
|
WBlks(p,z,blk,l,unlock);
|
|
blk+=l;
|
|
cnt-=l;
|
|
SwapInNext; //Prevent locking
|
|
}
|
|
Free(z);
|
|
}
|
|
|
|
//Very dangerous
|
|
BoolU4 SetDriveType(I1 drive,U8 type=PT_LT)
|
|
{
|
|
I8 i,j,ext_base,num_partition;
|
|
U8 offset,cur_type;
|
|
MasterBootStruct mbr;
|
|
LTBlkDev *bd=DriveToBlkDev(drive);
|
|
num_partition=bd->partition_base-'A';
|
|
switch (bd->type) {
|
|
case LTBDT_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==0xF)
|
|
j=i;
|
|
else {
|
|
if ((num_partition+'A')==drive) {
|
|
mbr.p[i].type=type;
|
|
ATAWriteBlks(bd,&mbr,offset,1);
|
|
return TRUE;
|
|
}
|
|
num_partition++;
|
|
}
|
|
}
|
|
}
|
|
if (j<0)
|
|
break;
|
|
if (mbr.p[j].offset==0)
|
|
break;
|
|
if (ext_base==INVALID_CLUSTER) {
|
|
offset=mbr.p[j].offset;
|
|
ext_base=offset;
|
|
} else
|
|
offset=mbr.p[j].offset+ext_base;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void FormatLT(I1 drive_letter,BoolU4 quick=TRUE)
|
|
{
|
|
U1 *root_dir;
|
|
LTDirEntry *dLT;
|
|
LTBootStruct *br=MAllocZ(BLK_SIZE);
|
|
LTPartition *p=DriveToPartition(drive_letter);
|
|
U8 i,l;
|
|
try {
|
|
LockPartition(p);
|
|
// SetDriveType(drive_letter,PT_LT);
|
|
SetDriveType(drive_letter,PT_FAT32);
|
|
p->type=PT_LT;
|
|
br->U1s_per_sector=BLK_SIZE;
|
|
if (p->size<0x2000)
|
|
br->sectors_per_cluster=1;
|
|
else if (p->size<0x20000)
|
|
br->sectors_per_cluster=2;
|
|
else if (p->size<0x200000)
|
|
br->sectors_per_cluster=4;
|
|
else if (p->size<0x2000000)
|
|
br->sectors_per_cluster=8;
|
|
else if (p->size<0x20000000)
|
|
br->sectors_per_cluster=16;
|
|
else
|
|
br->sectors_per_cluster=32;
|
|
|
|
br->signature=PT_LT;
|
|
br->signature2=0xAA55;
|
|
br->sectors=p->size;
|
|
l=br->sectors_per_cluster*(BLK_SIZE<<3);
|
|
l=(br->sectors+l-1)/l;
|
|
br->bitmap_sectors=l;
|
|
br->unique_id=BootTime;
|
|
br->root_cluster=0;
|
|
|
|
if (quick)
|
|
i=l+1;
|
|
else
|
|
i=p->size;
|
|
WZeroBlks(p,p->offset,i,FALSE);
|
|
|
|
WBlks(p,br,p->offset,1,FALSE);
|
|
InitLTPartition(p,FALSE);
|
|
AllocClusters(p,0,1,FALSE,FALSE); //Alloc #1
|
|
br->root_cluster=AllocClusters(p,0,1,FALSE,FALSE);
|
|
WBlks(p,br,p->offset,1,FALSE);
|
|
root_dir=MAllocZ(BLK_SIZE*p->spc);
|
|
|
|
dLT=root_dir-offset(LTDirEntry.start);
|
|
|
|
dLT->attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS;
|
|
dLT->name[0]='.';
|
|
dLT->cluster=br->root_cluster;
|
|
dLT->size=p->spc*BLK_SIZE;
|
|
dLT->expanded_size=dLT->size;
|
|
dLT->datetime=GetCurTimeLTDate;
|
|
|
|
dLT+=LT_DIR_ENTRY_SIZE;
|
|
|
|
dLT->name[0]='.';
|
|
dLT->name[1]='.';
|
|
dLT->attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS;
|
|
dLT->cluster=br->root_cluster;
|
|
dLT->datetime=GetCurTimeLTDate;
|
|
|
|
WBlks(p,root_dir,p->data+br->root_cluster*p->spc,1,FALSE);
|
|
InitLTPartition(p,FALSE);
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
Free(br);
|
|
Free(root_dir);
|
|
}
|
|
|
|
|
|
BoolU4 InitBlkDev(LTBlkDev *bd,BoolU4 unlock)
|
|
{
|
|
LTPartition *p=DriveToPartition(bd->partition_base);
|
|
BoolU4 old_preempt=Preempt(OFF),result=FALSE;
|
|
if (!(bd->flags & LTBDF_INITIALIZED)) {
|
|
bd->flags=bd->flags | LTBDF_INITIALIZED |
|
|
LTBDF_INIT_IN_PROGRESS;
|
|
switch(bd->type) {
|
|
case LTBDT_RAM:
|
|
bd->RAM_disk=AMAllocZ((bd->max_blk+1)*BLK_SIZE);
|
|
p->type=PT_LT;
|
|
//TODO: finish unlock?
|
|
FormatLT(bd->partition_base,FALSE);
|
|
break;
|
|
case LTBDT_FDC:
|
|
if (!monitor_floppy_tss) {
|
|
monitor_floppy_tss=Spawn(&MonitorFDCTsk,"FLOPPY MANAGER");
|
|
monitor_floppy_tss->user_aux0=bd;
|
|
}
|
|
bd->max_reads=1;
|
|
bd->max_writes=1;
|
|
bd->read_freq=750;
|
|
bd->write_freq=150;
|
|
break;
|
|
case LTBDT_ATA:
|
|
bd->max_reads=128;
|
|
bd->max_writes=1;
|
|
bd->read_freq=2000;
|
|
bd->write_freq=500;
|
|
IDEInit(bd,TRUE);
|
|
break;
|
|
case LTBDT_ATAPI:
|
|
bd->max_reads=128;
|
|
bd->max_writes=128;
|
|
bd->read_freq=1000;
|
|
bd->write_freq=250;
|
|
IDEInit(bd,TRUE);
|
|
break;
|
|
case LTBDT_FILE:
|
|
if (bd->flags & LTBDF_FORMAT) {
|
|
//TODO: finish unlock?
|
|
bd->f=FOpen(bd->filename,"wc",p->size);
|
|
if (!bd->f)
|
|
throw(EXCEPT_PARTITION,1);
|
|
//TODO: finish unlock?
|
|
FormatLT(bd->partition_base,TRUE);
|
|
} else {
|
|
bd->f=FOpen(bd->filename,"wc+");
|
|
if (!bd->f)
|
|
throw(EXCEPT_PARTITION,2);
|
|
bd->max_blk=(FSize(bd->f)+BLK_SIZE-1)/BLK_SIZE-1;
|
|
p->size=bd->max_blk+1;
|
|
InitLTPartition(p,unlock);
|
|
}
|
|
break;
|
|
}
|
|
if (bd->flags & LTBDF_READ_CACHE)
|
|
InvalidateDiskCache(p,unlock);
|
|
bd->flags=bd->flags & ~LTBDF_INIT_IN_PROGRESS;
|
|
result=TRUE;
|
|
}
|
|
Preempt(old_preempt);
|
|
return result;
|
|
}
|
|
|
|
BoolU4 RBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt,BoolU4 unlock)
|
|
{
|
|
BoolU4 result=TRUE;
|
|
LTBlkDev *bdev=p->bdev;
|
|
CheckLTPartition(p);
|
|
try {
|
|
LockPartition(p);
|
|
InitBlkDev(bdev,FALSE);
|
|
if ((p->offset && blk<p->offset) || blk+cnt>p->offset+p->size)
|
|
throw(EXCEPT_PARTITION,3);
|
|
blk+=bdev->offset;
|
|
|
|
if (bdev->flags & LTBDF_READ_CACHE)
|
|
RCache(p,&buf,&blk,&cnt);
|
|
if (cnt) {
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(bdev->read_freq);
|
|
disk_status_display.u2[0]=cnt;
|
|
result=p->RBlks(p,buf,blk,cnt);
|
|
bdev->last_jiffy=jiffies;
|
|
disk_status_display.u2[0]=0;
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(0);
|
|
if (bdev->flags & LTBDF_READ_CACHE)
|
|
LTDCAdd(p,buf,blk,cnt);
|
|
}
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
return result;
|
|
}
|
|
|
|
BoolU4 WBlks(LTPartition *p,U1 *buf, U8 blk, U8 cnt,BoolU4 unlock)
|
|
{
|
|
BoolU4 result;
|
|
LTBlkDev *bdev=p->bdev;
|
|
CheckLTPartition(p);
|
|
try {
|
|
LockPartition(p);
|
|
InitBlkDev(bdev,FALSE);
|
|
if ((bdev->flags & LTBDF_READ_ONLY) &&
|
|
!(bdev->flags & LTBDF_READ_ONLY_OVERRIDE))
|
|
throw(EXCEPT_BLKDEV,0);
|
|
if ((p->offset && blk<p->offset) || blk+cnt>p->offset+p->size)
|
|
throw(EXCEPT_PARTITION,4);
|
|
blk+=bdev->offset;
|
|
if (cnt) {
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(bdev->write_freq);
|
|
disk_status_display.u2[0]=cnt+0x8000;
|
|
result=p->WBlks(p,buf,blk,cnt);
|
|
bdev->last_jiffy=jiffies;
|
|
disk_status_display.u2[0]=0;
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(0);
|
|
if (bdev->flags & LTBDF_READ_CACHE)
|
|
LTDCAdd(p,buf,blk,cnt);
|
|
}
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
return result;
|
|
}
|
|
|
|
|
|
void InvalidateDiskCache(LTPartition *p,BoolU4 unlock)
|
|
{
|
|
LTBlkDev *bdev=p->bdev;
|
|
CheckLTPartition(p);
|
|
try {
|
|
LockPartition(p);
|
|
InitBlkDev(bdev,FALSE);
|
|
if (bdev->flags & LTBDF_READ_CACHE)
|
|
LTDCInvalidate(p);
|
|
if (bdev->type==LTBDT_FDC)
|
|
InitLTPartition(p,FALSE);
|
|
else if (p->type==PT_ISO9660) {
|
|
if (!(bdev->flags & LTBDF_READ_ONLY_OVERRIDE))
|
|
InitISOPartition(p,FALSE);
|
|
}
|
|
if(unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
|
|
void ChangeDisk(I1 drive_letter=0)
|
|
{
|
|
LTBlkDev *bdev=DriveToBlkDev(drive_letter);
|
|
if (!InitBlkDev(bdev,TRUE) && bdev->flags & LTBDF_REMOVABLE)
|
|
InvalidateDiskCache(DriveToPartition(drive_letter),TRUE);
|
|
Drive(drive_letter); //TODO: might preempt off
|
|
FreeLTFreeList(DriveToPartition(drive_letter),TRUE);
|
|
}
|
|
|
|
|
|
void PartitionRep()
|
|
{
|
|
I8 i;
|
|
I1 ch;
|
|
U2 u2;
|
|
U1 u1;
|
|
LTPartition *p;
|
|
LTBlkDev *bdev;
|
|
coutln "\r\nDefined Partitions:\r\n";
|
|
for (i=0;i<32;i++) {
|
|
p=local_partitions+sizeof(LTPartition)*i;
|
|
bdev=p->bdev;
|
|
if (p->type) {
|
|
if (p==default_partition)
|
|
cout "*";
|
|
else
|
|
cout " ";
|
|
ch=PartitionToDrive(p);
|
|
cout ch," ";
|
|
if (p->type==PT_LT)
|
|
cout "LT ";
|
|
else if (p->type==PT_FAT12)
|
|
cout "FAT12 ";
|
|
else if (p->type==PT_FAT32)
|
|
cout "FAT32 ";
|
|
else if (p->type==PT_ISO9660)
|
|
cout "ISO9660";
|
|
else
|
|
cout "-------";
|
|
cout " ",SysTextSub(bdev->type,"ST_BLKDEV_TYPES")," ";
|
|
cout p->offset,"-",p->offset+p->size-1," ";
|
|
u2=bdev->base0; cout u2," ";
|
|
u1=bdev->irq; cout u1," ";
|
|
u1=bdev->unit; coutln u1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ReleaseTaskPartitions()
|
|
{
|
|
I8 i;
|
|
LTPartition *p;
|
|
for (i=0;i<32;i++) {
|
|
p=local_partitions+sizeof(LTPartition)*i;
|
|
if (p->owning_task==Fs) {
|
|
UnlockPartition(p,TRUE);
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
U8 AddBlkDev(LTBlkDev *bd)
|
|
{
|
|
I8 i,j,ext_base,num_partition;
|
|
U8 offset;
|
|
MasterBootStruct mbr;
|
|
LTBootStruct br;
|
|
LTPartition *p;
|
|
I1 *drname;
|
|
|
|
bd->ch_L='L';
|
|
bd->ch_B='B';
|
|
bd->ch_D='D';
|
|
num_partition=bd->partition_base-'A';
|
|
p=local_partitions+sizeof(LTPartition)*num_partition;
|
|
MemSet(p,0,sizeof(LTPartition));
|
|
p->drive=num_partition+'A';
|
|
p->ch_L='L';
|
|
p->ch_P='P';
|
|
p->ch_E='E';
|
|
p->bdev=bd;
|
|
p->size=bd->max_blk+1;
|
|
j=(sys_boot_code.u1[1]==0xE0) ? 0:1;
|
|
switch (sys_boot_code.u1[0]) {
|
|
case BOOT_CODE_CDROM:
|
|
if (sys_boot_code.u2[1]==bd->base0 && j==bd->unit)
|
|
boot_blkdev=bd;
|
|
break;
|
|
case BOOT_CODE_HARDDRIVE:
|
|
if (sys_boot_code.u2[1]==bd->base0 && j==bd->unit)
|
|
boot_blkdev=bd;
|
|
break;
|
|
}
|
|
if (boot_blkdev==bd)
|
|
bd->flags|=LTBDF_HAS_BEEN_RESET;
|
|
|
|
switch (bd->type) {
|
|
case LTBDT_FDC:
|
|
p->type=PT_LT;
|
|
p->RBlks=&FDCRBlks;
|
|
p->WBlks=&FDCWBlks;
|
|
num_partition++;
|
|
break;
|
|
case LTBDT_RAM:
|
|
p->type=PT_LT;
|
|
p->RBlks=&RAMRBlks;
|
|
p->WBlks=&RAMWBlks;
|
|
num_partition++;
|
|
break;
|
|
case LTBDT_ATA:
|
|
InitBlkDev(bd,TRUE);
|
|
offset=0;
|
|
ext_base=INVALID_CLUSTER;
|
|
while (TRUE) {
|
|
ATAReadBlks(bd,&mbr,offset,1);
|
|
j=-1;
|
|
for (i=0;i<4;i++) {
|
|
if (mbr.p[i].type!=0) {
|
|
p=local_partitions+sizeof(LTPartition)*num_partition;
|
|
MemSet(p,0,sizeof(LTPartition));
|
|
p->drive=num_partition+'A';
|
|
p->ch_L='L';
|
|
p->ch_P='P';
|
|
p->ch_E='E';
|
|
p->bdev=bd;
|
|
p->RBlks=&IDERBlks;
|
|
p->WBlks=&IDEWBlks;
|
|
p->offset=mbr.p[i].offset+offset;
|
|
p->size =mbr.p[i].size;
|
|
p->type =mbr.p[i].type;
|
|
if (p->type==PT_LT)
|
|
InitLTPartition(p,TRUE);
|
|
else {
|
|
if (p->type==PT_FAT32+1) p->type=PT_FAT32;
|
|
if (p->type==PT_FAT32) {
|
|
ATAReadBlks(bd,&br,p->offset,1);
|
|
if (br.signature==PT_LT)
|
|
InitLTPartition(p,TRUE);
|
|
}
|
|
}
|
|
if (p->type==5 || p->type==0xF)
|
|
j=i;
|
|
else
|
|
num_partition++;
|
|
}
|
|
}
|
|
if (j<0)
|
|
break;
|
|
if (mbr.p[j].offset==0)
|
|
break;
|
|
if (ext_base==INVALID_CLUSTER) {
|
|
offset=mbr.p[j].offset;
|
|
ext_base=offset;
|
|
} else
|
|
offset=mbr.p[j].offset+ext_base;
|
|
}
|
|
break;
|
|
case LTBDT_ATAPI:
|
|
p->type=PT_ISO9660;
|
|
p->RBlks=&IDERBlks;
|
|
p->WBlks=&IDEWBlks;
|
|
p->size =CD_FILE_OFFSET;
|
|
num_partition++;
|
|
break;
|
|
case LTBDT_FILE:
|
|
drname=ChangeExtension(bd->filename,"DVC");
|
|
bd->filename=ANewString(drname);
|
|
Free(drname);
|
|
p->type=PT_LT;
|
|
p->RBlks=&FileRBlks;
|
|
p->WBlks=&FileWBlks;
|
|
num_partition++;
|
|
break;
|
|
}
|
|
return num_partition-(bd->partition_base-'A');
|
|
}
|
|
|
|
|
|
void AddDrives(BoolU4 show_rep=TRUE)
|
|
{
|
|
LTBlkDev *bd;
|
|
I8 base_partition,i,j,k;
|
|
I1 buf[32],buf2[128];
|
|
BoolU4 format;
|
|
do {
|
|
if (show_rep)
|
|
PartitionRep;
|
|
show_rep=TRUE;
|
|
PutSysText("ST_ADDDRIVES1");
|
|
base_partition=ToUpper(SysGetChar)-'A';
|
|
CrLf;
|
|
if (base_partition>=0 && base_partition<32) {
|
|
|
|
PutSysText("ST_ADDDRIVES2");
|
|
i=SysGetChar-'0';
|
|
CrLf;
|
|
|
|
j=1;k=0;
|
|
if (i==5) {
|
|
PutSysText("ST_ADDDRIVES3");
|
|
GetS(buf2,128);
|
|
PutSysText("ST_ADDDRIVES4");
|
|
format=YorN;
|
|
*buf=0;
|
|
}
|
|
if (i==1 || i==5 && format) {
|
|
PutSysText("ST_ADDDRIVES5");
|
|
GetS(buf,32);
|
|
} else if (i!=5) {
|
|
PutSysText("ST_ADDDRIVES10");
|
|
j=SysGetChar-'0';
|
|
CrLf;
|
|
|
|
PutSysText("ST_ADDDRIVES7");
|
|
k=SysGetChar-'0';
|
|
CrLf;
|
|
}
|
|
|
|
if (i>0 && i<=5 && j>0 && j<=4 && k>=0 && k<=1) {
|
|
bd=local_blkdevs+sizeof(LTBlkDev)*(num_blkdevs++);
|
|
bd->partition_base=base_partition+'A';
|
|
|
|
bd->type=i;
|
|
if (i==2 || i==4)
|
|
bd->flags=LTBDF_REMOVABLE;
|
|
else
|
|
bd->flags=0;
|
|
if (i!=1)
|
|
bd->flags|=LTBDF_READ_CACHE;
|
|
|
|
if (i==4) {
|
|
bd->blk_size=CD_BLK_SIZE;
|
|
bd->flags|=LTBDF_READ_ONLY;
|
|
} else
|
|
bd->blk_size=BLK_SIZE;
|
|
if (i==1 || i==5 && format) {
|
|
bd->max_blk=AtoI(buf)-1;
|
|
if (bd->max_blk<FDC_MAX_SECTOR)
|
|
bd->max_blk=FDC_MAX_SECTOR;
|
|
} else if (i==2)
|
|
bd->max_blk=FDC_MAX_SECTOR;
|
|
else
|
|
bd->max_blk=0xEFFFFFFF;
|
|
if (j==2) {
|
|
bd->base0=0x3F0;
|
|
bd->irq=6;
|
|
} else if (j==3) {
|
|
bd->base0=0x1F0;
|
|
bd->base1=0x3F6;
|
|
bd->irq=14;
|
|
} else if (j==4) {
|
|
bd->base0=0x170;
|
|
bd->base1=0x376;
|
|
bd->irq=15;
|
|
}
|
|
if (i==5) {
|
|
bd->filename=ANewString(buf2);
|
|
if (format)
|
|
bd->flags=bd->flags|LTBDF_FORMAT;
|
|
}
|
|
bd->unit=k;
|
|
if (!AddBlkDev(bd))
|
|
PutSysText("ST_FAILED");
|
|
} else
|
|
PutSysText("ST_FAILED");
|
|
}
|
|
} while (base_partition>=0 && base_partition<32);
|
|
}
|
|
|
|
void SetPromptedBaseUnit(LTBlkDev *bd)
|
|
{
|
|
if (sys_boot_code.u1[1]==0xE0)
|
|
bd->unit=0;
|
|
else
|
|
bd->unit=1;
|
|
if (sys_boot_code.u2[1]==0x1F0) {
|
|
bd->base0=0x1F0;
|
|
bd->base1=0x3F6;
|
|
bd->irq=14;
|
|
} else {
|
|
bd->base0=0x170;
|
|
bd->base1=0x376;
|
|
bd->irq=15;
|
|
}
|
|
}
|
|
|
|
void InitAllBlkDevs()
|
|
{
|
|
LTBlkDev *bd;
|
|
I8 i;
|
|
|
|
num_blkdevs=0;
|
|
boot_blkdev=NULL;
|
|
local_blkdevs=AMAllocZ(sizeof(LTBlkDev)<<4);
|
|
|
|
monitor_floppy_tss=NULL;
|
|
FDC_retries=2;
|
|
FDC_DRIVE_HEADS=2;
|
|
FDC_DISK_CYLINDERS=80;
|
|
FDC_DISK_SECTORS=18;
|
|
FDC_MAX_SECTOR=FDC_DRIVE_HEADS*FDC_DISK_CYLINDERS*FDC_DISK_SECTORS-1;
|
|
FDC_DMA_BUF=0xD000;
|
|
ext[EXT_IRQ06]=&Irq06Handler;
|
|
|
|
ext[EXT_IRQ0E]=&Irq0EHandler;
|
|
ext[EXT_IRQ0F]=&Irq0FHandler;
|
|
|
|
local_partitions=AMAllocZ(sizeof(LTPartition)<<5);
|
|
for (i=0;i<32;i++)
|
|
drive_to_partition[i]=local_partitions+sizeof(LTPartition)*i;
|
|
dc_col=0;
|
|
|
|
exe {
|
|
I8 base_partition,i,j,k,l,num=0;
|
|
I1 buf[32],buf2[128];
|
|
BoolU4 format;
|
|
PutSysText("ST_ADDDRIVES0");
|
|
do {
|
|
PutSysText("ST_ADDDRIVES1");
|
|
base_partition=ToUpper(GetChar)-'A';
|
|
CrLf;
|
|
if (base_partition>=0 && base_partition<32) {
|
|
PutSysText("ST_ADDDRIVES2");
|
|
i=GetChar-'0';
|
|
CrLf;
|
|
|
|
j=1;k=0;
|
|
if (i==5) {
|
|
PutSysText("ST_ADDDRIVES3");
|
|
GetS(buf2,128);
|
|
PutSysText("ST_ADDDRIVES4");
|
|
format=YorN;
|
|
*buf=0;
|
|
}
|
|
if (i==1 || i==5 && format) {
|
|
PutSysText("ST_ADDDRIVES5");
|
|
GetS(buf,32);
|
|
} else if (i!=5) {
|
|
PutSysText("ST_ADDDRIVES6");
|
|
j=GetChar-'0';
|
|
CrLf;
|
|
|
|
if (j!=5) {
|
|
PutSysText("ST_ADDDRIVES7");
|
|
k=GetChar-'0';
|
|
CrLf;
|
|
} else {
|
|
if (i!=4) {
|
|
PutSysText("ST_ADDDRIVES9");
|
|
j=0; //force error
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i>0 && i<=5 && j>0 && j<=5 && k>=0 && k<=1) {
|
|
ExePrintF("bd=local_blkdevs+sizeof(LTBlkDev)*(num_blkdevs++);");
|
|
ExePrintF("bd->partition_base=%d;",
|
|
base_partition+'A');
|
|
|
|
ExePrintF("bd->type=%d;",i);
|
|
if (i==2 || i==4)
|
|
ExePrintF("bd->flags=LTBDF_REMOVABLE;");
|
|
else
|
|
ExePrintF("bd->flags=0;");
|
|
if (i!=1)
|
|
ExePrintF("bd->flags=bd->flags|LTBDF_READ_CACHE;");
|
|
|
|
if (i==4) {
|
|
ExePrintF("bd->blk_size=CD_BLK_SIZE;");
|
|
ExePrintF("bd->flags=bd->flags | LTBDF_READ_ONLY;");
|
|
} else
|
|
ExePrintF("bd->blk_size=BLK_SIZE;");
|
|
if (i==1 || i==5 && format) {
|
|
l=AtoI(buf)-1;
|
|
if (l<FDC_MAX_SECTOR)
|
|
l=FDC_MAX_SECTOR;
|
|
ExePrintF("bd->max_blk=%d;",l);
|
|
} else if (i==2)
|
|
ExePrintF("bd->max_blk=FDC_MAX_SECTOR;");
|
|
else
|
|
ExePrintF("bd->max_blk=0xEFFFFFFF;");
|
|
|
|
ExePrintF("bd->unit=%d;",k);
|
|
|
|
if (j==2)
|
|
ExePrintF("bd->base0=0x3F0;bd->irq=6;");
|
|
else if (j==3)
|
|
ExePrintF("bd->base0=0x1F0;bd->base1=0x3F6;bd->irq=14;");
|
|
else if (j==4)
|
|
ExePrintF("bd->base0=0x170;bd->base1=0x376;bd->irq=15;");
|
|
else if (j==5)
|
|
ExePrintF("SetPromptedBaseUnit(bd);");
|
|
|
|
if (i==5) {
|
|
ExePrintF("bd->filename=ANewString(\"%s\");",buf2);
|
|
if (format)
|
|
ExePrintF("bd->flags=bd->flags|LTBDF_FORMAT;");
|
|
}
|
|
ExePrintF("AddBlkDev(bd);");
|
|
num++;
|
|
} else
|
|
PutSysText("ST_FAILED");
|
|
}
|
|
} while (num==0 || base_partition>=0 && base_partition<32);
|
|
cout "\r\nDefault Drive Letter for phase 2 of boot. "
|
|
"Usually it's the same as phase 1. "
|
|
"(hitting SPACE will prompt at boot): ";
|
|
i=GetChar;
|
|
if (i==13) {
|
|
i=Fs->user_aux1; //set by bootins
|
|
PrintF("Using Drive '%c'",i);
|
|
}
|
|
CrLf;
|
|
if (i!=CH_SPACE)
|
|
i=ToUpper(i);
|
|
if (i<'A' || i>'Z') {
|
|
i=0;
|
|
coutln "Drive will be prompted.";
|
|
}
|
|
ExePrintF("default_drive=%d;",i);
|
|
}
|
|
PartitionRep;
|
|
}
|
|
|
|
|
|
U8 NextClusterNum(LTPartition *p,U8 c,U8 cnt,BoolU4 unlock)
|
|
{
|
|
CheckLTPartition(p);
|
|
if (!cnt || !c) return c;
|
|
try {
|
|
LockPartition(p);
|
|
if (p->type==PT_ISO9660 || p->type==PT_LT)
|
|
c+=cnt;
|
|
else
|
|
c=INVALID_CLUSTER;
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
return c;
|
|
}
|
|
|
|
|
|
U8 ClusterBlk(LTPartition *p,U8 c)
|
|
{
|
|
CheckLTPartition(p);
|
|
return p->data+c*p->spc;
|
|
}
|
|
|
|
U8 RClusters(LTPartition *p,U1 *buf,U8 c,U8 cnt,BoolU4 unlock,BoolU4 update_display=FALSE)
|
|
{
|
|
CheckLTPartition(p);
|
|
if (!cnt) return c;
|
|
try {
|
|
LockPartition(p);
|
|
if (p->type==PT_ISO9660 || p->type==PT_LT) {
|
|
RBlks(p,buf,p->data+c*p->spc,p->spc*cnt,FALSE);
|
|
c+=cnt;
|
|
} else {
|
|
while (cnt && c && c!=INVALID_CLUSTER) {
|
|
RBlks(p,buf,p->data+c*p->spc,p->spc,FALSE);
|
|
buf+=p->spc*BLK_SIZE;
|
|
c=NextClusterNum(p,c,1,FALSE);
|
|
cnt--;
|
|
if (update_display)
|
|
disk_status_display.u2[1]--;
|
|
}
|
|
if (cnt)
|
|
UnrecoverableSysError(0x0FFF0001);
|
|
}
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
return c;
|
|
}
|
|
|
|
BoolU4 ToLTFilename(I1 *dst,I1 *src)
|
|
{
|
|
MemSet(dst,0,LT_MAX_FILENAME_LEN+1);
|
|
if (!CheckFileName(src))
|
|
return FALSE;
|
|
StrCpy(dst,src);
|
|
return TRUE;
|
|
}
|
|
|
|
BoolU4 FromISOName(I1 *dst,U1 *src)
|
|
{
|
|
BoolU4 result=TRUE;
|
|
I8 i,j,l;
|
|
MemSet(dst,0,LT_MAX_FILENAME_LEN+1);
|
|
l=*src++;
|
|
if (l==1 && !*src) {
|
|
dst[0]='.';
|
|
} else if (l==1 && *src==1) {
|
|
dst[0]='.';
|
|
dst[1]='.';
|
|
} else {
|
|
l/=2;
|
|
j=0;
|
|
for (i=0;i<l;i++) {
|
|
src++;
|
|
if (*src==';')
|
|
break;
|
|
if (Bt(filename_chars_bitmap,*src)) {
|
|
if (j>=LT_MAX_FILENAME_LEN)
|
|
return FALSE;
|
|
dst[j++]=*src++;
|
|
} else
|
|
return FALSE;
|
|
}
|
|
}
|
|
return CheckFileName(dst);
|
|
}
|
|
|
|
BoolU4 FillLTDirISO(LTPartition *p,LTDirEntry *tempm,ISODirEntry *de,BoolU4 unlock)
|
|
{
|
|
ArcCompressStruct *buf;
|
|
BoolU4 result;
|
|
MemSet(tempm,0,sizeof(LTDirEntry));
|
|
result=FromISOName(tempm->name,&de->name_len);
|
|
tempm->cluster=de->location.little;
|
|
tempm->size=de->size.little;
|
|
tempm->attr=FileAttr(tempm->name);
|
|
if (de->flags & ISO_ATTR_DIR)
|
|
tempm->attr|=LT_ATTR_DIR;
|
|
tempm->datetime=ISOToLTDate(&de->date);
|
|
if (tempm->attr & LT_ATTR_COMPRESSED) {
|
|
buf=MAlloc(BLK_SIZE*p->spc);
|
|
RClusters(p,buf,tempm->cluster,1,unlock);
|
|
tempm->expanded_size=buf->expanded_size;
|
|
Free(buf);
|
|
} else
|
|
tempm->expanded_size=tempm->size;
|
|
return result;
|
|
}
|
|
|
|
|
|
BoolU4 FindLTFile(LTPartition *p,U8 cur_dir_cluster,I1 *name,LTDirEntry *result,
|
|
BoolU4 dir_only,BoolU4 file_only,BoolU4 unlock)
|
|
{
|
|
BoolU4 res=FALSE;
|
|
LTDirEntry *buf,*buf2,*ptr;
|
|
I1 dname[LT_MAX_FILENAME_LEN+1];
|
|
U8 cnt;
|
|
BoolU4 cont2=FALSE;
|
|
U1 ch;
|
|
|
|
MemSet(result,0,sizeof(LTDirEntry));
|
|
CheckLTPartition(p);
|
|
if (p->type!=PT_LT)
|
|
PutSysText("ST_NOT_LT");
|
|
else if (!ToLTFilename(dname,name))
|
|
PutSysText("ST_INVALID_FILENAME");
|
|
else {
|
|
try {
|
|
LockPartition(p);
|
|
buf2=MAlloc(BLK_SIZE*p->spc);
|
|
RClusters(p,buf2,cur_dir_cluster,1,FALSE);
|
|
|
|
ptr=buf2-offset(LTDirEntry.start);
|
|
buf=MAlloc(ptr->size);
|
|
RClusters(p,buf,cur_dir_cluster,ptr->size/BLK_SIZE/p->spc,FALSE);
|
|
Free(buf2);
|
|
|
|
ptr=buf-offset(LTDirEntry.start);
|
|
cnt=ptr->size/LT_DIR_ENTRY_SIZE;
|
|
ptr->name[0]='.';
|
|
ptr->name[1]=0;
|
|
while (cnt--) {
|
|
ch=ptr->name[0];
|
|
if (!ch)
|
|
break;
|
|
else if (!(ptr->attr & LT_ATTR_DELETED)) {
|
|
if (dir_only && !(ptr->attr & LT_ATTR_DIR))
|
|
cont2=FALSE;
|
|
else if (file_only && ptr->attr & LT_ATTR_DIR)
|
|
cont2=FALSE;
|
|
else
|
|
cont2=TRUE;
|
|
if (cont2 && !StrCmp(dname,ptr->name)) {
|
|
MemCpy(&result->attr,&ptr->attr,LT_DIR_ENTRY_SIZE);
|
|
res=TRUE;
|
|
goto exit_this;
|
|
}
|
|
}
|
|
ptr+=LT_DIR_ENTRY_SIZE;
|
|
}
|
|
exit_this:
|
|
Free(buf);
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
BoolU4 FindISOFile(LTPartition *p,U8 cur_dir_cluster,I1 *name,LTDirEntry *result,
|
|
BoolU4 dir_only,BoolU4 file_only,BoolU4 unlock)
|
|
{
|
|
ISODirEntry *isoptr,*buf;
|
|
I1 dname[LT_MAX_FILENAME_LEN+1];
|
|
BoolU4 res=FALSE;
|
|
I8 i;
|
|
|
|
CheckLTPartition(p);
|
|
if (p->type!=PT_ISO9660)
|
|
PutSysText("ST_NOT_ISO9660");
|
|
else {
|
|
try {
|
|
LockPartition(p);
|
|
isoptr=MAlloc(BLK_SIZE*p->spc);
|
|
RClusters(Fs->cur_partition,isoptr,cur_dir_cluster,1,FALSE);
|
|
if (isoptr->name_len==1 && isoptr->name==0) { //curdir
|
|
i=(isoptr->size.little+BLK_SIZE*p->spc-1)/(BLK_SIZE*p->spc);
|
|
buf=MAlloc(BLK_SIZE*p->spc*i);
|
|
RClusters(Fs->cur_partition,buf,cur_dir_cluster,i,FALSE);
|
|
Free(isoptr);
|
|
} else {
|
|
buf=isoptr;
|
|
i=1;
|
|
}
|
|
i*=BLK_SIZE*p->spc;
|
|
isoptr=buf;
|
|
while (i>0) {
|
|
if (!isoptr->length) {
|
|
isoptr++;
|
|
i--;
|
|
} else {
|
|
FromISOName(dname,&isoptr->name_len);
|
|
if (*dname) {
|
|
if (!StrCmp(name,dname)) {
|
|
res=FillLTDirISO(p,result,isoptr,FALSE);
|
|
if (res &&
|
|
!(dir_only && !(result->attr & LT_ATTR_DIR)) &&
|
|
!(file_only && result->attr & LT_ATTR_DIR) )
|
|
goto exit_this;
|
|
else
|
|
res=FALSE;
|
|
}
|
|
}
|
|
i-=isoptr->length;
|
|
isoptr+=isoptr->length;
|
|
}
|
|
}
|
|
exit_this:
|
|
Free(buf);
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
U8 NameToDirCluster(LTPartition *p,I1 *name,BoolU4 unlock)
|
|
{
|
|
BoolU4 cont=TRUE;
|
|
U8 cur_dir_cluster;
|
|
LTDirEntry de;
|
|
I1 *buf=NewString(name),*buf2=NewString(name);
|
|
CheckLTPartition(p);
|
|
try {
|
|
LockPartition(p);
|
|
cur_dir_cluster=p->root_cluster;
|
|
while (*buf && cont) {
|
|
RemoveFirstSeg(buf,"/",buf2);
|
|
if (*buf2) {
|
|
if (p->type==PT_LT)
|
|
cont=FindLTFile(p,cur_dir_cluster,
|
|
buf2,&de,TRUE,FALSE,FALSE);
|
|
else if (p->type==PT_ISO9660)
|
|
cont=FindISOFile(p,cur_dir_cluster,
|
|
buf2,&de,TRUE,FALSE,FALSE);
|
|
else cont=FALSE;
|
|
cur_dir_cluster=de.cluster;
|
|
}
|
|
}
|
|
if (!cont) {
|
|
cout name," ",SysText("ST_FILE_NOT_FOUND");
|
|
cur_dir_cluster=0;
|
|
}
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
Free(buf);
|
|
Free(buf2);
|
|
return cur_dir_cluster;
|
|
}
|
|
|
|
U8 NameToParentDirCluster(LTPartition *p,I1 *name,BoolU4 unlock)
|
|
{
|
|
BoolU4 cont=TRUE;
|
|
U8 cur_dir_cluster,cur_dir_cluster2;
|
|
LTDirEntry de;
|
|
I1 *buf=NewString(name),*buf2=NewString(name);
|
|
CheckLTPartition(p);
|
|
try {
|
|
LockPartition(p);
|
|
cur_dir_cluster=p->root_cluster;
|
|
cur_dir_cluster2=p->root_cluster;
|
|
while (*buf && cont) {
|
|
cur_dir_cluster2=cur_dir_cluster;
|
|
RemoveFirstSeg(buf,"/",buf2);
|
|
if (*buf2) {
|
|
if (p->type==PT_LT)
|
|
cont=FindLTFile(p,cur_dir_cluster,
|
|
buf2,&de,TRUE,FALSE,FALSE);
|
|
else if (p->type==PT_ISO9660)
|
|
cont=FindISOFile(p,cur_dir_cluster,
|
|
buf2,&de,TRUE,FALSE,FALSE);
|
|
else cont=FALSE;
|
|
cur_dir_cluster=de.cluster;
|
|
}
|
|
}
|
|
if (!cont) {
|
|
cout name," ",SysText("ST_FILE_NOT_FOUND");
|
|
cur_dir_cluster2=0;
|
|
}
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
Free(buf);
|
|
Free(buf2);
|
|
return cur_dir_cluster2;
|
|
}
|
|
|
|
|
|
U1 *ReadISOFile(LTPartition *p,I1 *cur_dir,I1 *filename,U8 *size,
|
|
U8 *attr,BoolU4 raw,ArcCompressStruct **ac2)
|
|
{
|
|
U1 *buf=NULL;
|
|
LTDirEntry de;
|
|
U8 c,cluster_size=BLK_SIZE*p->spc,cluster_cnt;
|
|
ArcCompressStruct *ac;
|
|
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,TRUE);
|
|
|
|
CheckLTPartition(p);
|
|
if (size)
|
|
*size=0;
|
|
if (ac2)
|
|
*ac2=NULL;
|
|
if (attr)
|
|
*attr=0;
|
|
if (p->type!=PT_ISO9660)
|
|
PutSysText("ST_NOT_ISO9660");
|
|
else {
|
|
try {
|
|
LockPartition(p);
|
|
if (FindISOFile(p,cur_dir_cluster,filename,&de,FALSE,TRUE,FALSE)) {
|
|
if (attr)
|
|
*attr=de.attr;
|
|
cluster_cnt=(de.size+cluster_size-1)/cluster_size;
|
|
buf=MAlloc(cluster_cnt*cluster_size+1);
|
|
c=de.cluster;
|
|
disk_status_display.u2[1]=cluster_cnt;
|
|
c=RClusters(p,buf,c,cluster_cnt,FALSE,TRUE);
|
|
disk_status_display.u2[1]=0;
|
|
if ((FileAttr(de.name) & LT_ATTR_COMPRESSED) && !raw) {
|
|
ac=buf;
|
|
if (attr)
|
|
*attr=FileAttr(de.name,*attr);
|
|
if (size)
|
|
*size=ac->expanded_size;
|
|
if (ac2) {
|
|
*ac2=ac;
|
|
buf=ExpandBuf(ac);
|
|
} else {
|
|
buf=ExpandBuf(ac);
|
|
Free(ac);
|
|
}
|
|
} else {
|
|
buf[de.size]=0; //Terminate
|
|
if (size)
|
|
*size=de.size;
|
|
}
|
|
if (attr)
|
|
*attr=FileAttr(de.name,*attr);
|
|
}
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
|
|
|
|
U1 *ReadLTFile(LTPartition *p,I1 *cur_dir,I1 *filename,U8 *size,
|
|
U8 *attr,BoolU4 raw,ArcCompressStruct **ac2)
|
|
{
|
|
U1 *buf=NULL;
|
|
LTDirEntry de;
|
|
U8 c,cluster_size=BLK_SIZE*p->spc,cluster_cnt;
|
|
ArcCompressStruct *ac;
|
|
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,TRUE);
|
|
|
|
CheckLTPartition(p);
|
|
if (size)
|
|
*size=0;
|
|
if (ac2)
|
|
*ac2=NULL;
|
|
if (attr)
|
|
*attr=0;
|
|
if (p->type!=PT_LT)
|
|
PutSysText("ST_NOT_ISO9660");
|
|
else {
|
|
try {
|
|
LockPartition(p);
|
|
if (FindLTFile(p,cur_dir_cluster,filename,&de,FALSE,TRUE,FALSE)) {
|
|
if (attr)
|
|
*attr=de.attr;
|
|
cluster_cnt=(de.size+cluster_size-1)/cluster_size;
|
|
buf=MAlloc(cluster_cnt*cluster_size+1);
|
|
c=de.cluster;
|
|
disk_status_display.u2[1]=cluster_cnt;
|
|
c=RClusters(p,buf,c,cluster_cnt,FALSE,TRUE);
|
|
disk_status_display.u2[1]=0;
|
|
if (de.xsum) {
|
|
if ((de.xsum^ArcCheckSum(buf,de.size))!=LT_XSUM)
|
|
throw(EXCEPT_ARC_XSUM);
|
|
}
|
|
if ((FileAttr(de.name) & LT_ATTR_COMPRESSED) && !raw) {
|
|
ac=buf;
|
|
if (attr)
|
|
*attr=FileAttr(de.name,*attr);
|
|
if (size)
|
|
*size=ac->expanded_size;
|
|
if (ac2) {
|
|
*ac2=ac;
|
|
buf=ExpandBuf(ac);
|
|
} else {
|
|
buf=ExpandBuf(ac);
|
|
Free(ac);
|
|
}
|
|
} else {
|
|
buf[de.size]=0; //Terminate
|
|
if (size)
|
|
*size=de.size;
|
|
}
|
|
if (attr)
|
|
*attr=FileAttr(de.name,*attr);
|
|
}
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
BoolU4 CdLT(I1 *name,U8 cur_dir_cluster)
|
|
{
|
|
LTDirEntry de;
|
|
if (Fs->cur_partition->type!=PT_LT)
|
|
PutSysText("ST_NOT_LT");
|
|
else {
|
|
if (FindLTFile(Fs->cur_partition,cur_dir_cluster,
|
|
name,&de,TRUE,FALSE,TRUE)) {
|
|
return TRUE;
|
|
} else
|
|
cout name," ",SysText("ST_FILE_NOT_FOUND");
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BoolU4 CdISO(I1 *name,U8 cur_dir_cluster)
|
|
{
|
|
LTDirEntry de;
|
|
if (Fs->cur_partition->type!=PT_ISO9660)
|
|
PutSysText("ST_NOT_ISO9660");
|
|
else {
|
|
if (FindISOFile(Fs->cur_partition,cur_dir_cluster,
|
|
name,&de,TRUE,FALSE,TRUE)) {
|
|
return TRUE;
|
|
} else
|
|
cout name," ",SysText("ST_FILE_NOT_FOUND");
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
U8 WClusters(LTPartition *p,U1 *buf,U8 c,U8 cnt,BoolU4 unlock,BoolU4 update_display=FALSE)
|
|
{
|
|
CheckLTPartition(p);
|
|
update_display;
|
|
try {
|
|
LockPartition(p);
|
|
if (p->type==PT_LT) {
|
|
WBlks(p,buf,p->data+c*p->spc,p->spc*cnt,FALSE);
|
|
c=0;
|
|
}
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
return c;
|
|
}
|
|
|
|
void FreeLTClusters(LTPartition *p,U8 c,U8 cnt,BoolU4 unlock)
|
|
{
|
|
LTFreeList *tempf;
|
|
BoolU4 found=FALSE;
|
|
CheckLTPartition(p);
|
|
if (!c) return;
|
|
if (p->type!=PT_LT)
|
|
PutSysText("ST_NOT_LT");
|
|
else {
|
|
try {
|
|
LockPartition(p);
|
|
if (!p->next_free)
|
|
BuildLTFreeList(p,FALSE);
|
|
tempf=p->next_free;
|
|
while (!found && tempf!=&p->next_free) {
|
|
if (tempf->start+tempf->size==c) {
|
|
tempf->size+=cnt;
|
|
found=TRUE;
|
|
} else if (c+cnt==tempf->start) {
|
|
tempf->size+=cnt;
|
|
tempf->start=c;
|
|
found=TRUE;
|
|
}
|
|
tempf=tempf->next;
|
|
}
|
|
if (!found) {
|
|
tempf=AMAlloc(sizeof(LTFreeList));
|
|
tempf->size=cnt;
|
|
tempf->start=c;
|
|
InsQue(tempf,p->last_free);
|
|
}
|
|
while (cnt--) {
|
|
SetLTBuf(p,c);
|
|
Btr(p->cur_MAP_blk,c&(BLK_SIZE<<3-1));
|
|
Bts(p->buffered_MAP_dirty_bits,0);
|
|
c++;
|
|
}
|
|
CleanMAPBuf(p);
|
|
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
}
|
|
}
|
|
|
|
U8 AllocLTClusters(LTPartition *p,U8 cnt, BoolU4 unlock)
|
|
{
|
|
LTFreeList *tempf,*best_free=NULL;
|
|
U8 i,first,best_size=MAX_U8;
|
|
if (!cnt)
|
|
UnrecoverableSysError(0x0FFF0003);
|
|
try {
|
|
LockPartition(p);
|
|
if (!p->next_free)
|
|
BuildLTFreeList(p,FALSE);
|
|
tempf=p->next_free;
|
|
while (tempf!=&p->next_free) {
|
|
if (tempf->size>=cnt && tempf->size<best_size) {
|
|
best_free=tempf;
|
|
best_size=tempf->size;
|
|
}
|
|
tempf=tempf->next;
|
|
}
|
|
if (!best_free)
|
|
UnrecoverableSysError(0x0FFF0003);
|
|
first=best_free->start;
|
|
for (i=0;i<cnt;i++) {
|
|
SetLTBuf(p,first+i);
|
|
Bts(p->cur_MAP_blk,(first+i)&(BLK_SIZE<<3-1));
|
|
Bts(p->buffered_MAP_dirty_bits,0);
|
|
}
|
|
CleanMAPBuf(p);
|
|
if (best_free->size-=cnt)
|
|
best_free->start+=cnt;
|
|
else {
|
|
RemQue(best_free);
|
|
AFree(best_free);
|
|
}
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
return first;
|
|
}
|
|
|
|
//c=0 means first cluster in chain
|
|
U8 AllocClusters(LTPartition *p,U8 c,U8 cnt,BoolU4 contiguous,BoolU4 unlock)
|
|
{
|
|
contiguous; //no unused var warn
|
|
if (!cnt)
|
|
return c;
|
|
CheckLTPartition(p);
|
|
if (p->type==PT_LT)
|
|
return AllocLTClusters(p,cnt,unlock);
|
|
}
|
|
|
|
|
|
BoolU4 NewLTDirEntry2(LTPartition *p,I1 *cur_dir,LTDirEntry *de,BoolU4 free_old_chain,BoolU4 unlock)
|
|
{
|
|
LTDirEntry *buf,*buf2,*ptr,de2;
|
|
LTBootStruct *br;
|
|
U8 c,i=1,j=0,l=BLK_SIZE/LT_DIR_ENTRY_SIZE,cnt,dir_size;
|
|
BoolU4 written=FALSE;
|
|
U1 ch;
|
|
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,unlock);
|
|
I1 *temp,*parent_dir;
|
|
try {
|
|
de->attr|=LT_ATTR_CONTIGUOUS;
|
|
LockPartition(p);
|
|
buf2=MAlloc(BLK_SIZE*p->spc);
|
|
RClusters(p,buf2,cur_dir_cluster,1,FALSE);
|
|
|
|
ptr=buf2-offset(LTDirEntry.start);
|
|
buf=MAlloc(ptr->size);
|
|
RClusters(p,buf,cur_dir_cluster,ptr->size/BLK_SIZE/p->spc,FALSE);
|
|
|
|
dir_size=ptr->size;
|
|
cnt=ptr->size/LT_DIR_ENTRY_SIZE;
|
|
ptr=buf-offset(LTDirEntry.start)+LT_DIR_ENTRY_SIZE;
|
|
Free(buf2);
|
|
while (cnt--) {
|
|
ch=ptr->name[0];
|
|
if (!ch) {
|
|
if (written) break;
|
|
MemCpy(&ptr->start,&de->start,LT_DIR_ENTRY_SIZE);
|
|
if ((i+1)*LT_DIR_ENTRY_SIZE+j*BLK_SIZE<dir_size)
|
|
WBlks(p,buf+j*BLK_SIZE,
|
|
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
|
|
else {
|
|
buf2=MAllocZ(dir_size+p->spc*BLK_SIZE);
|
|
MemCpy(buf2,buf,dir_size);
|
|
FreeLTClusters(p,cur_dir_cluster,
|
|
dir_size/(p->spc*BLK_SIZE),FALSE);
|
|
dir_size+=p->spc*BLK_SIZE;
|
|
c=AllocClusters(p,0,dir_size/(p->spc*BLK_SIZE),TRUE,FALSE);
|
|
Free(buf);
|
|
buf=buf2;
|
|
ptr=buf-offset(LTDirEntry.start);
|
|
ptr->size=dir_size;
|
|
ptr->expanded_size=dir_size;
|
|
ptr->cluster=c;
|
|
WClusters(p,buf,c,dir_size/(p->spc*BLK_SIZE),FALSE);
|
|
if (cur_dir_cluster==p->root_cluster) {
|
|
br=MAllocZ(BLK_SIZE);
|
|
RBlks(p,br,p->offset,1,FALSE);
|
|
br->root_cluster=c;
|
|
WBlks(p,br,p->offset,1,FALSE);
|
|
Free(br);
|
|
p->root_cluster=c;
|
|
} else {
|
|
temp=NewString(cur_dir);
|
|
parent_dir=NewString(cur_dir);
|
|
RemoveLastSeg(parent_dir,"/",temp);
|
|
if (!*parent_dir) StrCpy(parent_dir,"/");
|
|
if (FindLTFile(p,NameToDirCluster(p,parent_dir,FALSE),
|
|
ptr->name,&de2,TRUE,FALSE,FALSE)) {
|
|
de2.cluster=c;
|
|
de2.size=dir_size;
|
|
de2.expanded_size=dir_size;
|
|
//TODO: is this supposed to free old chain?
|
|
NewLTDirEntry2(p,parent_dir,&de2,FALSE,FALSE);
|
|
} else
|
|
UnrecoverableSysError(0x0FFF0006);
|
|
Free(temp);
|
|
Free(parent_dir);
|
|
}
|
|
}
|
|
break;
|
|
} else if (ptr->attr & LT_ATTR_DELETED) {
|
|
if (!written) {
|
|
MemCpy(&ptr->start,&de->start,LT_DIR_ENTRY_SIZE);
|
|
WBlks(p,buf+j*BLK_SIZE,
|
|
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
|
|
written=TRUE;
|
|
}
|
|
} else {
|
|
if (!StrCmp(de->name,ptr->name)) {
|
|
if (free_old_chain)
|
|
FreeLTClusters(p,ptr->cluster,
|
|
(ptr->size+p->spc*BLK_SIZE-1)/(p->spc*BLK_SIZE),FALSE);
|
|
if (!written) {
|
|
MemCpy(&ptr->start,&de->start,LT_DIR_ENTRY_SIZE);
|
|
WBlks(p,buf+j*BLK_SIZE,
|
|
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
|
|
break;
|
|
} else {
|
|
ptr->attr|=LT_ATTR_DELETED;
|
|
WBlks(p,buf+j*BLK_SIZE,
|
|
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
|
|
}
|
|
}
|
|
}
|
|
ptr+=LT_DIR_ENTRY_SIZE;
|
|
if (++i>=l) {
|
|
j++;
|
|
i=0;
|
|
}
|
|
}
|
|
Free(buf);
|
|
if (unlock)
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
return FALSE;
|
|
}
|
|
|
|
BoolU4 NewLTDirEntry(LTPartition *p,I1 *cur_dir,LTDirEntry *tempm,BoolU4 free_old_chain=TRUE)
|
|
{
|
|
if (p->type==PT_LT)
|
|
return NewLTDirEntry2(p,cur_dir,tempm,free_old_chain,TRUE);
|
|
return FALSE;
|
|
}
|
|
|
|
BoolU4 DelLTFiles(LTPartition *p,I1 *cur_dir,I1 *wild,
|
|
BoolU4 del_dir=FALSE,BoolU4 print_msg=TRUE)
|
|
{
|
|
LTDirEntry *buf,*buf2,*ptr;
|
|
U8 cnt,i=0,j=0,l=BLK_SIZE/LT_DIR_ENTRY_SIZE;
|
|
U1 ch;
|
|
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,TRUE);
|
|
try {
|
|
LockPartition(p);
|
|
buf2=MAlloc(BLK_SIZE*p->spc);
|
|
RClusters(p,buf2,cur_dir_cluster,1,FALSE);
|
|
|
|
ptr=buf2-offset(LTDirEntry.start);
|
|
buf=MAlloc(ptr->size);
|
|
RClusters(p,buf,cur_dir_cluster,ptr->size/BLK_SIZE/p->spc,FALSE);
|
|
Free(buf2);
|
|
|
|
ptr=buf-offset(LTDirEntry.start);
|
|
cnt=ptr->size/LT_DIR_ENTRY_SIZE;
|
|
ptr->name[0]='.';
|
|
ptr->name[1]=0;
|
|
while (cnt--) {
|
|
ch=ptr->name[0];
|
|
if (!ch)
|
|
break;
|
|
else if (!(ptr->attr & LT_ATTR_DELETED) && ch!='.' && (del_dir ||
|
|
!(ptr->attr & LT_ATTR_DIR))) {
|
|
if (WildFileNameList(wild,ptr->name)) {
|
|
if (print_msg)
|
|
coutln SysText("ST_DELETE"),ptr->name;
|
|
ptr->attr|=LT_ATTR_DELETED;
|
|
WBlks(p,buf+j*BLK_SIZE,
|
|
p->data+cur_dir_cluster*p->spc+j,1,FALSE);
|
|
FreeLTClusters(p,ptr->cluster,
|
|
(ptr->size+p->spc*BLK_SIZE-1)/(p->spc*BLK_SIZE),FALSE);
|
|
}
|
|
}
|
|
ptr+=LT_DIR_ENTRY_SIZE;
|
|
if (++i>=l) {
|
|
j++;
|
|
i=0;
|
|
}
|
|
}
|
|
Free(buf);
|
|
UnlockPartition(p);
|
|
} catch
|
|
UnlockPartition(p);
|
|
return FALSE;
|
|
}
|
|
|
|
U8 WriteLTFile(LTPartition *p,I1 *cur_dir,I1 *name,U1 *buf,U8 size,
|
|
LTDate LTdatetime,U8 attr,BoolU4 raw,
|
|
ArcCompressStruct **ac2)
|
|
{
|
|
LTDirEntry de;
|
|
U8 c=0;
|
|
U8 flags=0,cluster_cnt,
|
|
cluster_size=BLK_SIZE*p->spc;
|
|
ArcCompressStruct *ac=NULL;
|
|
BoolU4 contiguous;
|
|
U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,TRUE);
|
|
MemSet(&de,0,sizeof(LTDirEntry));
|
|
if (ac2) *ac2=NULL;
|
|
if (!LTdatetime)
|
|
LTdatetime=GetCurTimeLTDate;
|
|
|
|
if (p->type!=PT_LT)
|
|
PutSysText("ST_NOT_LT");
|
|
else if (!ToLTFilename(de.name,name))
|
|
PutSysText("ST_INVALID_FILENAME");
|
|
else {
|
|
DelLTFiles(p,cur_dir,de.name,FALSE,FALSE);
|
|
attr=FileAttr(name,attr);
|
|
attr|=LT_ATTR_CONTIGUOUS;
|
|
contiguous=TRUE;
|
|
de.expanded_size=size;
|
|
if ((attr & LT_ATTR_COMPRESSED) && !raw) {
|
|
ac=CompressBuf(buf,size,flags);
|
|
size=ac->compressed_size;
|
|
buf=ac;
|
|
}
|
|
de.size=size;
|
|
de.xsum=ArcCheckSum(buf,size)^LT_XSUM;
|
|
cluster_cnt=(size+cluster_size-1)/cluster_size;
|
|
if (cluster_cnt)
|
|
c=AllocClusters(p,0,cluster_cnt,contiguous,TRUE);
|
|
else
|
|
c=INVALID_CLUSTER;
|
|
de.cluster=c;
|
|
de.attr=attr;
|
|
de.datetime=LTdatetime;
|
|
disk_status_display.u2[1]=0x8000+cluster_cnt;
|
|
if (cluster_cnt)
|
|
WClusters(p,buf,c,cluster_cnt,TRUE,TRUE);
|
|
disk_status_display.u2[1]=0;
|
|
NewLTDirEntry2(p,cur_dir,&de,TRUE,TRUE);
|
|
if (ac2)
|
|
*ac2=ac;
|
|
else
|
|
Free(ac);
|
|
}
|
|
return c;
|
|
}
|
|
|
|
void DelLTDirEntry(LTDirEntry *tempm)
|
|
{
|
|
if (tempm) {
|
|
Free(tempm->full_name);
|
|
Free(tempm);
|
|
}
|
|
}
|
|
|
|
void DelLTDirList(LTDirEntry *tempm)
|
|
{
|
|
LTDirEntry *tempm2;
|
|
while (tempm) {
|
|
tempm2=tempm->next;
|
|
if (tempm->sub)
|
|
DelLTDirList(tempm->sub);
|
|
DelLTDirEntry(tempm);
|
|
tempm=tempm2;
|
|
}
|
|
}
|
|
|
|
LTDirEntry *FindLTFiles(I1 *wild,U8 *fuf_flags)
|
|
{
|
|
LTPartition *p=Fs->cur_partition;
|
|
LTDirEntry *buf,*buf2,*ptr;
|
|
U8 cnt,cur_dir_cluster=NameToDirCluster(p,Fs->cur_dir,FALSE);
|
|
U1 ch;
|
|
LTDirEntry *result=NULL,*tempm;
|
|
|
|
LockPartition(p);
|
|
buf2=MAlloc(BLK_SIZE*p->spc);
|
|
RClusters(p,buf2,cur_dir_cluster,1,FALSE);
|
|
|
|
ptr=buf2-offset(LTDirEntry.start);
|
|
buf=MAlloc(ptr->size);
|
|
RClusters(p,buf,cur_dir_cluster,ptr->size/BLK_SIZE/p->spc,FALSE);
|
|
Free(buf2);
|
|
|
|
ptr=buf-offset(LTDirEntry.start);
|
|
cnt=ptr->size/LT_DIR_ENTRY_SIZE;
|
|
ptr->name[0]='.';
|
|
ptr->name[1]=0;
|
|
ptr+=LT_DIR_ENTRY_SIZE;
|
|
ptr->cluster=NameToParentDirCluster(p,Fs->cur_dir,FALSE);
|
|
ptr-=LT_DIR_ENTRY_SIZE;
|
|
while (cnt--) {
|
|
ch=ptr->name[0];
|
|
if (!ch)
|
|
break;
|
|
else if (!(ptr->attr & LT_ATTR_DELETED)) {
|
|
tempm=MAllocZ(sizeof(LTDirEntry));
|
|
MemCpy(&tempm->start,&ptr->start,LT_DIR_ENTRY_SIZE);
|
|
if (Bt(fuf_flags,FUf_RECURSE) && tempm->attr & LT_ATTR_DIR && tempm->name[0]!='.') {
|
|
tempm->next=result;
|
|
result=tempm;
|
|
tempm->full_name=AbsoluteDirName(tempm->name);
|
|
UnlockPartition(p);
|
|
Cd(tempm->name);
|
|
tempm->sub=FindLTFiles(wild,fuf_flags);
|
|
Cd("..");
|
|
LockPartition(p);
|
|
} else if ((!(tempm->attr & LT_ATTR_DIR) && !Bt(fuf_flags,FUf_JUST_DIRS)
|
|
|| !Bt(fuf_flags,FUf_RECURSE)) &&
|
|
WildFileNameList(wild,tempm->name)) {
|
|
tempm->next=result;
|
|
result=tempm;
|
|
tempm->full_name=AbsoluteFileName(tempm->name);
|
|
} else
|
|
DelLTDirEntry(tempm);
|
|
}
|
|
ptr+=LT_DIR_ENTRY_SIZE;
|
|
}
|
|
Free(buf);
|
|
UnlockPartition(p);
|
|
return result;
|
|
}
|
|
|
|
LTDirEntry *FindISOFiles(I1 *wild,U8 *fuf_flags)
|
|
{
|
|
LTPartition *p=Fs->cur_partition;
|
|
ISODirEntry *buf,*isoptr;
|
|
U8 cur_dir_cluster=NameToDirCluster(p,Fs->cur_dir,TRUE);
|
|
LTDirEntry *result=NULL,*tempm;
|
|
I8 i;
|
|
|
|
isoptr=MAlloc(BLK_SIZE*p->spc);
|
|
RClusters(Fs->cur_partition,isoptr,cur_dir_cluster,1,TRUE);
|
|
if (isoptr->name_len==1 && isoptr->name==0) { //curdir
|
|
i=(isoptr->size.little+BLK_SIZE*p->spc-1)/(BLK_SIZE*p->spc);
|
|
buf=MAlloc(BLK_SIZE*p->spc*i);
|
|
RClusters(Fs->cur_partition,buf,cur_dir_cluster,i,TRUE);
|
|
Free(isoptr);
|
|
} else {
|
|
buf=isoptr;
|
|
i=1;
|
|
}
|
|
i*=BLK_SIZE*p->spc;
|
|
while (i>0) {
|
|
if (!buf->length) {
|
|
buf++;
|
|
i--;
|
|
} else {
|
|
tempm=MAlloc(sizeof(LTDirEntry));
|
|
if (FillLTDirISO(Fs->cur_partition,tempm,buf,TRUE)) {
|
|
if (Bt(fuf_flags,FUf_RECURSE) && tempm->attr & LT_ATTR_DIR && tempm->name[0]!='.') {
|
|
tempm->next=result;
|
|
result=tempm;
|
|
tempm->full_name=AbsoluteDirName(tempm->name);
|
|
Cd(tempm->name);
|
|
tempm->sub=FindISOFiles(wild,fuf_flags);
|
|
Cd("..");
|
|
} else if ((!(tempm->attr & LT_ATTR_DIR) && !Bt(fuf_flags,FUf_JUST_DIRS)
|
|
|| !Bt(fuf_flags,FUf_RECURSE)) &&
|
|
WildFileNameList(wild,tempm->name)) {
|
|
tempm->next=result;
|
|
result=tempm;
|
|
tempm->full_name=AbsoluteFileName(tempm->name);
|
|
} else
|
|
DelLTDirEntry(tempm);
|
|
} else
|
|
DelLTDirEntry(tempm);
|
|
i-=buf->length;
|
|
buf+=buf->length;
|
|
}
|
|
}
|
|
Free(buf);
|
|
return result;
|
|
}
|
|
|
|
|
|
I8 CompareLTDir(LTDirEntry **e1,LTDirEntry **e2)
|
|
{
|
|
I1 buf1[LT_MAX_FILENAME_LEN+1],buf2[LT_MAX_FILENAME_LEN+1];
|
|
I1 buf3[LT_MAX_FILENAME_LEN+1],buf4[LT_MAX_FILENAME_LEN+1];
|
|
I8 d1=0,d2=0;
|
|
if ((*e1)->attr & LT_ATTR_DIR)
|
|
d1=1;
|
|
if ((*e2)->attr & LT_ATTR_DIR)
|
|
d2=1;
|
|
if (d1!=d2)
|
|
return d2-d1;
|
|
else {
|
|
StrCpy(buf1,(*e1)->name);
|
|
StrCpy(buf2,(*e2)->name);
|
|
RemoveLastSeg(buf1,".",buf3);
|
|
RemoveLastSeg(buf2,".",buf4);
|
|
if (d1=StrCmp(buf3,buf4))
|
|
return d1;
|
|
return StrCmp(buf1,buf2);
|
|
}
|
|
}
|
|
|
|
|
|
void SortLTDirFiles(LTDirEntry **tempm)
|
|
{
|
|
I8 i,cnt=0;
|
|
LTDirEntry *tempm1=*tempm,*tempm2,**sort_buf;
|
|
if (tempm1) {
|
|
tempm2=tempm1;
|
|
while (tempm2) {
|
|
cnt++;
|
|
tempm2=tempm2->next;
|
|
}
|
|
sort_buf=MAlloc(cnt*PTR_SIZE);
|
|
i=0;
|
|
tempm2=tempm1;
|
|
while (tempm2) {
|
|
sort_buf[i++]=tempm2;
|
|
tempm2=tempm2->next;
|
|
}
|
|
QSort(sort_buf,cnt,PTR_SIZE,&CompareLTDir);
|
|
tempm1=sort_buf[0];
|
|
*tempm=tempm1;
|
|
for (i=0;i<cnt-1;i++) {
|
|
tempm2=sort_buf[i];
|
|
tempm2->next=sort_buf[i+1];
|
|
}
|
|
tempm2=sort_buf[i];
|
|
tempm2->next=NULL;
|
|
Free(sort_buf);
|
|
|
|
tempm2=tempm1;
|
|
while (tempm2) {
|
|
if (tempm2->sub)
|
|
SortLTDirFiles(&tempm2->sub);
|
|
tempm2=tempm2->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
LTDirEntry *SysFindFiles(I1 *wild,U8 *fuf_flags=NULL)
|
|
{
|
|
LTPartition *p=Fs->cur_partition;
|
|
LTDirEntry *result=NULL;
|
|
U8 my_flags=0;
|
|
if (!fuf_flags) fuf_flags=&my_flags;
|
|
CheckLTPartition(p);
|
|
if (p->type==PT_LT)
|
|
result=FindLTFiles(wild,fuf_flags);
|
|
else if (p->type==PT_ISO9660)
|
|
result=FindISOFiles(wild,fuf_flags);
|
|
else {
|
|
PutSysText("ST_FILE_SYSTEM_NOT_SUPPORTED");
|
|
result=NULL;
|
|
}
|
|
SortLTDirFiles(&result);
|
|
return result;
|
|
}
|
|
|
|
|
|
void PutFileLink(I1 *name,I8 line=0,BoolU4 plain_text=FALSE)
|
|
{
|
|
I1 *buf;
|
|
if (!name) return;
|
|
buf=AbsoluteFileName(name);
|
|
if (plain_text) {
|
|
if (line)
|
|
PrintF("$$LK \"%s,%04d\",\"PL:%s,%d\"$$",
|
|
name,line,buf,line);
|
|
else
|
|
PrintF("$$LK \"%s\",\"PI:%s\"$$",
|
|
name,buf);
|
|
} else {
|
|
if (line)
|
|
PrintF("$$LK \"%s,%04d\",\"FL:%s,%d\"$$",
|
|
name,line,buf,line);
|
|
else
|
|
PrintF("$$LK \"%s\",\"FI:%s\"$$",
|
|
name,buf);
|
|
}
|
|
Free(buf);
|
|
}
|
|
|
|
void PutDirLink(I1 *name)
|
|
{
|
|
I1 *buf;
|
|
if (!name) return;
|
|
buf=AbsoluteDirName(name);
|
|
PrintF("$$MA +A \"%s\",\"Cd(\\\"%s\\\");Dir;\r\"$$",
|
|
name,buf);
|
|
Free(buf);
|
|
}
|
|
|
|
void DirLT(I1 *wild,BoolU4 full)
|
|
{
|
|
LTPartition *p=Fs->cur_partition;
|
|
LTDirEntry *tempm1=NULL,*tempm2;
|
|
U8 my_flags=0;
|
|
I1 *st;
|
|
tempm1=SysFindFiles(wild,&my_flags);
|
|
|
|
if (tempm1) {
|
|
st=CurDir;
|
|
if (full)
|
|
coutln "Directory of ",st,
|
|
"\r\n__DATE__ __TIME__ __SIZE__";
|
|
else
|
|
coutln "Directory of ",st,
|
|
"\r\nDATE_ TIME_ __SIZE__";
|
|
Free(st);
|
|
while (tempm1) {
|
|
tempm2=tempm1->next;
|
|
if (full) {
|
|
PrintF("%D %T %08X ",
|
|
tempm1->datetime.date,
|
|
tempm1->datetime.time,
|
|
tempm1->size);
|
|
cout " ",tempm1->expanded_size,
|
|
" ",tempm1->cluster;
|
|
} else {
|
|
PrintF("%h1D %h1T %08X ",
|
|
tempm1->datetime.date,
|
|
tempm1->datetime.time,
|
|
tempm1->size);
|
|
}
|
|
if (tempm1->attr & LT_ATTR_DIR)
|
|
PutDirLink(tempm1->name);
|
|
else
|
|
PutFileLink(tempm1->name);
|
|
|
|
CrLf;
|
|
DelLTDirEntry(tempm1);
|
|
tempm1=tempm2;
|
|
}
|
|
} else {
|
|
PutSysText("ST_NO_MATCHING_ENTRIES");
|
|
return;
|
|
}
|
|
}
|
|
|