/* * flxtp keys [name ...] * keys are: * w write to beginning of tape * a append to end of tape * r read named files from tape; if no names, extract all * t table named files; or table all * also may add: * v verbose * i wait for user 'y' before performing function * u leave extracted filenames in upper case (usually * filenames are mapped to lower case) * n don't rewind tape before performing action * [x,y] specify uic for tape * pooo use protection ooo on tape * bddd use blocksize ddd to write on tape * (tape read automagically determines blksize) * ddddd use density dddd (800 or 1600) * o ok to overwrite existing files when extracting * (default will not overwrite existing files) * m make a new directory for each uic found on tape and * put the extracted files in them * * name is a unix path name (for writing tapes) or the name of * a file on the tape. When writing tapes, a name may be a uic * in the same form as above. This causes all following files * to be written on the tape in that uic. */ #include #include #include #include #define FLXHD 14 #define FLXDATA 512 /* * len of longest unpacked filename, including the null at end * and one extra space for version 'number' */ #define FLXNM 15 #define MAXBASE (9+1) #define MAXEXT (3+1) /* note byte swap for DEC machines */ #define OFFNAME 0 #define OFFEXT 4 #define OFFUIC2 6 #define OFFUIC1 7 #define OFFPROT2 8 #define OFFPROT1 9 #define OFFDATE2 10 #define OFFDATE1 11 #define OFFOVER 12 #define DEFUIC1 '\001' #define DEFUIC2 '\001' #define DEFPROT1 '\000' #define DEFPROT2 '\233' #define CR '\015' #define LF '\012' #define NL '\012' #define TPWRITE 'w' #define TPAPPEND 'a' #define TPREAD 'r' #define TPTABLE 't' #define IOPT 'i' #define VOPT 'v' #define UOPT 'u' #define NOPT 'n' #define POPT 'p' #define BOPT 'b' #define DOPT 'd' #define OOPT 'o' #define MOPT 'm' #define NOCMD '\0' struct parsehdr { char phname[FLXNM]; char phuic1; char phuic2; char phprot1; char phprot2; char phdate[11]; }; int verbose, mkdirs, overwrite, inquire, allfiles, uicfiles, upcase, norewind = 0; int argsleft, filenbr, actnbr = 0; char tp1600[] = "/dev/nrmt0"; char tp1600rw[] = "/dev/rmt0"; char bsr1600[] = "mt -t /dev/nrmt0 bsr 1"; char tp800[] = "/dev/nrmt0"; char tp800rw[] = "/dev/rmt0"; char bsr800[] = "mt -t /dev/nrmt0 bsr 1"; char *devtp = tp1600; char *devtprw = tp1600rw; char *bsrcmd = bsr1600; int tpfd; FILE *dfd; char uic1 = DEFUIC1; char uic2 = DEFUIC2; char prot1 = DEFPROT1; char prot2 = DEFPROT2; char date1 = '\000'; char date2 = '\000'; #define BIGBLK 32768 unsigned tpblksiz = FLXDATA; char *tpbuf, *malloc(); char cmd = NOCMD; /* * flxtp - read or write flx format tape */ main (argc, argv) int argc; char **argv; { int k; int density; char c = '\0'; if (argc < 2) usage(); if (argc == 2) allfiles++; else argsleft = argc - 2; argv++; /* skip over command name */ k=0; while ( (c=(*argv)[k++]) != '\0') { switch (c) { case TPAPPEND: #ifndef PICKLE error ("append function not implemented"); #endif /* fall thru to write */ case TPWRITE: if (cmd != NOCMD) error ("Only one of rwat may be selected"); if (allfiles) error ("Name(s) must be given for w or a"); cmd = c; break; case TPREAD: /* fall thru */ case TPTABLE: if (cmd != NOCMD) error ("Only one of rwat may be selected"); cmd = c; break; case MOPT: mkdirs++; break; case OOPT: overwrite++; break; case NOPT: norewind++; break; case IOPT: inquire++; break; case VOPT: verbose++; break; case UOPT: upcase++; break; case '[': if(sscanf(&(*argv)[k],"%3o,%3o]",&uic1,&uic2)==2 ) { while ( (*argv)[k++] != ']'); } else error ("Uic must be given as [xxx,yyy]"); uicfiles++; break; case POPT: if(sscanf(&(*argv)[k],"%3o",&prot2) == 1 ) { while ( isdigit ( (*argv)[k]) ) k++; } else error ("Protection must be given as pooo"); break; case BOPT: if (sscanf(&(*argv)[k],"%d",&tpblksiz) == 1) { while ( isdigit ( (*argv)[k] ) ) k++; } else error ("Tape blocksize must be given as bddd"); break; case DOPT: if (sscanf(&(*argv)[k],"%d",&density) == 1) { while ( isdigit ( (*argv)[k] ) ) k++; if (density==1600) {/* already set */} else if (density==800) { devtp=tp800; devtprw=tp800rw; bsrcmd=bsr800; } else error ("Density must be given as d800 or d1600"); } else error ("Density must be given as d800 or d1600"); break; case '-': /* ignore */ break; default: usage(); } /* switch */ } /* while */ if (cmd == TPREAD | cmd == TPTABLE) tpblksiz = BIGBLK; if ( (tpbuf=malloc(tpblksiz)) == (char *) 0) error ("Sorry, can't get buffer for your blocksize"); argv++; /* skip over keys */ if ( !norewind) { if((tpfd=open(devtprw,0)) == -1) error ("Can't access tape"); close(tpfd); } switch (cmd) { case TPAPPEND: seekeot(); /* fall thru to put files */ case TPWRITE: putfiles (argv); break; case TPREAD: getfiles (argv); break; case TPTABLE: tblfiles (argv); break; default: error ("Pgm error; see sys msg"); } /* switch */ exit (0); } /* flxtp */ error (msg) char *msg; { fprintf (stderr,"%s\n",msg); exit (-1); } /* error */ usage () { fprintf (stderr,"Usage: flxtp (rwat)[vilnupOOObDDDdDDDD] [name ...]\nwhere u = [x,y]\n"); exit (-1); } /* usage */ int tblfiles (list) char **list; { char hdr[FLXHD]; struct parsehdr phdr; int nr, nbrblk, totblks = 0; if ( (tpfd=open(devtp,0)) == -1) error ("Can't open tape"); while (allfiles | argsleft) { if ((nr=read(tpfd,hdr,FLXHD)) == 0) break; expandhdr (hdr, &phdr); filenbr++; if (amatch (&phdr, list)) { nbrblk = gobblefile(); totblks += nbrblk; fprintf(stdout,"File %4d: %-13s %5d <%3o> [%3o,%3o]\n", filenbr, phdr.phname, nbrblk, phdr.phprot2&0xff, phdr.phuic1&0xff, phdr.phuic2&0xff); actnbr++; if (!allfiles) argsleft--; } else nbrblk = gobblefile(); } if(allfiles) fprintf (stdout,"Total %d data blocks in %d files listed\n", totblks,actnbr); if (!allfiles & argsleft) fprintf (stderr,"Other files not found\n"); close (tpfd); } /* tblfiles */ int gobblefile () { int nr, nbrblk = 0; while ((nr=read(tpfd,tpbuf,tpblksiz)) > 0) nbrblk++; return (nbrblk); } /* gobblefile */ int getfiles (list) char **list; { char wuic1, wuic2 = 0; char hdr[FLXHD], reply[2], *pfull, *p, *q, *v, *fname, overname[FLXNM]; static char versions[] = "!@#$%^&*()"; static char mkdircmd [] = "mkdir 000,000.dir"; static char *pathname = &mkdircmd[6]; static char fullname[27]; struct parsehdr phdr; int nr, ip, jp, nbrblk = 0; if ( (tpfd=open(devtp,0)) == -1) error ("Can't open tape"); while (allfiles | argsleft) { if ((nr=read(tpfd,hdr,FLXHD)) == 0) break; expandhdr ( hdr, &phdr); filenbr++; if (amatch (&phdr, list) ) { if (!allfiles) argsleft--; if (inquire) { fprintf (stdout,"Extract %s? (y/n) ",phdr.phname); fread(reply,1, 2, stdin); if (*reply != 'y') goto skip; } if (mkdirs) { if (phdr.phuic1 != wuic1 | phdr.phuic2 != wuic2) { wuic1=phdr.phuic1; wuic2=phdr.phuic2; sprintf(pathname, "%03o,%03o.dir", wuic1&0xff, wuic2&0xff); if (access(pathname,0) != 0) { if (system(mkdircmd) != 0) error ("Can't make directory"); } } pfull = fullname; p = pathname; while ( *pfull++ = *p++ ); pfull[-1] = '/'; p = phdr.phname; while ( *pfull++ = *p++); fname = fullname; } else fname = phdr.phname; if (verbose) fprintf (stdout, "get [%3o,%3o] %s file # %d\n", phdr.phuic1&0xff, phdr.phuic2&0xff, fname, filenbr); if (!overwrite && (access(fname,0 /* exists */) == 0)) { /* try adding 'version' char at end of name */ v=versions; p=fname; q=overname; while (*p) *q++ = *p++; *(q+1) = '\0'; while (*v) { *q = *v; if (access(overname,0)) break; v++; /* try next 'version' nbr */ } if (*v == 0) { /*already 10 versions */ printf("Can't overwrite %s\n", overname); goto skip; } printf("Duplicate filename; %s used\n", overname); fname = overname; } if ( (dfd=fopen(fname, "w")) == NULL) error ("Can't open disk file"); while ( (nr=read(tpfd, tpbuf, tpblksiz)) > 0){ ip = jp = 0; while (ip>8; } /* for */ } /* ator50 */ int radmap (c) char c; { if (islower(c)) return (c-96); if (isupper(c)) return (c-64); if (isdigit(c)) return (c-18); if (c==' ') return (0); if (c=='$') return (27); if (c=='.') return (28); return (29); } /* radmap */ #define MATCH 1 #define NOMATCH 0 int amatch (ph, list) struct parsehdr *ph; char **list; { if (allfiles) { if (uicfiles) { if (ph->phuic1 == uic1 & ph->phuic2 == uic2) return (MATCH); else return (NOMATCH); } else return (MATCH); } if (uicfiles) if (ph->phuic1 != uic1 | ph->phuic2 != uic2) return (NOMATCH); while (*list) { if (strncmp (ph->phname, *list, FLXNM) == 0) return (MATCH); list++; } /* while */ return (NOMATCH); } /* amatch */ expandhdr (hdr, ph) char *hdr; struct parsehdr *ph; { char *nm; nm = ph->phname; r50toa(&hdr[OFFNAME], 2 /* words */, nm); while (*nm > ' ') nm++; r50toa(&hdr[OFFOVER], 1 /* word */, nm); while (*nm > ' ') nm++; *nm++ = '.'; r50toa (&hdr[OFFEXT], 1 /* word */, nm); while (*nm > ' ') nm++; /* if filename ends in '.', just drop it */ if ( *(nm - 1) == '.') nm--; *nm = '\0'; ph->phuic1 = hdr[OFFUIC1]; ph->phuic2 = hdr[OFFUIC2]; ph->phprot1 = hdr[OFFPROT1]; ph->phprot2 = hdr[OFFPROT2]; ph->phdate[0] = '\0'; /* don't yet know how to parse date */ } /* expandhdr */