home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / tar / tar.c < prev   
Encoding:
C/C++ Source or Header  |  1979-02-08  |  16.0 KB  |  934 lines

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <sys/dir.h>
  5. #include <signal.h>
  6.  
  7. char    *sprintf();
  8. char    *strcat();
  9. daddr_t    bsrch();
  10. #define TBLOCK    512
  11. #define NBLOCK    20
  12. #define NAMSIZ    100
  13. union hblock {
  14.     char dummy[TBLOCK];
  15.     struct header {
  16.         char name[NAMSIZ];
  17.         char mode[8];
  18.         char uid[8];
  19.         char gid[8];
  20.         char size[12];
  21.         char mtime[12];
  22.         char chksum[8];
  23.         char linkflag;
  24.         char linkname[NAMSIZ];
  25.     } dbuf;
  26. } dblock, tbuf[NBLOCK];
  27.  
  28. struct linkbuf {
  29.     ino_t    inum;
  30.     dev_t    devnum;
  31.     int    count;
  32.     char    pathname[NAMSIZ];
  33.     struct    linkbuf *nextp;
  34. } *ihead;
  35.  
  36. struct stat stbuf;
  37.  
  38. int    rflag, xflag, vflag, tflag, mt, cflag, mflag;
  39. int    term, chksum, wflag, recno, first, linkerrok;
  40. int    freemem = 1;
  41. int    nblock = 1;
  42.  
  43. daddr_t    low;
  44. daddr_t    high;
  45.  
  46. FILE    *tfile;
  47. char    tname[] = "/tmp/tarXXXXXX";
  48.  
  49.  
  50. char    *usefile;
  51. char    magtape[]    = "/dev/mt1";
  52.  
  53. char    *malloc();
  54.  
  55. main(argc, argv)
  56. int    argc;
  57. char    *argv[];
  58. {
  59.     char *cp;
  60.     int onintr(), onquit(), onhup(), onterm();
  61.  
  62.     if (argc < 2)
  63.         usage();
  64.  
  65.     tfile = NULL;
  66.     usefile =  magtape;
  67.     argv[argc] = 0;
  68.     argv++;
  69.     for (cp = *argv++; *cp; cp++) 
  70.         switch(*cp) {
  71.         case 'f':
  72.             usefile = *argv++;
  73.             if (nblock == 1)
  74.                 nblock = 0;
  75.             break;
  76.         case 'c':
  77.             cflag++;
  78.             rflag++;
  79.             break;
  80.         case 'u':
  81.             mktemp(tname);
  82.             if ((tfile = fopen(tname, "w")) == NULL) {
  83.                 fprintf(stderr, "Tar: cannot create temporary file (%s)\n", tname);
  84.                 done(1);
  85.             }
  86.             fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n");
  87.             /* FALL THROUGH */
  88.         case 'r':
  89.             rflag++;
  90.             if (nblock != 1 && cflag == 0) {
  91. noupdate:
  92.                 fprintf(stderr, "Tar: Blocked tapes cannot be updated (yet)\n");
  93.                 done(1);
  94.             }
  95.             break;
  96.         case 'v':
  97.             vflag++;
  98.             break;
  99.         case 'w':
  100.             wflag++;
  101.             break;
  102.         case 'x':
  103.             xflag++;
  104.             break;
  105.         case 't':
  106.             tflag++;
  107.             break;
  108.         case 'm':
  109.             mflag++;
  110.             break;
  111.         case '-':
  112.             break;
  113.         case '0':
  114.         case '1':
  115.             magtape[7] = *cp;
  116.             usefile = magtape;
  117.             break;
  118.         case 'b':
  119.             nblock = atoi(*argv++);
  120.             if (nblock > NBLOCK || nblock <= 0) {
  121.                 fprintf(stderr, "Invalid blocksize. (Max %d)\n", NBLOCK);
  122.                 done(1);
  123.             }
  124.             if (rflag && !cflag)
  125.                 goto noupdate;
  126.             break;
  127.         case 'l':
  128.             linkerrok++;
  129.             break;
  130.         default:
  131.             fprintf(stderr, "tar: %c: unknown option\n", *cp);
  132.             usage();
  133.         }
  134.  
  135.     if (rflag) {
  136.         if (cflag && tfile != NULL) {
  137.             usage();
  138.             done(1);
  139.         }
  140.         if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  141.             signal(SIGINT, onintr);
  142.         if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  143.             signal(SIGHUP, onhup);
  144.         if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  145.             signal(SIGQUIT, onquit);
  146. /*
  147.         if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  148.             signal(SIGTERM, onterm);
  149. */
  150.         if (strcmp(usefile, "-") == 0) {
  151.             if (cflag == 0) {
  152.                 fprintf(stderr, "Can only create standard output archives\n");
  153.                 done(1);
  154.             }
  155.             mt = dup(1);
  156.             nblock = 1;
  157.         }
  158.         else if ((mt = open(usefile, 2)) < 0) {
  159.             if (cflag == 0 || (mt =  creat(usefile, 0666)) < 0) {
  160.                 fprintf(stderr, "tar: cannot open %s\n", usefile);
  161.                 done(1);
  162.             }
  163.         }
  164.         if (cflag == 0 && nblock == 0)
  165.             nblock = 1;
  166.         dorep(argv);
  167.     }
  168.     else if (xflag)  {
  169.         if (strcmp(usefile, "-") == 0) {
  170.             mt = dup(0);
  171.             nblock = 1;
  172.         }
  173.         else if ((mt = open(usefile, 0)) < 0) {
  174.             fprintf(stderr, "tar: cannot open %s\n", usefile);
  175.             done(1);
  176.         }
  177.         doxtract(argv);
  178.     }
  179.     else if (tflag) {
  180.         if (strcmp(usefile, "-") == 0) {
  181.             mt = dup(0);
  182.             nblock = 1;
  183.         }
  184.         else if ((mt = open(usefile, 0)) < 0) {
  185.             fprintf(stderr, "tar: cannot open %s\n", usefile);
  186.             done(1);
  187.         }
  188.         dotable();
  189.     }
  190.     else
  191.         usage();
  192.     done(0);
  193. }
  194.  
  195. usage()
  196. {
  197.     fprintf(stderr, "tar: usage  tar -{txru}[cvfblm] [tapefile] [blocksize] file1 file2...\n");
  198.     done(1);
  199. }
  200.  
  201. dorep(argv)
  202. char    *argv[];
  203. {
  204.     register char *cp, *cp2;
  205.     char wdir[60];
  206.  
  207.     if (!cflag) {
  208.         getdir();
  209.         do {
  210.             passtape();
  211.             if (term)
  212.                 done(0);
  213.             getdir();
  214.         } while (!endtape());
  215.         if (tfile != NULL) {
  216.             char buf[200];
  217.  
  218.             strcat(buf, "sort +0 -1 +1nr ");
  219.             strcat(buf, tname);
  220.             strcat(buf, " -o ");
  221.             strcat(buf, tname);
  222.             sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX;mv %sX %s",
  223.                 tname, tname, tname, tname, tname, tname);
  224.             fflush(tfile);
  225.             system(buf);
  226.             freopen(tname, "r", tfile);
  227.             fstat(fileno(tfile), &stbuf);
  228.             high = stbuf.st_size;
  229.         }
  230.     }
  231.  
  232.     getwdir(wdir);
  233.     while (*argv && ! term) {
  234.         cp2 = *argv;
  235.         for (cp = *argv; *cp; cp++)
  236.             if (*cp == '/')
  237.                 cp2 = cp;
  238.         if (cp2 != *argv) {
  239.             *cp2 = '\0';
  240.             chdir(*argv);
  241.             *cp2 = '/';
  242.             cp2++;
  243.         }
  244.         putfile(*argv++, cp2);
  245.         chdir(wdir);
  246.     }
  247.     putempty();
  248.     putempty();
  249.     flushtape();
  250.     if (linkerrok == 1)
  251.         for (; ihead != NULL; ihead = ihead->nextp)
  252.             if (ihead->count != 0)
  253.                 fprintf(stderr, "Missing links to %s\n", ihead->pathname);
  254. }
  255.  
  256. endtape()
  257. {
  258.     if (dblock.dbuf.name[0] == '\0') {
  259.         backtape();
  260.         return(1);
  261.     }
  262.     else
  263.         return(0);
  264. }
  265.  
  266. getdir()
  267. {
  268.     register struct stat *sp;
  269.     int i;
  270.  
  271.     readtape( (char *) &dblock);
  272.     if (dblock.dbuf.name[0] == '\0')
  273.         return;
  274.     sp = &stbuf;
  275.     sscanf(dblock.dbuf.mode, "%o", &i);
  276.     sp->st_mode = i;
  277.     sscanf(dblock.dbuf.uid, "%o", &i);
  278.     sp->st_uid = i;
  279.     sscanf(dblock.dbuf.gid, "%o", &i);
  280.     sp->st_gid = i;
  281.     sscanf(dblock.dbuf.size, "%lo", &sp->st_size);
  282.     sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime);
  283.     sscanf(dblock.dbuf.chksum, "%o", &chksum);
  284.     if (chksum != checksum()) {
  285.         fprintf(stderr, "directory checksum error\n");
  286.         done(2);
  287.     }
  288.     if (tfile != NULL)
  289.         fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime);
  290. }
  291.  
  292. passtape()
  293. {
  294.     long blocks;
  295.     char buf[TBLOCK];
  296.  
  297.     if (dblock.dbuf.linkflag == '1')
  298.         return;
  299.     blocks = stbuf.st_size;
  300.     blocks += TBLOCK-1;
  301.     blocks /= TBLOCK;
  302.  
  303.     while (blocks-- > 0)
  304.         readtape(buf);
  305. }
  306.  
  307. putfile(longname, shortname)
  308. char *longname;
  309. char *shortname;
  310. {
  311.     int infile;
  312.     long blocks;
  313.     char buf[TBLOCK];
  314.     register char *cp, *cp2;
  315.     struct direct dbuf;
  316.     int i, j;
  317.  
  318.     infile = open(shortname, 0);
  319.     if (infile < 0) {
  320.         fprintf(stderr, "tar: %s: cannot open file\n", longname);
  321.         return;
  322.     }
  323.  
  324.     fstat(infile, &stbuf);
  325.  
  326.     if (tfile != NULL && checkupdate(longname) == 0) {
  327.         close(infile);
  328.         return;
  329.     }
  330.     if (checkw('r', longname) == 0) {
  331.         close(infile);
  332.         return;
  333.     }
  334.  
  335.     if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
  336.         for (i = 0, cp = buf; *cp++ = longname[i++];);
  337.         *--cp = '/';
  338.         cp++;
  339.         i = 0;
  340.         chdir(shortname);
  341.         while (read(infile, (char *)&dbuf, sizeof(dbuf)) > 0 && !term) {
  342.             if (dbuf.d_ino == 0) {
  343.                 i++;
  344.                 continue;
  345.             }
  346.             if (strcmp(".", dbuf.d_name) == 0 || strcmp("..", dbuf.d_name) == 0) {
  347.                 i++;
  348.                 continue;
  349.             }
  350.             cp2 = cp;
  351.             for (j=0; j < DIRSIZ; j++)
  352.                 *cp2++ = dbuf.d_name[j];
  353.             *cp2 = '\0';
  354.             close(infile);
  355.             putfile(buf, cp);
  356.             infile = open(".", 0);
  357.             i++;
  358.             lseek(infile, (long) (sizeof(dbuf) * i), 0);
  359.         }
  360.         close(infile);
  361.         chdir("..");
  362.         return;
  363.     }
  364.     if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
  365.         fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname);
  366.         return;
  367.     }
  368.  
  369.     tomodes(&stbuf);
  370.  
  371.     cp2 = longname;
  372.     for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++);
  373.     if (i >= NAMSIZ) {
  374.         fprintf(stderr, "%s: file name too long\n", longname);
  375.         close(infile);
  376.         return;
  377.     }
  378.  
  379.     if (stbuf.st_nlink > 1) {
  380.         struct linkbuf *lp;
  381.         int found = 0;
  382.  
  383.         for (lp = ihead; lp != NULL; lp = lp->nextp) {
  384.             if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) {
  385.                 found++;
  386.                 break;
  387.             }
  388.         }
  389.         if (found) {
  390.             strcpy(dblock.dbuf.linkname, lp->pathname);
  391.             dblock.dbuf.linkflag = '1';
  392.             sprintf(dblock.dbuf.chksum, "%6o", checksum());
  393.             writetape( (char *) &dblock);
  394.             if (vflag) {
  395.                 fprintf(stderr, "a %s ", longname);
  396.                 fprintf(stderr, "link to %s\n", lp->pathname);
  397.             }
  398.             lp->count--;
  399.             close(infile);
  400.             return;
  401.         }
  402.         else {
  403.             lp = (struct linkbuf *) malloc(sizeof(*lp));
  404.             if (lp == NULL) {
  405.                 if (freemem) {
  406.                     fprintf(stderr, "Out of memory. Link information lost\n");
  407.                     freemem = 0;
  408.                 }
  409.             }
  410.             else {
  411.                 lp->nextp = ihead;
  412.                 ihead = lp;
  413.                 lp->inum = stbuf.st_ino;
  414.                 lp->devnum = stbuf.st_dev;
  415.                 lp->count = stbuf.st_nlink - 1;
  416.                 strcpy(lp->pathname, longname);
  417.             }
  418.         }
  419.     }
  420.  
  421.     blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK;
  422.     if (vflag) {
  423.         fprintf(stderr, "a %s ", longname);
  424.         fprintf(stderr, "%ld blocks\n", blocks);
  425.     }
  426.     sprintf(dblock.dbuf.chksum, "%6o", checksum());
  427.     writetape( (char *) &dblock);
  428.  
  429.     while ((i = read(infile, buf, TBLOCK)) > 0 && blocks > 0) {
  430.         writetape(buf);
  431.         blocks--;
  432.     }
  433.     close(infile);
  434.     if (blocks != 0 || i != 0)
  435.         fprintf(stderr, "%s: file changed size\n", longname);
  436.     while (blocks-- >  0)
  437.         putempty();
  438. }
  439.  
  440.  
  441.  
  442. doxtract(argv)
  443. char    *argv[];
  444. {
  445.     long blocks, bytes;
  446.     char buf[TBLOCK];
  447.     char **cp;
  448.     int ofile;
  449.  
  450.     for (;;) {
  451.         getdir();
  452.         if (endtape())
  453.             break;
  454.  
  455.         if (*argv == 0)
  456.             goto gotit;
  457.  
  458.         for (cp = argv; *cp; cp++)
  459.             if (prefix(*cp, dblock.dbuf.name))
  460.                 goto gotit;
  461.         passtape();
  462.         continue;
  463.  
  464. gotit:
  465.         if (checkw('x', dblock.dbuf.name) == 0) {
  466.             passtape();
  467.             continue;
  468.         }
  469.  
  470.         checkdir(dblock.dbuf.name);
  471.  
  472.         if (dblock.dbuf.linkflag == '1') {
  473.             unlink(dblock.dbuf.name);
  474.             if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) {
  475.                 fprintf(stderr, "%s: cannot link\n", dblock.dbuf.name);
  476.                 continue;
  477.             }
  478.             if (vflag)
  479.                 fprintf(stderr, "%s linked to %s\n", dblock.dbuf.name, dblock.dbuf.linkname);
  480.             continue;
  481.         }
  482.         if ((ofile = creat(dblock.dbuf.name, stbuf.st_mode & 07777)) < 0) {
  483.             fprintf(stderr, "tar: %s - cannot create\n", dblock.dbuf.name);
  484.             passtape();
  485.             continue;
  486.         }
  487.  
  488.         chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid);
  489.  
  490.         blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK;
  491.         if (vflag)
  492.             fprintf(stderr, "x %s, %ld bytes, %ld tape blocks\n", dblock.dbuf.name, bytes, blocks);
  493.         while (blocks-- > 0) {
  494.             readtape(buf);
  495.             if (bytes > TBLOCK) {
  496.                 if (write(ofile, buf, TBLOCK) < 0) {
  497.                     fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name);
  498.                     done(2);
  499.                 }
  500.             } else
  501.                 if (write(ofile, buf, (int) bytes) < 0) {
  502.                     fprintf(stderr, "tar: %s: HELP - extract write error\n", dblock.dbuf.name);
  503.                     done(2);
  504.                 }
  505.             bytes -= TBLOCK;
  506.         }
  507.         close(ofile);
  508.         if (mflag == 0) {
  509.             time_t timep[2];
  510.  
  511.             timep[0] = time(NULL);
  512.             timep[1] = stbuf.st_mtime;
  513.             utime(dblock.dbuf.name, timep);
  514.         }
  515.     }
  516. }
  517.  
  518. dotable()
  519. {
  520.     for (;;) {
  521.         getdir();
  522.         if (endtape())
  523.             break;
  524.         if (vflag)
  525.             longt(&stbuf);
  526.         printf("%s", dblock.dbuf.name);
  527.         if (dblock.dbuf.linkflag == '1')
  528.             printf(" linked to %s", dblock.dbuf.linkname);
  529.         printf("\n");
  530.         passtape();
  531.     }
  532. }
  533.  
  534. putempty()
  535. {
  536.     char buf[TBLOCK];
  537.     char *cp;
  538.  
  539.     for (cp = buf; cp < &buf[TBLOCK]; )
  540.         *cp++ = '\0';
  541.     writetape(buf);
  542. }
  543.  
  544. longt(st)
  545. register struct stat *st;
  546. {
  547.     register char *cp;
  548.     char *ctime();
  549.  
  550.     pmode(st);
  551.     printf("%3d/%1d", st->st_uid, st->st_gid);
  552.     printf("%7D", st->st_size);
  553.     cp = ctime(&st->st_mtime);
  554.     printf(" %-12.12s %-4.4s ", cp+4, cp+20);
  555. }
  556.  
  557. #define    SUID    04000
  558. #define    SGID    02000
  559. #define    ROWN    0400
  560. #define    WOWN    0200
  561. #define    XOWN    0100
  562. #define    RGRP    040
  563. #define    WGRP    020
  564. #define    XGRP    010
  565. #define    ROTH    04
  566. #define    WOTH    02
  567. #define    XOTH    01
  568. #define    STXT    01000
  569. int    m1[] = { 1, ROWN, 'r', '-' };
  570. int    m2[] = { 1, WOWN, 'w', '-' };
  571. int    m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
  572. int    m4[] = { 1, RGRP, 'r', '-' };
  573. int    m5[] = { 1, WGRP, 'w', '-' };
  574. int    m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
  575. int    m7[] = { 1, ROTH, 'r', '-' };
  576. int    m8[] = { 1, WOTH, 'w', '-' };
  577. int    m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
  578.  
  579. int    *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};
  580.  
  581. pmode(st)
  582. register struct stat *st;
  583. {
  584.     register int **mp;
  585.  
  586.     for (mp = &m[0]; mp < &m[9];)
  587.         select(*mp++, st);
  588. }
  589.  
  590. select(pairp, st)
  591. int *pairp;
  592. struct stat *st;
  593. {
  594.     register int n, *ap;
  595.  
  596.     ap = pairp;
  597.     n = *ap++;
  598.     while (--n>=0 && (st->st_mode&*ap++)==0)
  599.         ap++;
  600.     printf("%c", *ap);
  601. }
  602.  
  603. checkdir(name)
  604. register char *name;
  605. {
  606.     register char *cp;
  607.     int i;
  608.     for (cp = name; *cp; cp++) {
  609.         if (*cp == '/') {
  610.             *cp = '\0';
  611.             if (access(name, 01) < 0) {
  612.                 if (fork() == 0) {
  613.                     execl("/bin/mkdir", "mkdir", name, 0);
  614.                     execl("/usr/bin/mkdir", "mkdir", name, 0);
  615.                     fprintf(stderr, "tar: cannot find mkdir!\n");
  616.                     done(0);
  617.                 }
  618.                 while (wait(&i) >= 0);
  619.                 chown(name, stbuf.st_uid, stbuf.st_gid);
  620.             }
  621.             *cp = '/';
  622.         }
  623.     }
  624. }
  625.  
  626. onintr()
  627. {
  628.     signal(SIGINT, SIG_IGN);
  629.     term++;
  630. }
  631.  
  632. onquit()
  633. {
  634.     signal(SIGQUIT, SIG_IGN);
  635.     term++;
  636. }
  637.  
  638. onhup()
  639. {
  640.     signal(SIGHUP, SIG_IGN);
  641.     term++;
  642. }
  643.  
  644. onterm()
  645. {
  646.     signal(SIGTERM, SIG_IGN);
  647.     term++;
  648. }
  649.  
  650. tomodes(sp)
  651. register struct stat *sp;
  652. {
  653.     register char *cp;
  654.  
  655.     for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
  656.         *cp = '\0';
  657.     sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777);
  658.     sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid);
  659.     sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid);
  660.     sprintf(dblock.dbuf.size, "%11lo ", sp->st_size);
  661.     sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime);
  662. }
  663.  
  664. checksum()
  665. {
  666.     register i;
  667.     register char *cp;
  668.  
  669.     for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
  670.         *cp = ' ';
  671.     i = 0;
  672.     for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
  673.         i += *cp;
  674.     return(i);
  675. }
  676.  
  677. checkw(c, name)
  678. char *name;
  679. {
  680.     if (wflag) {
  681.         printf("%c ", c);
  682.         if (vflag)
  683.             longt(&stbuf);
  684.         printf("%s: ", name);
  685.         if (response() == 'y'){
  686.             return(1);
  687.         }
  688.         return(0);
  689.     }
  690.     return(1);
  691. }
  692.  
  693. response()
  694. {
  695.     char c;
  696.  
  697.     c = getchar();
  698.     if (c != '\n')
  699.         while (getchar() != '\n');
  700.     else c = 'n';
  701.     return(c);
  702. }
  703.  
  704. checkupdate(arg)
  705. char    *arg;
  706. {
  707.     char name[100];
  708.     long    mtime;
  709.     daddr_t seekp;
  710.     daddr_t    lookup();
  711.  
  712.     rewind(tfile);
  713.     for (;;) {
  714.         if ((seekp = lookup(arg)) < 0)
  715.             return(1);
  716.         fseek(tfile, seekp, 0);
  717.         fscanf(tfile, "%s %lo", name, &mtime);
  718.         if (stbuf.st_mtime > mtime)
  719.             return(1);
  720.         else
  721.             return(0);
  722.     }
  723. }
  724.  
  725. done(n)
  726. {
  727.     unlink(tname);
  728.     exit(n);
  729. }
  730.  
  731. prefix(s1, s2)
  732. register char *s1, *s2;
  733. {
  734.     while (*s1)
  735.         if (*s1++ != *s2++)
  736.             return(0);
  737.     if (*s2)
  738.         return(*s2 == '/');
  739.     return(1);
  740. }
  741.  
  742. getwdir(s)
  743. char *s;
  744. {
  745.     int i;
  746.     int    pipdes[2];
  747.  
  748.     pipe(pipdes);
  749.     if ((i = fork()) == 0) {
  750.         close(1);
  751.         dup(pipdes[1]);
  752.         execl("/bin/pwd", "pwd", 0);
  753.         execl("/usr/bin/pwd", "pwd", 0);
  754.         fprintf(stderr, "pwd failed!\n");
  755.         printf("/\n");
  756.         exit(1);
  757.     }
  758.     while (wait((int *)NULL) != -1)
  759.             ;
  760.     read(pipdes[0], s, 50);
  761.     while(*s != '\n')
  762.         s++;
  763.     *s = '\0';
  764.     close(pipdes[0]);
  765.     close(pipdes[1]);
  766. }
  767.  
  768. #define    N    200
  769. int    njab;
  770. daddr_t
  771. lookup(s)
  772. char *s;
  773. {
  774.     register i;
  775.     daddr_t a;
  776.  
  777.     for(i=0; s[i]; i++)
  778.         if(s[i] == ' ')
  779.             break;
  780.     a = bsrch(s, i, low, high);
  781.     return(a);
  782. }
  783.  
  784. daddr_t
  785. bsrch(s, n, l, h)
  786. daddr_t l, h;
  787. char *s;
  788. {
  789.     register i, j;
  790.     char b[N];
  791.     daddr_t m, m1;
  792.  
  793.     njab = 0;
  794.  
  795. loop:
  796.     if(l >= h)
  797.         return(-1L);
  798.     m = l + (h-l)/2 - N/2;
  799.     if(m < l)
  800.         m = l;
  801.     fseek(tfile, m, 0);
  802.     fread(b, 1, N, tfile);
  803.     njab++;
  804.     for(i=0; i<N; i++) {
  805.         if(b[i] == '\n')
  806.             break;
  807.         m++;
  808.     }
  809.     if(m >= h)
  810.         return(-1L);
  811.     m1 = m;
  812.     j = i;
  813.     for(i++; i<N; i++) {
  814.         m1++;
  815.         if(b[i] == '\n')
  816.             break;
  817.     }
  818.     i = cmp(b+j, s, n);
  819.     if(i < 0) {
  820.         h = m;
  821.         goto loop;
  822.     }
  823.     if(i > 0) {
  824.         l = m1;
  825.         goto loop;
  826.     }
  827.     return(m);
  828. }
  829.  
  830. cmp(b, s, n)
  831. char *b, *s;
  832. {
  833.     register i;
  834.  
  835.     if(b[0] != '\n')
  836.         exit(2);
  837.     for(i=0; i<n; i++) {
  838.         if(b[i+1] > s[i])
  839.             return(-1);
  840.         if(b[i+1] < s[i])
  841.             return(1);
  842.     }
  843.     return(b[i+1] == ' '? 0 : -1);
  844. }
  845.  
  846. readtape(buffer)
  847. char *buffer;
  848. {
  849.     int i, j;
  850.  
  851.     if (recno >= nblock || first == 0) {
  852.         if (first == 0 && nblock == 0)
  853.             j = NBLOCK;
  854.         else
  855.             j = nblock;
  856.         if ((i = read(mt, tbuf, TBLOCK*j)) < 0) {
  857.             fprintf(stderr, "Tar: tape read error\n");
  858.             done(3);
  859.         }
  860.         if (first == 0) {
  861.             if ((i % TBLOCK) != 0) {
  862.                 fprintf(stderr, "Tar: tape blocksize error\n");
  863.                 done(3);
  864.             }
  865.             i /= TBLOCK;
  866.             if (rflag && i != 1) {
  867.                 fprintf(stderr, "Tar: Cannot update blocked tapes (yet)\n");
  868.                 done(4);
  869.             }
  870.             if (i != nblock && i != 1) {
  871.                 fprintf(stderr, "Tar: blocksize = %d\n", i);
  872.                 nblock = i;
  873.             }
  874.         }
  875.         recno = 0;
  876.     }
  877.     first = 1;
  878.     copy(buffer, &tbuf[recno++]);
  879.     return(TBLOCK);
  880. }
  881.  
  882. writetape(buffer)
  883. char *buffer;
  884. {
  885.     first = 1;
  886.     if (nblock == 0)
  887.         nblock = 1;
  888.     if (recno >= nblock) {
  889.         if (write(mt, tbuf, TBLOCK*nblock) < 0) {
  890.             fprintf(stderr, "Tar: tape write error\n");
  891.             done(2);
  892.         }
  893.         recno = 0;
  894.     }
  895.     copy(&tbuf[recno++], buffer);
  896.     if (recno >= nblock) {
  897.         if (write(mt, tbuf, TBLOCK*nblock) < 0) {
  898.             fprintf(stderr, "Tar: tape write error\n");
  899.             done(2);
  900.         }
  901.         recno = 0;
  902.     }
  903.     return(TBLOCK);
  904. }
  905.  
  906. backtape()
  907. {
  908.     lseek(mt, (long) -TBLOCK, 1);
  909.     if (recno >= nblock) {
  910.         recno = nblock - 1;
  911.         if (read(mt, tbuf, TBLOCK*nblock) < 0) {
  912.             fprintf(stderr, "Tar: tape read error after seek\n");
  913.             done(4);
  914.         }
  915.         lseek(mt, (long) -TBLOCK, 1);
  916.     }
  917. }
  918.  
  919. flushtape()
  920. {
  921.     write(mt, tbuf, TBLOCK*nblock);
  922. }
  923.  
  924. copy(to, from)
  925. register char *to, *from;
  926. {
  927.     register i;
  928.  
  929.     i = TBLOCK;
  930.     do {
  931.         *to++ = *from++;
  932.     } while (--i);
  933. }
  934.