#include "exec/types.h" #include "exec/ports.h" #include "exec/libraries.h" #include "exec/io.h" #include "exec/tasks.h" #include "exec/execbase.h" #include "libraries/dos.h" #include "libraries/dosextens.h" #include "workbench/workbench.h" #include "workbench/startup.h" #include "devices/scsidisk.h" #include "stdio.h" #include "time.h" #include "functions.h" #define RZ_BMAGIC 0x525a4d42 #define RZ_CMAGIC 0x525a4d43 #define RZ_SCSI "HardFrame.device" #define RZ_DISK 000 #define RZ_TAPE 001 #define RZ_BLKS 128 #define RZ_BYTS 512 #define RZ_IOR struct IORequest extern struct ExecBase *SysBase; struct Library *IconBase; void dsk2tap(); void tapelst(); void tap2dsk(); long bk_create(char *name); void bk_d2t(); void bk_extract(); void bk_t2d(); long bk_write(struct FileInfoBlock *fib); long dk_capacity(); long dk_close(); long dk_init(); long dk_read(long lba,long len); long dk_write(long lba,long len); void tmconv(struct DateStamp *date,char *dstr,char *tstr); long tp_close(); long tp_eof(); long tp_init(); long tp_read(long len); long tp_rewind(); long tp_sense(); long tp_write(long len); long disk = RZ_DISK; long tape = RZ_TAPE; char scsi[] = RZ_SCSI; long nest; char refname[256]; UBYTE dkcmd[32]; UBYTE tpcmd[32]; UWORD data[RZ_BLKS * RZ_BYTS / 2]; ULONG *ldata = (ULONG *)data; UBYTE *bdata = (UBYTE *)data; UBYTE *dptr; struct MsgPort dkmp = {{0,0,NT_MSGPORT,0,0},0,SIGB_SINGLE,0,{0,0,0,0,0}}; struct IOStdReq dkior = {{{0,0,NT_MESSAGE,0,0},&dkmp,0},0,0,0,0,0,0,0,0,0}; struct SCSICmd dksc; struct MsgPort tpmp = {{0,0,NT_MSGPORT,0,0},0,SIGB_SINGLE,0,{0,0,0,0,0}}; struct IOStdReq tpior = {{{0,0,NT_MESSAGE,0,0},&tpmp,0},0,0,0,0,0,0,0,0,0}; struct SCSICmd tpsc; struct WBStartup *wbsm; struct WBArg *wba; struct DiskObject *dobj; union FHeader { struct FHBlock { ULONG magic; long nest; struct FileInfoBlock fib; } fhb; UBYTE fhbuf[sizeof(struct FHBlock)]; } fhdr; struct FileInfoBlock *gfib = &(fhdr.fhb.fib); /* ---------------------------------------------------------------------- */ main(long argc, char **argv) { long i; long err; long func; char *cptr; struct FileLock *olddir; fprintf(stderr,"\ntabu - QIC tape backup utility\n"); fprintf(stderr,"Copyright 1990 - Roy C. Sigsbey\n\n"); if (argc == 0) { if ((IconBase = OpenLibrary("icon.library",0)) == NULL) { fprintf(stderr,"tabu: Icon library open failed, bye\n"); fprintf(stderr,"tabu finished, Press RETURN when ready.\n"); getchar(); exit(1); } else { wbsm = (struct WBStartup *)argv; wba = wbsm->sm_ArgList; olddir = CurrentDir((struct FileLock *)wba->wa_Lock); dobj = GetDiskObject(wba->wa_Name); err = 0; if ((cptr = FindToolType(dobj->do_ToolTypes,"OPER")) != NULL) { switch(cptr[0]) { case 'B': case 'b': func = 1; break; case 'C': case 'c': func = 2; break; case 'L': case 'l': func = 3; break; case 'R': case 'r': func = 4; break; case 'X': case 'x': func = 5; break; default: err = 1; break; } } else err = 1; if ((cptr = FindToolType(dobj->do_ToolTypes,"NAME")) != NULL) strcpy(refname,cptr); else refname[0] = '\0'; if ((cptr = FindToolType(dobj->do_ToolTypes,"LIST")) != NULL) { if (freopen(cptr,"w",stdout) == NULL) err = 1; } if ((cptr = FindToolType(dobj->do_ToolTypes,"SCSI")) != NULL) { strcpy(scsi,cptr); } if ((cptr = FindToolType(dobj->do_ToolTypes,"DISK")) != NULL) { if (sscanf(cptr,"%3d",&disk) != 1) err = 1; } if ((cptr = FindToolType(dobj->do_ToolTypes,"TAPE")) != NULL) { if (sscanf(cptr,"%3d",&tape) != 1) err = 1; } CurrentDir(olddir); CloseLibrary(IconBase); } } else { err = 0; func = 0; refname[0] = '\0'; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'B': case 'b': func = 1; break; case 'C': case 'c': func = 2; break; case 'D': case 'd': if (sscanf(&(argv[i][2]),"%3d",&disk) != 1) err = 1; break; case 'L': case 'l': func = 3; break; case 'R': case 'r': func = 4; break; case 'S': case 's': strcpy(scsi,&(argv[i][2])); break; case 'T': case 't': if (sscanf(&(argv[i][2]),"%3d",&tape) != 1) err = 1; break; case 'X': case 'x': func = 5; break; default: err = 1; break; } } else strcpy(refname,argv[i]); } } if (err != 0) func = 0; switch (func) { case 1: bk_d2t(); break; case 2: dsk2tap(); break; case 3: tapelst(); break; case 4: bk_t2d(); break; case 5: tap2dsk(); break; default: fprintf(stderr, "usage: tabu [-ddsk] [-sscsi] [-ttap] -b|c|l|r|x [name]\n"); fprintf(stderr," -b = backup by blocks to tape\n"); fprintf(stderr," -c = create backup to tape\n"); fprintf(stderr," -d = dsk is scsi address for disk\n"); fprintf(stderr," -l = list tape contents\n"); fprintf(stderr," -r = restore by blocks from tape\n"); fprintf(stderr," -s = scsi is scsi device name\n"); fprintf(stderr," -t = tap is scsi address for tape\n"); fprintf(stderr," -x = extract from tape\n"); fprintf(stderr," name = reference name (req'd - c or x)\n"); fprintf(stderr,"tabu.info ToolTypes may be set as follows:\n"); fprintf(stderr," OPER=B backup\n"); fprintf(stderr," OPER=C create\n"); fprintf(stderr," OPER=L list\n"); fprintf(stderr," OPER=R restore\n"); fprintf(stderr," OPER=X extract\n"); fprintf(stderr," NAME=name reference name (req'd - C or X)\n"); fprintf(stderr," LIST=name list to file or printer\n"); fprintf(stderr," DISK=nnn disk scsi address\n"); fprintf(stderr," TAPE=nnn tape scsi address\n"); fprintf(stderr," SCSI=name scsi device name\n"); } fprintf(stderr,"tabu finished, Press RETURN when ready.\n"); getchar(); exit(0); } /* ---------------------------------------------------------------------- */ void dsk2tap() { time_t timer; if (strlen(refname) == 0) { fprintf(stderr,"tabu: reference name required for create\n"); return; } nest = 0; dptr = bdata; if (tp_init()) return; if (bdata[8] & 0x10) { fprintf(stderr,"tabu: tape is write protected\n"); tp_close(); return; } time(&timer); printf("\ntabu: backup %s\n",ctime(&timer)); if (bk_create(refname)) { tp_close(); return; } if (dptr != bdata) { if (tp_write(((long)(dptr - bdata) / RZ_BYTS))) { tp_close(); return; } } tp_eof(); tp_close(); return; } /* ---------------------------------------------------------------------- */ void tapelst() { long i; long first_time; char datestr[16]; char timestr[16]; if (tp_init()) return; first_time = 1; tpsc.scsi_Actual = RZ_BYTS * RZ_BLKS; while (tpsc.scsi_Actual == (RZ_BYTS * RZ_BLKS)) { if (tp_read(RZ_BLKS)) { tp_close(); return; } if (first_time) { if ((bdata[0] != 'R') || (bdata[1] != 'Z') || (bdata[2] != 'M')) { fprintf(stderr,"tabu: tape is not a tabu backup\n"); break; } if (bdata[3] == 'B') { fprintf(stderr,"tabu: tape is a tabu disk image backup\n"); fprintf(stderr," backup date = %s\n",&(bdata[4])); break; } first_time = 0; } for (dptr = bdata; dptr < (bdata + tpsc.scsi_Actual); dptr += RZ_BYTS) { if ((dptr[0] == 'R') && (dptr[1] == 'Z') && (dptr[2] == 'M') && (dptr[3] == 'C')) { for (i = 0; i < sizeof(struct FHBlock); i++) fhdr.fhbuf[i] = dptr[i]; tmconv(&(gfib->fib_Date),datestr,timestr); printf("l - %08x %s %s %9d ",gfib->fib_Protection,datestr, timestr,gfib->fib_Size); for (i = 0; i < fhdr.fhb.nest; i++) printf("| "); printf("%s\n",gfib->fib_FileName); } } } tp_close(); return; } /* ---------------------------------------------------------------------- */ void tap2dsk() { struct FileInfoBlock *fib; struct FileLock *fl,*ofl; /* access refname which must be a directory or disk */ if (strlen(refname) == 0) { fprintf(stderr,"tabu: reference name required for extract\n"); return; } fib = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),0); if (fib == NULL) { fprintf(stderr,"tabu: tap2dsk, fib allocation failed\n"); return; } if ((fl = Lock(refname,ACCESS_READ)) == NULL) { FreeMem(fib,sizeof(struct FileInfoBlock)); fprintf(stderr,"tabu: tap2dsk, Lock of %s failed\n",refname); return; } if (!Examine(fl,fib)) { UnLock(fl); FreeMem(fib,sizeof(struct FileInfoBlock)); fprintf(stderr,"tabu: tap2dsk, Examine of %s failed\n",refname); return; } if(fib->fib_DirEntryType <= 0) { UnLock(fl); FreeMem(fib,sizeof(struct FileInfoBlock)); fprintf(stderr,"tabu: reference for extract must be a directory\n"); return; } /* initialize tape */ if (tp_init()) { UnLock(fl); FreeMem(fib,sizeof(struct FileInfoBlock)); return; } /* cd to refname and ready to extract tape contents into it */ ofl = CurrentDir(fl); tpsc.scsi_Actual = RZ_BYTS * RZ_BLKS; dptr = bdata + tpsc.scsi_Actual; /* extract tape contents */ nest = 0; bk_extract(); /* done - cd back to where we were before */ ofl = CurrentDir(ofl); UnLock(fl); FreeMem(fib,sizeof(struct FileInfoBlock)); tp_close(); return; } /* ---------------------------------------------------------------------- */ long bk_create(char *name) { long i; long fin; struct FileInfoBlock *fib; struct FileLock *fl,*ofl; char datestr[16]; char timestr[16]; /* access the named object */ fib = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),0); if (fib == NULL) { fprintf(stderr,"tabu: bk_create, fib allocation failed\n"); return 1; } if ((fl = Lock(name,ACCESS_READ)) == NULL) { fprintf(stderr,"tabu: bk_create, Lock of %s failed\n",name); FreeMem(fib,sizeof(struct FileInfoBlock)); return 1; } if (!Examine(fl,fib)) { fprintf(stderr,"tabu: bk_create, Examine of %s failed\n",name); UnLock(fl); FreeMem(fib,sizeof(struct FileInfoBlock)); return 1; } /* Don't write disk device block to tape */ if (name[strlen(name) - 1] == ':') nest--; else { /* print line describing current object name */ tmconv(&(fib->fib_Date),datestr,timestr); printf("c - %08x %s %s %9d ",fib->fib_Protection,datestr,timestr, fib->fib_Size); for (i = 0; i < nest; i++) printf("| "); printf("%s\n",fib->fib_FileName); /* build tape image of FileInfoBlock and write it to tape */ fhdr.fhb.magic = RZ_CMAGIC; fhdr.fhb.nest = nest; gfib->fib_DiskKey = fib->fib_DiskKey; gfib->fib_DirEntryType = fib->fib_DirEntryType; strcpy(gfib->fib_FileName,fib->fib_FileName); for (i = (strlen(gfib->fib_FileName) + 1); i < 108; i++) gfib->fib_FileName[i] = '\0'; gfib->fib_Protection = fib->fib_Protection; gfib->fib_EntryType = fib->fib_EntryType; gfib->fib_Size = fib->fib_Size; gfib->fib_NumBlocks = fib->fib_NumBlocks; gfib->fib_Date.ds_Days = fib->fib_Date.ds_Days; gfib->fib_Date.ds_Minute = fib->fib_Date.ds_Minute; gfib->fib_Date.ds_Tick = fib->fib_Date.ds_Tick; for (i = 0; i < 80; i++) gfib->fib_Comment[i] = fib->fib_Comment[i]; for (i = 0; i < 36; i++) gfib->fib_Reserved[i] = fib->fib_Reserved[i]; for (i = 0; i < RZ_BYTS; i++) { if (i < sizeof(struct FHBlock)) dptr[i] = fhdr.fhbuf[i]; else dptr[i] = 0x00; } dptr += RZ_BYTS; if (dptr >= (bdata + (RZ_BLKS * RZ_BYTS))) { dptr = bdata; if (tp_write(RZ_BLKS)) { UnLock(fl); FreeMem(fib,sizeof(struct FileInfoBlock)); return 1; } } } /* if object is a directory: */ if(fib->fib_DirEntryType > 0) { nest++; ofl = CurrentDir(fl); fin = 0; while (fin == 0) { if (ExNext(fl,fib)) { if (bk_create(fib->fib_FileName)) fin = 2; } else { if ((fin = IoErr()) != ERROR_NO_MORE_ENTRIES) { fprintf(stderr,"tabu: ExNext error = %d\n",fin); fin = 2; } else fin = 1; } } ofl = CurrentDir(ofl); nest--; } /* else it is a file: */ else { fin = 1; if (bk_write(fib)) fin++; } /* done with this object */ UnLock(fl); FreeMem(fib,sizeof(struct FileInfoBlock)); return --fin; } /* ---------------------------------------------------------------------- */ void bk_d2t() { long size; time_t timer; if (dk_init()) return; if (tp_init()) { dk_close(); return; } ldata[0] = RZ_BMAGIC; time(&timer); strcpy(&(bdata[4]),ctime(&timer)); if (tp_write(1)) { tp_close(); dk_close(); return; } dksc.scsi_Actual = RZ_BYTS * RZ_BLKS; for (size = 0; dksc.scsi_Actual == (RZ_BYTS * RZ_BLKS); size += dksc.scsi_Actual) { if (dk_read((size / RZ_BYTS),RZ_BLKS)) break; if (tp_write(dksc.scsi_Actual / RZ_BYTS)) break; } fprintf(stderr,"tabu: backup bytes = %d\n",size); tp_eof(); tp_close(); dk_close(); } /* ---------------------------------------------------------------------- */ void bk_extract() { long i; long wrsz; long timer; char namestr[256]; char datestr[16]; char timestr[16]; struct FileLock *fl,*ofl; struct FileHandle *fhndl; /* normal exit is nest level change or end of tape */ while (1) { /* ready next data block from tape */ if (dptr >= bdata + tpsc.scsi_Actual) { if (tpsc.scsi_Actual != (RZ_BYTS * RZ_BLKS)) return; if (tp_read(RZ_BLKS)) return; dptr = bdata; } /* copy tape block to header area */ for (i = 0; i < sizeof(struct FHBlock); i++) fhdr.fhbuf[i] = dptr[i]; /* this had better be header block, not data block */ if (fhdr.fhb.magic != RZ_CMAGIC) { fprintf(stderr,"tabu: tape is not tabu file image backup\n"); return; } /* this item is a sibling to a higher nest level (lower number) */ if (fhdr.fhb.nest < nest) return; /* we should never have a nest jump greater than one */ if (fhdr.fhb.nest > nest) { fprintf(stderr,"tabu: bk_extract, header nest error\n"); return; } /* List header block being processed */ tmconv(&(gfib->fib_Date),datestr,timestr); printf("x - %08x %s %s %9d ",gfib->fib_Protection,datestr,timestr, gfib->fib_Size); for (i = 0; i < fhdr.fhb.nest; i++) printf("| "); printf("%s\n",gfib->fib_FileName); /* set up name for SetDate fexecl call */ sprintf(namestr,"\"%s\"",gfib->fib_FileName); /* Directory header block processing */ if(gfib->fib_DirEntryType > 0) { dptr += RZ_BYTS; if ((fl = Lock(gfib->fib_FileName,ACCESS_READ)) == NULL) { if ((fl = CreateDir(gfib->fib_FileName)) == NULL) { fprintf(stderr,"tabu: CreateDir failed for %s\n", gfib->fib_FileName); dptr = bdata; tpsc.scsi_Actual = 0; return; } } ofl = CurrentDir(fl); nest++; bk_extract(); nest--; ofl = CurrentDir(ofl); UnLock(fl); SetProtection(gfib->fib_FileName,gfib->fib_Protection); SetComment(gfib->fib_FileName,gfib->fib_Comment); fexecl("SetDate","SetDate",namestr,datestr,timestr,NULL); } /* File block(s) processing */ else { /* File header block */ if ((dptr += RZ_BYTS) >= bdata + tpsc.scsi_Actual) { if (tpsc.scsi_Actual != (RZ_BYTS * RZ_BLKS)) { fprintf(stderr, "tabu: extract, tape eof before file size satisfied\n"); return; } if (tp_read(RZ_BLKS)) return; dptr = bdata; } if ((fl = Lock(gfib->fib_FileName,ACCESS_WRITE)) == NULL) { if ((fhndl = Open(gfib->fib_FileName,MODE_NEWFILE)) == NULL) { fprintf(stderr,"tabu: bk_extract, Open failed for %s\n", gfib->fib_FileName); dptr = bdata; tpsc.scsi_Actual = 0; return; } } else { UnLock(fl); if ((fhndl = Open(gfib->fib_FileName,MODE_READWRITE)) == NULL) { fprintf(stderr,"tabu: bk_extract, Open failed for %s\n", gfib->fib_FileName); dptr = bdata; tpsc.scsi_Actual = 0; return; } } /* File data block(s) */ for (i = gfib->fib_Size; i > 0; i -= RZ_BYTS) { if (i >= RZ_BYTS) wrsz = RZ_BYTS; else wrsz = i; if (Write(fhndl,(char *)dptr,wrsz) != wrsz) { fprintf(stderr,"tabu: bk_extract, file data write failed\n"); Close(fhndl); SetProtection(gfib->fib_FileName,gfib->fib_Protection); SetComment(gfib->fib_FileName,gfib->fib_Comment); fexecl("SetDate","SetDate",namestr,datestr,timestr,NULL); dptr = bdata; tpsc.scsi_Actual = 0; return; } if ((dptr += RZ_BYTS) >= (bdata + tpsc.scsi_Actual)) { if (tpsc.scsi_Actual != (RZ_BYTS * RZ_BLKS)) { if ((i - RZ_BYTS) > 0) fprintf(stderr, "tabu: extract, tape eof before file size satisfied\n"); Close(fhndl); SetProtection(gfib->fib_FileName,gfib->fib_Protection); SetComment(gfib->fib_FileName,gfib->fib_Comment); fexecl("SetDate","SetDate",namestr,datestr,timestr,NULL); return; } if (tp_read(RZ_BLKS)) { Close(fhndl); SetProtection(gfib->fib_FileName,gfib->fib_Protection); SetComment(gfib->fib_FileName,gfib->fib_Comment); fexecl("SetDate","SetDate",namestr,datestr,timestr,NULL); return; } dptr = bdata; } } Close(fhndl); SetProtection(gfib->fib_FileName,gfib->fib_Protection); SetComment(gfib->fib_FileName,gfib->fib_Comment); fexecl("SetDate","SetDate",namestr,datestr,timestr,NULL); } } } /* ---------------------------------------------------------------------- */ void bk_t2d() { long size; if (tp_init()) return; if (tp_read(1)) { tp_close(); return; } if (ldata[0] != RZ_BMAGIC) { fprintf(stderr,"tabu: tape is not a tabu disk image backup\n"); tp_close(); return; } fprintf(stderr,"tabu: backup date = %s\n",&(bdata[4])); if (dk_init()) { tp_close(); return; } tpsc.scsi_Actual = RZ_BYTS * RZ_BLKS; for (size = 0; tpsc.scsi_Actual == (RZ_BYTS * RZ_BLKS); size += tpsc.scsi_Actual) { if (tp_read(RZ_BLKS)) break; if (dk_write((size / RZ_BYTS),(tpsc.scsi_Actual / RZ_BYTS))) break; } fprintf(stderr,"tabu: restore bytes = %d\n",size); dk_close(); tp_close(); } /* ---------------------------------------------------------------------- */ long bk_write(struct FileInfoBlock *fib) { long recd; long remn; long totl; struct FileHandle *fhndl; if ((fhndl = Open(fib->fib_FileName,MODE_OLDFILE)) == NULL) { fprintf(stderr,"tabu: file Open error = %d\n",IoErr()); return 1; } totl = 0; remn = (RZ_BYTS * RZ_BLKS) - (long)(dptr - bdata); while ((recd = Read(fhndl,(char *)dptr,remn)) == remn) { dptr = bdata; if (tp_write(RZ_BLKS)) { Close(fhndl); return 1; } totl += recd; remn = (RZ_BYTS * RZ_BLKS); } if (recd != 0) { if (recd > 0) { totl += recd; for (; (recd % RZ_BYTS) != 0; recd++) dptr[recd] = 0x00; dptr += recd; if (dptr >= (bdata + (RZ_BLKS * RZ_BYTS))) { dptr = bdata; if (tp_write(RZ_BLKS)) { Close(fhndl); return 1; } } } else { fprintf(stderr,"tabu: file Read error = %d\n",IoErr()); Close(fhndl); return 1; } } Close(fhndl); if (totl != fib->fib_Size) { fprintf(stderr,"tabu: size error, expected %d, received %d\n", fib->fib_Size,totl); return 1; } return 0; } /* ---------------------------------------------------------------------- */ long dk_capacity() { dksc.scsi_Data = data; dksc.scsi_Length = 8; dksc.scsi_Command = dkcmd; dksc.scsi_CmdLength = 10; dksc.scsi_Flags = SCSIF_READ; dkcmd[0] = 0x25; /* read capacity command */ dkcmd[1] = 0x00; dkcmd[2] = 0x00; dkcmd[3] = 0x00; dkcmd[4] = 0x00; dkcmd[5] = 0x00; dkcmd[6] = 0x00; dkcmd[7] = 0x00; dkcmd[8] = 0x00; dkcmd[9] = 0x00; if (DoIO((RZ_IOR *)&dkior)) { fprintf(stderr,"tabu: dk_capacity, DoIO error = %d\n",dkior.io_Error); return 1; } return 0; } /* ---------------------------------------------------------------------- */ long dk_close() { CloseDevice((RZ_IOR *)&dkior); } /* ---------------------------------------------------------------------- */ long dk_init() { long i; if (FindName(&SysBase->DeviceList,scsi) == NULL) { fprintf(stderr,"tabu: Device %s not found\n",scsi); return 1; } dkmp.mp_SigTask = (struct Task *)FindTask(NULL); NewList(&dkmp.mp_MsgList); if (OpenDevice(scsi,disk,(RZ_IOR *)&dkior,0)) { fprintf(stderr,"tabu: Device %s open failed.\n",scsi); return 1; } dkior.io_Command = HD_SCSICMD; dkior.io_Length = sizeof(dksc); dkior.io_Data = (APTR) &dksc; return 0; } /* ---------------------------------------------------------------------- */ long dk_read(long lba,long len) { dksc.scsi_Data = data; dksc.scsi_Length = len * RZ_BYTS; dksc.scsi_Command = dkcmd; dksc.scsi_CmdLength = 6; dksc.scsi_Flags = SCSIF_READ; dkcmd[0] = 0x08; /* read command */ dkcmd[1] = (lba & 0x1f0000) >> 16; /* MSB logical block address */ dkcmd[2] = (lba & 0xff00) >> 8; /* logical block address */ dkcmd[3] = lba & 0xff; /* LSB logical block address */ dkcmd[4] = len & 0xff; /* number of blocks */ dkcmd[5] = 0x00; if (DoIO((RZ_IOR *)&dkior)) { fprintf(stderr,"tabu: dk_read, DoIO error = %d\n",dkior.io_Error); return 1; } return 0; } /* ---------------------------------------------------------------------- */ long dk_write(long lba,long len) { dksc.scsi_Data = data; dksc.scsi_Length = len * RZ_BYTS; dksc.scsi_Command = dkcmd; dksc.scsi_CmdLength = 6; dksc.scsi_Flags = SCSIF_WRITE; dkcmd[0] = 0x0a; /* write command */ dkcmd[1] = (lba & 0x1f0000) >> 16; /* MSB logical block address */ dkcmd[2] = (lba & 0xff00) >> 8; /* logical block address */ dkcmd[3] = lba & 0xff; /* LSB logical block address */ dkcmd[4] = len & 0xff; /* number of blocks */ dkcmd[5] = 0x00; if (DoIO((RZ_IOR *)&dkior)) { fprintf(stderr,"tabu: dk_write, DoIO error = %d\n",dkior.io_Error); return 1; } return 0; } /* ---------------------------------------------------------------------- */ void tmconv(struct DateStamp *date,char *dstr,char *tstr) { long timer; struct tm *tptr; timer = (date->ds_Days + 2922) * 86400; timer += date->ds_Minute * 60; timer += date->ds_Tick / TICKS_PER_SECOND; tptr = localtime((time_t *)(&timer)); switch (tptr->tm_mon) { case 0: strcpy(tstr,"Jan"); break; case 1: strcpy(tstr,"Feb"); break; case 2: strcpy(tstr,"Mar"); break; case 3: strcpy(tstr,"Apr"); break; case 4: strcpy(tstr,"May"); break; case 5: strcpy(tstr,"Jun"); break; case 6: strcpy(tstr,"Jul"); break; case 7: strcpy(tstr,"Aug"); break; case 8: strcpy(tstr,"Sep"); break; case 9: strcpy(tstr,"Oct"); break; case 10: strcpy(tstr,"Nov"); break; case 11: strcpy(tstr,"Dec"); break; } sprintf(dstr,"%02d-%s-%02d",tptr->tm_mday,tstr,tptr->tm_year); sprintf(tstr,"%02d:%02d:%02d",tptr->tm_hour,tptr->tm_min,tptr->tm_sec); return; } /* ---------------------------------------------------------------------- */ long tp_close() { tp_rewind(); CloseDevice((RZ_IOR *)&tpior); fprintf(stderr,"tabu finished, Press RETURN when ready.\n"); getchar(); exit(1); } /* ---------------------------------------------------------------------- */ long tp_eof() { tpsc.scsi_Data = NULL; tpsc.scsi_Length = 0; tpsc.scsi_Command = tpcmd; tpsc.scsi_CmdLength = 6; tpsc.scsi_Flags = 0; tpcmd[0] = 0x10; /* write filemark command */ tpcmd[1] = 0; tpcmd[2] = 0; /* MSB Number of filemarks */ tpcmd[3] = 0; /* Number of filemarks */ tpcmd[4] = 2; /* LSB Number of filemarks */ tpcmd[5] = 0; if (DoIO((RZ_IOR *)&tpior)) { fprintf(stderr,"tabu: tp_eof, DoIO error = %d\n",tpior.io_Error); return 1; } return 0; } /* ---------------------------------------------------------------------- */ long tp_init() { if (FindName(&SysBase->DeviceList,scsi) == NULL) { fprintf(stderr,"tabu: Device %s not found\n",scsi); return 1; } tpmp.mp_SigTask = (struct Task *)FindTask(NULL); NewList(&tpmp.mp_MsgList); if (OpenDevice(scsi,tape,(RZ_IOR *)&tpior,0)) { fprintf(stderr,"tabu: Device %s open failed.\n",scsi); return 1; } tpior.io_Command = HD_SCSICMD; tpior.io_Length = sizeof(tpsc); tpior.io_Data = (APTR) &tpsc; if (tp_sense()) { tp_close(); return 1; } if (bdata[8] & 0x40) { fprintf(stderr,"tabu: No tape in drive!\n"); return 1; } if (tp_rewind()) { tp_close(); return 1; } return 0; } /* ---------------------------------------------------------------------- */ long tp_read(long len) { tpsc.scsi_Data = data; tpsc.scsi_Length = len * RZ_BYTS; tpsc.scsi_Command = tpcmd; tpsc.scsi_CmdLength = 6; tpsc.scsi_Flags = SCSIF_READ; tpcmd[0] = 0x08; /* read command */ tpcmd[1] = 0x01; tpcmd[2] = (len & 0xff0000) >> 16; /* MSB number of blocks */ tpcmd[3] = (len & 0xff00) >> 8; /* number of blocks */ tpcmd[4] = len & 0xff; /* LSB number of blocks */ tpcmd[5] = 0x00; if (DoIO((RZ_IOR *)&tpior)) { fprintf(stderr,"tabu: tp_read, DoIO error = %d\n",tpior.io_Error); return 1; } return 0; } /* ---------------------------------------------------------------------- */ long tp_rewind() { tpsc.scsi_Data = NULL; tpsc.scsi_Length = 0; tpsc.scsi_Command = tpcmd; tpsc.scsi_CmdLength = 6; tpsc.scsi_Flags = 0; tpcmd[0] = 0x01; /* rewind command */ tpcmd[1] = 0; tpcmd[2] = 0; tpcmd[3] = 0; tpcmd[4] = 0; tpcmd[5] = 0; if (DoIO((RZ_IOR *)&tpior)) { fprintf(stderr,"tabu: tp_rewind, DoIO error = %d\n",tpior.io_Error); return 1; } return 0; } /* ---------------------------------------------------------------------- */ long tp_sense() { tpsc.scsi_Data = data; tpsc.scsi_Length = 14; tpsc.scsi_Command = tpcmd; tpsc.scsi_CmdLength = 6; tpsc.scsi_Flags = SCSIF_READ; tpcmd[0] = 0x03; /* sense command */ tpcmd[1] = 0x00; tpcmd[2] = 0x00; tpcmd[3] = 0x00; tpcmd[4] = 0x0e; /* number of sense bytes to fetch */ tpcmd[5] = 0x00; if (DoIO((RZ_IOR *)&tpior)) { fprintf(stderr,"tabu: tp_sense, DoIO error = %d\n",tpior.io_Error); return 1; } return 0; } /* ---------------------------------------------------------------------- */ long tp_write(long len) { tpsc.scsi_Data = data; tpsc.scsi_Length = len * RZ_BYTS; tpsc.scsi_Command = tpcmd; tpsc.scsi_CmdLength = 6; tpsc.scsi_Flags = SCSIF_WRITE; tpcmd[0] = 0x0a; /* write command */ tpcmd[1] = 0x01; tpcmd[2] = (len & 0xff0000) >> 16; /* MSB number of blocks */ tpcmd[3] = (len & 0xff00) >> 8; /* number of blocks */ tpcmd[4] = len & 0xff; /* LSB number of blocks */ tpcmd[5] = 0x00; if (DoIO((RZ_IOR *)&tpior)) { fprintf(stderr,"tabu: tp_write, DoIO error = %d\n",tpior.io_Error); return 1; } return 0; } /* end of code ---------------------------------------------------------- */