/* BACK.C Written By Stephen Vermeulen, some code from an example called "TrackDisk" on Fish Disk 1 by Rob Peck. This code may be used to develop other Amiga applications. This is a program to speed up the process of saving backup data to floppies and to add a verify feature to ensure the data gets there... and stays there... I wrote this because I got POed at th AmigaDOS Copy command not verifing that the data was written to disk correctly. Also this program (with verify) is still faster than the DOS Copy command (without verify). Note that this only stores one file per disk (but this is ok if you are using Matt Dillon's BackUp/Restore utility). Syntax is BACK filename drivenumber The back file is a straight foward copy of the original file onto the floppy starting with the THIRD block of track 0. There are a few bytes used for header info (total number of file bytes, number of name bytes, date stamp and the original filename */ #include #include "exec/types.h" #include "exec/nodes.h" #include "exec/lists.h" #include "exec/memory.h" #include "exec/interrupts.h" #include "exec/ports.h" #include "exec/libraries.h" #include "exec/io.h" #include "exec/tasks.h" #include "exec/execbase.h" #include "exec/devices.h" #include "devices/trackdisk.h" #include "libraries/dos.h" #include #include #include #include long _stack = 4000; long _priority = 0; long _BackGroundIO = 0; char *_procname = NULL; #define TD_READ CMD_READ #define BLOCKSIZE TD_SECTOR #define TRKSIZE NUMSECS*BLOCKSIZE #define NUMTRKS 160L #define BACK (('B' << 24L) + ('A' << 16L) + ('C' << 8L) + ((long) 'K')) SHORT error; struct MsgPort *diskport; struct IOExtTD *diskreq; BYTE *diskbuffer; SHORT testval; extern struct MsgPort *CreatePort(); extern struct IORequest *CreateExtIO(); ULONG diskChangeCount; ReadCyl(trk) SHORT trk; { diskreq->iotd_Req.io_Length = TRKSIZE; diskreq->iotd_Req.io_Data = (APTR) diskbuffer; /* show where to put the data when read */ diskreq->iotd_Req.io_Command = ETD_READ; /* check that disk not changed before reading */ diskreq->iotd_Count = diskChangeCount; /* convert from cylinder, head, sector to byte-offset value to get * right one (as dos and everyone else sees it)...*/ /* driver reads one track at a time (head does not move for * 11 sequential sector reads */ diskreq->iotd_Req.io_Offset = TRKSIZE * trk; DoIO(diskreq); return(0); } WriteCyl(trk) SHORT trk; { diskreq->iotd_Req.io_Length = TRKSIZE; diskreq->iotd_Req.io_Data = (APTR) diskbuffer; /* show where to put the data when read */ diskreq->iotd_Req.io_Command = TD_FORMAT; /* check that disk not changed before reading */ diskreq->iotd_Count = diskChangeCount; /* convert from cylinder, head, sector to byte-offset value to get * right one (as dos and everyone else sees it)...*/ /* driver reads one track at a time (head does not move for * 11 sequential sector reads */ diskreq->iotd_Req.io_Offset = TRKSIZE * trk; DoIO(diskreq); return(0); } MotorOn() { /* TURN ON DISK MOTOR ... old motor state is returned in io_Actual */ diskreq->iotd_Req.io_Length = 1; /* this says motor is to be turned on */ diskreq->iotd_Req.io_Command = TD_MOTOR; /* do something with the motor */ DoIO(diskreq); return(0); } MotorOff() { diskreq->iotd_Req.io_Length = 0; /* says that motor is to be turned on */ diskreq->iotd_Req.io_Command = TD_MOTOR; /* do something with the motor */ DoIO(diskreq); return(0); } char *dnames[4] = { "DF0:", "DF1:", "DF2:", "DF3:" }; main(argc, argv) int argc; char *argv[]; { SHORT track,head,sector, i, j, ok, loaded; int k, usedrive; ULONG file; long dlen, chksum, *lptr, first, filelen; struct FileInfoBlock *fib; fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct FileInfoBlock), MEMF_PUBLIC); if (!fib) return; if (argc != 3) { puts("Syntax: BACK filename DRIVE"); puts("where drive is 0, 1, 2, 3 for DF0:, DF1:, DF2: or DF3:"); return; } usedrive = atoi(argv[2]); if ((usedrive < 0) || (usedrive > 3)) { puts("Drive number MUST be one of 0, 1, 2, or 3"); return; } /** open the file, get the file length **/ file = (ULONG) Lock(argv[1], ACCESS_READ); if (!file) { puts("Could not read the file"); return; } Examine(file, fib); filelen = fib->fib_Size; UnLock(file); if (filelen > 22L*512L*80L - 2L*512L - strlen(argv[1]) - 1L - 12L) { puts("File is too large to fit on a floppy."); FreeMem(fib, (long) sizeof(struct FileInfoBlock)); return; } file = (ULONG) Open(argv[1], MODE_OLDFILE); if (!file) { puts("Could not read the file"); return; } diskChangeCount = -1L; diskbuffer = (BYTE *) AllocMem(TRKSIZE, MEMF_CHIP | MEMF_PUBLIC); if (diskbuffer) { diskport = CreatePort(0L,0L); if (diskport) { diskreq = (struct IOExtTD *)CreateExtIO(diskport, (long) sizeof(struct IOExtTD)); /* make an io request block for communicating with the disk */ if (diskreq) { error = OpenDevice(TD_NAME, (long) usedrive, diskreq, 0L); if (!error) { dos_packet(DeviceProc(dnames[usedrive]), ACTION_INHIBIT, TRUE, 0L, 0L, 0L, 0L, 0L, 0L); puts("Press RETURN to proceed, `garbage' RETURN to abort"); fgets(diskbuffer, 80, stdin); if (diskbuffer[0] != 10) goto abort_now; /* ready to go, now wait for the user to do something */ diskChangeCount = -1L; MotorOn(); lptr = (long *) diskbuffer; for (i = 0; i < 256; ++i) lptr[i] = BACK; track = 0; /** get the file length and then read the first 9*512 bytes (missing the 2 boot blocks...) less 4 bytes for the true file length **/ lptr[256] = filelen; lptr[257] = time(NULL); lptr[258] = strlen(argv[1]) + 1; CopyMem(argv[1], &lptr[259], lptr[258]); Read(file, ((long) &lptr[259]) + lptr[258], 9L*512L - lptr[258] - 12L); filelen -= 9L*512L - lptr[258] - 12L; while (track < NUMTRKS) /* tracks to copy */ { WriteCyl(track); if (diskreq->iotd_Req.io_Error) { puts("Error writing. Aborting."); break; } /** now do verify pass... **/ ReadCyl(track); if (diskreq->iotd_Req.io_Error) { puts("Error verifing. Aborting."); break; } /** read all data ? **/ if (filelen <= 0L) break; /** get more data **/ Read(file, diskbuffer, 11L*512L); filelen -= 11L*512L; track++; } MotorOff(); CloseDevice(diskreq); abort_now: dos_packet(DeviceProc(dnames[usedrive]), ACTION_INHIBIT, FALSE, 0L, 0L, 0L, 0L, 0L, 0L); } DeleteExtIO(diskreq, (long) sizeof(struct IOExtTD)); } DeletePort(diskport); } FreeMem(diskbuffer, TRKSIZE); } Close(file); FreeMem(fib, (long) sizeof(struct FileInfoBlock)); } /* end of main */