Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site amd.UUCP Path: utzoo!watmath!clyde!amd!eager From: eager@amd.UUCP (Mike Eager) Newsgroups: net.sources Subject: Improved ansitar -- ansi tape utility Message-ID: <668@amd.UUCP> Date: Thu, 29-Nov-84 17:32:56 EST Article-I.D.: amd.668 Posted: Thu Nov 29 17:32:56 1984 Date-Received: Fri, 30-Nov-84 07:16:56 EST Distribution: net Organization: AMD Applications, Santa Clara, CA Lines: 1726 Here is a new copy of the ansitar utility that was distributed across the net some months ago. A manual page has been created, several bugs fixed, and a couple options added. These options keep the tape from re-winding when the program completes, improved support VMS "D" type files. See manual page for more info. ---------------------ansitar.1------------------------ .TH ANSITAR 1 "AMD local" .SH NAME ANSITAR \- a program to read and write ANSI labeled tapes .SH SYNOPSIS .B ansitar [crxtvblnf] [blocksize] [labelsize] [filecount] file .SH DESCRIPTION .PP .I Ansitar is a program which reads and writes ANSI format labelled tapes. Its options are similar to tar: .TP 8 .B c create a tape .TP 8 .B r replace (update) a tape .TP 8 .B x extract files .TP 8 .B t print table of contents .TP 8 .B v set verbose mode: for crx, print names; for t print labels .TP 8 .B 0-9 select drive 0-9 (default 0) .TP 8 .B b use next argument as a block size (default is 2048 bytes) .TP 8 .B B use next argument as tape block size, and following argument as line size (for blocking/unblocking) .TP 8 .B l use next arg as a label size .TP 8 .B U select upper(out)/lower(in) case translation of names .TP 8 .B R use RT11 label and name conventions (UGH!) .TP 8 .B S use RSTS conventions (==RT11 except 80-byte labels) .TP 8 .B P create/read files in "pip" (FILES-11) counted format. .TP 8 .B D read variable length records (D format) .TP 8 .B n do not rewind tape at completion of processing .TP 8 .B f use next argument as number of files to search for .B t or .B x options. Ignored if file names specified. .PP The filename may contain * to indicate a wild card; however, the asterisk should be enclosed in quotes to prevent the shell from interpreting it. .PP Examples of usage: .PP ansitar tv Verbose table of contents .PP ansitar xvDUb 2000 file1 file2 Extract file1 and file2 from .br tape with 2000 bytes/block .br and variable length records .PP ansitar xv *.c Extract all files with .c .br extension from tape with .br 2048 byte/block .PP ansitar tvfn 5 List contents of first 5 .br files and do not rewind tape .PP ansitar xvf 5 Extract the first five files .SH FILES /dev/mt?? .SH SEE ALSO tar(1), mt(4) .SH DIAGNOSTICS .PP Many and verbose. Most are self-explanatory. .PP bad block size: block size <= 0 .PP bad line size: line size <= 0 or not divisor of block size .PP label size must be >= : label size too small to hold header .PP can't open : couldn't open tape device .PP can't allocate buffer of bytes: malloc couldn't get buffer .PP can't allocate line buffer of bytes: malloc couldn't get buffer .PP can't create .PP can't open .SH BUGS .PP Writing variable length records (D format) is not implemented. .PP Wild cards have not been extensively tested. .PP Warning: The routines skipfile and backspace use nonstandard (4.1BSD) ioctl calls! .SH AUTHOR Gotten from varian!david Wed Mar 28 14:05:58 1984. .PP Man page written by Phil Ngai. ---------------------ansitar.c------------------------ /* >From varian!david Wed Mar 28 14:05:58 1984 Message-ID: <201@varian.UUCP> ANSITAR - a program to read and write ANSI labeled tapes The following extremely useful program was posted to net last summer by uiucuxc!root (sorry I can't give any better credits than that, the poster's name seems to be lost due to notes); we here at Varian and utah-gr!thomas have made a few improvements since. I mentioned the existence of ansitar in net.unix last week, and the response was such that I felt it was time to post it. Sorry there's no manual page, but there is a note on usage in the source. I'd love to hear about bugs and improvements. David Brown (415) 945-2199 Varian Instruments 2700 Mitchell Dr. Walnut Creek, Ca. 94598 {zehntel,amd70,fortune}!varian!david */ /* >From pur-ee!uiucdcs!uiucuxc!root Sat Jul 2 04:31:32 1983 Subject: Ansitar.c - (nf) * * 08/29/84 MJE: extract only first copy of file & stop reading tape when * all requested files have been extracted * 08/29/84 MJE: make blocksize symbolic & default to 2048 (same default as * VMS output tapes. * 08/30/84 MJE: add -n option to keep tape from rewinding at end * 08/30/84 MJE: add -f # count of files to process option * 10/28/83 DRB: new option 'D': read variable length records (D format) * 10/29/83 FGH: 1. wildcard ability added to filenames. * 2. when output filename isn't valid for Unix (as it's perhaps * taken from a foreign tape), this program now just skips that * file rather than exiting the whole job. * 10/30/83 FGH: 1. some problems with varunblock's handling of end of record. * still must use 'D' option with 'b' such that b's argument * exceeds the tape's physical record size (2048 in my case) * 2. changed varunblock/doxtract to correct the byte count. * * 10/31/83 DRB: * new option P - create/read files in "pip" (FILES-11) counted format. * handle tape read error * From utah-gr!thomas Tue Aug 2 21:27:08 1983 * (=Spencer) (#ifdef PIP) */ #define VARIAN #define PIP #ifdef VARIAN #define DEBUG 0 /* set to nonzero to debug new Varian code */ #define DBG if(DEBUG) fprintf(stderr, #define WILDCARD '*' #endif VARIAN #include #include #include #include #include #include #include /* ansitar -- archiver for ansi-format labelled tapes * * ansitar [crxtvbl] [blocksize] [labelsize] file ... * * The options are similar to tar: * c - create a tape * r - replace (update) a tape * x - extract files * t - print table of contents * v - set verbose mode: for crx, print names; for t print labels * 0-9 - select drive 0-9 * b - use next argument as a block size (default is 2048) * B - use next argument as tape block size, and * following argument as line size (for blocking/unblocking) * l - use next arg as a label size * U - select upper(out)/lower(in) case translation of names * R - use RT11 label and name conventions (UGH!) * S - use RSTS conventions (==RT11 except 80-byte labels) * P - create/read files in "pip" (FILES-11) counted format. * D - read variable length records (D format) * n - do not rewind tape at end of processing * f - use next argument as count of files to process (options t & x) * V - use next argument as volume serial number * * The filename may contain * to indicate a wild card; however, the * asterick should be enclosed in quotes to prevent the shell from * interpreting it. * * Examples of usage: * ansitar tv Verbose table of contents * ansitar xvDUb 2000 file1 file2 Extract file1 and file2 from * tape with 2000 bytes/block * and variable length records * * BUGS: * Writing variable length records (D format) is not implemented. * Wild cards have not been extensively tested. * * Warning: The routines skipfile and backspace use nonstandard * (4.1BSD) ioctl calls! */ #define Skiparg() argc--; argv++ #define MAXLINE 256 #define TRUE 1 #define FALSE 0 #define READ 0 #define READWRITE 2 #define BLKSIZE 2048 /* default blocksize = VMS standard blocksize */ /* field sizes */ #define LABID 3 #define SERIAL 6 #define OWNER 14 #define FILEID 17 #define SETID 6 #define SECNO 4 #define SEQNO 4 #define GENNO 4 #define GENVSNO 2 #define CRDATE 6 #define EXDATE 6 #define BLOCKS 6 #define SYSTEM 13 #define BLKLEN 5 #define RECLEN 5 #define BUFOFF 2 /* pad fields (reserved for future use) */ #define VRES1 20 #define VRES2 6 #define VRES3 28 #define H1RES1 7 #define H2RES1 35 #define H2RES2 28 /* Volume header label */ struct vol { char v_labid[LABID]; /* label identifier "VOL" */ char v_labno; /* label number */ char v_serial[SERIAL]; /* volume serial number */ char v_access; /* accessibility */ char v_res1[VRES1]; /* reserved for future use */ char v_res2[VRES2]; /* reserved for future use */ char v_owner[OWNER]; /* owner identifier */ char v_res3[VRES3]; /* reserved for future use */ char v_stdlabel; /* standard label flag */ }; /* file header/eof label */ struct hdr_1 { char h1_labid[LABID]; /* label identifier */ char h1_labno; /* label number */ char h1_fileid[FILEID]; /* file identifier */ char h1_setid[SETID]; /* file set identifier */ char h1_secno[SECNO]; /* file section number */ char h1_seqno[SEQNO]; /* file sequence number */ char h1_genno[GENNO]; /* generation number */ char h1_genvsno[GENVSNO]; /* generation vsn number */ char h1_crdate[CRDATE]; /* creation date */ char h1_exdate[EXDATE]; /* expiration date */ char h1_access; /* accessibility */ char h1_blocks[BLOCKS]; /* block count */ char h1_system[SYSTEM]; /* system code */ char h1_x1[7]; /* reserved */ } ; struct hdr_2 { char h2_labid[LABID]; /* label identifier */ char h2_labno; /* label number */ char h2_recfm; /* record format */ char h2_blklen[BLKLEN]; /* block length */ char h2_reclen[RECLEN]; /* record length */ char h2_res1[H2RES1]; /* reserved */ char h2_bufoff[BUFOFF]; /* buffer offset */ char h2_res2[H2RES2]; /* reserved */ } ; struct vol vol1; struct hdr_1 hdr1, eof1; struct hdr_2 hdr2; char *tapefile = "/dev/rmt8"; char *buffer, *linebuffer, *malloc(), *index(); char **filetab; int blocksize = BLKSIZE; int linesize = 0; int bfactor = 0; int labelsize = sizeof(struct vol); char recfm = 'F'; char line[MAXLINE]; int tapeunit = 0; int tf; char *defvsn = ""; char curdate[CRDATE+1]; char *alongtime = " 99364"; #ifdef PIP int create, replace, xtract, table, verbose, confirm, filecnt, norewind, pipfile; #else int create, replace, xtract, table, verbose, confirm, filecnt, norewind; #endif int blocking; int RT11, Upper; #ifdef VARIAN int Varlen; #endif VARIAN main(argc, argv) int argc; char **argv; { char *ap; int bufsize, openmode; if (argc < 2) usage(); Skiparg(); openmode = READ; ap = argv[0]; Skiparg(); while (*ap) { switch (*ap) { case 'c': create++; openmode = READWRITE; break; case 'r': replace++; openmode = READWRITE; break; case 'x': xtract++; break; case 't': table++; break; case 'v': verbose++; break; case 'w': confirm++; break; case 'b': case 'B': blocking++; blocksize = atoi(argv[0]); if (blocksize <= 0) fatal("bad block size %s\n", argv[0]); Skiparg(); if (*ap == 'B') { linesize = atoi(argv[0]); if (linesize <= 0 || blocksize % linesize != 0) fatal("bad line size %s\n", argv[0]); bfactor = blocksize / linesize; Skiparg(); } break; case 'l': labelsize = atoi(argv[0]); if (labelsize < sizeof(struct hdr_1)) fatal("label size must be >= %d\n", sizeof(struct hdr_1)); Skiparg(); break; case 'U': Upper++; break; case 'V': defvsn = argv[0]; if (strlen(defvsn) > SERIAL) defvsn[SERIAL] = '\0'; Skiparg(); break; case 'S': case 'R': RT11++; Upper++; if (*ap == 'R') labelsize = 512; break; #ifdef VARIAN case 'D': Varlen++; recfm = 'D'; break; #endif VARIAN #ifdef PIP case 'P': pipfile++; break; #endif PIP case 'n': norewind++; break; case 'f': filecnt = atoi(argv[0]); if (filecnt <= 0) fatal("bad file count: %s\n", argv[0]); Skiparg(); break; default: if (isdigit(*ap)) { tapeunit = *ap; break; } fatal("bad flag: %c\n", *ap); } ap++; } filetab = argv; filetab[argc] = NULL; if (norewind) tapefile = "/dev/rmt12"; if (filecnt == 0) filecnt = 32767; if (tapeunit) tapefile[strlen(tapefile)-1] = tapeunit; tf = open(tapefile, openmode); if (tf < 0) fatal("can't open %s%s\n", tapefile, (openmode != READ) ? " for writing" : ""); bufsize = max(blocksize, labelsize); /*###218 [lint] malloc arg. 1 used inconsistently llib-lc(59) :: ansitar.c(218)%%%*/ buffer = malloc(bufsize + 10); if (buffer == NULL) fatal("can't allocate buffer of %d bytes\n", blocksize); if (linesize) { /*###222 [lint] malloc arg. 1 used inconsistently llib-lc(59) :: ansitar.c(222)%%%*/ linebuffer = malloc(linesize + 10); if (linebuffer == NULL) fatal("can't allocate line buffer of %d bytes\n", linesize); } getansidate(curdate); if (verbose && blocking) { printf("Blocksize: %d", blocksize); if (linesize) printf(" Linesize: %d", linesize); putc('\n', stdout); } if (create || replace) doupdate(tf); else if (xtract) doxtract(tf, filecnt); else if (table) dotable(tf, filecnt); else usage(); exit(0); } usage() { fatal("usage: ansitar crxtvblnf [blocksize] [labelsize] [filecnt] file ...\n"); } dotable(tf, fc) int tf, fc; { char fileid[FILEID+1]; int files, n; int blocks; long bytes; getvol(tf, &vol1); prtvol(&vol1); putc('\n', stdout); files = 0; while ((files < fc) && (gethdr(tf, &hdr1))) { files++; if (verbose) { prthdr(&hdr1); if (gethdr(tf, &hdr2)) prthdr(&hdr2); } getmark(tf); sncpy(fileid, hdr1.h1_fileid, FILEID); blocks = 0; bytes = 0L; while ((n = getrec(tf, buffer, blocksize)) > 0) { blocks++; bytes += n; } geteof(tf, &eof1); if (verbose) { prthdr(&eof1); putc('\n', stdout); } getmark(tf); cmphdreof(&hdr1, &eof1); printf("t %s %d blocks %D bytes\n", fileid, blocks, bytes); if (verbose) putc('\n', stdout); } printf("\n%d files\n", files); } doxtract(tf, fc) int tf, fc; { char fileid[FILEID+1]; FILE *fp; long bytes; int blocks; int n, xall; #ifdef VARIAN int newn; #endif VARIAN if (filetab[0] == NULL) if ((xall = fc) == 0) xall = 65535; getvol(tf, &vol1); if (verbose) prtvol(&vol1); while ((xall || morefiles(filetab)) && gethdr(tf, &hdr1)) { getmark(tf); sncpy(fileid, hdr1.h1_fileid, FILEID); trimsp(fileid); if (RT11) fromRT11(fileid); /* if 1.you're doing all the files or 2. this file matches */ /* one of the the names in the arglist, then copy it, else */ /* skip this file. filetab is really 'argv' list. */ if ( (xall || lookup(filetab, fileid, Upper)) && checkw('x', fileid) ) { if (xall) xall--; if (Upper) makelower(fileid); /* name to lower case*/ fp = fopen(fileid, "w"); #ifdef VARIAN if (fp == NULL) { printf("can't create %s - will skip\n", fileid); skipfile(tf); } #else if (fp == NULL) fatal("can't create %s\n", fileid); #endif VARIAN else{ /* file OK, do the copy */ blocks = 0; bytes = 0L; while ((n = getrec(tf, buffer, blocksize)) > 0) { if (linesize) lunblock(fp, buffer, n, linesize); else #ifdef VARIAN if (Varlen) { newn = varunblock(fp,buffer,n); n = newn; /* now it's # written */ } else #endif VARIAN #ifdef PIP if (pipfile) pipunblock(fp, buffer, n); else #endif PIP fwrite(buffer, n, 1, fp); blocks++; bytes += n; } fclose(fp); if (verbose) printf("x %s %d blocks %D bytes\n", fileid, blocks, bytes); } /* end 'if file open was OK' */ } /* end 'if filename OK or copying all' */ else /* if this file is not be copied */ skipfile(tf); geteof(tf, &eof1); cmphdreof(&hdr1, &eof1); getmark(tf); } } doupdate(tf) int tf; { int i, n; int blocks; long bytes; char fileid[FILEID+1]; FILE *fp; int sequence; sequence = 0; if (create) { initvol(&vol1); putvol(tf, &vol1); } else { /* replace */ getvol(tf, &vol1); while (gethdr(tf, &hdr1)) { sncpy(line, hdr1.h1_seqno, SEQNO); sequence = atoi(line); getmark(tf); skipfile(tf); geteof(tf, &eof1); getmark(tf); } backspace(tf); } for (i=0; filetab[i] != NULL; i++) { if (!checkw('a', filetab[i])) continue; strncpy(fileid, filetab[i], FILEID); fileid[FILEID] = '\0'; fp = fopen(fileid, "r"); if (fp == NULL) fatal("can't open %s\n", fileid); sequence++; if (RT11) toRT11(fileid); if (Upper) makeupper(fileid); inithdr1(&hdr1, fileid, sequence); puthdr(tf, &hdr1, sizeof(struct hdr_1)); inithdr2(&hdr2, recfm, blocksize, (linesize == 0) ? blocksize : linesize); puthdr(tf, &hdr2, sizeof(struct hdr_2)); tapemark(tf); blocks = 0; bytes = 0L; *line = '\0'; if (Varlen) while ((n = dblock(fp, buffer, blocksize)) > 0) { n = write(tf, buffer, n); blocks++; bytes += n; } else if (linesize) while ((n = lblock(fp, buffer, linesize, bfactor)) > 0) { if (n % 2) { buffer[n] = '\0'; n++; } n = write(tf, buffer, n); blocks++; bytes += n; } #ifdef PIP else if (pipfile) while ((n = pipblock(fp, buffer, blocksize)) > 0) { n = write(tf, buffer, n); blocks++; bytes += n; } else #else else #endif PIP while ((n = fread(buffer, sizeof(char), blocksize, fp)) > 0) { if (n % 2) { buffer[n] = '\0'; n++; } n = write(tf, buffer, n); blocks++; bytes += n; } fclose(fp); tapemark(tf); blcopy(hdr1.h1_labid, "EOF", LABID); utoaz(blocks, line, BLOCKS); blcopy(hdr1.h1_blocks, line, BLOCKS); puthdr(tf, &hdr1, sizeof(struct hdr_1)); tapemark(tf); if (verbose) printf("a %s %d blocks %D bytes\n", fileid, blocks, bytes); } tapemark(tf); } getvol(tf, volp) int tf; struct vol *volp; { int n; if (labelsize == sizeof(struct vol)) n = read(tf, (char *)volp, sizeof(struct vol)); else { n = read(tf, buffer, labelsize); bcopy((char *)volp, buffer, sizeof(struct vol)); } #ifdef PIP if (n<0) { perror("Tape read error"); exit(1); } #endif PIP if (n != labelsize || strncmp(volp->v_labid, "VOL", LABID) != 0 || volp->v_labno != '1') { printf("Warning: Volume label (VOL1) missing\n"); backspace(tf); return; } /* check for RT11 boot block between VOL1 and first HDR1 */ if (RT11) { /* must have labelsize = 512 */ n = read(tf, buffer, labelsize); bcopy((char *)&hdr1, buffer, sizeof(struct hdr_1)); if (n == labelsize && strncmp(hdr1.h1_labid, "HDR", LABID) == 0) backspace(tf); else printf("Possible RT11 bootstrap block.\n"); } } int gethdr(tf, hdrp) int tf; char *hdrp; { int n; if (labelsize == sizeof(struct hdr_1)) n = read(tf, hdrp, sizeof(struct hdr_1)); else { n = read(tf, buffer, labelsize); bcopy(hdrp, buffer, sizeof(struct hdr_1)); } if (n == 0) return(FALSE); if (n != labelsize || strncmp(hdrp, "HDR", LABID) != 0) hdrerr(tf, hdrp); return(TRUE); } hdrerr(tf, hdrp) int tf; char *hdrp; { int found, n; printf("Warning: File label error - skipping\n"); found = FALSE; while (!found) { skipfile(tf); if (labelsize == sizeof(struct hdr_1)) n = read(tf, hdrp, sizeof(struct hdr_1)); else { n = read(tf, buffer, labelsize); bcopy(hdrp, buffer, sizeof(struct hdr_1)); } if ((n == labelsize) && (strncmp(hdrp, "HDR", LABID) == 0)) found = TRUE; } } geteof(tf, eofp) int tf; struct hdr_1 *eofp; { int n; if (labelsize == sizeof(struct hdr_1)) /*###526 [lint] read arg. 2 used inconsistently llib-lc(41) :: ansitar.c(526)%%%*/ n = read(tf, eofp, sizeof(struct hdr_1)); else { n = read(tf, buffer, labelsize); bcopy((char *)eofp, buffer, sizeof(struct hdr_1)); } if (n != labelsize || strncmp(eofp->h1_labid, "EOF", LABID) != 0 || eofp->h1_labno != '1') printf("Warning: File label (EOF1) error\n"); } int getrec(f, buf, size) int f; char *buf; int size; { int n; n = read(f, buf, size); if (n < 0) fatal("Read error (record may be larger than %db)\n", size); return(n); } getmark(tf) int tf; { char rec[sizeof(struct hdr_1)]; int n; n = read(tf, rec, sizeof(rec)); if (n == 0) return; /* skip HDR3-9 */ while (n == sizeof(struct hdr_1) && (strncmp("HDR", rec, 3)==0 || strncmp("EOF", rec, 3)==0)) { n = read(tf, rec, sizeof(rec)); if (n == 0) return; } printf("Warning: tape mark missing\n"); } cmphdreof(hdrp, eofp) struct hdr_1 *hdrp, *eofp; { char line[MAXLINE]; static int len = FILEID+SETID+SECNO+SEQNO+GENNO+GENVSNO+ CRDATE+EXDATE+1; if (strncmp(hdrp->h1_fileid, eofp->h1_fileid, len) != 0 || strncmp(hdrp->h1_system, eofp->h1_system, SYSTEM) != 0) { sncpy(line, hdrp->h1_fileid, FILEID); fprintf(stderr, "Warning: HDR and EOF labels for %s disagree\n", line); } } putvol(tf, volp) int tf; struct vol *volp; { int len; if (labelsize == sizeof(struct vol)) { /*###606 [lint] write arg. 2 used inconsistently llib-lc(57) :: ansitar.c(606)%%%*/ write(tf, volp, sizeof(struct vol)); return; } bcopy(buffer, (char *)volp, sizeof(struct vol)); len = labelsize - sizeof(struct vol); blcopy(&buffer[sizeof(struct vol)], "", len); write(tf, buffer, labelsize); } puthdr(tf, hdrp, hdrlen) int tf; char *hdrp; { int len; if (labelsize == hdrlen) { /*###625 [lint] write arg. 2 used inconsistently llib-lc(57) :: ansitar.c(625)%%%*/ write(tf, hdrp, hdrlen); return; } bcopy(buffer, (char *)hdrp, hdrlen); len = labelsize - hdrlen; blcopy(&buffer[hdrlen], "", len); write(tf, buffer, labelsize); } prtvol(volp) struct vol *volp; { char labid[LABID+1], serial[SERIAL+1], owner[OWNER+1]; sncpy(labid, volp->v_labid, LABID); sncpy(serial, volp->v_serial, SERIAL); sncpy(owner, volp->v_owner, OWNER); printf("Volume label:\n"); printf("\tLabel: %s%c Serial: %s Access: %c\n", labid, volp->v_labno, serial, volp->v_access); printf("\tOwner: %s Standard: %c\n", owner, volp->v_stdlabel); } prthdr(hdrp) char *hdrp; { struct hdr_1 *hdrp1; struct hdr_2 *hdrp2; char labid[LABID+1], fileid[FILEID+1], setid[SETID+1]; char secno[SECNO+1], seqno[SEQNO+1]; char genno[GENNO+1], genvsno[GENVSNO+1]; char crdate[CRDATE+1], exdate[EXDATE+1]; char blocks[BLOCKS+1], system[SYSTEM+1]; char blklen[BLKLEN+1], reclen[RECLEN+1]; hdrp1 = (struct hdr_1 *)hdrp; hdrp2 = (struct hdr_2 *)hdrp; switch (hdrp1->h1_labno) { case '1': sncpy(labid, hdrp1->h1_labid, LABID); sncpy(fileid, hdrp1->h1_fileid, FILEID); sncpy(setid, hdrp1->h1_setid, SETID); sncpy(secno, hdrp1->h1_secno, SECNO); sncpy(seqno, hdrp1->h1_seqno, SEQNO); sncpy(genno, hdrp1->h1_genno, GENNO); sncpy(genvsno, hdrp1->h1_genvsno, GENVSNO); sncpy(crdate, hdrp1->h1_crdate, CRDATE); sncpy(exdate, hdrp1->h1_exdate, EXDATE); sncpy(blocks, hdrp1->h1_blocks, BLOCKS); sncpy(system, hdrp1->h1_system, SYSTEM); printf("\nFile Label: %s%c File: %s\n", labid, hdrp1->h1_labno, fileid); printf("\tSet: %s Section: %s Sequence: %s\n", setid, secno, seqno); printf("\tGeneration: %s Generation Version: %s\n", genno, genvsno); printf("\tCreated: %s Expires: %s Access: %c\n", crdate, exdate, hdrp1->h1_access); printf("\tBlocks: %s System: %s\n", blocks, system); break; case '2': sncpy(labid, hdrp2->h2_labid, LABID); sncpy(blklen, hdrp2->h2_blklen, BLKLEN); sncpy(reclen, hdrp2->h2_reclen, RECLEN); printf("\nFile Label: %s%c\n", labid, hdrp2->h2_labno); printf("\tRecord Format: %c Block length: %s\n", hdrp2->h2_recfm, blklen); printf("\tRecord length: %s\n", reclen); break; } } initvol(volp) struct vol *volp; { struct passwd *passwp, *getpwuid(); /*###697 [lint] blcopy arg. 1 used inconsistently ansitar.c(799) :: ansitar.c(697)%%%*/ blcopy(volp, "", sizeof(struct vol)); blcopy(volp->v_labid, "VOL", LABID); volp->v_labno = '1'; blcopy(volp->v_serial, defvsn, SERIAL); volp->v_access = ' '; passwp = getpwuid(getuid()); blcopy(volp->v_owner, passwp->pw_name, OWNER); volp->v_stdlabel = '1'; } inithdr1(hdrp, filename, seq) struct hdr_1 *hdrp; char *filename; int seq; { char seqno[SEQNO+1]; /*###718 [lint] blcopy arg. 1 used inconsistently ansitar.c(799) :: ansitar.c(718)%%%*/ blcopy(hdrp, "", sizeof(struct hdr_1)); blcopy(hdrp->h1_labid, "HDR", LABID); hdrp->h1_labno = '1'; blcopy(hdrp->h1_fileid, filename, FILEID); blcopy(hdrp->h1_secno, "0001", SECNO); utoaz(seq, seqno, SEQNO); blcopy(hdrp->h1_seqno, seqno, SEQNO); blcopy(hdrp->h1_genno, "0001", GENNO); blcopy(hdrp->h1_genvsno, "00", GENVSNO); blcopy(hdrp->h1_crdate, curdate, CRDATE); blcopy(hdrp->h1_exdate, alongtime, EXDATE); blcopy(hdrp->h1_blocks, "000000", BLOCKS); blcopy(hdrp->h1_system, "Unix V7", SYSTEM); } inithdr2(hdrp, recfm, blklen, reclen) struct hdr_2 *hdrp; int recfm, blklen, reclen; { char line[MAXLINE]; blcopy(hdrp, "", sizeof(struct hdr_2)); blcopy(hdrp->h2_labid, "HDR", LABID); hdrp->h2_labno = '2'; hdrp->h2_recfm = recfm; utoaz(blklen, line, BLKLEN); blcopy(hdrp->h2_blklen, line, BLKLEN); utoaz(reclen, line, RECLEN); blcopy(hdrp->h2_reclen, line, RECLEN); blcopy(hdrp->h2_bufoff, "00", BUFOFF); } int lblock(fp, buffer, lsize, bfactor) FILE *fp; char *buffer; int lsize, bfactor; { register char *lp, *linelim; register int c; int i; char *bp; bp = buffer; for (i=0; i blocksize-4) { printf("Line too long (%d), truncated\n", i); i = blocksize-4; } sprintf(bp, "%04d", i+4); bp+= 4; bcopy(bp, line, i); bp+= i; *line = '\0'; } while (fgets(line, MAXLINE, fp) != NULL) { i = strlen(line) - 1; if ((bp + i + 4) > blocklim) break; sprintf(bp, "%04d", i+4); bp+= 4; bcopy(bp, line, i); bp+= i; *line = '\0'; } if (bp == buffer) return(0); while (bp < blocklim) *bp++ = 0x5e; return(bp - buffer); } lunblock(fp, buffer, blen, lsize) FILE *fp; char *buffer; int blen, lsize; { register char *lastp, *bp1; char *bp, *buflim; buflim = &buffer[blen]; bp = buffer; while (bp < buflim) { lastp = &bp[lsize-1]; while (lastp >= bp && isspace(*lastp)) lastp--; for (bp1=bp; bp1<=lastp; bp1++) putc(*bp1, fp); putc('\n', fp); bp += lsize; } } blcopy(dest, src, n) char *dest, *src; int n; /*###799 [lint] blcopy arg. 1 used inconsistently ansitar.c(799) :: ansitar.c(718)%%%*/ /*###799 [lint] blcopy arg. 1 used inconsistently ansitar.c(799) :: ansitar.c(697)%%%*/ { int i; i=0; while (i < n && *src) { *dest++ = *src++; i++; } while (i++ < n) *dest++ = ' '; } sncpy(dest, src, n) char *dest, *src; int n; { int i; i = 0; while (*src && i= buf && n != 0) { *p = '0' + (n % 10); n /= 10; p--; } while (p >= buf) { *p = '0'; p--; } } tapemark(tf) int tf; { struct mtop mtop; mtop.mt_count = 1; mtop.mt_op = MTWEOF; ioctl(tf, MTIOCTOP, &mtop); } skipfile(tf) int tf; { struct mtop mtop; mtop.mt_count = 1; mtop.mt_op = MTFSF; ioctl(tf, MTIOCTOP, &mtop); } backspace(tf) int tf; { struct mtop mtop; mtop.mt_count = 1; mtop.mt_op = MTBSR; ioctl(tf, MTIOCTOP, &mtop); } /* getansidate -- return the current date in ansi format * * Ansi dates are strings of the form " yyddd" where * yy = the year and ddd = the day in the year. There must * be an initial blank. */ getansidate(curdate) char *curdate; { time_t now, time(); struct tm *timep, *localtime(); /*###901 [lint] time value declared inconsistently llib-lc(54) :: ansitar.c(901)%%%*/ /*###901 [lint] time value used inconsistently llib-lc(54) :: ansitar.c(901)%%%*/ /*###901 [lint] time arg. 1 used inconsistently llib-lc(54) :: ansitar.c(901)%%%*/ now = time(NULL); /*###902 [lint] localtime arg. 1 used inconsistently llib-lc(90) :: ansitar.c(902)%%%*/ timep = localtime(&now); curdate[0] = ' '; utoaz(timep->tm_year, &curdate[1], 2); utoaz(timep->tm_yday, &curdate[3], 3); curdate[6] = '\0'; } int lookup(tab, name, Upper) char *tab[]; char *name; int Upper; { int i; char lower[MAXLINE]; if (Upper) { strcpy(lower, name); makelower(lower); } for (i=0; tab[i] != NULL; i++) #ifdef VARIAN if (wildcmp(tab[i], name, WILDCARD) == 0 || (Upper && wildcmp(tab[i], lower, WILDCARD)==0)) #else if (strcmp(tab[i], name) == 0 || (Upper && strcmp(tab[i], lower)==0)) #endif VARIAN { if (!(index(tab[i], '*'))) *tab[i] = '\0'; return(TRUE); } return(FALSE); } morefiles(tab) char *tab[]; { int i; for (i=0; tab[i] != NULL; i++) if (*tab[i]) return(TRUE); return(FALSE); } makelower(s) char *s; { register char *p; p = s; while (*p) { if (isupper(*p)) *p = tolower(*p); p++; } } makeupper(s) char *s; { register char *p; p = s; while (*p) { if (islower(*p)) *p = toupper(*p); p++; } } int haslower(p) register char *p; { while (*p) { if (islower(*p)) return(TRUE); p++; } return(FALSE); } toRT11(name) char *name; { char buf[32], *extp; extp = index(name, '.'); if (extp != NULL) { *extp = '\0'; extp++; } blcopy(buf, name, 6); buf[6] = '.'; if (extp != NULL) blcopy(&buf[7], extp, 3); else strcpy(&buf[7], "ext"); buf[10] = '\0'; /*###1001 [lint] strcpy value declared inconsistently llib-lc(49) :: ansitar.c(1001)%%%*/ strcpy(name, buf); } fromRT11(name) char *name; { char *op, *np; op = np = name; while (*op) { if (!isspace(*op)) *np++ = *op; op++; } *np = '\0'; } trimsp(s) char *s; { register char *p; p = &s[strlen(s)-1]; while (p >= s && isspace(*p)) p--; *++p = '\0'; } bcopy(dest, src, size) char *dest, *src; int size; { while (size-- > 0) *dest++ = *src++; } int max(a, b) int a, b; { if (a > b) return(a); return(b); } int checkw(c, name) char c, *name; { if (!confirm) return(TRUE); printf("%c %s:", c, name); c = getchar(); if (c != '\n') while ((c = getchar()) != '\n') ; return(c == 'y' || c == 'Y'); } /* VARARGS */ fatal(s, a1, a2, a3, a4) char *s; { fprintf(stderr, "ansitar: "); fprintf(stderr, s, a1, a2, a3, a4); exit(1); } #ifdef VARIAN /* varunblock - unblock variable length records ("D" format) * Beginning of each record contains a 4 digit number which is the * length of the record (including the count). * There are no line terminators (CR or LF). */ varunblock(fp, buffer, blen) FILE *fp; char *buffer; int blen; { /* the function now returns the # of bytes it decided to write */ register char *lastp, *bp1; char *bp, *buflim; int count; int newblen; /* this will count the actual bytes written out */ buflim = &buffer[blen]; bp = buffer; newblen = 0; #if DEBUG DBG" varunblock called. length %d\n",blen); if(DEBUG)hexdmp(" buffer passed to varunblock",buffer,blen); DBG" "); #endif DEBUG while (bp < buflim) { #if DEBUG DBG" count being made from %2x %2x %2x %2x %2x\n", *bp,*(bp+1),*(bp+2),*(bp+3),*(bp+4)); #endif sscanf(bp,"%4d",&count); count = count - 4; /* count includes the count itself */ #if DEBUG DBG" count %3d\n ",count); #endif if (*bp == 0x5e) /* if fill encountered for length */ { /* then abandon this record */ #if DEBUG DBG" hit filler. assume eor. break\n"); #endif break; } bp = bp+4; /* point to the end of line */ lastp = bp + count; while (bp not supported */ char *l,*s; int flag; /* will watch for multiple *'s in 'wild'*/ char wcrd; if (strlen(str) == 0) return(-1); /* don't match phantom */ wcrd = wc & 127; flag = 0; /* wildcard not encountered yet */ for (l=wilds,s=str ; *l != '\0' ; ) { if (*l == wcrd) /* if wildcard emcountered, adjust pointers*/ { if (flag) return(0); flag = 1; l++; /* skip the wildcard */ s = str + strlen(str) - (strlen(wilds) - (l - wilds) ); } else{ /* no wildcard, increment pointers normally */ if (*l != *s) return(*l - *s); l++; s++; } } if (*s != '\0') return(*l - *s); return(0); /* returning "success" indicator. they were equal */ } #endif VARIAN #ifdef PIP /***************************************************************** * TAG( pipunblock ) * * Unblock pip records. These are in a counted format with a 4 byte * count, followed by the record. (Count includes the length of the * count). Blank space at the end of a block is filled with '^' * characters. */ pipunblock(fp, buffer, n) FILE *fp; char *buffer; { register char *cp; int len, i; for (cp=buffer; cp 0; len--) putc(*cp++, fp); putc('\n', fp); while (*cp == '^' && cp (508 - (cp-buffer)%512) || (nline < 0 && (cp-buffer)%512 != 0)) while ( (cp-buffer)%512 != 0 ) *cp++ = '^'; if (cp-buffer >= blocksize || nline < 0) return cp-buffer; sprintf(cp, "%04d", nline+4); cp += 4; strncpy(cp, linebuf, 508); cp += nline; nline = 0; } return cp-buffer; /* should never get here, but you never know */ } #endif PIP ---------------------Makefile------------------------- CFLAGS = -O all: ansitar.1 ansitar ansitar: ansitar.o cc -o ansitar ansitar.o install: all install -s ansitar /usr/local/bin cp ansitar.1 /usr/man/man1 ------------------------------------------------------