1015 lines
25 KiB
Plaintext
1015 lines
25 KiB
Plaintext
void MapDrive(I1 ch,LTPartition *p)
|
|
{
|
|
drive_to_partition[ToUpper(ch)-'A']=p;
|
|
p->drive=ToUpper(ch);
|
|
}
|
|
|
|
BoolU4 Drive(I1 drive_letter)
|
|
{
|
|
LTPartition *p;
|
|
LTBlkDev *bdev;
|
|
BoolU4 different=FALSE;
|
|
LTPartition *new_partition=DriveToPartition(drive_letter);
|
|
if (!new_partition) {
|
|
PutSysText("ST_INVALID_DRIVE");
|
|
return FALSE;
|
|
}
|
|
if (new_partition!=Fs->cur_partition) {
|
|
different=TRUE;
|
|
Fs->cur_partition=new_partition;
|
|
}
|
|
p=Fs->cur_partition;
|
|
CheckLTPartition(p);
|
|
bdev=p->bdev;
|
|
CheckLTBlkDev(bdev);
|
|
if (different) {
|
|
if ((bdev->flags & LTBDF_REMOVABLE) &&
|
|
!(bdev->flags & LTBDF_INITIALIZED) )
|
|
ChangeDisk(p->drive);
|
|
if (bdev->type==LTBDT_RAM || bdev->type==LTBDT_FILE)
|
|
InitBlkDev(bdev,TRUE);
|
|
}
|
|
Free(Fs->cur_dir);
|
|
Fs->cur_dir=NewString("/");
|
|
if (p->type==PT_ISO9660 || p->type==PT_LT)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
BoolU4 Cd(I1 *name,BoolU4 make_dirs=FALSE)
|
|
{
|
|
I8 maxlen;
|
|
BoolU4 result=TRUE;
|
|
I1 *buf2,*buf3,*buf,*hdir;
|
|
LTPartition *p;
|
|
U8 cur_dir_cluster=0;
|
|
if (*name && name[1]==':') {
|
|
if (*name==':') {
|
|
if (Fs->cur_partition!=default_partition)
|
|
if (!Drive(*name)) return FALSE;
|
|
} else {
|
|
if (Fs->cur_partition!=
|
|
DriveToPartition(*name))
|
|
if (!Drive(*name)) return FALSE;
|
|
}
|
|
name+=2;
|
|
}
|
|
if (*name=='/') {
|
|
Free(Fs->cur_dir);
|
|
Fs->cur_dir=NewString("/");
|
|
name++;
|
|
}
|
|
buf2=MStringUtil(name,
|
|
SU_REMOVE_LEADING|SU_REMOVE_TRAILING|
|
|
SU_DISCARD_PARITY|SU_REMOVE_CTRL_CHARS);
|
|
maxlen=StrLen(Fs->cur_dir)+1+StrLen(buf2)+1;
|
|
buf3=MAlloc(maxlen);
|
|
buf=MAlloc(maxlen);
|
|
StrCpy(buf3,Fs->cur_dir);
|
|
while (*buf2 && result) {
|
|
RemoveFirstSeg(buf2,"/",buf);
|
|
if (!*buf)
|
|
StrCpy(buf3,"/");
|
|
else if (!StrCmp(buf,"..")) {
|
|
RemoveLastSeg(buf3,"/",buf);
|
|
if (!*buf3)
|
|
StrCpy(buf3,"/");
|
|
} else if (!StrCmp(buf,".")) {
|
|
;
|
|
} else if (*buf) {
|
|
if (!StrCmp(buf,"HOME")) {
|
|
hdir=HomeDirString;
|
|
result=Cd(hdir);
|
|
Free(buf3);
|
|
buf3=MAlloc(maxlen+StrLen(hdir));
|
|
StrCpy(buf3,hdir+2);
|
|
Free(hdir);
|
|
} else {
|
|
p=Fs->cur_partition;
|
|
cur_dir_cluster=NameToDirCluster(p,buf3,TRUE);
|
|
if (p->type==PT_LT)
|
|
result=CdLT(buf,cur_dir_cluster);
|
|
else if (p->type==PT_ISO9660)
|
|
result=CdISO(buf,cur_dir_cluster);
|
|
else result=FALSE;
|
|
if (!result && make_dirs) {
|
|
Free(Fs->cur_dir);
|
|
Fs->cur_dir=NewString(buf3);
|
|
result=MkDir(buf);
|
|
}
|
|
if (result) {
|
|
if (StrCmp(buf3,"/"))
|
|
StrCat(buf3,"/");
|
|
StrCat(buf3,buf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Free(Fs->cur_dir);
|
|
Fs->cur_dir=NewString(buf3);
|
|
Free(buf);
|
|
Free(buf2);
|
|
Free(buf3);
|
|
return result;
|
|
}
|
|
|
|
void DelLTFileAccess(LTFileAccess *fa)
|
|
{
|
|
LTBlkDev *bdev;
|
|
if (!fa) return;
|
|
bdev=fa->old_partition->bdev;
|
|
if (!(bdev->flags & LTBDF_INIT_IN_PROGRESS)) {
|
|
if (fa->old_dir) {
|
|
Drive(PartitionToDrive(fa->old_partition));
|
|
Cd(fa->old_dir);
|
|
}
|
|
} else {
|
|
Fs->cur_partition=fa->old_partition;
|
|
Free(Fs->cur_dir);
|
|
Fs->cur_dir=NewString("/");
|
|
}
|
|
Free(fa->old_dir);
|
|
Free(fa->mask);
|
|
Free(fa);
|
|
}
|
|
|
|
LTFileAccess *NewLTFileAccess(I1 *mask,BoolU4 make_mask=FALSE,BoolU4 make_dirs=FALSE)
|
|
{
|
|
BoolU4 valid=TRUE;
|
|
I1 *buf,*my_mask,*temp_mask;
|
|
BoolU4 old_silent;
|
|
LTFileAccess *fa=MAllocZ(sizeof(LTFileAccess));
|
|
my_mask=MStringUtil(mask,
|
|
SU_REMOVE_LEADING|SU_REMOVE_TRAILING|
|
|
SU_DISCARD_PARITY|SU_REMOVE_CTRL_CHARS);
|
|
temp_mask=my_mask;
|
|
fa->old_dir=NewString(Fs->cur_dir);
|
|
fa->old_partition=Fs->cur_partition;
|
|
if (*my_mask && my_mask[1]==':') {
|
|
if (Fs->cur_partition!=DriveToPartition(*my_mask))
|
|
if (!Drive(*my_mask)) valid=FALSE;
|
|
my_mask+=2;
|
|
}
|
|
if (StrStr(my_mask,"HOME")) { //TODO
|
|
if (Fs->cur_partition!=DriveToPartition(':'))
|
|
Drive(':');
|
|
}
|
|
fa->p=Fs->cur_partition;
|
|
CheckLTPartition(fa->p);
|
|
buf=NewString(my_mask);
|
|
fa->mask=MAlloc(StrLen(buf)+1);
|
|
RemoveLastSeg(buf,"/",fa->mask);
|
|
if (*my_mask=='/' && !*buf)
|
|
StrCpy(buf,"/");
|
|
if (*buf)
|
|
if (!Cd(buf,make_dirs))
|
|
valid=FALSE;
|
|
if (valid && make_mask) {
|
|
if (!make_dirs || CheckFileName(fa->mask)) {
|
|
old_silent=Silent(ON);
|
|
if (Cd(fa->mask,make_dirs)) {
|
|
Free(fa->mask);
|
|
fa->mask=NewString("*");
|
|
}
|
|
Silent(old_silent);
|
|
}
|
|
}
|
|
Free(buf);
|
|
Free(temp_mask);
|
|
if (!valid) {
|
|
DelLTFileAccess(fa);
|
|
fa=NULL;
|
|
// throw(EXCEPT_FILE);
|
|
}
|
|
return fa;
|
|
}
|
|
|
|
LTDirEntry *FindFiles(I1 *wild,U8 *fuf_flags=NULL)
|
|
{
|
|
U8 my_flags=0;
|
|
LTDirEntry *result=NULL;
|
|
LTFileAccess *fa=NewLTFileAccess(wild,TRUE);
|
|
if (!fuf_flags) fuf_flags=&my_flags;
|
|
if (fa) {
|
|
result=SysFindFiles(fa->mask,fuf_flags);
|
|
DelLTFileAccess(fa);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
BoolU4 IsDir(I1 *dir_name)
|
|
{
|
|
BoolU4 result=FALSE;
|
|
I1 *mask=MSPrintF("%s/*",dir_name);
|
|
BoolU4 old_silent=Silent(ON);
|
|
LTFileAccess *fa=NewLTFileAccess(mask);
|
|
if (fa) {
|
|
result=TRUE;
|
|
DelLTFileAccess(fa);
|
|
}
|
|
Free(mask);
|
|
Silent(old_silent);
|
|
return result;
|
|
}
|
|
|
|
void Dir(I1 *wild=NULL,BoolU4 full=FALSE)
|
|
{
|
|
I1 *w;
|
|
LTFileAccess *fa;
|
|
if (!wild)
|
|
w=NewString("*"); //We must do this because of bug that prevents string defaults
|
|
else
|
|
w=NewString(wild);
|
|
fa=NewLTFileAccess(w,TRUE);
|
|
if (fa) {
|
|
DirLT(fa->mask,full);
|
|
DelLTFileAccess(fa);
|
|
}
|
|
Free(w);
|
|
}
|
|
|
|
|
|
void Del(I1 *wild,BoolU4 print_msg=TRUE)
|
|
{
|
|
LTFileAccess *fa=NewLTFileAccess(wild);
|
|
if (fa) {
|
|
if (fa->p->type==PT_LT)
|
|
DelLTFiles(fa->p,Fs->cur_dir,fa->mask,FALSE,print_msg);
|
|
DelLTFileAccess(fa);
|
|
}
|
|
}
|
|
|
|
U1 *ReadFile(I1 *filename,U8 *size=NULL,U8 *attr=NULL,BoolU4 raw=FALSE)
|
|
{
|
|
SysHashEntry *temph,**temph1;
|
|
I1 *absname;
|
|
U1 *result=NULL;
|
|
U8 size2=0,attr2=0;
|
|
LTFileAccess *fa;
|
|
ArcCompressStruct *ac=NULL;
|
|
|
|
if (attr)
|
|
*attr=0;
|
|
absname=AbsoluteFileName(filename);
|
|
if (!raw && (temph=FindHashEntry(absname,adam_tss->hash_table,HTT_FILE))) {
|
|
if (FileAttr(absname) & LT_ATTR_COMPRESSED) {
|
|
ac=temph->user0;
|
|
if (size)
|
|
*size=ac->expanded_size;
|
|
if (attr)
|
|
*attr=FileAttr(absname,*attr);
|
|
result=ExpandBuf(ac);
|
|
} else { //Not implimented
|
|
result=MAlloc(temph->user1+1);
|
|
MemCpy(result,temph->user0,temph->user1);
|
|
result[temph->user1]=0; //Terminate
|
|
if (size)
|
|
*size=temph->user1;
|
|
}
|
|
} else {
|
|
fa=NewLTFileAccess(absname);
|
|
if (fa) {
|
|
if (fa->p->type==PT_LT)
|
|
result=ReadLTFile(fa->p,Fs->cur_dir,fa->mask,&size2,&attr2,raw,&ac);
|
|
else if (fa->p->type==PT_ISO9660)
|
|
result=ReadISOFile(fa->p,Fs->cur_dir,fa->mask,&size2,&attr2,raw,&ac);
|
|
while (!result && StrCmp(Fs->cur_dir,"/")) {
|
|
Cd("..");
|
|
if (Fs->cur_partition->type==PT_LT)
|
|
result=ReadLTFile(fa->p,Fs->cur_dir,fa->mask,&size2,&attr2,raw,&ac);
|
|
else if (fa->p->type==PT_ISO9660)
|
|
result=ReadISOFile(fa->p,Fs->cur_dir,fa->mask,&size2,&attr2,raw,&ac);
|
|
}
|
|
if (!result)
|
|
cout filename," ",SysText("ST_FILE_NOT_FOUND");
|
|
DelLTFileAccess(fa);
|
|
}
|
|
if (size)
|
|
*size=size2;
|
|
if (attr)
|
|
*attr=attr2;
|
|
if (!raw && attr2 & LT_ATTR_RESIDENT) {
|
|
temph=AMAllocZ(sizeof(SysHashEntry));
|
|
temph->string=ANewString(absname);
|
|
temph->type=HTT_FILE;
|
|
temph->use_cnt=0;
|
|
temph->source_link=NULL;
|
|
temph->user0=AMAllocIdentical(ac);
|
|
temph->user1=size2;
|
|
temph1=FindHashBucket(temph->string,adam_tss->hash_table);
|
|
temph->next=*temph1;
|
|
*temph1=temph;
|
|
}
|
|
Free(ac);
|
|
}
|
|
Free(absname);
|
|
return result;
|
|
}
|
|
|
|
I1 *ReadTextFile(I1 *filename,U8 *attr=NULL)
|
|
{
|
|
return ReadFile(filename,NULL,attr);
|
|
}
|
|
|
|
|
|
BoolU4 FindFile(I1 *filename,LTDirEntry *rde=NULL,
|
|
BoolU4 dir_only=FALSE,BoolU4 file_only=FALSE,BoolU4 scan_parents=FALSE)
|
|
{
|
|
U8 cur_dir_cluster;
|
|
BoolU4 result=FALSE;
|
|
LTDirEntry de;
|
|
LTFileAccess *fa=NewLTFileAccess(filename);
|
|
if (fa) {
|
|
cur_dir_cluster=NameToDirCluster(fa->p,Fs->cur_dir,TRUE);
|
|
if (fa->p->type==PT_LT)
|
|
result=FindLTFile(fa->p,cur_dir_cluster,fa->mask,
|
|
&de,dir_only,file_only,TRUE);
|
|
else if (fa->p->type==PT_ISO9660)
|
|
result=FindISOFile(fa->p,cur_dir_cluster,fa->mask,
|
|
&de,dir_only,file_only,TRUE);
|
|
if (scan_parents) {
|
|
while (!result && StrCmp(Fs->cur_dir,"/")) {
|
|
Cd("..");
|
|
cur_dir_cluster=NameToDirCluster(fa->p,Fs->cur_dir,TRUE);
|
|
if (fa->p->type==PT_LT)
|
|
result=FindLTFile(fa->p,cur_dir_cluster,fa->mask,
|
|
&de,dir_only,file_only,TRUE);
|
|
else if (fa->p->type==PT_ISO9660)
|
|
result=FindISOFile(fa->p,cur_dir_cluster,fa->mask,
|
|
&de,dir_only,file_only,TRUE);
|
|
}
|
|
}
|
|
DelLTFileAccess(fa);
|
|
}
|
|
if (result && rde)
|
|
MemCpy(rde,&de,sizeof(LTDirEntry));
|
|
return result;
|
|
}
|
|
|
|
|
|
U8 WriteFile(I1 *filename,U1 *fbuf,
|
|
U8 size,LTDate LTdatetime=0,U8 attr=0,BoolU4 raw=FALSE)
|
|
{
|
|
U8 c=0;
|
|
SysHashEntry *temph,**temph1;
|
|
LTFileAccess *fa=NewLTFileAccess(filename);
|
|
ArcCompressStruct *ac=NULL;
|
|
I1 *absname=AbsoluteFileName(filename);
|
|
if (fa) {
|
|
if (fa->p->type==PT_LT)
|
|
c=WriteLTFile(fa->p,Fs->cur_dir,fa->mask,
|
|
fbuf,size,LTdatetime,attr,raw,&ac);
|
|
if (temph=FindHashEntry(absname,adam_tss->hash_table,HTT_FILE)) {
|
|
AFree(temph->user0);
|
|
if (!raw && ac && attr & LT_ATTR_RESIDENT) {
|
|
temph->user0=AMAllocIdentical(ac);
|
|
temph->user1=size;
|
|
} else {
|
|
temph->user0=0;
|
|
temph->type=HTT_INVALID;
|
|
}
|
|
} else if (!raw && ac && attr & LT_ATTR_RESIDENT) {
|
|
temph=AMAllocZ(sizeof(SysHashEntry));
|
|
temph->string=ANewString(absname);
|
|
temph->type=HTT_FILE;
|
|
temph->use_cnt=0;
|
|
temph->source_link=NULL;
|
|
temph->user0=AMAllocIdentical(ac);
|
|
temph->user1=size;
|
|
temph1=FindHashBucket(temph->string,adam_tss->hash_table);
|
|
temph->next=*temph1;
|
|
*temph1=temph;
|
|
}
|
|
Free(ac);
|
|
DelLTFileAccess(fa);
|
|
}
|
|
Free(absname);
|
|
return c;
|
|
}
|
|
|
|
void WriteTextFile(I1 *filename,I1 *st,U8 attr=0)
|
|
{
|
|
WriteFile(filename,st,StrLen(st),0,attr);
|
|
}
|
|
|
|
|
|
void FAllocFile(LTFile *f,U8 cnt,BoolU4 contiguous)
|
|
{
|
|
LTPartition *fp=f->p;
|
|
LTFileAccess *fa=NewLTFileAccess(f->de.full_name);
|
|
f->de.cluster=AllocClusters(fp,0,(cnt+fp->spc-1)/fp->spc,contiguous,TRUE);
|
|
f->de.size=BLK_SIZE*cnt;
|
|
f->de.expanded_size=f->de.size;
|
|
if (fa) {
|
|
NewLTDirEntry(fa->p,Fs->cur_dir,&f->de,TRUE);
|
|
DelLTFileAccess(fa);
|
|
}
|
|
f->flags&=~LTF_NEW_FILE;
|
|
}
|
|
|
|
U8 FSize(LTFile *f)
|
|
{
|
|
if (f)
|
|
return f->de.size;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void FSync(LTFile *f)
|
|
{
|
|
if (f->flags & LTF_BUF_DIRTY) {
|
|
WClusters(f->p,f->cluster_buf,f->cluster,1,TRUE,TRUE);
|
|
f->flags&=~LTF_BUF_DIRTY;
|
|
}
|
|
disk_status_display.u2[1]=0;
|
|
}
|
|
|
|
|
|
LTFile *FOpen(I1 *filename,I1 *flags,U8 cnt=0)
|
|
{ //allows flags "r","w","w+" and "c" (contiguous)
|
|
LTFile *f=AMAllocZ(sizeof(LTFile));
|
|
LTFileAccess *fa;
|
|
I1 *full_name,*full_name2;
|
|
BoolU4 contiguous=Occurrences(flags,'c');
|
|
|
|
f->cluster=INVALID_CLUSTER;
|
|
f->file_ptr=0;
|
|
f->fblk_num=0;
|
|
if (cnt)
|
|
f->max_blk=cnt-1;
|
|
else
|
|
f->max_blk=INVALID_CLUSTER;
|
|
f->file_cluster_num=INVALID_CLUSTER;
|
|
full_name2=AbsoluteFileName(filename);
|
|
full_name=ANewString(full_name2);
|
|
Free(full_name2);
|
|
f->p=DriveToPartition(*full_name);
|
|
if (contiguous) {
|
|
f->flags|=LTF_CONTIGUOUS;
|
|
if (f->p->type!=PT_LT) {
|
|
if (!(FileAttr(filename) & LT_ATTR_CONTIGUOUS))
|
|
throw(EXCEPT_FILE,60);
|
|
}
|
|
}
|
|
f->cluster_buf=AMAllocZ(f->p->spc*BLK_SIZE);
|
|
if (Occurrences(flags,'w')) {
|
|
f->flags=f->flags|LTF_WRITE|LTF_NEEDS_WRITE;
|
|
if (Occurrences(flags,'+')) {
|
|
if (FindFile(full_name,&f->de,FALSE,TRUE)) {
|
|
f->de.full_name=full_name;
|
|
if (contiguous)
|
|
f->max_blk=(FSize(f)+BLK_SIZE-1)/BLK_SIZE-1;
|
|
return f;
|
|
}
|
|
} else
|
|
Del(full_name,FALSE);
|
|
f->de.full_name=full_name;
|
|
f->flags|=LTF_NEW_FILE;
|
|
fa=NewLTFileAccess(full_name);
|
|
if (fa) {
|
|
StrCpy(f->de.name,fa->mask);
|
|
DelLTFileAccess(fa);
|
|
if (cnt)
|
|
FAllocFile(f,cnt,contiguous);
|
|
if (!contiguous || cnt)
|
|
return f;
|
|
}
|
|
} else {
|
|
if (FindFile(full_name,&f->de,FALSE,TRUE)) {
|
|
f->de.full_name=full_name;
|
|
if (contiguous)
|
|
f->max_blk=(FSize(f)+BLK_SIZE-1)/BLK_SIZE-1;
|
|
return f;
|
|
}
|
|
}
|
|
AFree(f->cluster_buf);
|
|
AFree(full_name);
|
|
AFree(f);
|
|
return NULL;
|
|
}
|
|
|
|
void FClose(LTFile *f)
|
|
{
|
|
LTFileAccess *fa;
|
|
if (f) {
|
|
FSync(f);
|
|
if (f->flags & LTF_NEEDS_WRITE) {
|
|
fa=NewLTFileAccess(f->de.full_name);
|
|
if (fa) {
|
|
if (!(f->flags & LTF_USE_OLD_DATETIME))
|
|
f->de.datetime=GetCurTimeLTDate;
|
|
if (f->flags & LTF_NEW_FILE)
|
|
NewLTDirEntry(fa->p,Fs->cur_dir,&f->de,TRUE);
|
|
else
|
|
NewLTDirEntry(fa->p,Fs->cur_dir,&f->de,FALSE);
|
|
DelLTFileAccess(fa);
|
|
} else
|
|
throw(EXCEPT_FILE,40);
|
|
}
|
|
AFree(f->cluster_buf);
|
|
AFree(f->de.full_name);
|
|
AFree(f);
|
|
}
|
|
}
|
|
|
|
U8 FSetCluster(LTFile *f,U8 c,U8 blk,BoolU4 read)
|
|
{
|
|
if (f->cluster!=c) {
|
|
if (f->flags & LTF_BUF_DIRTY) {
|
|
WClusters(f->p,f->cluster_buf,f->cluster,1,TRUE,TRUE);
|
|
f->flags=f->flags & ~LTF_BUF_DIRTY;
|
|
}
|
|
f->cluster=c;
|
|
f->file_cluster_num=blk/f->p->spc;
|
|
if (read)
|
|
c=RClusters(f->p,f->cluster_buf,c,1,TRUE,TRUE);
|
|
}
|
|
return c;
|
|
}
|
|
|
|
BoolU4 FRBlks(LTFile *f,U1 *buf,U8 blk=LTFB_NEXT_BLK,U8 cnt=1)
|
|
{
|
|
LTPartition *p=f->p;
|
|
U8 spc=p->spc,i,j,c=f->de.cluster;
|
|
|
|
if (!f || !p) return FALSE;
|
|
if (blk==LTFB_NEXT_BLK)
|
|
blk=f->fblk_num;
|
|
if (blk+cnt-1>f->max_blk)
|
|
return FALSE;
|
|
if (!cnt) return TRUE;
|
|
|
|
disk_status_display.u2[1]=cnt/spc;
|
|
if (f->flags & LTF_CONTIGUOUS) {
|
|
RBlks(p,buf,ClusterBlk(p,c)+blk,cnt,TRUE);
|
|
blk+=cnt;
|
|
} else {
|
|
i=blk/spc;
|
|
if (i>=f->file_cluster_num) {
|
|
c=f->cluster;
|
|
i-=f->file_cluster_num;
|
|
}
|
|
if (i)
|
|
c=NextClusterNum(p,c,i,TRUE);
|
|
|
|
i=blk%spc;
|
|
if (i) {
|
|
c=FSetCluster(f,c,blk,TRUE);
|
|
j=(cnt<spc-i) ? cnt : spc-i;
|
|
MemCpy(buf,f->cluster_buf+BLK_SIZE*i,j*BLK_SIZE);
|
|
buf+=j*BLK_SIZE;
|
|
cnt-=j;
|
|
blk+=j;
|
|
}
|
|
while (cnt>=spc) {
|
|
c=FSetCluster(f,c,blk,TRUE);
|
|
MemCpy(buf,f->cluster_buf,spc*BLK_SIZE);
|
|
buf+=spc*BLK_SIZE;
|
|
cnt-=spc;
|
|
blk+=spc;
|
|
}
|
|
if (cnt) {
|
|
c=FSetCluster(f,c,blk,TRUE);
|
|
MemCpy(buf,f->cluster_buf,cnt*BLK_SIZE);
|
|
buf+=cnt*BLK_SIZE;
|
|
blk+=cnt;
|
|
}
|
|
}
|
|
f->fblk_num=blk;
|
|
disk_status_display.u2[1]=0;
|
|
return TRUE;
|
|
}
|
|
|
|
BoolU4 FWBlks(LTFile *f,U1 *buf,U8 blk=LTFB_NEXT_BLK,U8 cnt=1)
|
|
{
|
|
LTPartition *p=f->p;
|
|
U8 spc=p->spc,i,j,c=f->de.cluster,c1;
|
|
|
|
if (!f || !p) return FALSE;
|
|
if (blk==LTFB_NEXT_BLK)
|
|
blk=f->fblk_num;
|
|
if (blk+cnt-1>f->max_blk)
|
|
return FALSE;
|
|
if (!(f->flags & LTF_WRITE))
|
|
return FALSE;
|
|
if (!cnt) return TRUE;
|
|
disk_status_display.u2[1]=0x8000+cnt/spc;
|
|
if (f->flags & LTF_CONTIGUOUS) {
|
|
WBlks(p,buf,ClusterBlk(p,c)+blk,cnt,TRUE);
|
|
blk+=cnt;
|
|
} else {
|
|
if (!c) {
|
|
c=AllocClusters(p,0,1,FALSE,TRUE);
|
|
f->file_cluster_num=0;
|
|
f->cluster=c;
|
|
f->de.cluster=c;
|
|
f->flags|=LTF_NEEDS_WRITE|LTF_NEW_FILE;
|
|
}
|
|
i=blk/spc;
|
|
if (i>=f->file_cluster_num) {
|
|
c=f->cluster;
|
|
i-=f->file_cluster_num;
|
|
}
|
|
while (i) {
|
|
c1=c;
|
|
c=NextClusterNum(p,c1,1,TRUE);
|
|
if (c==INVALID_CLUSTER) {
|
|
c=AllocClusters(p,c1,i,FALSE,TRUE);
|
|
if (i>1)
|
|
c=NextClusterNum(p,c,i-1,TRUE);
|
|
break;
|
|
} else
|
|
i--;
|
|
}
|
|
|
|
i=blk%spc;
|
|
if (i) {
|
|
FSetCluster(f,c,blk,TRUE);
|
|
j=(cnt<spc-i) ? cnt : spc-i;
|
|
MemCpy(f->cluster_buf+BLK_SIZE*i,buf,j*BLK_SIZE);
|
|
f->flags|=LTF_BUF_DIRTY;
|
|
buf+=j*BLK_SIZE;
|
|
cnt-=j;
|
|
blk+=j;
|
|
if (cnt) {
|
|
c1=c;
|
|
c=NextClusterNum(p,c1,1,TRUE);
|
|
if (c==INVALID_CLUSTER)
|
|
c=AllocClusters(p,c1,1,FALSE,TRUE);
|
|
}
|
|
}
|
|
while (cnt>=spc) {
|
|
FSetCluster(f,c,blk,FALSE);
|
|
MemCpy(f->cluster_buf,buf,spc*BLK_SIZE);
|
|
f->flags|=LTF_BUF_DIRTY;
|
|
buf+=spc*BLK_SIZE;
|
|
cnt-=spc;
|
|
blk+=spc;
|
|
if (cnt) {
|
|
c1=c;
|
|
c=NextClusterNum(p,c1,1,TRUE);
|
|
if (c==INVALID_CLUSTER)
|
|
c=AllocClusters(p,c1,1,FALSE,TRUE);
|
|
}
|
|
}
|
|
if (cnt) {
|
|
FSetCluster(f,c,blk,TRUE);
|
|
MemCpy(f->cluster_buf,buf,cnt*BLK_SIZE);
|
|
f->flags|=LTF_BUF_DIRTY;
|
|
buf+=cnt*BLK_SIZE;
|
|
blk+=cnt;
|
|
}
|
|
if (f->de.size<blk*BLK_SIZE)
|
|
f->de.size=blk*BLK_SIZE;
|
|
if (f->de.expanded_size<blk*BLK_SIZE)
|
|
f->de.expanded_size=blk*BLK_SIZE;
|
|
}
|
|
f->fblk_num=blk;
|
|
disk_status_display.u2[1]=0;
|
|
return TRUE;
|
|
}
|
|
|
|
void SelectDefaultDrive()
|
|
{
|
|
I1 ch;
|
|
LTPartition *p;
|
|
|
|
if (!default_drive)
|
|
AddDrives(FALSE);
|
|
while (!default_drive) {
|
|
cout "\r\nContinue Boot to Which Drive? ";
|
|
p=DriveToPartition(SysGetChar);
|
|
CrLf;
|
|
if (!p || p->type!=PT_ISO9660 && p->type!=PT_LT) {
|
|
coutln "Invalid Partition";
|
|
PartitionRep;
|
|
} else {
|
|
if (p->bdev->flags & LTBDF_REMOVABLE) {
|
|
ch=p->drive;
|
|
coutln "Insert Diskette in Drive ",ch;
|
|
}
|
|
default_drive=p->drive;
|
|
}
|
|
}
|
|
default_partition=DriveToPartition(default_drive);
|
|
Fs->cur_partition=-1; //Null screws-up cache
|
|
Fs->cur_dir=NewString("/");
|
|
ChangeDisk(':');
|
|
}
|
|
|
|
BoolU4 CopySingleZ(I1 *f1,I1 *f2) //Just one file
|
|
{
|
|
U1 *file_buf=NULL;
|
|
U8 size,attr=0;
|
|
LTDirEntry de;
|
|
|
|
if (FindFile(f1,&de,FALSE,TRUE)) {
|
|
file_buf=ReadFile(f1,&size,&attr);
|
|
attr=FileAttr(f2,attr);
|
|
if (file_buf) {
|
|
coutln "Copying ",f1," to ",f2;
|
|
WriteFile(f2,file_buf,size,de.datetime,attr);
|
|
Free(file_buf);
|
|
return TRUE;
|
|
} else PutSysText("ST_FILE_NOT_FOUND");
|
|
} else PutSysText("ST_FILE_NOT_FOUND");
|
|
return FALSE;
|
|
}
|
|
|
|
#define COPY_BUF_BLKS 0x400
|
|
BoolU4 CopySingle(I1 *f1,I1 *f2) //Just one file
|
|
{
|
|
U1 *buf;
|
|
U8 cnt,l,size,attr1=FileAttr(f1),attr2=FileAttr(f2);
|
|
LTFile *in_file=NULL,*out_file=NULL;
|
|
U8 xsum=LT_XSUM,i,j;
|
|
if (!StrCmp(f1,f2))
|
|
return FALSE;
|
|
if (attr1!=attr2)
|
|
return CopySingleZ(f1,f2);
|
|
buf=MAlloc(COPY_BUF_BLKS*BLK_SIZE);
|
|
if (attr2 & LT_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;
|
|
if (attr2 & LT_ATTR_CONTIGUOUS)
|
|
out_file=FOpen(f2,"wc",cnt);
|
|
else
|
|
out_file=FOpen(f2,"w",cnt);
|
|
if (out_file) {
|
|
coutln "Copying ",f1," to ",f2;
|
|
j=size;
|
|
while (cnt) {
|
|
if (cnt>COPY_BUF_BLKS) {
|
|
l=COPY_BUF_BLKS;
|
|
i=l*BLK_SIZE;
|
|
} else {
|
|
l=cnt;
|
|
i=j;
|
|
}
|
|
FRBlks(in_file, buf,LTFB_NEXT_BLK,l);
|
|
xsum^=ArcCheckSum(buf,i);
|
|
FWBlks(out_file,buf,LTFB_NEXT_BLK,l);
|
|
cnt-=l;
|
|
j-=l*BLK_SIZE;
|
|
}
|
|
if (in_file->de.xsum &&
|
|
in_file->de.xsum!=xsum)
|
|
throw(EXCEPT_ARC_XSUM);
|
|
out_file->de.xsum=xsum;
|
|
out_file->flags|=LTF_USE_OLD_DATETIME;
|
|
out_file->de.datetime=in_file->de.datetime;
|
|
out_file->de.size=size;
|
|
out_file->de.expanded_size=in_file->de.expanded_size;
|
|
out_file->de.attr=FileAttr(f2,in_file->de.attr);
|
|
FClose(out_file);
|
|
FClose(in_file);
|
|
Free(buf);
|
|
return TRUE;
|
|
} else PutSysText("ST_FILE_NOT_FOUND");
|
|
FClose(in_file);
|
|
} else PutSysText("ST_FILE_NOT_FOUND");
|
|
Free(buf);
|
|
return FALSE;
|
|
}
|
|
|
|
BoolU4 MkDir(I1 *filename)
|
|
{
|
|
U8 c,size,cur_dir_cluster;
|
|
U1 *buf;
|
|
BoolU4 result=FALSE;
|
|
LTDirEntry *dLT;
|
|
I1 *name;
|
|
if (FindFile(filename,NULL,TRUE))
|
|
return FALSE;
|
|
LTFileAccess *fa=NewLTFileAccess(filename);
|
|
if (fa) {
|
|
if (!CheckFileName(fa->mask))
|
|
PutSysText("ST_INVALID_FILENAME");
|
|
else {
|
|
name=MStringUtil(fa->mask,
|
|
SU_REMOVE_LEADING|SU_REMOVE_TRAILING|
|
|
SU_DISCARD_PARITY|SU_REMOVE_CTRL_CHARS);
|
|
size=fa->p->spc*BLK_SIZE;
|
|
buf=MAllocZ(size);
|
|
cur_dir_cluster=NameToDirCluster(fa->p,Fs->cur_dir,TRUE);
|
|
if (fa->p->type==PT_LT) {
|
|
dLT=buf-offset(LTDirEntry.start);
|
|
c=WriteFile(name,buf,size,0,LT_ATTR_DIR,FALSE);
|
|
|
|
dLT->attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS;
|
|
StrCpy(dLT->name,name);
|
|
dLT->cluster=c;
|
|
dLT->size=size;
|
|
dLT->expanded_size=size;
|
|
dLT->datetime=GetCurTimeLTDate;
|
|
|
|
dLT+=LT_DIR_ENTRY_SIZE;
|
|
|
|
dLT->attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS;
|
|
dLT->name[0]='.';
|
|
dLT->name[1]='.';
|
|
dLT->name[2]=0;
|
|
dLT->cluster=cur_dir_cluster;
|
|
dLT->size=0;
|
|
dLT->expanded_size=0;
|
|
dLT->datetime=GetCurTimeLTDate;
|
|
|
|
}
|
|
WClusters(fa->p,buf,c,1,TRUE);
|
|
Free(buf);
|
|
Free(name);
|
|
result=TRUE;
|
|
}
|
|
DelLTFileAccess(fa);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void SysDel(I1 *wild,BoolU4 make_mask) //this is dangerous
|
|
{
|
|
LTFileAccess *fa=NewLTFileAccess(wild,make_mask);
|
|
if (fa) {
|
|
if (fa->p->type==PT_LT)
|
|
DelLTFiles(fa->p,Fs->cur_dir,fa->mask,TRUE);
|
|
DelLTFileAccess(fa);
|
|
}
|
|
}
|
|
|
|
void Format(I8 drive_letter,BoolU4 quick=TRUE,BoolU4 confirm=TRUE,U8 type=PT_LT)
|
|
{
|
|
LTPartition *p=DriveToPartition(drive_letter);
|
|
if (confirm) {
|
|
cout "Are you sure ";
|
|
if (!YorN)
|
|
return;
|
|
}
|
|
if (!p) {
|
|
PutSysText("ST_INVALID_DRIVE");
|
|
return;
|
|
}
|
|
if (type==PT_LT) {
|
|
Drive(drive_letter);
|
|
FormatLT(drive_letter,quick);
|
|
InvalidateDiskCache(DriveToPartition(drive_letter),TRUE);
|
|
Drive(drive_letter);
|
|
}
|
|
}
|
|
|
|
|
|
void ReadCDImage(I1 drive,I1 *out_name)
|
|
{
|
|
LTBlkDev *bdev=DriveToBlkDev(drive);
|
|
LTPartition *p=DriveToPartition(drive);
|
|
U1 *buf=MAlloc(COPY_BUF_BLKS*BLK_SIZE);
|
|
I1 *out_name2=DefaultExtension(out_name,"ISO");
|
|
LTFile *f=FOpen(out_name2,"w");
|
|
U8 l,dv,blk=0,cnt;
|
|
InitBlkDev(bdev,TRUE);
|
|
if (bdev->type!=LTBDT_ATAPI)
|
|
throw(EXCEPT_BLKDEV,3);
|
|
dv=bdev->blk_size/BLK_SIZE;
|
|
cnt=((p->size+dv-1)/dv)*dv;
|
|
while (cnt) {
|
|
if (cnt>COPY_BUF_BLKS)
|
|
l=COPY_BUF_BLKS;
|
|
else
|
|
l=cnt;
|
|
if (l>bdev->max_reads)
|
|
l=bdev->max_reads;
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(bdev->read_freq);
|
|
disk_status_display.u2[1]=cnt/l;
|
|
disk_status_display.u2[0]=l/dv;
|
|
ATAPIReadBlks2(bdev,buf,blk/dv,l/dv);
|
|
disk_status_display=0;
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(0);
|
|
FWBlks(f,buf,blk,l);
|
|
cnt-=l;
|
|
blk+=l;
|
|
}
|
|
FClose(f);
|
|
Free(buf);
|
|
Free(out_name2);
|
|
}
|
|
|
|
class LTDuelBuf
|
|
{
|
|
U1 *buf0,*buf1;
|
|
U8 in_buf,out_buf,cnt;
|
|
I1 *filename;
|
|
LTBlkDev *CD_bdev;
|
|
};
|
|
|
|
|
|
void WriteCDImageTsk()
|
|
{
|
|
LTDuelBuf *d=Fs->user_aux1;
|
|
U1 *buf;
|
|
U8 l,blk=0,cnt=d->cnt;
|
|
LTFile *f;
|
|
if (FileAttr(d->filename)<_ATTR_CONTIGUOUS)
|
|
f=FOpen(d->filename,"rc");
|
|
else
|
|
f=FOpen(d->filename,"r");
|
|
while (cnt) {
|
|
if (cnt>COPY_BUF_BLKS)
|
|
l=COPY_BUF_BLKS;
|
|
else
|
|
l=cnt;
|
|
if (l>d->CD_bdev->max_writes)
|
|
l=d->CD_bdev->max_writes;
|
|
buf=(d->in_buf & 1) ? d->buf1:d->buf0;
|
|
while (d->in_buf>d->out_buf+1)
|
|
SwapInNext;
|
|
FRBlks(f,buf,blk,l);
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(d->CD_bdev->write_freq);
|
|
d->in_buf++;
|
|
cnt-=l;
|
|
blk+=l;
|
|
}
|
|
FClose(f);
|
|
}
|
|
|
|
void WriteCDImage(I1 drive,I1 *in_name)
|
|
{
|
|
LTDuelBuf *d=MAllocZ(sizeof(LTDuelBuf));
|
|
U1 *buf;
|
|
I1 *in_name3=DefaultExtension(in_name,"ISO");
|
|
I1 *in_name2=AbsoluteFileName(in_name3);
|
|
U8 l,dv,blk=0,cnt;
|
|
LTPartition *p=DriveToPartition(drive);
|
|
LTBlkDev *bdev=p->bdev;
|
|
TssStruct *tss;
|
|
BoolU4 old_preempt;
|
|
LTFile *f=FOpen(in_name2,"r");
|
|
|
|
if (!f) {
|
|
Free(d);
|
|
return;
|
|
}
|
|
cnt=(FSize(f)+BLK_SIZE-1)/BLK_SIZE;
|
|
FClose(f);
|
|
if (bdev->type!=LTBDT_ATAPI)
|
|
throw(EXCEPT_BLKDEV,4);
|
|
bdev->flags|=LTBDF_READ_ONLY_OVERRIDE;
|
|
InitBlkDev(bdev,TRUE);
|
|
dv=bdev->blk_size/BLK_SIZE;
|
|
if (p->size<cnt)
|
|
p->size=cnt;
|
|
|
|
d->filename=in_name2;
|
|
d->CD_bdev=bdev;
|
|
d->buf0=MAlloc(COPY_BUF_BLKS*BLK_SIZE);
|
|
d->buf1=MAlloc(COPY_BUF_BLKS*BLK_SIZE);
|
|
d->cnt=cnt;
|
|
|
|
old_preempt=Preempt(OFF);
|
|
tss=Spawn(&WriteCDImageTsk,"WRITE CD");
|
|
tss->user_aux1=d;
|
|
Preempt(old_preempt);
|
|
|
|
while (d->in_buf<=d->out_buf)
|
|
SwapInNext;
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(bdev->write_freq);
|
|
IDEWaitForDrive(bdev);
|
|
ATAPIWaitReady(bdev);
|
|
while (cnt) {
|
|
if (cnt>COPY_BUF_BLKS)
|
|
l=COPY_BUF_BLKS;
|
|
else
|
|
l=cnt;
|
|
if (l>bdev->max_writes)
|
|
l=bdev->max_writes;
|
|
buf=(d->out_buf&1) ? d->buf1:d->buf0;
|
|
while (d->in_buf<=d->out_buf)
|
|
SwapInNext;
|
|
disk_status_display.u2[1]=cnt/l+0x8000;
|
|
disk_status_display.u2[0]=l/dv+0x8000;
|
|
ATAPIWriteBlks(bdev,buf,blk/dv,(l+dv-1)/dv);
|
|
disk_status_display=0;
|
|
d->out_buf++;
|
|
cnt-=l;
|
|
blk+=l;
|
|
}
|
|
ATAPISync(bdev);
|
|
ATAPIClose(bdev);
|
|
if (!Bt(&sys_flags,SYSf_NO_IO_SOUND))
|
|
Sound(0);
|
|
bdev->flags&=~LTBDF_READ_ONLY_OVERRIDE;
|
|
Btr(&sys_irq_busy_flags,bdev->irq);
|
|
Free(d->buf0);
|
|
Free(d->buf1);
|
|
Free(d);
|
|
Free(in_name2);
|
|
Free(in_name3);
|
|
}
|
|
|