/* * ostape.c: reads OS standard labeled tapes, using dd to do the real work. * * Usage: ostape * * Christine Gianone, CUCCA, December 1986 * */ /* Preprocessor Stuff */ #include #include #define MAXLEN 90 /* Max length for a label line */ #define MAXFN 17 /* Max length for filename */ #define XVOL1 0 /* Symbols for label identifiers */ #define XEOV1 1 #define XHDR1 2 #define XHDR2 3 #define XEOF1 4 #define XEOF2 5 #define XUVL1 6 #define XUHL1 7 #define XUTL1 8 /* Global Declarations */ char buff[MAXLEN]; /* Input line buffer */ FILE *fp, *fopen(); /* File pointer & open function */ struct lbl { /* Label ids and case indexes */ char *id; int code; }; struct lbl tbl[10] = { "VOL1", XVOL1, /* Volume label */ "EOV1", XEOV1, /* End-of-Volume */ "HDR1", XHDR1, /* Header 1 */ "HDR2", XHDR2, /* Header 2 */ "EOF1", XEOF1, /* End of file 1 */ "EOF2", XEOF2, /* and 2 */ "UVL1", XUVL1, /* User labels */ "UHL1", XUHL1, /* are */ "UTL1", XUTL1 /* ignored... */ }; int nids = (sizeof(tbl) / sizeof(struct lbl)); extern int errno; /* System error stuff */ extern char *sys_errlist[]; char vn[6]; /* Volume name */ char fn[MAXFN]; /* File name */ int bs; /* Blocksize */ int rl; /* Record length */ int bc; /* Block count in EOF1 */ char rf; /* Record format */ char *ddhdr = "dd if=/dev/rmt12 of=hdr.tmp ibs=800 cbs=80 conv=unblock,ascii"; /* Main function */ main(argc,argv) int argc; /* Command line arguments */ char *argv[]; /* (not used) */ { int x; /* Declare local variables */ int files = 0; /* Files processed */ int skip = 0; /* Files skipped */ char ddcmd[200]; for (files = 0 ; ; ) { unlink("hdr.tmp"); /* Delete temp header file */ system(ddhdr); if ((x = phdr()) < 0) /* Process the header */ break; else if (x == 0) { printf("dd cannot read %s in %c format", fn, rf); system("mt fsf 2"); /* Skip forward 2 files */ skip++; /* to next tape header. */ continue; } sprintf(ddcmd, "dd if=/dev/rmt12 of=%s ibs=%d cbs=%d conv=unblock,ascii", fn,bs,rl); system(ddcmd); /* Run the dd command above */ sprintf(ddcmd, "ls -l %s", fn); /* to read the tape file */ files++; /* Count the file. */ system(ddcmd); /* Run the list command above */ unlink("eof.tmp"); /* Delete old temp trailer file */ system(ddhdr); if ((x = peof()) < 0) /* Process trailer labels */ break; } unlink("hdr.tmp"); unlink("eof.tmp"); printf("All done! Files Read: %d -- Files Skipped: %d\n", files, skip); } /* Process a header ... */ /* Returns 1 valid file header with recfm F, */ /* 0 if valid file header with some other recfm (which dd can't handle), or */ /* -1 otherwise - fatal error or end of tape */ phdr() { int i, j, k, l = 0; char c; *fn=bs=rl=rf=0; /* Initialize file variables */ fp = fopen("hdr.tmp", "r"); /* Try to open header file */ if (fp == NULL) /* Check for errors */ { printf("%s\n",sys_errlist[errno]); /* Oops, can't... */ return(-1); } while (fgets(buff, MAXLEN, fp) != NULL) /* Read each line */ { switch (k = lookup()) { /* Got line, look up label id */ case XVOL1: /* VOL1 */ buff[10] = 0; printf("VOL: '%s'\n", buff+4); /* Print volid */ break; case XEOV1: /* End of volume */ printf("End of volume\n"); return(-1); case XHDR1: /* File header 1 */ for (i = 0; i < MAXFN; i++) /* Copy name */ { c = buff[i+4]; /* and convert to lower case */ fn[i] = isupper(c) ? tolower(c) : c; } for (i = MAXFN - 1; i > 0; i--) /* Trim trailing blanks */ { if (fn[i] == ' ') fn[i] = '\0'; else break; } printf("Filename: '%s'\n", fn); /* Print the name */ break; case XHDR2: /* File header 2 */ buff[15] = 0; rl = atoi (buff + 10); /* Record length */ buff[10] = 0; bs = atoi (buff + 5); /* Block size */ rf = buff[4]; /* Record format */ printf ("rl: %d, bs: %d, rf: %c\n", rl, bs, rf); break; case XUVL1: /* User headers */ case XUHL1: /* (ignored) */ break; default: printf("Unexpected ID header label:\n%s\n",buff); if(++l > 3) /* Give up if too many, */ return(-1); /* probably not real headers */ break; } } if (fclose(fp) == EOF) /* Close the file */ { printf("%s\n",sys_errlist[errno]); return(-1); } if (*fn != '\0' ) /* If we have a filename */ return((rf == 'F') ? 1 : 0); /* return 1 or 0 based on recfm */ else return(-1); /* otherwise probably end of tape */ } /* Process trailer labels... */ /* Returns -1 if the trailer label is invalid, otherwise 0. */ peof() { int i, j, k, l = 0; /* Local variables */ char c; bc = 0; /* Block count */ fp = fopen("eof.tmp", "r"); /* Try to open trailer label file */ if (fp == NULL) /* Check for errors */ { printf("%s\n",sys_errlist[errno]); return(-1); } while (fgets(buff, MAXLEN, fp) != NULL) /* Read each line */ { switch (k = lookup()) /* Got line, look up label id */ { case XEOF1: /* End of file 1 */ buff[60] = 0; bc = atoi (buff + 54); /* Get block count & print it */ printf("EOF: %d block%c\n", bc, (bc == 1) ? ' ' : 's'); break; case XEOV1: /* End of volume */ printf("End of volume"); return(-1); case XEOF2: /* End of file 2 */ break; case XUTL1: /* User trailer */ break; /* (ignored) */ default: printf("Unexpected ID in trailer label:\n%s\n",buff); if (++l > 3) /* If too many unknowns, */ return(-1); /* probably not a real trailer. */ break; } } if (fclose(fp) == EOF) /* Close the file */ { printf("%s\n",sys_errlist[errno]); return(-1); } return(0); } /* Lookup */ lookup() /* Look up label ID, */ { /* return case index, or -1. */ int i, j; for (j = 0; j < nids; j++) /* For each ID in our list (row) */ { for (i = 0; i < 4; i++) /* Compare each character (column) */ { if (buff[i] != tbl[j].id[i]) /* If chars differ, */ break; /* then try next row, */ else continue; /* otherwise keep comparing. */ } if (i == 4) return (tbl[j].code); /* i is 4 if all chars match. */ } return (-1); /* No match, return -1. */ }