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

  1. /* 
  2.  * exetoc.c  --  A program to read, write, and rewrite tables of contents
  3.  *          on tapes in an exebyte tape drive.
  4.  * 
  5.  * USAGE:    exetoc [-t|f tape] [-g file] [-p file] [-i] [-v] [-q]
  6.  * 
  7.  *             -t specifies the tape drive, default is /dev/rsmt0
  8.  *            -f is a synonym for -t, a la mt.
  9.  *             -g gets the table of contents from the tape and
  10.  *                 sticks it into "file", which may be "-"
  11.  *                 for standard output.
  12.  *             -p puts the table of contents contained in "file"
  13.  *                 onto the front of the tape.  You can use
  14.  *                 "-" to take the table of contents from
  15.  *                 standard input.
  16.  *             -i initializes the tape by creating a blank table
  17.  *                 of contents.
  18.  *             -v verifies that this tape has been initialized.
  19.  *             -q causes the program to work quietly.
  20.  * 
  21.  *         You MUST provide exactly one of the -i, -g, -p, or -v flags.
  22.  */
  23.  
  24. #if !lint && !SABER
  25. static char RcsId[] = "$Header: exetoc.c,v 1.3 89/10/27 16:14:34 mlandau Exp $";
  26. #endif
  27.  
  28. #include <stdio.h>
  29. #include <fcntl.h>
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32.  
  33. #include "exitcodes.h"
  34. #include "smtops.h"
  35.  
  36. #define    FORWARD        /* nothing */
  37.  
  38. #define KBytes(n)    (n * 1024)
  39. #define MBytes(n)    (1024 * KBytes(n))
  40. #define MIN(a, b)    ((a) < (b) ? (a) : (b))
  41. #define    streq(s1, s2)    (!strcmp(s1, s2))
  42.  
  43. #define    IOBUF_SIZE    KBytes(62)    /* Exebyte likes 62KB chunks */
  44. #define TOC_SIZE     MBytes(10)    /* TOC occupied 10 MB on the tape */
  45. #define    TOC_USEABLE    MBytes(2)    /* About 2 MB of it can be used */
  46.  
  47. #define TOC_MARKER    "[ExeTOC Table of Contents]"
  48.  
  49. #define OP_NONE        0
  50. #define OP_VERIFY    1
  51. #define OP_INIT        2
  52. #define OP_FETCH    3
  53. #define OP_STORE    4
  54.  
  55. /* Getopt stuff */
  56. extern    char    *optarg;
  57. extern    int    optind;
  58. extern    int    opterr;
  59.  
  60. /* Linked in later */
  61. extern    char    *getenv();
  62. extern    char    *rindex();
  63.  
  64. /* Shut Saber up */
  65. FORWARD void    usage();
  66. FORWARD void    set_operation();
  67. FORWARD void    mark_tape();
  68. FORWARD    void    initialize_tape();
  69. FORWARD int    check_tape();
  70. FORWARD void    toc_to_file();
  71. FORWARD void    toc_from_file();
  72. FORWARD void    rewind_named_device();
  73.  
  74.  
  75. /* Only need one big buffer to hold the table of contents */
  76. static char Buffer[IOBUF_SIZE];
  77. static int  Quiet = 0;
  78.  
  79. main(argc, argv)
  80. int    argc;
  81. char    **argv;
  82. {   
  83.     int      option;
  84.     int      operation = OP_NONE;
  85.     char *tapename = "/dev/rsmt0";
  86.     int      hastoc;
  87.     int   tapefd;
  88.     int      tocfd;
  89.     
  90.     opterr = 0;
  91.     if ((tapename = getenv("EXEBYTE")) == NULL)
  92.     tapename = "/dev/rsmt0";
  93.     while ((option = getopt(argc, argv, "t:f:g:p:ivq")) != EOF)
  94.     {   
  95.     switch (option)
  96.     {   
  97.       case 't':
  98.       case 'f':
  99.         tapename = optarg;
  100.         break;
  101.         
  102.       case 'g':
  103.         set_operation(&operation, OP_FETCH);
  104.         if (streq(optarg, "-"))
  105.         tocfd = fileno(stdout);
  106.         else
  107.         tocfd = check_open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
  108.         break;
  109.         
  110.       case 'p':
  111.         set_operation(&operation, OP_STORE);
  112.         if (streq(optarg, "-"))
  113.         tocfd = fileno(stdin);
  114.         else 
  115.         tocfd = check_open(optarg, O_RDONLY, 0666);
  116.         break;
  117.         
  118.       case 'i':
  119.         set_operation(&operation, OP_INIT);
  120.         break;
  121.         
  122.       case 'v':
  123.         set_operation(&operation, OP_VERIFY);
  124.         break;
  125.         
  126.       case 'q':
  127.         Quiet = 1;
  128.         break;
  129.         
  130.       default:
  131.         usage(argv[0]);
  132.         exit(EXIT_USAGE);
  133.         /* NOTREACHED */
  134.         break;
  135.     }
  136.     }
  137.     
  138.     switch (operation)
  139.     {   
  140.       case OP_NONE:
  141.     fputs("You must specify one of -g, -p, -i, or -v\n", stderr);
  142.     exit(EXIT_USAGE);
  143.     
  144.       case OP_INIT:
  145.     tapefd = smt_open(tapename, O_WRONLY);
  146.     initialize_tape(tapefd);
  147.     smt_close(tapefd);
  148.     rewind_named_device(tapename);
  149.     exit(EXIT_OK);
  150.     
  151.       case OP_VERIFY:
  152.     tapefd = smt_open(tapename, O_RDONLY);
  153.     hastoc = check_tape(tapefd);
  154.     smt_close(tapefd);
  155.     rewind_named_device(tapename);
  156.     if (!Quiet)
  157.         printf("Tape in %s %s a labeled ExeTOC tape.\n", 
  158.            tapename, hastoc ? "is" : "is not");
  159.     exit(hastoc ? EXIT_OK : EXIT_NOTOC);
  160.     
  161.       case OP_FETCH:
  162.     tapefd = smt_open(tapename, O_RDWR);
  163.     if (!check_tape(tapefd))
  164.     {   
  165.         fprintf(stderr, "Tape in %s is not a labeled ExeTOC tape.\n", 
  166.                     tapename);
  167.         exit(EXIT_NOTOC);
  168.     }
  169.     toc_to_file(tapefd, tocfd);
  170.     smt_close(tapefd);
  171.     rewind_named_device(tapename);
  172.     if (tocfd != fileno(stdout))
  173.         close(tocfd);
  174.     exit(EXIT_OK);
  175.     
  176.       case OP_STORE:
  177.     tapefd = smt_open(tapename, O_RDWR);
  178.     if (!check_tape(tapefd))
  179.     {   
  180.         fprintf(stderr, "Tape in %s is not a labeled ExeTOC tape.\n", 
  181.                     tapename);
  182.         exit(EXIT_NOTOC);
  183.     }
  184.     mark_tape(tapefd);
  185.     toc_from_file(tapefd, tocfd);
  186.     smt_close_without_eof(tapefd);
  187.     rewind_named_device(tapename);
  188.     if (tocfd != fileno(stdin))
  189.         close(tocfd);
  190.     exit(EXIT_OK);
  191.     
  192.       default:
  193.     fprintf(stderr, "Unknown tape operation code (%d)\n", operation);
  194.     exit(EXIT_USAGE);
  195.     }
  196. }
  197.  
  198. void    usage(progname)
  199. char    *progname;
  200. {   
  201.     static char *summary = 
  202.     "usage: %s [-t tape] [-g file] [-p file] [-i] [-v] [-q]\n";
  203.     static char *syntax[] = {
  204.     "",
  205.     "\t-t specifies the tape device.  Default is $EXEBYTE, or /dev/rsmt0.",
  206.     "\t-g gets the table of contents from the tape into the named file.",
  207.     "\t-p puts the table of contants in the named file onto the tape.",
  208.     "\t-i initializes a new tape so it can include a table of contents.",
  209.     "\t-v verifies that a tape has previously been initialized.",
  210.     "\t-q causes the program to work more quietly than usual.",
  211.     "",
  212.     "(Note: the tape is always rewound after any of these operations.)",
  213.     NULL
  214.     };
  215.     char    *p;
  216.     register int i;
  217.     
  218.     if ((p = rindex(progname, '/')) != NULL)
  219.     progname = p+1;
  220.  
  221.     fprintf(stderr, summary, progname);
  222.     for (i = 0; syntax[i] != NULL; ++i)
  223.     fprintf(stderr, "%s\n", syntax[i]);
  224. }
  225.  
  226.  
  227.      
  228. void    rewind_named_device(name)
  229. char    *name;
  230. {   
  231.     int tapefd = smt_open(name, O_RDONLY);
  232.     
  233.     smt_rewind(tapefd);
  234.     smt_close(tapefd);
  235. }
  236.  
  237.  
  238. void    set_operation(op, opcode)
  239. int    *op;
  240. int    opcode;
  241. {   
  242.     if (*op != OP_NONE)
  243.     {   
  244.     fputs("Only one of -g, -p, -i, and -q may be supplied.\n", stderr);
  245.     exit(EXIT_USAGE);
  246.     }
  247.     *op = opcode;
  248. }
  249.  
  250.  
  251. int    check_open(name, mode, perm)
  252. char    *name;
  253. int    mode;
  254. int    perm;
  255. {   
  256.     int    fd;
  257.     
  258.     if ((fd = open(name, mode, perm)) < 0)
  259.     {   
  260.     perror(name);
  261.     exit(EXIT_IO);
  262.     }
  263.     return (fd);
  264. }
  265.  
  266.  
  267. void    mark_tape(tapefd)
  268. int    tapefd;
  269. {   
  270.     bzero(Buffer, sizeof(Buffer));
  271.     strcpy(Buffer, TOC_MARKER);
  272.     smt_rewind(tapefd);
  273.     if (smt_write(tapefd, Buffer, sizeof(Buffer)) < sizeof(Buffer))
  274.     {   
  275.     perror("tape label");
  276.     exit(EXIT_IO);
  277.     }
  278. }
  279.  
  280.  
  281. void    initialize_tape(tapefd)
  282. int    tapefd;
  283. {   
  284.     int    nbufs = (TOC_SIZE / IOBUF_SIZE);
  285.     
  286.     mark_tape(tapefd);
  287.     bzero(Buffer, sizeof(Buffer));
  288.     while (--nbufs > 0)
  289.     smt_write(tapefd, Buffer, sizeof(Buffer));
  290. }
  291.  
  292.  
  293. int    check_tape(tapefd)
  294. int    tapefd;
  295. {   
  296.     smt_rewind(tapefd);
  297.     return (smt_read(tapefd, Buffer, sizeof(Buffer)) == sizeof(Buffer) 
  298.         &&
  299.         streq(Buffer, TOC_MARKER));
  300. }
  301.  
  302.  
  303. void    toc_to_file(tapefd, tocfd)
  304. int    tapefd;
  305. int    tocfd;
  306. {   
  307.     int           n;
  308.     register int   i;
  309.     register char *bp;
  310.     
  311.     bzero(Buffer, sizeof(Buffer));
  312.     while ((n = smt_read(tapefd, Buffer, sizeof(Buffer))) > 0)
  313.     {   
  314.     if (n < sizeof(Buffer))
  315.     {   
  316.         perror("tape read");
  317.         exit(EXIT_IO);
  318.     }
  319.     for (bp = Buffer, i = 0; i < sizeof(Buffer) && *bp != 0; bp++, i++)
  320.         continue;
  321.     if (write(tocfd, Buffer, i) != i)
  322.     {   
  323.         perror("file write");
  324.         exit(EXIT_IO);
  325.     }
  326.     if (i < sizeof(Buffer))
  327.         break;
  328.     }
  329. }
  330.  
  331.  
  332. void     toc_from_file(tapefd, tocfd)
  333. int    tapefd;
  334. int    tocfd;
  335. {   
  336.     struct stat s;
  337.     int        n;
  338.     
  339.     if (tocfd != fileno(stdin))
  340.     {   
  341.     if (fstat(tocfd, &s) < 0)
  342.     {   
  343.         perror("fstat");
  344.         exit(EXIT_IO);
  345.     }
  346.     if (s.st_size > TOC_USEABLE)
  347.     {   
  348.         fputs("Table of Contents file is too large.\n", stderr);
  349.         exit(EXIT_TOOBIG);
  350.     }
  351.     }
  352.     
  353.     bzero(Buffer, sizeof(Buffer));
  354.     while ((n = read(tocfd, Buffer, sizeof(Buffer))) > 0)
  355.     {   
  356.     if (n < sizeof(Buffer))
  357.         bzero(Buffer + n, sizeof(Buffer) - n);
  358.     if (smt_write(tapefd, Buffer, sizeof(Buffer)) < sizeof(Buffer))
  359.     {   
  360.         perror("tape write");
  361.         exit(EXIT_IO);
  362.     }
  363.     }
  364.     if (n < 0)
  365.     {   
  366.     perror("file read");
  367.     exit(EXIT_IO);
  368.     }
  369. }
  370.