home *** CD-ROM | disk | FTP | other *** search
- /*
- * exetoc.c -- A program to read, write, and rewrite tables of contents
- * on tapes in an exebyte tape drive.
- *
- * USAGE: exetoc [-t|f tape] [-g file] [-p file] [-i] [-v] [-q]
- *
- * -t specifies the tape drive, default is /dev/rsmt0
- * -f is a synonym for -t, a la mt.
- * -g gets the table of contents from the tape and
- * sticks it into "file", which may be "-"
- * for standard output.
- * -p puts the table of contents contained in "file"
- * onto the front of the tape. You can use
- * "-" to take the table of contents from
- * standard input.
- * -i initializes the tape by creating a blank table
- * of contents.
- * -v verifies that this tape has been initialized.
- * -q causes the program to work quietly.
- *
- * You MUST provide exactly one of the -i, -g, -p, or -v flags.
- */
-
- #if !lint && !SABER
- static char RcsId[] = "$Header: exetoc.c,v 1.3 89/10/27 16:14:34 mlandau Exp $";
- #endif
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #include "exitcodes.h"
- #include "smtops.h"
-
- #define FORWARD /* nothing */
-
- #define KBytes(n) (n * 1024)
- #define MBytes(n) (1024 * KBytes(n))
- #define MIN(a, b) ((a) < (b) ? (a) : (b))
- #define streq(s1, s2) (!strcmp(s1, s2))
-
- #define IOBUF_SIZE KBytes(62) /* Exebyte likes 62KB chunks */
- #define TOC_SIZE MBytes(10) /* TOC occupied 10 MB on the tape */
- #define TOC_USEABLE MBytes(2) /* About 2 MB of it can be used */
-
- #define TOC_MARKER "[ExeTOC Table of Contents]"
-
- #define OP_NONE 0
- #define OP_VERIFY 1
- #define OP_INIT 2
- #define OP_FETCH 3
- #define OP_STORE 4
-
- /* Getopt stuff */
- extern char *optarg;
- extern int optind;
- extern int opterr;
-
- /* Linked in later */
- extern char *getenv();
- extern char *rindex();
-
- /* Shut Saber up */
- FORWARD void usage();
- FORWARD void set_operation();
- FORWARD void mark_tape();
- FORWARD void initialize_tape();
- FORWARD int check_tape();
- FORWARD void toc_to_file();
- FORWARD void toc_from_file();
- FORWARD void rewind_named_device();
-
-
- /* Only need one big buffer to hold the table of contents */
- static char Buffer[IOBUF_SIZE];
- static int Quiet = 0;
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- int option;
- int operation = OP_NONE;
- char *tapename = "/dev/rsmt0";
- int hastoc;
- int tapefd;
- int tocfd;
-
- opterr = 0;
- if ((tapename = getenv("EXEBYTE")) == NULL)
- tapename = "/dev/rsmt0";
- while ((option = getopt(argc, argv, "t:f:g:p:ivq")) != EOF)
- {
- switch (option)
- {
- case 't':
- case 'f':
- tapename = optarg;
- break;
-
- case 'g':
- set_operation(&operation, OP_FETCH);
- if (streq(optarg, "-"))
- tocfd = fileno(stdout);
- else
- tocfd = check_open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
- break;
-
- case 'p':
- set_operation(&operation, OP_STORE);
- if (streq(optarg, "-"))
- tocfd = fileno(stdin);
- else
- tocfd = check_open(optarg, O_RDONLY, 0666);
- break;
-
- case 'i':
- set_operation(&operation, OP_INIT);
- break;
-
- case 'v':
- set_operation(&operation, OP_VERIFY);
- break;
-
- case 'q':
- Quiet = 1;
- break;
-
- default:
- usage(argv[0]);
- exit(EXIT_USAGE);
- /* NOTREACHED */
- break;
- }
- }
-
- switch (operation)
- {
- case OP_NONE:
- fputs("You must specify one of -g, -p, -i, or -v\n", stderr);
- exit(EXIT_USAGE);
-
- case OP_INIT:
- tapefd = smt_open(tapename, O_WRONLY);
- initialize_tape(tapefd);
- smt_close(tapefd);
- rewind_named_device(tapename);
- exit(EXIT_OK);
-
- case OP_VERIFY:
- tapefd = smt_open(tapename, O_RDONLY);
- hastoc = check_tape(tapefd);
- smt_close(tapefd);
- rewind_named_device(tapename);
- if (!Quiet)
- printf("Tape in %s %s a labeled ExeTOC tape.\n",
- tapename, hastoc ? "is" : "is not");
- exit(hastoc ? EXIT_OK : EXIT_NOTOC);
-
- case OP_FETCH:
- tapefd = smt_open(tapename, O_RDWR);
- if (!check_tape(tapefd))
- {
- fprintf(stderr, "Tape in %s is not a labeled ExeTOC tape.\n",
- tapename);
- exit(EXIT_NOTOC);
- }
- toc_to_file(tapefd, tocfd);
- smt_close(tapefd);
- rewind_named_device(tapename);
- if (tocfd != fileno(stdout))
- close(tocfd);
- exit(EXIT_OK);
-
- case OP_STORE:
- tapefd = smt_open(tapename, O_RDWR);
- if (!check_tape(tapefd))
- {
- fprintf(stderr, "Tape in %s is not a labeled ExeTOC tape.\n",
- tapename);
- exit(EXIT_NOTOC);
- }
- mark_tape(tapefd);
- toc_from_file(tapefd, tocfd);
- smt_close_without_eof(tapefd);
- rewind_named_device(tapename);
- if (tocfd != fileno(stdin))
- close(tocfd);
- exit(EXIT_OK);
-
- default:
- fprintf(stderr, "Unknown tape operation code (%d)\n", operation);
- exit(EXIT_USAGE);
- }
- }
-
- void usage(progname)
- char *progname;
- {
- static char *summary =
- "usage: %s [-t tape] [-g file] [-p file] [-i] [-v] [-q]\n";
- static char *syntax[] = {
- "",
- "\t-t specifies the tape device. Default is $EXEBYTE, or /dev/rsmt0.",
- "\t-g gets the table of contents from the tape into the named file.",
- "\t-p puts the table of contants in the named file onto the tape.",
- "\t-i initializes a new tape so it can include a table of contents.",
- "\t-v verifies that a tape has previously been initialized.",
- "\t-q causes the program to work more quietly than usual.",
- "",
- "(Note: the tape is always rewound after any of these operations.)",
- NULL
- };
- char *p;
- register int i;
-
- if ((p = rindex(progname, '/')) != NULL)
- progname = p+1;
-
- fprintf(stderr, summary, progname);
- for (i = 0; syntax[i] != NULL; ++i)
- fprintf(stderr, "%s\n", syntax[i]);
- }
-
-
-
- void rewind_named_device(name)
- char *name;
- {
- int tapefd = smt_open(name, O_RDONLY);
-
- smt_rewind(tapefd);
- smt_close(tapefd);
- }
-
-
- void set_operation(op, opcode)
- int *op;
- int opcode;
- {
- if (*op != OP_NONE)
- {
- fputs("Only one of -g, -p, -i, and -q may be supplied.\n", stderr);
- exit(EXIT_USAGE);
- }
- *op = opcode;
- }
-
-
- int check_open(name, mode, perm)
- char *name;
- int mode;
- int perm;
- {
- int fd;
-
- if ((fd = open(name, mode, perm)) < 0)
- {
- perror(name);
- exit(EXIT_IO);
- }
- return (fd);
- }
-
-
- void mark_tape(tapefd)
- int tapefd;
- {
- bzero(Buffer, sizeof(Buffer));
- strcpy(Buffer, TOC_MARKER);
- smt_rewind(tapefd);
- if (smt_write(tapefd, Buffer, sizeof(Buffer)) < sizeof(Buffer))
- {
- perror("tape label");
- exit(EXIT_IO);
- }
- }
-
-
- void initialize_tape(tapefd)
- int tapefd;
- {
- int nbufs = (TOC_SIZE / IOBUF_SIZE);
-
- mark_tape(tapefd);
- bzero(Buffer, sizeof(Buffer));
- while (--nbufs > 0)
- smt_write(tapefd, Buffer, sizeof(Buffer));
- }
-
-
- int check_tape(tapefd)
- int tapefd;
- {
- smt_rewind(tapefd);
- return (smt_read(tapefd, Buffer, sizeof(Buffer)) == sizeof(Buffer)
- &&
- streq(Buffer, TOC_MARKER));
- }
-
-
- void toc_to_file(tapefd, tocfd)
- int tapefd;
- int tocfd;
- {
- int n;
- register int i;
- register char *bp;
-
- bzero(Buffer, sizeof(Buffer));
- while ((n = smt_read(tapefd, Buffer, sizeof(Buffer))) > 0)
- {
- if (n < sizeof(Buffer))
- {
- perror("tape read");
- exit(EXIT_IO);
- }
- for (bp = Buffer, i = 0; i < sizeof(Buffer) && *bp != 0; bp++, i++)
- continue;
- if (write(tocfd, Buffer, i) != i)
- {
- perror("file write");
- exit(EXIT_IO);
- }
- if (i < sizeof(Buffer))
- break;
- }
- }
-
-
- void toc_from_file(tapefd, tocfd)
- int tapefd;
- int tocfd;
- {
- struct stat s;
- int n;
-
- if (tocfd != fileno(stdin))
- {
- if (fstat(tocfd, &s) < 0)
- {
- perror("fstat");
- exit(EXIT_IO);
- }
- if (s.st_size > TOC_USEABLE)
- {
- fputs("Table of Contents file is too large.\n", stderr);
- exit(EXIT_TOOBIG);
- }
- }
-
- bzero(Buffer, sizeof(Buffer));
- while ((n = read(tocfd, Buffer, sizeof(Buffer))) > 0)
- {
- if (n < sizeof(Buffer))
- bzero(Buffer + n, sizeof(Buffer) - n);
- if (smt_write(tapefd, Buffer, sizeof(Buffer)) < sizeof(Buffer))
- {
- perror("tape write");
- exit(EXIT_IO);
- }
- }
- if (n < 0)
- {
- perror("file read");
- exit(EXIT_IO);
- }
- }
-