home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume21
/
exebyte_toc
/
exetoc.c
next >
Wrap
C/C++ Source or Header
|
1990-04-29
|
8KB
|
370 lines
/*
* 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);
}
}