/* ** FO v1.0 by FBJ ** ** (c)Copyright 1991, Campagne Fabien, All Rights Reserved ** ** Campagne Fabien ** 805, Rue des Gentianes ** 39000 Lons Le saunier ** FRANCE ** ** un optimiseur de disk (rapide). ** FO doit être linké avec TD.o ** pour compiler: cc FO "objects:TD.o -gs" ** ** */ #include #include #include #include #include #include #include "fbj/Blocks.h" #include "fbj/ShortBlocks.h" #include "fbj/TDprotos.h" /*#define DEBUG 1 */ #define ON 1L #define OFF 0L #define R CMD_READ #define W CMD_WRITE #define used 0 #define var Variables #define BBM VarAdr->BuffBitMap /*#define BootB VarAdr->BuffTrack*/ #define BT VarAdr->BuffTrack #define sourceDrive VarAdr->sourcedrive #define destDrive VarAdr->destdrive #define dsklist VarAdr->disklist #define CLI VarAdr->Cli #define err VarAdr->Err #define GFree VarAdr->GestFree #define DFree VarAdr->DataFree #define FLnog VarAdr->FLnoG #define drivebusy VarAdr->DriveBusy #define FORMAT VarAdr->Format #define CHECK VarAdr->Check extern struct DosLibrary *DOSBase; struct Variables{ LONG *BuffBitMap; /* adr du buffer contenant le bloc BitMap */ WORD BitMap; /* n° du Block BitMap */ LONG *BuffTrack; /* Buffer de track pour le formattage de la destination */ LONG *Empty; /* pointeur sur zone contenant datas pour blocs vides */ BYTE sourcedrive; /* */ BYTE destdrive; /* */ LONG TotalBlocks; /* */ LONG (*TableMem)[]; /* */ WORD EndTMem; /* indice sur le dernier LONG occupé de TableMem */ WORD GestFree; /* dernier bloc de Gestion libre */ WORD DataFree; /* dernier bloc de Data libre */ LONG *inCHIP; /* Buffer 512L en CHIP pour TD */ struct DiskList *disklist; /* */ BYTE Cli; /* if non set, optimize for WB use */ BYTE FLnoG; /* if set, File List will no longuer be considered as Gestion B */ BYTE Format; /* if set, the whole disk is formatted */ BYTE Check; /* if set, The Dos Structure of Source is Checked */ WORD Err; /* compteur d' erreur */ BYTE DriveBusy[5]; }; struct var *VarAdr; void RendMem(void); void FreeBusy(void); main(ac,av) BYTE *av[]; WORD ac; { WORD TotalBlocks,i,j=0,Perr=0; LONG k; BYTE argn; puts("FO v1.0 Fast Optimiser by FBJ."); VarAdr=(struct var *)AllocMem(sizeof(struct var),MEMF_CLEAR|MEMF_PUBLIC); atexit(RendMem); WBench(1); /* ( Par défault ) */ forFDir(0); NoFormat(0); Check(0); if (ac<3 ) { if (*av[1]=='?') {help(); exit(0);} else puts("? for help");exit(0); } if (strnicmp(av[1],"df",2)) {puts("1st arg: source drive"); exit(0);} if (strnicmp(av[2],"df",2)) {puts("2nd arg: dest drive"); exit(0);} sourceDrive=*(av[1]+2)-48; destDrive= *(av[2]+2)-48; if (sourceDrive<0 || sourceDrive>3) {puts("1st arg: source drive"); exit(0);} if (destDrive<0 || destDrive>3) {puts("2nd arg: dest drive"); exit(0);} argn=3; while (ac>=argn && *av[argn]=='-') { switch (*(av[argn]+1)) { case 'w' : WBench(1); break; case 'W' : WBench(1); break; case 'c' : ComLineInt(1); break; case 'n' : if ( !strnicmp(av[argn]+1,"nfo",3) ) NoFormat(1); break; case 'N' : if ( !strnicmp(av[argn]+1,"nfo",3) ) NoFormat(1); break; case 'F' : if ( !strnicmp(av[argn]+1,"FDir",4) ) forFDir(1); break; case 'C' : Check(1); break; } argn++; } puts("Now insert SOURCE disk and RETURN"); while ( (getchar()) != 10) ; DiskBUSY(av[2],1); atexit(FreeBusy); strncpy(drivebusy,av[2],5); if (!OpenTD(sourceDrive)) {puts("Source drive Not Available"); exit(0);} if (!OpenTD(destDrive)) {puts("Dest drive Not Available"); exit(0);} atexit(CloseTD); VarAdr->inCHIP=(LONG *)AllocMem(512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC); VarAdr->BuffBitMap=(LONG *)AllocMem(512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC); Read_WriteB(R,sourceDrive,BBM,880L); /* charge le Root */ /* on trouve BitMap */ VarAdr->BitMap=(WORD)((struct RootB *)(VarAdr->BuffBitMap))->BitMapTable[0]; #ifdef DEBUG printf("n ° du bloc BitMap :%d\n",VarAdr->BitMap); #endif /* on le charge */ Read_WriteB(R,sourceDrive,BBM,VarAdr->BitMap); /* on réserve le buffer de track et on charge le bootBlock oû il faut */ BT=(LONG *)AllocMem(11*512L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC); Read_WriteB(R,sourceDrive,BT,0L); Read_WriteB(R,sourceDrive,BT+128L,1L); #ifdef DEBUG printf("Adr du Buff de Track : %p\n",BT); #endif VarAdr->Empty=(LONG *)AllocMem(512L,MEMF_CLEAR|MEMF_PUBLIC); if (VarAdr->Empty==0) Perr++; VarAdr->TotalBlocks=HowBlockUsed(BBM); #ifdef DEBUG printf("Total des Blocks Alloués : %d\n",VarAdr->TotalBlocks); #endif VarAdr->TableMem=(APTR)AllocMem(VarAdr->TotalBlocks*4+4,MEMF_CLEAR|MEMF_PUBLIC); #ifdef DEBUG printf("Adr de TableMem : %p\n",&VarAdr->TableMem); #endif j=0; for (i=0;i!=VarAdr->TotalBlocks;i++) { k=AllocMem(512L,MEMF_CLEAR|MEMF_PUBLIC); if (k==0) {Perr=103; break;} (*VarAdr->TableMem)[j++]=k; } (*VarAdr->TableMem)[j]=0L; VarAdr->EndTMem=j-1; if (Perr) { puts("Désolé, pas assez de mémoire pour optimisation rapide"); exit(0); } /* On initialise la strucure DiskList */ dsklist=(struct SinitB*)AllocMem(sizeof(struct SinitB),MEMF_CLEAR|MEMF_PUBLIC); dsklist->dl_Bloc=-9; ((struct SinitB*)dsklist)->dl_Type=0; /* Avec un bloc initial qui ne sert à rien mais est bien pratique */ LoadBinMem(); MtrOff(sourceDrive); if (CHECK) { puts("Checking Dos Structure of disk"); CheckDosStruct(); if (!err) puts("No Error in Dos Structure"); else {printf("%d ERRORS on disk !! FO Stopped\n",err); exit(0);} } MtrOff(sourceDrive); puts("Now I optimize ..."); Optimize(); BitMap(); ChangeBlocks(); puts("Writing result to destination disk"); MemToDisk(); puts("Fast Optimization done."); exit(0); } void RendMem() { LONG M=1; WORD i=0; if (VarAdr->BuffBitMap) { FreeMem(BBM,512L); BBM=0L; } if (VarAdr->BuffTrack) { FreeMem(BT,11*512L); BT=0L; } if (VarAdr->Empty) { FreeMem(VarAdr->Empty,512L); VarAdr->Empty=0; } i=0; while (M) { M=(*VarAdr->TableMem)[i++]; if (M) FreeMem(M,512L); else break; } if (VarAdr->TableMem) FreeMem(VarAdr->TableMem,VarAdr->TotalBlocks*4+4); if (dsklist) FreeDiskList(); if (VarAdr->inCHIP) {FreeMem(VarAdr->inCHIP,512L); VarAdr->inCHIP=0;} if (VarAdr) {FreeMem(VarAdr,sizeof(struct var)); VarAdr=0;} } void FreeBusy() { DiskBUSY(drivebusy,0); } /* isBlocUsed renvoie 1 si Block libre ou 0 si block occuppé il se réfère au BitMap */ isBlocUsed(Bloc) WORD Bloc; { LONG A,B; if (Bloc==0 || Bloc==1) return(1); /* Faux car blocks used mais pratique ! */ A=*(BBM+1+(Bloc-2)/32); B=(A>>(((Bloc-2)%32)) & 0x1L); return(B); } HowBlockUsed(AdrBM) LONG *AdrBM; { WORD i,TotalBlocks=0; for (i=2;i<=1760;i++) { TotalBlocks+=(WORD)!(isBlocUsed(i)); } return(TotalBlocks); } LoadBinMem() { LONG n,m=0; APTR buff1,buff2,inCHIP; struct DiskList *dlist; inCHIP=VarAdr->inCHIP; puts("Reading Source and preparing for Fast Optimising"); for (n=2;n<1760;n++) { if (isBlocUsed(n)==used) { buff1=(APTR)(Buffer(m++)); if (TypeOfMem(buff1)&MEMF_CHIP) buff2=buff1; else buff2=inCHIP; if (Read_WriteB(R,(LONG)sourceDrive,buff2,n)) { puts("Read Error, can' t optimize"); exit(0); } if (buff2==inCHIP) CopyMemQuick(buff2,buff1,512L); #ifdef DEBUG if (!Buffer(m-1)) { puts("Problème avec LoadBinMem !"); exit(0); } #endif Organising(buff1,dlist,n); } if ((n%22)==0) { printf("CYL %d",n/22); putchar(13); fflush(stdout); } } } /* Cherche et renvoie l' adresse oû ranger le bloc */ Buffer(m) LONG m; { return((*VarAdr->TableMem)[m]); } Organising(buff1,dlist,n) LONG *buff1; LONG n; struct DiskList *dlist; { switch (*buff1) { case 2L : { switch (*(buff1+127)) { case 1L: /* RootBlock */ { /* printf("Type : RootB , bloc #%d\n",n);*/ dlist=(struct DiskList *)Preparing(sizeof(struct SRootB),dsklist); dlist->dl_NextB=0; dlist->dl_Bloc=n; dlist->dl_Bloc2=n; dlist->dl_Data=0; dlist->dl_Type=3; dlist->dl_types.dl_type3.reserved1=0; dlist->dl_AdrB=buff1; break; } case -3L: /* File Header Block */ { /* printf("Type : File HeaderB , bloc #%d\n",n);*/ dlist=(struct DiskList *)Preparing(sizeof(struct SFileHderB),dsklist); dlist->dl_NextB=0; dlist->dl_Bloc=n; dlist->dl_Bloc2=0; dlist->dl_Type=-1; dlist->dl_types.dl_type1.dl_Parent=((struct FileHeaderB*)buff1)->ParentDir; dlist->dl_types.dl_type1.dl_NextHash=((struct FileHeaderB*)buff1)->NextHash; dlist->dl_types.dl_type1.dl_Extension=((struct FileHeaderB*)buff1)->Extension; dlist->dl_AdrB=buff1; dlist->dl_Data=isinfo(buff1); break; } case 2L: /* User Directory Block */ { /* printf("Type : User DirB , bloc #%d\n",n);*/ dlist=(struct DiskList *)Preparing(sizeof(struct SUserDirB),dsklist); dlist->dl_NextB=0; dlist->dl_Bloc=n; dlist->dl_Bloc2=0; dlist->dl_Type=4; dlist->dl_types.dl_type4.dl_Parent=((struct UserDirB*)buff1)->ParentDir; dlist->dl_types.dl_type4.dl_NextHash=((struct UserDirB*)buff1)->NextHash; dlist->dl_AdrB=buff1; dlist->dl_Data=isinfo(buff1); break; } default : { printf("Type : UnknownB1 , bloc #%d\n",n); dlist=(struct DiskList *)Preparing(sizeof(struct SUnknownB),dsklist); dlist->dl_NextB=0; dlist->dl_Bloc=n; dlist->dl_Bloc2=n; dlist->dl_Data=0; dlist->dl_Type=-2; dlist->dl_AdrB=buff1; break; } } break; } case 16L: if (*(buff1+127)==-3) /* FileList Block */ { /* printf("Type : File ListB , bloc #%d\n",n);*/ dlist=(struct DiskList *)Preparing(sizeof(struct SFileListB),dsklist); dlist->dl_NextB=0; dlist->dl_Bloc=n; dlist->dl_Bloc2=0; dlist->dl_Data=0; dlist->dl_Type=13; dlist->dl_types.dl_type13.dl_FileHeader=((struct FileListB*)buff1)->ParentFH; dlist->dl_types.dl_type13.dl_Extension=((struct FileListB*)buff1)->Extension; dlist->dl_AdrB=buff1; break; } case 8L: /* Data Block */ { /* printf("Type : DataB , bloc #%d\n",n);*/ dlist=(struct DiskList *)Preparing(sizeof(struct SDataB),dsklist); dlist->dl_NextB=0; dlist->dl_Bloc=n; dlist->dl_Bloc2=0; dlist->dl_Data=0; dlist->dl_Type=8; dlist->dl_types.dl_type8.dl_FileHeader=((struct DataB*)buff1)->HeaderKey; dlist->dl_types.dl_type8.dl_NextData=((struct DataB*)buff1)->NextDataBlock; dlist->dl_AdrB=buff1; break; } default : { /* printf("Type : UnknownB2 , bloc #%d\n",n); *//* Par ex le B BitMap */ if (n==VarAdr->BitMap) break; dlist=(struct DiskList *)Preparing(sizeof(struct SUnknownB),dsklist); dlist->dl_NextB=0; dlist->dl_Bloc=n; dlist->dl_Bloc2=n; dlist->dl_Data=0; dlist->dl_Type=-2; dlist->dl_AdrB=buff1; break; } } } Preparing(structsize,adr) LONG structsize; struct DiskList *adr; { static struct DiskList *Sadr=0; if (Sadr==0) Sadr=adr; else adr=Sadr; if (adr->dl_NextB==0) { adr->dl_NextB=(struct DiskList *)AllocMem(structsize,MEMF_PUBLIC); if (adr->dl_NextB==0) { puts("Pas de mem pour Preparing()"); exit(0); } Sadr=adr->dl_NextB; return(adr->dl_NextB); } else return(Preparing(structsize,adr->dl_NextB)); } FreeDiskList() { struct DiskList *dlist; LONG length=0; APTR tmp; dlist=dsklist; do { length=Length(dlist); tmp=dlist->dl_NextB; if (dlist && length) FreeMem(dlist,length); dlist=tmp; } while (dlist->dl_NextB!=0); FreeMem(dlist,Length(dlist)); dsklist=0; } Length(dlist) struct DiskList *dlist; { LONG length; switch (dlist->dl_Type) { case -2L: length=sizeof(struct SUnknownB); break; case 13L: length=sizeof(struct SFileListB); break; case 8L: length=sizeof(struct SDataB); break; case 4L: length=sizeof(struct SUserDirB); break; case 3L: length=sizeof(struct SRootB); break; case -1L: length=sizeof(struct SFileHderB); break; case 0L: length=sizeof(struct SinitB); break; default : length=0; puts("err in FreeDiskList"); break; } return(length); } CheckDosStruct() { struct DiskList *dlist; WORD n; struct RootB *adr; dlist=(APTR)whereB(880); if (dlist==0) NotSet(880); else { adr=(struct RootB *)dlist->dl_AdrB; for (n=0;n<72;n++) /* 72 compris puisque n++ */ { explore(adr->HashTable[n],880); } } } /* explore: suit une chaine de Hash à partir du bloc header en paramètre */ explore(bloc,parent) WORD bloc; WORD parent; { struct DiskList *dlist; WORD n,nextbloc; struct UserDirB *adr; if (bloc==0) return(0); /*printf("dans explore bloc: %d, parent: %d\n",bloc,parent);*/ dlist=VarAdr->disklist; while (dlist->dl_Bloc!=bloc && dlist!=0) dlist=dlist->dl_NextB; if (dlist==0) NotSet(bloc,parent); else if (dlist->dl_Type!=-1 && dlist->dl_Type!=4) { printf ("ERR : Block #%d SHOULD BE Header or UserDir block\n",bloc); err++; } if (dlist->dl_types.dl_type4.dl_Parent!=parent) { printf("ERR : Link Error between block #%d and #%d\n",bloc,parent); err++; } if (dlist->dl_Type==-1) CheckHeader(dlist); if (dlist->dl_Type==4) { adr=(struct UserDirB *)dlist->dl_AdrB; for (n=0;n<72;n++) { explore(adr->HashTable[n],bloc); } } if (nextbloc=dlist->dl_types.dl_type1.dl_NextHash==0) return(0); else explore(nextbloc,parent); } CheckHeader(dlist) struct DiskList *dlist; { WORD bloc,n; struct FileHeaderB *adr; BYTE errfile=0; bloc=dlist->dl_Bloc; /*printf("dans CheckHeader bloc: %d\n",bloc);*/ adr=dlist->dl_AdrB; for (n=0;n<72;n++) { errfile+=CheckLink(adr->DataTable[n],bloc); } if (adr->Extension) CheckFList(adr->Extension,bloc); if (errfile) badFile(adr->FileName); return(0); } CheckFList(bloc,fhb) WORD bloc,fhb; { struct SFileListB *dlistFL; struct FileListB *adr; BYTE errfile=0; WORD n; dlistFL=(APTR)whereB(bloc); /* printf("dans CheckFList bloc: %d, pour FHB: %d\n",bloc,fhb);*/ if (dlistFL==0) NotSet(bloc,fhb); else{ if (dlistFL->dl_Type!=13) { printf ("ERR : Block #%d SHOULD BE FileList block\n",bloc); err++; errfile++; } else { adr=(struct FileListB *)dlistFL->dl_AdrB; if (adr->ParentFH!=fhb) { printf("ERR : Link Error between block #%d and #%d\n",bloc,fhb); err++; } for (n=0;n<72;n++) { errfile+=CheckLink(adr->DataTable[n],fhb); } } if (adr->Extension) errfile+=CheckFList(adr->Extension,fhb); } return(errfile); } CheckLink(dataB,fhB) WORD dataB,fhB; { struct SDataB *dlist; BYTE errdata=0; if (dataB==0) return(0); /* printf("dans CheckLink data : %d, fh : %d\n",dataB,fhB);*/ dlist=(struct SDataB *)VarAdr->disklist; while (dlist->dl_Bloc!=dataB && dlist!=0) dlist=dlist->dl_NextB; if (dlist==0) NotSet(dataB,fhB); else if (dlist->dl_Type!=8) { printf ("ERR : Block #%d SHOULD BE data block (pointed by FHB #%d)\n",dataB,fhB); err++; errdata=1; } else if (dlist->dl_type8.dl_FileHeader!=fhB) { printf("ERR : Link Error between block #%d and #%d\n",fhB,dataB); err++; errdata=1; } return(errdata); } badFile(adrName) BYTE *adrName; { BYTE length; BYTE buff[30]; length=*adrName; adrName++; strncpy(buff,adrName,length); buff[length]=0; printf("File %s contains errors\n",buff); } NotSet(bloc,where) WORD bloc,where; { printf("Block #%d Not Found ! (not unset in BitMap), in %p\n",bloc,where); err++; } whereB(bloc) WORD bloc; { struct DiskList *dlist; dlist=VarAdr->disklist; while (dlist->dl_Bloc!=bloc && dlist!=0) dlist=dlist->dl_NextB; return(dlist); } isinfo(buff) BYTE *buff; { BYTE name[30],length,n; length=buff[108*4]; strncpy(name,buff+108*4+1,length); name[length]=0; for (n=0; ndl_type4.dl_Parent; if (UDBP) /* null si Root */ { udbp=(APTR)whereB(UDBP); if (udbp==0) {NotSet(UDBP,1); return(0);} } adrf=udbf->dl_AdrB; /*printf("adrf : %p\n",adrf);*/ if (UDBP) /* Cas du User Dir B */ { adrp=udbp->dl_AdrB; parent=adrf->ParentDir=udbp->dl_Bloc2; /* Les Parents sont tjs déplacés avt */ } for (n=71;n!=-1;n--) { bloc=adrf->HashTable[n]; if (bloc) { adrf->HashTable[n]=gfree; do { fhB=(APTR)whereB(bloc); if (fhB==0) {NotSet(bloc,2); break;} if (fhB->dl_Type==-1) { gfree=MoveHderB(bloc,gfree,&dfree,UDB,i); } else if (fhB->dl_Type==4) { gfree=MoveUserDirB(bloc,gfree,parent); UDB[(*i)++]=bloc; UDB[*i]=0; } adrh=(struct FileHeaderB *)fhB->dl_AdrB; bloc=adrh->NextHash; adrh->NextHash= (bloc ? gfree : 0); /*printf("adrh: %p,bloc: %d\n",adrh,bloc);*/ } while (bloc); } } /*printf("gfree: %d dfree: %d\n",gfree,dfree);*/ GFree=gfree; DFree=dfree; return(1); } Inc(datafree) WORD *datafree; { #ifdef DEBUG /* printf("in Inc() datafree: %d\n",*datafree);*/ #endif if (*datafree<879) (*datafree)++; /* Ainsi 879 est donné mais pas 880 */ else { if (*datafree==879) *datafree=1759; else (*datafree)--; } return(*datafree); } Nextdfree(datafree) WORD *datafree; { if (*datafree<879) return(*datafree+1); else { if ((*datafree+1)==880) return(1759); else return(*datafree-1); } } /* MoveHderB déplace le Header spécifié du bloc lB au bloc nB. nB: nouveau n° de bloc. oB: ancien n° de bloc. */ MoveHderB(oB,nB,datafree,UDB,i) WORD nB,oB,*datafree; WORD UDB[],*i; { struct SFileHderB *dlistB,*fhB; struct FileHeaderB *adr; struct DiskList *hdb; struct FileHeaderB *adrh; WORD n,ret,ext,bloc,*nflB; WORD gfree; LONG AdrD; BYTE first; #ifdef DEBUG printf("in MoveHderB() oB: %d, nB: %d,datafree: %d\n",oB,nB,*datafree); #endif dlistB=(APTR)whereB(oB); if (dlistB==0) NotSet(oB,4); else { if (dlistB->dl_Type!=-1) return(0); adr=(struct FileHeaderB *)dlistB->dl_AdrB; /* On change le HeaderKey du bloc */ adr->HeaderKey=nB; dlistB->dl_Bloc2=nB; /* On change tous les DatasB en conséquence */ gfree=nB+1; first=1; for (n=71;n!=-1;n--) { if (adr->DataTable[n]) { if ( (dlistB->dl_Data==1) && (CLI==0) ) /* bloc de data ds gestion */ { AdrD=ModifyDataHder(adr->DataTable[n],nB,gfree,adr); adr->DataTable[n]=gfree; if (first) {adr->FirstDataB=gfree; first=0;} gfree++; if (n) ModifyDataNext(AdrD,gfree); else ModifyDataNext(AdrD,gfree+1); } else { AdrD=ModifyDataHder(adr->DataTable[n],nB,*datafree,adr); adr->DataTable[n]=*datafree; if (first) {adr->FirstDataB=*datafree; first=0;} Inc(datafree); if (n) ModifyDataNext(AdrD,*datafree); else { if (FLnog) ModifyDataNext(AdrD,Nextdfree(datafree)); else ModifyDataNext(AdrD,*datafree); } } } } if (adr->Extension) { if (FLnog) { nflB=datafree; ext=*datafree; } else { nflB=&gfree; ext=gfree; } if (CLI) /* pas de .info dans les blocs de gestion */ { ModifyFList(adr->Extension,nB,nflB,datafree,0); } else if (dlistB->dl_Data==1) /* si .info alors ds les blocs de gestion */ { ModifyFList(adr->Extension,nB,nflB,&gfree,1); } else { ModifyFList(adr->Extension,nB,nflB,datafree,0); } adr->Extension=ext; } } return(gfree); } ModifyDataHder(bloc,nfhB,ndataB,adrfh) WORD bloc,nfhB,ndataB; LONG adrfh; { struct SDataB *dlistD; struct DataB *adr; #ifdef DEBUG printf("in MofifyDataHder() bloc: %d, nfhB : %d, ndataB: %d\n",bloc,nfhB,ndataB); #endif dlistD=(APTR)whereB(bloc); if (dlistD==0) {NotSet(bloc,adrfh); exit(0);} else dlistD->dl_Bloc2=ndataB; dlistD->dl_type8.dl_FileHeader=nfhB; adr=dlistD->dl_AdrB; adr->HeaderKey=nfhB; return(adr); } ModifyDataNext(adr,ndataNext) WORD ndataNext; struct DataB *adr; { if (adr->NextDataBlock) adr->NextDataBlock=ndataNext; } /* Renvoie n° du prochain bloc libre */ ModifyFList(bloc,nfhB,nflB,datafree,data) WORD bloc,nfhB,*nflB,*datafree,data; { struct SFileListB *dlistFL; struct FileListB *adr; LONG *AdrD; WORD n,ret=0,ext; BYTE first; #ifdef DEBUG printf("in MofifyFList() bloc: %d, nfhB : %d, nflB: %d,datafree: %d\n",bloc,nfhB,*nflB,(*datafree)+1); #endif dlistFL=(APTR)whereB(bloc); if (dlistFL==0) NotSet(bloc,5); else { /*printf(" Type du bloc: %d\n",dlistFL->dl_Type);*/ dlistFL->dl_type13.dl_FileHeader=nfhB; dlistFL->dl_Bloc2=*nflB; adr=(struct FileListB *)dlistFL->dl_AdrB; adr->ParentFH=nfhB; adr->HeaderKey=*nflB; if (FLnog) Inc(nflB); else (*nflB)++; first=1; for (n=71;n!=-1;n--) { if(adr->DataTable[n]) { AdrD=(APTR)ModifyDataHder(adr->DataTable[n],nfhB,*datafree,bloc); adr->DataTable[n]=*datafree; if (first) {adr->FirstDataB=*datafree; first=0;} if (data==0) Inc(datafree); else (*datafree)++; if (n) { if (data==0) ModifyDataNext(AdrD,*datafree); else ModifyDataNext(AdrD,*datafree+1); } else { if (FLnog) ModifyDataNext(AdrD,Nextdfree(datafree)); else ModifyDataNext(AdrD,*datafree); } } } ext=*nflB; if (adr->Extension) { ret+=ModifyFList(adr->Extension,nfhB,nflB,datafree,data); adr->Extension=ext; return(++ret); } return(ext); } } MoveUserDirB(oB,nB,parent) WORD oB,nB,parent; { struct SUserDirB *dlist; struct UserDirB *adr; WORD n; #ifdef DEBUG printf("in MoveUserDir() oB: %d, nB: %d, parent: %d\n",oB,nB,parent); #endif dlist=(APTR)whereB(oB); if (dlist==0) NotSet(oB,6); else { if (dlist->dl_Type==4) { adr=dlist->dl_AdrB; dlist->dl_Bloc2=nB; adr->HeaderKey=nB; for (n=71;n!=-1;n--) { if (adr->HashTable[n]) { MoveHashFils(adr->HashTable[n],nB); } } return(nB+1); } else puts("err in MoveUserDirB"); } } MoveHashFils(bloc,parent) WORD bloc,parent; { struct DiskList *dlist; struct FileHeaderB *adr; #ifdef DEBUG printf("in MoveHashFils() bloc: %d, parent: %d\n",bloc,parent); #endif dlist=(APTR)whereB(bloc); if (dlist==0) {NotSet(bloc,7); return(0);} if (dlist->dl_Type==-1) adr=dlist->dl_AdrB; if (dlist->dl_Type==4) adr=dlist->dl_AdrB; dlist->dl_types.dl_type4.dl_Parent=parent; adr->ParentDir=parent; } ChangeBlocks() { struct DiskList *dlist; dlist=(struct DiskList *)VarAdr->disklist; while (dlist) { dlist->dl_Bloc=dlist->dl_Bloc2; dlist=dlist->dl_NextB; } } MemToDisk() { WORD n,bitmap; LONG offset,*adrB,*empty,ddrive,A; BYTE *BuffT,write,length; WORD c,Form; struct DiskList *dlist=0; struct RootNode *RN; struct RootB *adr; if (sourceDrive==destDrive) {puts("Now insert dest disk and RETURN"); while ( (c=getchar()) != 10) ;} MtrOn(destDrive); MtrOff(destDrive); if (isInserted(destDrive)) {puts("YOU MUST insert DESTINATION disk and RETURN"); while ( (c=getchar()) != 10) ; while (isInserted(destDrive)) fflush(stdout); } if (isProtected(destDrive)) {puts("UnProtect DESTINATION disk and press RETURN"); while ( (c=getchar()) != 10) ; while (isProtected(destDrive)) fflush(stdout);} offset=2*512L; /* Le boot Block est déja dans le Buffer de Track */ BuffT=BT; /* On met à jour la date de dernière modif de la disquette */ dlist=(APTR)whereB(880); if (dlist==0) NotSet(880,8); adr=dlist->dl_AdrB; RN=(struct RootNode *)(DOSBase->dl_Root); adr->Mday=RN->rn_Time.ds_Days; adr->Mmin=RN->rn_Time.ds_Minute; adr->Mtick=RN->rn_Time.ds_Tick; length=adr->DiskName[0]; adr->DiskName[0]=length+1; adr->DiskName[length+1]='.'; bitmap=VarAdr->BitMap; empty=VarAdr->Empty; ddrive=destDrive; A=('F'<<24|'B'<<16|'J'<<8|'.'); for (n=0;n<128;n++) { empty[n]=A; } /*printf("buffer a l' adresse %p\n",empty);*/ putchar(13); Form=FORMAT; /*printf("Form : %d, VarAdr->Format: %ld\n",Form,VarAdr->Format);*/ write=Form; for (n=2;n<1761;n++) { if (offset==11*512) { /*printf("(n-12): %d\n",(n-11)); */ if (write) CMDonD(ddrive,TD_FORMAT,0,11*512L,BuffT,(n-11)*512L); offset=0L; if (!Form) write=0; } if (( (n-22) % 22 )==0) { printf("CYL n°: %d",n/22); putchar(13); fflush(stdout); } if (n==881) {adrB=BBM; write=1;} else { dlist=(APTR)whereB(n); if (dlist==0) adrB=empty; else { adrB=dlist->dl_AdrB; BuildCheckSum(adrB); write=1; } } CopyMemQuick(adrB,BuffT+offset,512L); offset+=512L; } } BuildCheckSum(Buffer) ULONG *Buffer; { ULONG B; WORD n; Buffer[5]=0; n=0; B=0; while (n<=127) { B+=Buffer[n]; n++; } Buffer[5]=-B; } BitMap() { struct DiskList *dlist; struct RootB *adr; WORD n; LONG *buffbm,SBM=0; buffbm=BBM; dlist=(APTR)whereB(880); if (dlist==0) NotSet(880,9); adr=dlist->dl_AdrB; adr->BitMapTable[0]=881L; adr->BMvalid=-1; /*printf("GFree: %d DFree: %d\n",GFree,DFree);*/ for (n=0;n!=56;n++) buffbm[n]=-1L; /* on nettoye le BitMap */ for (n=56;n!=128;n++) buffbm[n]=0L; if (DFree<880) { for (n=0;nFormat=!flag; /* printf("in NoFormat, Format set to %d\n",VarAdr->Format);*/ } forFDir(flag) BYTE flag; { FLnog=flag; /* printf("in forFDir, FLnog set to %d\n",flag);*/ } Check(flag) BYTE flag; { CHECK=flag; } help() { puts("FO is FreeWare but contributions are welcomed: "); puts(""); puts("Send any donations to CAMPAGNE Fabien"); puts(" 805, Rue des Gentianes"); puts(" 39000 Lons Le Saunier"); puts(" France"); puts(""); puts("Now how to use FO:"); puts(" 1st argument must be SOURCE drive"); puts(" 2nd argument must be DESTINATION drive"); puts(" (They could be the same)"); puts("Options:"); puts(" -w : Worbench optimization ( all .info files (ex disk.info) are"); puts(" near gestion-blocks)"); puts(" -c : CLI optimization ( .info files are in the area of data-blocks)"); puts(" -nFo or -nFormat if you use disk already formatted on destination."); puts(" -C : Check of the Dos Structure of Source disk before optimization."); puts(" -FDir : to use in conjunction with FDir (the Fast Dir by mine)"); puts(" (File List blocks are moved in data-area)"); puts(""); puts(" Enjoy FO. FBJ."); }