821 lines
21 KiB
Plaintext
821 lines
21 KiB
Plaintext
|
|
public BoolU4 Copy(I1 *f1,I1 *f2=".")
|
|
{
|
|
BoolU4 result=TRUE;
|
|
LTFileAccess *fa;
|
|
LTDirEntry *tempm,*tempm1;
|
|
U8 my_flags=0;
|
|
if (!(tempm=FindFiles(f1,&my_flags)))
|
|
return FALSE;
|
|
if (IsDir(f2)) {
|
|
fa=NewLTFileAccess(f2,TRUE);
|
|
if (fa) {
|
|
while (tempm) {
|
|
tempm1=tempm->next;
|
|
if (!(tempm->attr & LT_ATTR_DIR)) {
|
|
if (!CopySingle(tempm->full_name,tempm->name))
|
|
result=FALSE;
|
|
}
|
|
DelLTDirEntry(tempm);
|
|
tempm=tempm1;
|
|
}
|
|
DelLTFileAccess(fa);
|
|
}
|
|
return result;
|
|
} else
|
|
return CopySingle(f1,f2);
|
|
}
|
|
|
|
public BoolU4 Move(I1 *f1,I1 *f2)
|
|
{
|
|
if (Copy(f1,f2)) {
|
|
Del(f1);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
U8 PutCopyTree(LTDirEntry *tempm,U8 src_dir_len,U8 dst_dir_len,I1 *dst_dir)
|
|
{
|
|
U8 result=0;
|
|
I1 *st;
|
|
while (tempm) {
|
|
st=MAlloc(StrLen(tempm->full_name)+dst_dir_len+2);
|
|
MemCpy(st,dst_dir,dst_dir_len);
|
|
StrCpy(st+dst_dir_len,tempm->full_name+src_dir_len);
|
|
if (tempm->attr & LT_ATTR_DIR) {
|
|
MkDir(st);
|
|
if (IsDir(st) && tempm->sub)
|
|
result+=PutCopyTree(tempm->sub,src_dir_len,dst_dir_len,dst_dir);
|
|
} else
|
|
if (CopySingle(tempm->full_name,st))
|
|
result++;
|
|
Free(st);
|
|
tempm=tempm->next;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public U8 CopyTree(I1 *src_mask,I1 *dst_mask)
|
|
{ //returns count of copied files (not dirs)
|
|
LTFileAccess *fa;
|
|
LTDirEntry *tempm=NULL;
|
|
U8 result=0,i1,i2,my_flags=(1<<FUf_RECURSE);
|
|
I1 *st1,*st2;
|
|
|
|
fa=NewLTFileAccess(src_mask,TRUE);
|
|
if (fa) {
|
|
tempm=SysFindFiles(fa->mask,&my_flags);
|
|
st1=CurDir;
|
|
DelLTFileAccess(fa);
|
|
i1=StrLen(st1);
|
|
if (i1==3) i1--;
|
|
|
|
fa=NewLTFileAccess(dst_mask,TRUE,TRUE);
|
|
if (fa) {
|
|
st2=CurDir;
|
|
i2=StrLen(st2);
|
|
if (i2==3) i2--;
|
|
result=PutCopyTree(tempm,i1,i2,st2);
|
|
DelLTFileAccess(fa);
|
|
Free(st2);
|
|
}
|
|
DelLTDirList(tempm);
|
|
Free(st1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void DoDelTree(LTDirEntry *tempm1)
|
|
{
|
|
U8 result=0;
|
|
LTDirEntry *tempm2;
|
|
while (tempm1) {
|
|
tempm2=tempm1->next;
|
|
if (tempm1->attr & LT_ATTR_DIR) {
|
|
if (tempm1->sub)
|
|
result+=DoDelTree(tempm1->sub);
|
|
SysDel(tempm1->full_name,TRUE);
|
|
}
|
|
DelLTDirEntry(tempm1);
|
|
tempm1=tempm2;
|
|
}
|
|
}
|
|
|
|
public BoolU4 DelTree(I1 *mask)
|
|
{
|
|
U8 my_flags=(1<<FUf_RECURSE);
|
|
if (!IsDir(mask)) {
|
|
coutln "Not a Directory";
|
|
return FALSE;
|
|
}
|
|
DoDelTree(FindFiles(mask,&my_flags));
|
|
SysDel(mask,TRUE);
|
|
SysDel(mask,FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
void DoDelMask(LTDirEntry *tempm1)
|
|
{
|
|
LTDirEntry *tempm2;
|
|
while (tempm1) {
|
|
tempm2=tempm1->next;
|
|
if (tempm1->attr & LT_ATTR_DIR) {
|
|
if (tempm1->sub)
|
|
DoDelMask(tempm1->sub);
|
|
} else
|
|
Del(tempm1->full_name);
|
|
DelLTDirEntry(tempm1);
|
|
tempm1=tempm2;
|
|
}
|
|
}
|
|
|
|
public BoolU4 DelMask(I1 *mask)
|
|
{ //Purges select filetypes from tree
|
|
U8 my_flags=(1<<FUf_RECURSE);
|
|
if (IsDir(mask)) {
|
|
coutln "Not a Mask";
|
|
return FALSE;
|
|
}
|
|
DoDelMask(FindFiles(mask,&my_flags));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void TouchFile(I1 *filename,I1 *attr) //LTust one file
|
|
{
|
|
U1 *temp_st=NewString(filename),
|
|
*cur_dir=NewString(filename);
|
|
LTPartition *p=DriveToPartition(*filename);
|
|
FlagsStruct f;
|
|
LTDirEntry de;
|
|
I1 buf[64];
|
|
if (FindFile(filename,&de,FALSE,TRUE)) {
|
|
if (!StrCmp(attr,"+?"))
|
|
PrintF("%-32ts %s\r\n",filename,SPrintFFlags(buf,"ST_FILE_ATTRS",de.attr));
|
|
else {
|
|
GetFFlags(&f,"ST_FILE_ATTRS",attr);
|
|
RemoveFirstSeg(cur_dir,":",temp_st);
|
|
RemoveLastSeg(cur_dir,"/",temp_st);
|
|
if (!*cur_dir)
|
|
StrCpy(cur_dir,"/");
|
|
de.attr=de.attr&f.off|f.on;
|
|
de.datetime=GetCurTimeLTDate;
|
|
NewLTDirEntry(p,cur_dir,&de,FALSE);
|
|
}
|
|
} else PutSysText("ST_FILE_NOT_FOUND");
|
|
}
|
|
|
|
void TouchList(LTDirEntry *tempm1,I1 *attr)
|
|
{
|
|
LTDirEntry *tempm2;
|
|
while (tempm1) {
|
|
tempm2=tempm1->next;
|
|
if (tempm1->attr & LT_ATTR_DIR) {
|
|
if (tempm1->sub) {
|
|
coutln SysText("ST_SCANNING_DIRECTORY"),tempm1->full_name;
|
|
TouchList(tempm1->sub,attr);
|
|
}
|
|
} else
|
|
TouchFile(tempm1->full_name,attr);
|
|
DelLTDirEntry(tempm1);
|
|
tempm1=tempm2;
|
|
}
|
|
}
|
|
|
|
//Attr "+?" =show
|
|
// "+T" = resident
|
|
//flags "+r"=recurse
|
|
public void Touch(I1 *wild,I1 *attr="+?",I1 *flags="")
|
|
{
|
|
FlagsStruct f;
|
|
GetFFlags(&f,"ST_FILE_UTIL_FLAGS",flags);
|
|
TouchList(FindFiles(wild,&f.on),attr);
|
|
}
|
|
|
|
void FillBigEndianU2(U2 *dst,U2 w)
|
|
{
|
|
U2 *src=&w;
|
|
dst->u1[0]=src->u1[1];
|
|
dst->u1[1]=src->u1[0];
|
|
}
|
|
|
|
void FillBigEndianU4(U4 *dst,U8 d)
|
|
{
|
|
U8 *src=&d;
|
|
dst->u1[0]=src->u1[3];
|
|
dst->u1[1]=src->u1[2];
|
|
dst->u1[2]=src->u1[1];
|
|
dst->u1[3]=src->u1[0];
|
|
}
|
|
|
|
void FillU2Palindrome(U2Palindrome *dst,U2 w)
|
|
{
|
|
FillBigEndianU2(&dst->big,w);
|
|
dst->little=w;
|
|
}
|
|
|
|
void FillU4Palindrome(U4Palindrome *dst,U8 d)
|
|
{
|
|
FillBigEndianU4(&dst->big,d);
|
|
dst->little=d;
|
|
}
|
|
|
|
|
|
class CCdUserData
|
|
{
|
|
U8 location,path_entry_num,
|
|
short_dir_blks,long_dir_blks;
|
|
};
|
|
|
|
U8 DoCreateCDFile(LTFile *out_file,LTDirEntry *tempm,
|
|
ISODirEntry *tempi,ISODirEntry *tempi2,
|
|
U8 *cur_blk,
|
|
LTDirEntry *parent,BoolU4 write)
|
|
{
|
|
CCdUserData *tempc;
|
|
LTDirEntry *tempm1,*tempm2;
|
|
LTFile *in_file;
|
|
U1 *buf=MAlloc(CD_BLK_SIZE),*ptr1,*ptr2;
|
|
ISODirEntry *dir_blk_buf=MAllocZ(CD_BLK_SIZE*128),
|
|
*de=dir_blk_buf,*de1;
|
|
ISODirEntry *dir_blk_buf2=MAllocZ(CD_BLK_SIZE*128),
|
|
*de2=dir_blk_buf2,*de12;
|
|
U8 i,l;
|
|
|
|
tempc=parent->user_data;
|
|
|
|
de->length=sizeof(ISODirEntry)-1;
|
|
de->ext_attr_length=0;
|
|
FillU2Palindrome(&de->volume_sequence_num,1);
|
|
LTDateToISO(&de->date,tempm->datetime);
|
|
de->flags=ISO_ATTR_DIR;
|
|
de->name_len=1;
|
|
de->name=0;
|
|
de->length+=de->name_len;
|
|
de+=de->length;
|
|
|
|
de->length=sizeof(ISODirEntry)-1;
|
|
de->ext_attr_length=0;
|
|
FillU4Palindrome(&de->location,tempc->location);
|
|
FillU4Palindrome(&de->size,tempc->short_dir_blks*CD_BLK_SIZE);
|
|
FillU2Palindrome(&de->volume_sequence_num,1);
|
|
LTDateToISO(&de->date,parent->datetime);
|
|
de->flags=ISO_ATTR_DIR;
|
|
de->name_len=1;
|
|
de->name=1;
|
|
de->length+=de->name_len;
|
|
de+=de->length;
|
|
|
|
de2->length=sizeof(ISODirEntry)-1;
|
|
de2->ext_attr_length=0;
|
|
FillU2Palindrome(&de2->volume_sequence_num,1);
|
|
LTDateToISO(&de2->date,tempm->datetime);
|
|
de2->flags=ISO_ATTR_DIR;
|
|
de2->name_len=1;
|
|
de2->name=0;
|
|
de2->length=de2->length+de2->name_len;
|
|
de2+=de2->length;
|
|
|
|
de2->length=sizeof(ISODirEntry)-1;
|
|
de2->ext_attr_length=0;
|
|
FillU4Palindrome(&de2->location,tempc->location+tempc->short_dir_blks);
|
|
FillU4Palindrome(&de2->size,tempc->long_dir_blks*CD_BLK_SIZE);
|
|
FillU2Palindrome(&de2->volume_sequence_num,1);
|
|
LTDateToISO(&de2->date,parent->datetime);
|
|
de2->flags=ISO_ATTR_DIR;
|
|
de2->name_len=1;
|
|
de2->name=1;
|
|
de2->length+=de2->name_len;
|
|
de2+=de2->length;
|
|
|
|
tempm1=tempm->sub;
|
|
while (tempm1) {
|
|
tempm2=tempm1->next;
|
|
if (!write) tempm1->user_data=MAllocZ(sizeof(CCdUserData));
|
|
de1=de;
|
|
de12=de2;
|
|
if (tempm1->attr & LT_ATTR_DIR) {
|
|
l=DoCreateCDFile(out_file,tempm1,de,de2,cur_blk,tempm,write);
|
|
de+=sizeof(ISODirEntry)-1+l;
|
|
de2+=sizeof(ISODirEntry)-1+l<<1;
|
|
} else {
|
|
tempc=tempm1->user_data;
|
|
de->length=sizeof(ISODirEntry)-1;
|
|
de->ext_attr_length=0;
|
|
FillU4Palindrome(&de->location,*cur_blk);
|
|
tempc->location=*cur_blk;
|
|
if (write)
|
|
coutln *cur_blk,":",tempm1->full_name;
|
|
FillU4Palindrome(&de->size,tempm1->size);
|
|
FillU2Palindrome(&de->volume_sequence_num,1);
|
|
LTDateToISO(&de->date,tempm1->datetime);
|
|
de->flags=0;
|
|
de->name_len=StrLen(tempm1->name);
|
|
StrCpy(&de->name,tempm1->name);
|
|
de->length=de->length+de->name_len;
|
|
de+=de->length;
|
|
|
|
de2->length=sizeof(ISODirEntry)-1;
|
|
de2->ext_attr_length=0;
|
|
FillU4Palindrome(&de2->location,*cur_blk);
|
|
FillU4Palindrome(&de2->size,tempm1->size);
|
|
FillU2Palindrome(&de2->volume_sequence_num,1);
|
|
LTDateToISO(&de2->date,tempm1->datetime);
|
|
de2->flags=0;
|
|
de2->name_len=StrLen(tempm1->name)<<1;
|
|
ptr1=&de2->name;
|
|
ptr2=&tempm1->name;
|
|
for (i=0;i<de2->name_len;i=i+2) {
|
|
ptr1++;
|
|
*ptr1++=*ptr2++;
|
|
}
|
|
de2->length+=de2->name_len;
|
|
de2+=de2->length;
|
|
|
|
in_file=FOpen(tempm1->full_name,"r");
|
|
for (i=0;i<(FSize(in_file)+CD_BLK_SIZE-1)/CD_BLK_SIZE;i++) {
|
|
l=4;
|
|
if ((i+1)<<2>(FSize(in_file)+BLK_SIZE-1)/BLK_SIZE) {
|
|
l=((FSize(in_file)+BLK_SIZE-1)/BLK_SIZE)%4;
|
|
MemSet(buf,0,CD_BLK_SIZE);
|
|
}
|
|
if (write) {
|
|
FRBlks(in_file,buf,i<<2,l);
|
|
FWBlks(out_file,buf,(*cur_blk)<<2,l);
|
|
}
|
|
*cur_blk+=1;
|
|
}
|
|
FClose(in_file);
|
|
}
|
|
if ((de1-dir_blk_buf)/CD_BLK_SIZE!=
|
|
(de -dir_blk_buf)/CD_BLK_SIZE) {
|
|
i=de1->length;
|
|
MemCpy(buf,de1,i);
|
|
MemSet(de1,0,i);
|
|
de=dir_blk_buf+((de-dir_blk_buf)/CD_BLK_SIZE)*CD_BLK_SIZE;
|
|
MemCpy(de,buf,i);
|
|
de+=i;
|
|
}
|
|
if ((de12-dir_blk_buf2)/CD_BLK_SIZE!=
|
|
(de2 -dir_blk_buf2)/CD_BLK_SIZE) {
|
|
i=de12->length;
|
|
MemCpy(buf,de12,i);
|
|
MemSet(de12,0,i);
|
|
de2=dir_blk_buf2+((de2-dir_blk_buf2)/CD_BLK_SIZE)*CD_BLK_SIZE;
|
|
MemCpy(de2,buf,i);
|
|
de2+=i;
|
|
}
|
|
tempm1=tempm2;
|
|
}
|
|
|
|
tempc=tempm->user_data;
|
|
|
|
tempi->length=sizeof(ISODirEntry)-1;
|
|
tempi->ext_attr_length=0;
|
|
tempi->flags=ISO_ATTR_DIR;
|
|
if (!tempm->name[0]) {
|
|
tempi->name_len=1;
|
|
tempi->name=1;
|
|
} else {
|
|
tempi->name_len=StrLen(tempm->name);
|
|
StrCpy(&tempi->name,tempm->name);
|
|
}
|
|
tempi->length+=tempi->name_len;
|
|
|
|
l=de+1-dir_blk_buf;
|
|
l=(l+CD_BLK_SIZE-1)/CD_BLK_SIZE;
|
|
FillU4Palindrome(&tempi->size,l*CD_BLK_SIZE);
|
|
FillU4Palindrome(&tempi->location,*cur_blk);
|
|
tempc->short_dir_blks=l;
|
|
tempc->location=*cur_blk;
|
|
FillU4Palindrome(&dir_blk_buf->size,l*CD_BLK_SIZE);
|
|
FillU4Palindrome(&dir_blk_buf->location,*cur_blk);
|
|
FillU2Palindrome(&tempi->volume_sequence_num,1);
|
|
LTDateToISO(&tempi->date,tempm->datetime);
|
|
if (write)
|
|
coutln *cur_blk,":",tempm->full_name;
|
|
if (write)
|
|
FWBlks(out_file,dir_blk_buf,(*cur_blk)<<2,l<<2);
|
|
*cur_blk+=l;
|
|
|
|
tempi2->length=sizeof(ISODirEntry)-1;
|
|
tempi2->ext_attr_length=0;
|
|
tempi2->flags=ISO_ATTR_DIR;
|
|
if (!tempm->name[0]) {
|
|
tempi2->name_len=1;
|
|
tempi->name=1;
|
|
} else {
|
|
tempi2->name_len=StrLen(tempm->name)<<1;
|
|
ptr1=&tempi2->name;
|
|
ptr2=&tempm->name;
|
|
for (i=0;i<tempi2->name_len;i=i+2) {
|
|
ptr1++;
|
|
*ptr1++=*ptr2++;
|
|
}
|
|
}
|
|
tempi2->length+=tempi2->name_len;
|
|
l=de2+1-dir_blk_buf2;
|
|
l=(l+CD_BLK_SIZE-1)/CD_BLK_SIZE;
|
|
FillU4Palindrome(&tempi2->size,l*CD_BLK_SIZE);
|
|
FillU4Palindrome(&tempi2->location,*cur_blk);
|
|
tempc->long_dir_blks=l;
|
|
FillU4Palindrome(&dir_blk_buf2->size,l*CD_BLK_SIZE);
|
|
FillU4Palindrome(&dir_blk_buf2->location,*cur_blk);
|
|
FillU2Palindrome(&tempi2->volume_sequence_num,1);
|
|
LTDateToISO(&tempi2->date,tempm->datetime);
|
|
if (write)
|
|
coutln *cur_blk,":",tempm->full_name;
|
|
if (write)
|
|
FWBlks(out_file,dir_blk_buf2,(*cur_blk)<<2,l<<2);
|
|
*cur_blk+=l;
|
|
|
|
Free(dir_blk_buf);
|
|
Free(dir_blk_buf2);
|
|
Free(buf);
|
|
return tempi->name_len;
|
|
}
|
|
|
|
U8 CDTableLength(LTDirEntry *tempm,U8 *size1,U8 *size2,U8 cur_depth)
|
|
//returns depth
|
|
{
|
|
LTDirEntry *tempm1=tempm->sub;
|
|
U8 max_depth=cur_depth,i;
|
|
while (tempm1) {
|
|
if (tempm1->attr & LT_ATTR_DIR) {
|
|
*size1+=sizeof(ISOPathTableEntry)-2+((StrLen(tempm1->name)+1) & -0x2);
|
|
*size2+=sizeof(ISOPathTableEntry)-2+StrLen(tempm1->name)<<1;
|
|
i=CDTableLength(tempm1,size1,size2,cur_depth+1);
|
|
if (i>max_depth) max_depth=i;
|
|
}
|
|
tempm1=tempm1->next;
|
|
}
|
|
return max_depth;
|
|
}
|
|
|
|
void CDFillPathTable(LTDirEntry *tempm,
|
|
ISOPathTableEntry *itabbuf,ISOPathTableEntry *itabbuf2,
|
|
U8 parent_entry_num,BoolU4 big_endian,U8 *first_free,I8 cur_level,I8 output_level)
|
|
{
|
|
I1 *ptr1,*ptr2;
|
|
U8 i;
|
|
ISOPathTableEntry *tabbuf=*itabbuf;
|
|
ISOPathTableEntry *tabbuf2=*itabbuf2;
|
|
LTDirEntry *tempm1=tempm->sub,*tempm2;
|
|
CCdUserData *tempc;
|
|
|
|
if (cur_level==output_level) {
|
|
while (tempm1) {
|
|
if (tempm1->attr & LT_ATTR_DIR) {
|
|
tempc=tempm1->user_data;
|
|
tempc->path_entry_num=*first_free;
|
|
tabbuf->name_len=StrLen(tempm1->name);
|
|
if (big_endian) {
|
|
FillBigEndianU4(&tabbuf->blk,tempc->location);
|
|
FillBigEndianU2(&tabbuf->parent_entry_num,parent_entry_num);
|
|
} else {
|
|
tabbuf->blk=tempc->location;
|
|
tabbuf->parent_entry_num=parent_entry_num;
|
|
}
|
|
StrCpy(&tabbuf->name,tempm1->name);
|
|
|
|
tabbuf+=sizeof(ISOPathTableEntry)-2+
|
|
((StrLen(tempm1->name)+1) & -0x2);
|
|
|
|
tabbuf2->name_len=StrLen(tempm1->name)<<1;
|
|
if (big_endian) {
|
|
FillBigEndianU4(&tabbuf2->blk,tempc->location+tempc->short_dir_blks);
|
|
FillBigEndianU2(&tabbuf2->parent_entry_num,parent_entry_num);
|
|
} else {
|
|
tabbuf2->blk=tempc->location+tempc->short_dir_blks;
|
|
tabbuf2->parent_entry_num=parent_entry_num;
|
|
}
|
|
ptr1=&tabbuf2->name;
|
|
ptr2=&tempm1->name;
|
|
for (i=0;i<tabbuf2->name_len;i=i+2) {
|
|
ptr1++;
|
|
*ptr1++=*ptr2++;
|
|
}
|
|
tabbuf2+=sizeof(ISOPathTableEntry)-2+
|
|
StrLen(tempm1->name)<<1;
|
|
*first_free+=1;
|
|
}
|
|
tempm1=tempm1->next;
|
|
}
|
|
*itabbuf=tabbuf;
|
|
*itabbuf2=tabbuf2;
|
|
}
|
|
tempm1=tempm->sub;
|
|
while (tempm1) {
|
|
tempm2=tempm1->next;
|
|
if (tempm1->attr & LT_ATTR_DIR) {
|
|
tempc=tempm1->user_data;
|
|
CDFillPathTable(tempm1,itabbuf,itabbuf2,tempc->path_entry_num,
|
|
big_endian,first_free,cur_level+1,output_level);
|
|
}
|
|
tempm1=tempm2;
|
|
}
|
|
}
|
|
|
|
class ElTorito
|
|
{
|
|
U2 w[16];
|
|
U1 bootable; //88=bootable 00=not bootable
|
|
U1 media_type; //0=no emulation 4=hard disk
|
|
U2 load_seg; //0000->07C0
|
|
U1 sys_type;
|
|
U1 zero;
|
|
U2 sector_cnt;
|
|
U4 load_rba; //start address of virtual disk
|
|
U1 zero2[20];
|
|
};
|
|
|
|
public U8 CreateCDFile(I1 *filename,I1 src_drive,
|
|
I1 *bootfile=NULL)
|
|
{
|
|
ISOPrimaryDescriptor *iso =MAllocZ(CD_BLK_SIZE),
|
|
*iso1=MAllocZ(CD_BLK_SIZE),
|
|
*iso2=MAllocZ(CD_BLK_SIZE),
|
|
*iso3=MAllocZ(CD_BLK_SIZE);
|
|
LTDirEntry *rootdir=MAllocZ(sizeof(LTDirEntry));
|
|
U8 my_flags=(1<<FUf_RECURSE);
|
|
U8 cur_blk=0,bsize,tabsize,tabsize2,first_free,max_depth;
|
|
U4 *d;
|
|
I1 mask[8];
|
|
I1 *filename2=DefaultExtension(filename,"ISO");
|
|
ElTorito *et=MAllocZ(CD_BLK_SIZE);
|
|
U1 *buf=MAllocZ(CD_BLK_SIZE),
|
|
*bootfile_buf=NULL;
|
|
ISOPathTableEntry *tabbuf=NULL,*tabbuf2=NULL,
|
|
*itabbuf,*itabbuf2;
|
|
BoolU4 okay=TRUE;
|
|
U8 i,j;
|
|
LTFile *out_file=NULL;
|
|
ISODirEntry *tempi;
|
|
CCdUserData *tempc;
|
|
|
|
SPrintF(mask,"%c:/*",src_drive);
|
|
if (bootfile)
|
|
bootfile_buf=ReadFile(bootfile,&bsize);
|
|
rootdir->attr=LT_ATTR_DIR;
|
|
rootdir->sub=FindFiles(mask,&my_flags);
|
|
rootdir->datetime=GetCurTimeLTDate;
|
|
rootdir->user_data=MAllocZ(sizeof(CCdUserData));
|
|
tempc=rootdir->user_data;
|
|
tempc->path_entry_num=1;
|
|
|
|
if (okay) {
|
|
cur_blk=CD_FILE_OFFSET>>2;
|
|
if (bootfile_buf)
|
|
cur_blk+=2;
|
|
DoCreateCDFile(out_file,rootdir,
|
|
&iso->root_directory_record,
|
|
&iso2->root_directory_record,
|
|
&cur_blk,rootdir,FALSE);
|
|
tabsize=sizeof(ISOPathTableEntry);
|
|
tabsize2=sizeof(ISOPathTableEntry);
|
|
max_depth=CDTableLength(rootdir,&tabsize,&tabsize2,1);
|
|
FillU4Palindrome(&iso->path_table_size,tabsize);
|
|
FillU4Palindrome(&iso2->path_table_size,tabsize2);
|
|
tabsize=(tabsize+CD_BLK_SIZE-1)/CD_BLK_SIZE;
|
|
cur_blk+=tabsize<<1;
|
|
tabsize2=(tabsize2+CD_BLK_SIZE-1)/CD_BLK_SIZE;
|
|
cur_blk+=tabsize2<<1;
|
|
}
|
|
if (okay) {
|
|
if (FileAttr(filename2) & LT_ATTR_CONTIGUOUS)
|
|
out_file=FOpen(filename2,"wc",cur_blk<<2);
|
|
else
|
|
out_file=FOpen(filename2,"w",cur_blk<<2);
|
|
if (!out_file)
|
|
okay=FALSE;
|
|
}
|
|
if (okay) {
|
|
cur_blk=0;
|
|
while (cur_blk<CD_FILE_OFFSET>>2) {
|
|
FWBlks(out_file,buf,cur_blk<<2,4);
|
|
cur_blk++;
|
|
}
|
|
iso->type=ISOT_PRIMARY_VOLUME_DESC;
|
|
StrCpy(iso->id,"CD001");
|
|
iso->version=1;
|
|
FillU2Palindrome(&iso->volume_set_size,1);
|
|
FillU2Palindrome(&iso->volume_sequence_number,1);
|
|
FillU2Palindrome(&iso->logical_block_size,CD_BLK_SIZE);
|
|
iso->file_structure_version=1;
|
|
|
|
iso2->type=ISOT_SUPPLEMENTARY_DESC;
|
|
StrCpy(iso2->id,"CD001");
|
|
iso2->version=1;
|
|
FillU2Palindrome(&iso2->volume_set_size,1);
|
|
FillU2Palindrome(&iso2->volume_sequence_number,1);
|
|
FillU2Palindrome(&iso2->logical_block_size,CD_BLK_SIZE);
|
|
iso2->file_structure_version=1;
|
|
|
|
iso1->type=ISOT_BOOT_RECORD;
|
|
StrCpy(iso1->id,"CD001");
|
|
iso1->version=1;
|
|
StrCpy(iso1+7,"EL TORITO SPECIFICATION");
|
|
|
|
cur_blk=CD_FILE_OFFSET>>2;
|
|
|
|
if (bootfile_buf) {
|
|
d=iso1+0x47;
|
|
*d=cur_blk;
|
|
et->w[0]=1;
|
|
StrCpy(&et->w[2],"LoseThos");
|
|
et->w[15]=0xAA55;
|
|
j=0;
|
|
for (i=0;i<16;i++) //Checksum
|
|
j+=et->w[i];
|
|
et->w[14]=-j;
|
|
if (bootfile_buf)
|
|
et->bootable=0x88;
|
|
et->media_type=0; //0=no emu 2=1.44meg 4=hard drive
|
|
et->sector_cnt=4;
|
|
et->load_rba=cur_blk+1;
|
|
coutln cur_blk,": Pre Boot Blk";
|
|
FWBlks(out_file,et,cur_blk<<2,4);
|
|
cur_blk++;
|
|
|
|
coutln cur_blk,": Boot Blk";
|
|
FWBlks(out_file,bootfile_buf,cur_blk<<2,4);
|
|
cur_blk++;
|
|
}
|
|
|
|
DoCreateCDFile(out_file,rootdir,
|
|
&iso->root_directory_record,
|
|
&iso2->root_directory_record,
|
|
&cur_blk,rootdir,TRUE);
|
|
|
|
tabbuf=MAllocZ(tabsize*CD_BLK_SIZE);
|
|
iso->type_l_path_table=cur_blk;
|
|
tabbuf->name_len=2; //Fill-in adam entry
|
|
tempi=&iso->root_directory_record;
|
|
tabbuf->blk=tempi->location.little;
|
|
tabbuf->parent_entry_num=1;
|
|
tabbuf2=MAllocZ(tabsize2*CD_BLK_SIZE);
|
|
iso2->type_l_path_table=cur_blk+tabsize;
|
|
tabbuf2->name_len=2; //Fill-in adam entry
|
|
tempi=&iso2->root_directory_record;
|
|
tabbuf2->blk=tempi->location.little;
|
|
tabbuf2->parent_entry_num=1;
|
|
itabbuf=tabbuf+sizeof(ISOPathTableEntry);
|
|
itabbuf2=tabbuf2+sizeof(ISOPathTableEntry);
|
|
first_free=2;
|
|
for (i=1;i<=max_depth;i++)
|
|
CDFillPathTable(rootdir,&itabbuf,&itabbuf2,
|
|
1,FALSE,&first_free,1,i);
|
|
coutln cur_blk,": Path Table 0";
|
|
FWBlks(out_file,tabbuf,cur_blk<<2,tabsize<<2);
|
|
cur_blk+=tabsize;
|
|
coutln cur_blk,": Path Table 1";
|
|
FWBlks(out_file,tabbuf2,cur_blk<<2,tabsize2<<2);
|
|
cur_blk+=tabsize2;
|
|
|
|
|
|
MemSet(tabbuf,0,tabsize*CD_BLK_SIZE);
|
|
FillBigEndianU4(&iso->type_m_path_table,cur_blk);
|
|
tabbuf->name_len=2; //Fill-in adam entry
|
|
tempi=&iso->root_directory_record;
|
|
tabbuf->blk=tempi->location.big;
|
|
FillBigEndianU2(&tabbuf->parent_entry_num,1);
|
|
MemSet(tabbuf2,0,tabsize2*CD_BLK_SIZE);
|
|
FillBigEndianU4(&iso2->type_m_path_table,cur_blk+tabsize);
|
|
tabbuf2->name_len=2; //Fill-in adam entry
|
|
tempi=&iso2->root_directory_record;
|
|
tabbuf2->blk=tempi->location.big;
|
|
FillBigEndianU2(&tabbuf2->parent_entry_num,1);
|
|
itabbuf=tabbuf+sizeof(ISOPathTableEntry);
|
|
itabbuf2=tabbuf2+sizeof(ISOPathTableEntry);
|
|
first_free=2;
|
|
for (i=1;i<=max_depth;i++)
|
|
CDFillPathTable(rootdir,&itabbuf,&itabbuf2,
|
|
1,TRUE,&first_free,1,i);
|
|
coutln cur_blk,": Path Table 2";
|
|
FWBlks(out_file,tabbuf,cur_blk<<2,tabsize<<2);
|
|
cur_blk+=tabsize;
|
|
coutln cur_blk,": Path Table 3";
|
|
FWBlks(out_file,tabbuf2,cur_blk<<2,tabsize2<<2);
|
|
cur_blk+=tabsize2;
|
|
|
|
DelLTDirList(rootdir); //TODO: Free user_data
|
|
FillU4Palindrome(&iso->volume_space_size,cur_blk);
|
|
FillU4Palindrome(&iso2->volume_space_size,cur_blk);
|
|
FWBlks(out_file,iso,16<<2,4);
|
|
|
|
iso3->type=ISOT_TERMINATOR;
|
|
StrCpy(iso3->id,"CD001");
|
|
iso3->version=1;
|
|
if (bootfile_buf) {
|
|
FWBlks(out_file,iso1,17<<2,4);
|
|
FWBlks(out_file,iso2,18<<2,4);
|
|
FWBlks(out_file,iso3,19<<2,4);
|
|
} else {
|
|
FWBlks(out_file,iso2,17<<2,4);
|
|
FWBlks(out_file,iso3,18<<2,4);
|
|
}
|
|
} else
|
|
cur_blk=0;
|
|
|
|
FClose(out_file);
|
|
Free(tabbuf);
|
|
Free(tabbuf2);
|
|
Free(et);
|
|
Free(bootfile_buf);
|
|
Free(iso);
|
|
Free(iso1);
|
|
Free(iso2);
|
|
Free(iso3);
|
|
Free(filename2);
|
|
return cur_blk;
|
|
}
|
|
|
|
|
|
public void SetDriveTextAttr(I1 drive=0,U1 attr)
|
|
{
|
|
LTPartition *p;
|
|
try {
|
|
p=DriveToPartition(drive);
|
|
p->text_attr=attr;
|
|
} catch {
|
|
Fs->catch_except=TRUE;
|
|
}
|
|
}
|
|
|
|
public void PrintFDriveTextAttr(I1 drive=0)
|
|
{
|
|
LTPartition *p=DriveToPartition(drive);
|
|
U1 fg=p->text_attr&0xF,bg=p->text_attr>>4;
|
|
if (fg!=bg)
|
|
PrintF("$$FG,%d$$$$BG,%d$$",fg,bg);
|
|
}
|
|
|
|
U8 SizeFlattenLTDirTree(LTDirEntry *tempm)
|
|
{
|
|
U8 result=0;
|
|
while (tempm) {
|
|
result+=LT_DIR_ENTRY_SIZE+1;
|
|
if (tempm->attr & LT_ATTR_DIR)
|
|
result+=SizeFlattenLTDirTree(tempm->sub);
|
|
tempm=tempm->next;
|
|
}
|
|
return result+1;
|
|
}
|
|
|
|
U8 FillFlattenLTDirTree(LTDirEntry *tempm,U1 *dst)
|
|
{
|
|
U8 result=0,i;
|
|
while (tempm) {
|
|
*dst++=1;
|
|
result++;
|
|
i=LT_DIR_ENTRY_SIZE;
|
|
MemCpy(dst,&tempm->start,i);
|
|
dst+=i;
|
|
result+=i;
|
|
if (tempm->attr & LT_ATTR_DIR) {
|
|
i=FillFlattenLTDirTree(tempm->sub,dst);
|
|
dst+=i;
|
|
result+=i;
|
|
}
|
|
tempm=tempm->next;
|
|
}
|
|
*dst=0;
|
|
return result+1;
|
|
}
|
|
|
|
public U1 *FlattenLTDirTree(LTDirEntry *tempm,U8 *size=NULL)
|
|
{
|
|
U8 i=SizeFlattenLTDirTree(tempm);
|
|
U1 *buf=MAlloc(i);
|
|
FillFlattenLTDirTree(tempm,buf);
|
|
if (size) *size=i;
|
|
return buf;
|
|
}
|
|
|
|
U1 *DoUnflattenLTDirTree(U1 *src,LTDirEntry **tempm)
|
|
{
|
|
U8 i;
|
|
LTDirEntry *tempm1;
|
|
if (*src++) {
|
|
tempm1=MAllocZ(sizeof(LTDirEntry));
|
|
*tempm=tempm1;
|
|
i=LT_DIR_ENTRY_SIZE;
|
|
MemCpy(&tempm1->start,src,i);
|
|
src+=i;
|
|
if (tempm1->attr & LT_ATTR_DIR)
|
|
src=DoUnflattenLTDirTree(src,&tempm1->sub);
|
|
src=DoUnflattenLTDirTree(src,&tempm1->next);
|
|
} else
|
|
*tempm=NULL;
|
|
return src;
|
|
}
|
|
|
|
public LTDirEntry *UnflattenLTDirTree(U1 *src)
|
|
{
|
|
LTDirEntry *tempm=NULL;
|
|
DoUnflattenLTDirTree(src,&tempm);
|
|
return tempm;
|
|
}
|