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 if (unlock) 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 (firstcur_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 if (unlock) UnlockPartition(p); } void InitLTPartition(LTPartition *p,BoolU4 unlock) { LTBootStruct br; try { LockPartition(p); RBlks(p,&br,p->offset,1,FALSE); if (br.signature!=PT_LT || br.signature2!=0xAA55) throw(EXCEPT_PARTITION,12); p->type=PT_LT; FreeLTFreeList(p,FALSE); p->spc=br.sectors_per_cluster; p->size=br.sectors; p->data=p->offset+1+br.bitmap_sectors-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 if (unlock) UnlockPartition(p); } 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,n; 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<0x20000) br->sectors_per_cluster=1; else if (p->size<0x200000) br->sectors_per_cluster=2; else if (p->size<0x2000000) br->sectors_per_cluster=4; else if (p->size<0x20000000) br->sectors_per_cluster=8; else if (p->size<0x200000000) br->sectors_per_cluster=16; else br->sectors_per_cluster=32; br->signature=PT_LT; br->signature2=0xAA55; br->sectors=p->size; n=br->sectors_per_cluster*(BLK_SIZE<<3); n=(br->sectors+n-1)/n; br->bitmap_sectors=n; br->unique_id=BootTime; br->root_cluster=0; if (quick) i=n+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(p->spc<attr=LT_ATTR_DIR|LT_ATTR_CONTIGUOUS; dLT->name[0]='.'; dLT->cluster=br->root_cluster; dLT->size=p->spc<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,p->spc,FALSE); InitLTPartition(p,FALSE); UnlockPartition(p); } catch UnlockPartition(p); Free(br); Free(root_dir); } BoolU8 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]; BoolU4 cont2=FALSE; U1 ch; MemSet(result,0,sizeof(LTDirEntry)); CheckLTPartition(p); if (p->type!=PT_LT) PutSysTextErr("ST_NOT_LT"); else if (!ToLTFilename(dname,name)) PutSysTextErr("ST_INVALID_FILENAME"); else { try { LockPartition(p); buf2=MAlloc(p->spc<size); RClusters(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS/p->spc,FALSE); Free(buf2); ptr=buf-offset(LTDirEntry.start); ptr->name[0]='.'; ptr->name[1]=0; while (TRUE) { 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 if (unlock) UnlockPartition(p); } return res; } 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=p->spc<type!=PT_LT) PutSysTextErr("ST_NOT_LT"); 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; c=RClusters(p,buf,c,cluster_cnt,FALSE,TRUE); 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; } BoolU8 CdLT(I1 *name,U8 cur_dir_cluster) { LTDirEntry de; if (Fs->cur_partition->type!=PT_LT) PutSysTextErr("ST_NOT_LT"); else { if (FindLTFile(Fs->cur_partition,cur_dir_cluster, name,&de,TRUE,FALSE,TRUE)) { return TRUE; } else { cout name," "; PutSysTextErr("ST_FILE_NOT_FOUND"); } } return FALSE; } 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) PutSysTextErr("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 if (unlock) UnlockPartition(p); } } U8 AllocLTClusters(LTPartition *p,U8 cnt, BoolU4 unlock) { LTFreeList *tempf,*best_free=NULL; U8 i,first,best_size=MAX_U8; if (!cnt) Debugger; try { LockPartition(p); if (!p->next_free) BuildLTFreeList(p,FALSE); tempf=p->next_free; while (tempf!=&p->next_free) { if (tempf->size>=cnt && tempf->sizesize; if (tempf->size==cnt) break; } tempf=tempf->next; } if (!best_free) Debugger; first=best_free->start; for (i=0;icur_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 if (unlock) UnlockPartition(p); return first; } BoolU8 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,n=BLK_SIZE/LT_DIR_ENTRY_SIZE,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(p->spc<size); RClusters(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS/p->spc,FALSE); dir_size=ptr->size; ptr=buf-offset(LTDirEntry.start)+LT_DIR_ENTRY_SIZE; Free(buf2); while (TRUE) { ch=ptr->name[0]; if (!ch) { if (!written) MemCpy(&ptr->start,&de->start,LT_DIR_ENTRY_SIZE); if ((i+1)*LT_DIR_ENTRY_SIZE+j<data+cur_dir_cluster*p->spc+j,1,FALSE); else { buf2=MAllocZ(dir_size+p->spc<spc<spc<spc<size=dir_size; ptr->expanded_size=dir_size; ptr->cluster=c; WClusters(p,buf,c,dir_size/(p->spc<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=NewStr(cur_dir); parent_dir=NewStr(cur_dir); RemoveLastSeg(parent_dir,"/",temp); if (!*parent_dir) { Free(parent_dir); parent_dir=NewStr("/"); } if (FindLTFile(p,NameToDirCluster(p,parent_dir,FALSE), temp,&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 Debugger; 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<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<spc<start,&de->start,LT_DIR_ENTRY_SIZE); else ptr->attr|=LT_ATTR_DELETED; WBlks(p,buf+j<data+cur_dir_cluster*p->spc+j,1,FALSE); break; } } ptr+=LT_DIR_ENTRY_SIZE; if (++i>=n) { j++; i=0; } } Free(buf); if (unlock) UnlockPartition(p); } catch if (unlock) UnlockPartition(p); return FALSE; } BoolU8 DelLTFiles(LTPartition *p,I1 *cur_dir,I1 *wild, BoolU4 del_dir=FALSE,BoolU4 print_msg=TRUE) { LTDirEntry *buf,*buf2,*ptr; U8 i=0,j=0,n=BLK_SIZE/LT_DIR_ENTRY_SIZE; U1 ch; U8 cur_dir_cluster=NameToDirCluster(p,cur_dir,TRUE); try { LockPartition(p); buf2=MAlloc(p->spc<size); RClusters(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS/p->spc,FALSE); Free(buf2); ptr=buf-offset(LTDirEntry.start); ptr->name[0]='.'; ptr->name[1]=0; while (TRUE) { 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<data+cur_dir_cluster*p->spc+j,1,FALSE); FreeLTClusters(p,ptr->cluster, (ptr->size+p->spc<spc<=n) { 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=p->spc<type!=PT_LT) PutSysTextErr("ST_NOT_LT"); else if (!ToLTFilename(de.name,name)) PutSysTextErr("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; if (cluster_cnt) WClusters(p,buf,c,cluster_cnt,TRUE,TRUE); NewLTDirEntry2(p,cur_dir,&de,TRUE,TRUE); if (ac2) *ac2=ac; else Free(ac); } return c; } LTDirEntry *FindLTFiles(I1 *wild,U8 fuf_flags,LTDirEntry *parent=NULL) { LTPartition *p=Fs->cur_partition; LTDirEntry *buf,*buf2,*ptr; U8 cur_dir_cluster=NameToDirCluster(p,Fs->cur_dir,FALSE); U1 ch; LTDirEntry *result=NULL,*tempm; LockPartition(p); buf2=MAlloc(p->spc<size); RClusters(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS/p->spc,FALSE); Free(buf2); ptr=buf-offset(LTDirEntry.start); 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 (TRUE) { 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); tempm->parent=parent; 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,tempm); Cd(".."); LockPartition(p); } else if ((!(tempm->attr & LT_ATTR_DIR) && !Bt(&fuf_flags,FUf_JUST_DIRS) || !Bt(&fuf_flags,FUf_RECURSE)) && !(Bt(&fuf_flags,FUf_RECURSE) && tempm->name[0]=='.') && 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; }