/* FASTDISK by Thorsten Stolpmann Reworked for Lattice C 5.0.4. by Olli 1.11.89: first attempt to make it compile under lattice 2.11.89: build in ARP-Support 3.11.89: complete rework, gone cause to machine failure :-< 4.11.89: complete rework, second attempt. add In' features 5.11.89: do misc code optimizing do more code optimizing removed ALV-generation for "cback.o" please remove the above sentence :-( */ #define scmp !strnicmp #define error(); { closeall(); loop(); } #include #include #include #include #include #include #include #include /* Diskspezifische Daten */ #define NUMHEADS 2 #define BLOCKSIZE 512 #define SIZE 128 #define NUM_ENTRIES 72 #define NUMBLOCKS 1760 /* (NUMCYLC * NUMHEADS * NUMSECS) */ #define ROOTBLOCK 880 #define NUMLONGS 55 #define SECS_PER_TRACK 22 /* Diskblockparameter */ #define TYPE 0 #define HEADER_KEY 1 #define HIGHEST_SEQ 2 #define SEQ_NUM 2 #define BLOCK_COUNT 2 #define DATA_SIZE 3 #define FIRST_DATA 4 #define NEXT_DATA 4 #define CHECKSUM 5 #define DIR_HASHTAB 6 #define FH_ENDLIST 6 #define FH_BLOCKLIST 77 #define BITMAPINDEX 79 #define NAME 108 #define CREATE_TICKS 123 #define HASHCHAIN 124 #define PARENT 125 #define EXTENSION 126 #define SECONDARY_TYPE 127 #define BITMAP_CHECKSUM 0 #define NAMEOFFSET 433 #define NAMELENGTH 432 /* Diskblock-Typ Definitionen */ #define T_SHORT 2 #define T_DATA 8 #define T_LIST 16 #define ST_ROOT 1 #define ST_DIR 2 #define ST_FILE -3 #define EMPTY (unsigned long*) 0 #define BLOCKED (unsigned long*) 0xFFFFFFFF #define SOURCE 0 #define DESTINATION 1 /* Globale Variablen */ extern struct Library *ArpBase; struct IOExtTD diskreq0,diskreq1,diskreq2; struct MsgPort *diskport; int diskchangecount0,diskchangecount1; unsigned long dirstack [NUMBLOCKS]; unsigned short sectormap [NUMBLOCKS]; unsigned long *buffermap [NUMBLOCKS]; unsigned long *readmap [NUMBLOCKS]; unsigned short filestack [NUMBLOCKS/2]; unsigned char trackmap [160]; unsigned short dirstackptr ,filestackptr ,smptr; unsigned char formatflag, fastloadflag; unsigned long seccount, rootoff; unsigned long *trackbuffer; unsigned long *oldbuffer; unsigned short sourcedrive ,destinationdrive; char sourcedevice[5] = "DF0:"; char destdevice[5] = "DF1:"; char spb[34]; /* Prototypes */ void moveblock(void); void sortfiles(void); void makefiles(void); void makeroot(void); void writeheaders(void); void writeblank(void); void writeboot(void); void closeall(void); void travel(int); int is_special(unsigned char *); int getfreesector(void); void dofile(unsigned long*); void makedirs(void); void init(void); void pushdir(int); int popdir(void); void pushfile(int); int popfile(void); void DoCheckSum(unsigned long*,int); void ReadSector(int,unsigned long*); unsigned long *GetSector(int); void formattrack(int); void WriteSector(int,unsigned long*); void PutSector(int,unsigned long*); unsigned long *allocbuffer(void); void releasebuffer(unsigned long *); void openall(void); void checkdisks(void); /*void error(void);*/ void closeall(void); void sprintf(char*,char*,); void do_fast(int,int,int,int); void loop(void); void pmsg(char*,int); void do_fast(dr1,dr2,fastdir,noformat) int dr1,dr2,fastdir,noformat; { sourcedrive=dr1; destinationdrive=dr2; sourcedevice[2] = (char) ('0' + (char) sourcedrive); destdevice[2] = (char) ('0' + (char) destinationdrive); fastloadflag=!fastdir; formatflag=!noformat; pmsg("setting up",0); openall (); checkdisks(); init (); pmsg("analyzing",0); travel (ROOTBLOCK); pmsg("moving blocks",0); moveblock (); pmsg("sorting files",0); sortfiles (); pmsg("making files",0); makefiles (); pmsg("making dirs",0); makedirs (); pmsg("making route",0); makeroot (); pmsg("writing headers",0); writeheaders (); pmsg("formating blanks",0); writeblank(); pmsg("copying bootblock",0); writeboot (); pmsg("optimizing completed!",0); closeall (); } void travel(head) int head; { unsigned long *headbuffer,*workbuffer,*auxbuffer; int sector,hc,i,count; /* Rekursives Durchlaufen des Directory-Trees in Zwischenordnung */ headbuffer = buffermap[head]; for (i=DIR_HASHTAB; i<=FH_BLOCKLIST; i++) { sector=headbuffer[i]; if (sector) { workbuffer = buffermap[sector] = GetSector(sector); if ((workbuffer[TYPE] == T_SHORT) && (workbuffer[SECONDARY_TYPE] == ST_DIR)) { if (fastloadflag) { sectormap[sector] = ROOTBLOCK+2+dirstackptr; } else { sectormap[sector] = smptr++; } pushdir(sector); travel(sector); } else { sectormap[sector] = smptr++; pushfile(sector); /* Existieren File List Blocks ? */ auxbuffer = buffermap[sector]; count = workbuffer[HIGHEST_SEQ]; while (auxbuffer[EXTENSION]) { sector = auxbuffer[EXTENSION]; auxbuffer = buffermap[sector] = GetSector(sector); count += auxbuffer[BLOCK_COUNT]; sectormap[sector] = smptr++; } /* Ist es ein .info-File? */ if (is_special(workbuffer)) { sectormap[workbuffer[FIRST_DATA]] = smptr; smptr += count; } } /* Weitere Header-Blocks in der Hashchain ? */ hc=workbuffer[HASHCHAIN]; while (hc) { workbuffer = buffermap[hc] = GetSector(hc); if ((workbuffer[TYPE] == T_SHORT) && (workbuffer[SECONDARY_TYPE] == ST_DIR)) { sectormap[hc] = ROOTBLOCK+2+dirstackptr; if (fastloadflag) { sectormap[hc] = ROOTBLOCK+2+dirstackptr; } else { sectormap[hc] = smptr++; } pushdir(hc); travel(hc); } else { sectormap[hc]=smptr++; pushfile(hc); /* Existieren File List Blocks ? */ auxbuffer = buffermap[hc]; count = workbuffer[HIGHEST_SEQ]; while (auxbuffer[EXTENSION]) { sector = auxbuffer[EXTENSION]; auxbuffer = buffermap[sector] = GetSector(sector); count += auxbuffer[BLOCK_COUNT]; sectormap[sector] = smptr++; } /* Ist es ein .info-File ? */ if (is_special(workbuffer)) { sectormap[workbuffer[FIRST_DATA]] = smptr; smptr += count; } } hc=workbuffer[HASHCHAIN]; } } } } void moveblock() { int sector,dest,diff; /* Zentriert die Header-Blocks auf der Diskette */ if ((diff = (smptr-881)/SECS_PER_TRACK) > 2) { diff = (((diff/2)+1) * SECS_PER_TRACK) - 2; } else { diff = 0; } if (fastloadflag) { rootoff += dirstackptr; diff -= dirstackptr; } for (sector=2; sector < NUMBLOCKS; ++sector) { dest = sectormap[sector]; if ((dest) && (dest != 880) && (dest != 881) && !((fastloadflag) && (buffermap[sector][SECONDARY_TYPE] == ST_DIR))) { if ((dest >= 882) && (dest-diff < ROOTBLOCK+rootoff)) { sectormap[sector] -= (ULONG) (diff+rootoff); } else { sectormap[sector] -= (ULONG) diff; } } } seccount = (ULONG) ROOTBLOCK - diff; } void sortfiles() { int file,count,top,temp; /* Erst die .info-Files kopieren */ top = filestackptr-1; for (file = 0; file < top;file++) { if (is_special(buffermap[filestack[file]])) { temp = filestack[file]; for (count=file; count < top; count++) { filestack[count] = filestack[count+1]; } filestack[top--] = temp; file--; } } } int is_special(buffer) unsigned char *buffer; { /* Diese Files werden direkt hinter ihrem Headerblock abgelegt */ pmsg(buffer+NAMEOFFSET,0); if (fastloadflag) { return (1); } if (scmp(buffer+NAMEOFFSET+buffer[NAMELENGTH]-5,".INFO",5)) { return (1); } if (scmp(buffer+NAMEOFFSET,"SYSTEM-CONFIGURATION",20)) { return (1); } if (scmp(buffer+NAMEOFFSET,"STARTUP-SEQUENCE",16)) { return (1); } return (0); } int getfreesector() { /* Liefert naechsten freier Sector auf der Diskette */ if (seccount == 2) { return (seccount = NUMBLOCKS-1); } else { return (--seccount); } } void makefiles() { int file; /* kopiert alle File-Datenblocks auf die Zieldiskette. Die neuen Sectorpositionen werden in den Headerblocks korrigiert. */ while (file = popfile()) { dofile(buffermap[file]); } } void dofile(headbuffer) unsigned long *headbuffer; { unsigned long *workbuffer; int sector,next_sector,more_to_come; if (headbuffer[FIRST_DATA]) { workbuffer = GetSector(headbuffer[FIRST_DATA]); if (is_special(headbuffer)) { sector = sectormap[headbuffer[FIRST_DATA]]; if (sector == ROOTBLOCK) { sector += rootoff; } } else { sector = getfreesector(); } sectormap[headbuffer[FIRST_DATA]] = sector; do { workbuffer[HEADER_KEY]=sectormap[headbuffer[HEADER_KEY]]; more_to_come = workbuffer[NEXT_DATA]; if (more_to_come) { if (is_special(headbuffer)) { next_sector = sector + 1; if (next_sector == ROOTBLOCK) { next_sector += rootoff; } } else { next_sector = getfreesector(); } workbuffer[NEXT_DATA] = next_sector; } DoCheckSum(workbuffer,CHECKSUM); PutSector(sector,workbuffer); if (more_to_come) { workbuffer = GetSector(more_to_come); sector = sectormap[more_to_come] = next_sector; } } while (more_to_come); } /* Aenderungen in File Header & File List Blocks */ do { more_to_come = headbuffer[EXTENSION]; sector = FH_BLOCKLIST; while (sector >= FH_ENDLIST) { headbuffer[sector--]=sectormap[headbuffer[sector]]; } headbuffer[PARENT] = sectormap[headbuffer[PARENT]]; headbuffer[HEADER_KEY] = sectormap[headbuffer[HEADER_KEY]]; headbuffer[FIRST_DATA] = sectormap[headbuffer[FIRST_DATA]]; headbuffer[HASHCHAIN] = sectormap[headbuffer[HASHCHAIN]]; headbuffer[EXTENSION] = sectormap[headbuffer[EXTENSION]]; DoCheckSum(headbuffer,CHECKSUM); if (more_to_come) { headbuffer = buffermap[more_to_come]; } } while (more_to_come); } void makedirs() { unsigned long *headbuffer; int dir,sector; /* Aenderungen in den Directory-Header Blocks */ while (dir = popdir()) { headbuffer = buffermap[dir]; for ( sector = FH_BLOCKLIST; sector >= FH_ENDLIST; --sector) { if (headbuffer[sector]) { headbuffer[sector]=sectormap[headbuffer[sector]]; } } headbuffer[PARENT] = sectormap[headbuffer[PARENT]]; headbuffer[HEADER_KEY] = sectormap[headbuffer[HEADER_KEY]]; headbuffer[HASHCHAIN] = sectormap[headbuffer[HASHCHAIN]]; headbuffer[EXTENSION] = sectormap[headbuffer[EXTENSION]]; DoCheckSum(headbuffer,CHECKSUM); } } void makeroot() { unsigned long *headbuffer,*workbuffer; int sector,bmsector,mask,offset,count; workbuffer = allocbuffer(); headbuffer = buffermap[ROOTBLOCK]; /* Aenderungen im Rootblock */ bmsector = sectormap[headbuffer[BITMAPINDEX]]; for ( sector = FH_BLOCKLIST; sector >= FH_ENDLIST; --sector) { if (headbuffer[sector]) { headbuffer[sector]=sectormap[headbuffer[sector]]; } } headbuffer[BITMAPINDEX] = bmsector; headbuffer[CREATE_TICKS] += 1; /* Wichtig ! Hiermit wird gesichert, */ /* dass AmigaDOS Quell- und Zieldisk */ /* unterscheiden kann. */ DoCheckSum(headbuffer,CHECKSUM); /* Neuen Bit-Map Sector erstellen */ for (count=1; count <= NUMLONGS; ++count) { workbuffer[count] = 0xFFFFFFFF; } for (count = 2; count < NUMBLOCKS; ++count) { sector = sectormap[count]; if (sector) { offset = 1 + ((sector-2)/32); mask = (ULONG) 1 << ((sector-2) & 0x1f); workbuffer[offset] -= (ULONG) mask; } } DoCheckSum(workbuffer,BITMAP_CHECKSUM); PutSector(bmsector,workbuffer); } void writeheaders() { int buffer; /* Alle Header-Blocks werden auf Zieldisk geschrieben */ for (buffer=0; buffer= NUMBLOCKS) { sprintf(spb,"DF%ld: illegal sector %ld!",(int)sourcedrive,(int)sector); pmsg(spb,1); error(); } if (readmap[sector]) { if (readmap[sector] == BLOCKED) { sprintf(spb,"DF%ld: double reference to %ld!",(int)sourcedrive,(int)sector); pmsg(spb,1); error(); } else { temp = readmap[sector]; readmap[sector] = BLOCKED; return (temp); } } else { workbuffer = allocbuffer(); ReadSector (sector,workbuffer); readmap[sector] = BLOCKED; track = sector / SECS_PER_TRACK; for (sec=track*SECS_PER_TRACK; sec < (track+1)*SECS_PER_TRACK; sec++) { if (readmap[sec] == EMPTY) { if (readmap[sec] = allocbuffer()) { ReadSector(sec,readmap[sec]); } else { break; } } } return (workbuffer); } } void formattrack(track) int track; { /* Formatiert einen Track auf der Zieldiskette */ diskreq2 . iotd_Req.io_Length = NUMSECS * BLOCKSIZE; diskreq2 . iotd_Req.io_Data = (APTR) trackbuffer; diskreq2 . iotd_Req.io_Command = TD_FORMAT; diskreq2 . iotd_Count = diskchangecount1; diskreq2 . iotd_Req.io_Offset = track * (NUMSECS * BLOCKSIZE); SendIO (&diskreq2); if (diskreq1 . iotd_Req.io_Error) { sprintf(spb,"DF%ld: formaterror %ld on cyl %ld!",(int)destinationdrive,(int)diskreq2.iotd_Req.io_Error,(int)track/2); error(); } } void WriteSector(sector,buffer) int sector; unsigned long *buffer; { short int track; /* Falls noch nicht geschehen, formatieren des Ziel-Tracks */ track = (sector / 11); if ( (formatflag) && !(trackmap[track])) { formattrack(track); trackmap[track] = 1; } /* Schreibt einen Sector auf die Ziel-Diskette */ diskreq1 . iotd_Req.io_Length = BLOCKSIZE; diskreq1 . iotd_Req.io_Data = (APTR) buffer; diskreq1 . iotd_Req.io_Command = ETD_WRITE; diskreq1 . iotd_Count = diskchangecount1; diskreq1 . iotd_Req.io_Offset = sector*512; SendIO (&diskreq1); /* Asynchroner Schreibzugriff */ } void PutSector(sector,buffer) int sector; unsigned long *buffer; { /* Schreibt Sector auf Zieldisk und deallociert den Buffer */ if (oldbuffer) { WaitIO(&diskreq1); /* Warten auf das Ende des letzten Schreibzugriffs */ if (diskreq1 . iotd_Req.io_Error) { sprintf(spb,"DF%ld: write error %ld on %ld!",(int)destinationdrive,(int)diskreq1.iotd_Req.io_Error,(int)sector); pmsg(spb,1); error(); } releasebuffer(oldbuffer); } if (oldbuffer = buffer) { WriteSector(sector, buffer); } } unsigned long *allocbuffer() { unsigned long *buffer; int sec; /* Allociert 512 Byte Chip-Memory als Sector-Buffer */ /* Falls kein Chip-Mem mehr vorhanden ist, wird ein */ /* bestehender, nicht unbedingt benoetigter Sector */ /* deallociert. */ buffer = AllocMem((long) BLOCKSIZE, MEMF_CHIP); if (buffer == NULL) { for (sec=2; sec