home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / 2.9-derivatives / 2.9-pro350 / misc / restor.c < prev   
Encoding:
C/C++ Source or Header  |  1985-02-28  |  19.6 KB  |  1,203 lines

  1. /*
  2.  *    NOTE:    This Program is must be loaded 407
  3.  *        to run standalone.  Make sure to keep
  4.  *        the size under 48K or it will run out
  5.  *        of stack space
  6.  */
  7.  
  8. #include    <whoami.h>
  9. #ifdef    NONSEPARATE
  10. #define MAXINO    500
  11. #else
  12. #define MAXINO    3000
  13. #endif
  14. #define BITS    8
  15. #define MAXXTR    60
  16. #ifndef    STANDALONE
  17. #define NCACHE    3
  18. #else
  19. #define NCACHE    1    /* Size reduction as refered to above */
  20. #endif
  21.  
  22. #ifndef STANDALONE
  23. #include <stdio.h>
  24. #include <signal.h>
  25. #endif
  26. #include <sys/param.h>
  27. #include <sys/inode.h>
  28. #include <sys/ino.h>
  29. #include <sys/fblk.h>
  30. #include <sys/filsys.h>
  31. #include <sys/dir.h>
  32. #include <dumprestor.h>
  33.  
  34. #define    MWORD(m,i) (m[(unsigned)(i-1)/MLEN])
  35. #define    MBIT(i)    (1<<((unsigned)(i-1)%MLEN))
  36. #define    BIS(i,w)    (MWORD(w,i) |=  MBIT(i))
  37. #define    BIC(i,w)    (MWORD(w,i) &= ~MBIT(i))
  38. #define    BIT(i,w)    (MWORD(w,i) & MBIT(i))
  39.  
  40. struct    filsys    sblock;
  41.  
  42. int    fi;
  43. ino_t    ino, maxi, curino;
  44.  
  45. int    mt;
  46. char    tapename[] = "/dev/rr50";
  47. char    *magtape = tapename;
  48. #ifdef STANDALONE
  49. char    mbuf[50];
  50. char    module[] = "Restor";
  51. #endif
  52.  
  53. #ifndef STANDALONE
  54. daddr_t    seekpt;
  55. int    df, ofile;
  56. char    dirfile[] = "rstXXXXXX";
  57.  
  58. struct {
  59.     ino_t    t_ino;
  60.     daddr_t    t_seekpt;
  61. } inotab[MAXINO];
  62. int    ipos;
  63.  
  64. #define ONTAPE    1
  65. #define XTRACTD    2
  66. #define XINUSE    4
  67. struct xtrlist {
  68.     ino_t    x_ino;
  69.     char    x_flags;
  70. } xtrlist[MAXXTR];
  71.  
  72. char    name[12];
  73.  
  74. char    drblock[BSIZE];
  75. int    bpt;
  76. #endif
  77.  
  78. int    eflag;
  79.  
  80. int    volno = 1;
  81.  
  82. struct dinode tino, dino;
  83. daddr_t    taddr[NADDR];
  84.  
  85. daddr_t    curbno;
  86.  
  87. #ifndef    STANDALONE
  88. short    dumpmap[MSIZ];
  89. #endif
  90. short    clrimap[MSIZ];
  91.  
  92.  
  93. int bct = NTREC+1;
  94. char tbf[NTREC*BSIZE];
  95.  
  96. struct    cache {
  97.     daddr_t    c_bno;
  98.     int    c_time;
  99.     char    c_block[BSIZE];
  100. } cache[NCACHE];
  101. int    curcache;
  102.  
  103. main(argc, argv)
  104. char *argv[];
  105. {
  106.     register char *cp;
  107.     char command;
  108.     int done();
  109.  
  110. #ifndef STANDALONE
  111.     mktemp(dirfile);
  112.     if (argc < 2) {
  113. usage:
  114.         printf("Usage: restor x file file..., restor r filesys, or restor t\n");
  115.         exit(1);
  116.     }
  117.     argv++;
  118.     argc -= 2;
  119.     for (cp = *argv++; *cp; cp++) {
  120.         switch (*cp) {
  121.         case '-':
  122.             break;
  123.         case 'f':
  124.             magtape = *argv++;
  125.             argc--;
  126.             break;
  127.         case 'r':
  128.         case 'R':
  129.         case 't':
  130.         case 'x':
  131.             command = *cp;
  132.             break;
  133.         default:
  134.             printf("Bad key character %c\n", *cp);
  135.             goto usage;
  136.         }
  137.     }
  138.     if (command == 'x') {
  139.         if (signal(SIGINT, done) == SIG_IGN)
  140.             signal(SIGINT, SIG_IGN);
  141.         if (signal(SIGTERM, done) == SIG_IGN)
  142.             signal(SIGTERM, SIG_IGN);
  143.  
  144.         df = creat(dirfile, 0666);
  145.         if (df < 0) {
  146.             printf("restor: %s - cannot create directory temporary\n", dirfile);
  147.             exit(1);
  148.         }
  149.         close(df);
  150.         df = open(dirfile, 2);
  151.     }
  152.     doit(command, argc, argv);
  153.     if (command == 'x')
  154.         unlink(dirfile);
  155.     exit(0);
  156. #else
  157.     printf("%s\n",module);
  158.     magtape = "tape";
  159.     doit('r', 1, 0);
  160. #endif
  161. }
  162.  
  163. doit(command, argc, argv)
  164. char    command;
  165. int    argc;
  166. char    *argv[];
  167. {
  168.     extern char *ctime();
  169.     register i, k;
  170.     ino_t    d;
  171. #ifndef STANDALONE
  172.     int    xtrfile(), skip(), null();
  173. #endif
  174.     int    rstrfile(), rstrskip();
  175.     struct dinode *ip, *ip1;
  176.  
  177. #ifndef STANDALONE
  178.     if ((mt = open(magtape, 0)) < 0) {
  179.         printf("%s: cannot open tape\n", magtape);
  180.         exit(1);
  181.     }
  182. #else
  183.     do {
  184.         printf("Tape? ");
  185.         gets(mbuf);
  186.         mt = open(mbuf, 0);
  187.     } while (mt == -1);
  188.     magtape = mbuf;
  189. #endif
  190.     switch(command) {
  191. #ifndef STANDALONE
  192.     case 't':
  193.         if (readhdr(&spcl) == 0) {
  194.             printf("Tape is not a dump tape\n");
  195.             exit(1);
  196.         }
  197.         printf("Dump   date: %s", ctime(&spcl.c_date));
  198.         printf("Dumped from: %s", ctime(&spcl.c_ddate));
  199.         return;
  200.     case 'x':
  201.         if (readhdr(&spcl) == 0) {
  202.             printf("Tape is not a dump tape\n");
  203.             exit(1);
  204.         }
  205.         if (checkvol(&spcl, 1) == 0) {
  206.             printf("Tape is not volume 1 of the dump\n");
  207.             exit(1);
  208.         }
  209.         pass1();  /* This sets the various maps on the way by */
  210.         i = 0;
  211.         while (i < MAXXTR-1 && argc--) {
  212.             if ((d = psearch(*argv)) == 0 || BIT(d, dumpmap) == 0) {
  213.                 printf("%s: not on the tape\n", *argv++);
  214.                 continue;
  215.             }
  216.             xtrlist[i].x_ino = d;
  217.             xtrlist[i].x_flags |= XINUSE;
  218.             printf("%s: inode %u\n", *argv, d);
  219.             argv++;
  220.             i++;
  221.         }
  222. newvol:
  223.         flsht();
  224.         close(mt);
  225. getvol:
  226.         printf("Mount desired tape volume: Specify volume #: ");
  227.         if (gets(tbf) == NULL)
  228.             return;
  229.         volno = atoi(tbf);
  230.         if (volno <= 0) {
  231.             printf("Volume numbers are positive numerics\n");
  232.             goto getvol;
  233.         }
  234.         mt = open(magtape, 0);
  235.         if (readhdr(&spcl) == 0) {
  236.             printf("tape is not dump tape\n");
  237.             goto newvol;
  238.         }
  239.         if (checkvol(&spcl, volno) == 0) {
  240.             printf("Wrong volume (%d)\n", spcl.c_volume);
  241.             goto newvol;
  242.         }
  243. rbits:
  244.         while (gethead(&spcl) == 0)
  245.             ;
  246.         if (checktype(&spcl, TS_INODE) == 1) {
  247.             printf("Can't find inode mask!\n");
  248.             goto newvol;
  249.         }
  250.         if (checktype(&spcl, TS_BITS) == 0)
  251.             goto rbits;
  252.         readbits(dumpmap);
  253.         i = 0;
  254.         for (k = 0; xtrlist[k].x_flags; k++) {
  255.             if (BIT(xtrlist[k].x_ino, dumpmap)) {
  256.                 xtrlist[k].x_flags |= ONTAPE;
  257.                 i++;
  258.             }
  259.         }
  260.         while (i > 0) {
  261. again:
  262.             if (ishead(&spcl) == 0)
  263.                 while(gethead(&spcl) == 0)
  264.                     ;
  265.             if (checktype(&spcl, TS_END) == 1) {
  266.                 printf("end of tape\n");
  267. checkdone:
  268.                 for (k = 0; xtrlist[k].x_flags; k++)
  269.                     if ((xtrlist[k].x_flags&XTRACTD) == 0)
  270.                         goto newvol;
  271.                     return;
  272.             }
  273.             if (checktype(&spcl, TS_INODE) == 0) {
  274.                 gethead(&spcl);
  275.                 goto again;
  276.             }
  277.             d = spcl.c_inumber;
  278.             for (k = 0; xtrlist[k].x_flags; k++) {
  279.                 if (d == xtrlist[k].x_ino) {
  280.                     printf("extract file %u\n", xtrlist[k].x_ino);
  281.                     sprintf(name, "%u", xtrlist[k].x_ino);
  282.                     if ((ofile = creat(name, 0666)) < 0) {
  283.                         printf("%s: cannot create file\n", name);
  284.                         i--;
  285.                         continue;
  286.                     }
  287.                     chown(name, spcl.c_dinode.di_uid, spcl.c_dinode.di_gid);
  288.                     getfile(d, xtrfile, skip, spcl.c_dinode.di_size);
  289.                     i--;
  290.                     xtrlist[k].x_flags |= XTRACTD;
  291.                     close(ofile);
  292.                     goto done;
  293.                 }
  294.             }
  295.             getfile(d, null, null, spcl.c_dinode.di_size);
  296. done:
  297.             ;
  298.         }
  299.         goto checkdone;
  300. #endif
  301.     case 'r':
  302.     case 'R':
  303. #ifndef STANDALONE
  304.         if ((fi = open(*argv, 2)) < 0) {
  305.             printf("%s: cannot open\n", *argv);
  306.             exit(1);
  307.         }
  308. #else
  309.         do {
  310.             char charbuf[50];
  311.  
  312.             printf("Disk? ");
  313.             gets(charbuf);
  314.             fi = open(charbuf, 2);
  315.         } while (fi == -1);
  316. #endif
  317. #ifndef STANDALONE
  318.         if (command == 'R') {
  319.             printf("Enter starting volume number: ");
  320.             if (gets(tbf) == EOF) {
  321.                 volno = 1;
  322.                 printf("\n");
  323.             }
  324.             else
  325.                 volno = atoi(tbf);
  326.         }
  327.         else
  328. #endif
  329.             volno = 1;
  330.         printf("Last chance before scribbling on %s. ",
  331. #ifdef STANDALONE
  332.                                 "disk");
  333. #else
  334.                                 *argv);
  335. #endif
  336.         while (getchar() != '\n');
  337.         dread((daddr_t)1, (char *)&sblock, sizeof(sblock));
  338.         maxi = (sblock.s_isize-2)*INOPB;
  339.         if (readhdr(&spcl) == 0) {
  340.             printf("Missing volume record\n");
  341.             exit(1);
  342.         }
  343.         if (checkvol(&spcl, volno) == 0) {
  344.             printf("Tape is not volume %d\n", volno);
  345.             exit(1);
  346.         }
  347.         gethead(&spcl);
  348.         for (;;) {
  349. ragain:
  350.             if (ishead(&spcl) == 0) {
  351.                 printf("Missing header block\n");
  352.                 while (gethead(&spcl) == 0)
  353.                     ;
  354.                 eflag++;
  355.             }
  356.             if (checktype(&spcl, TS_END) == 1) {
  357.                 printf("End of tape\n");
  358.                 close(mt);
  359.                 dwrite( (daddr_t) 1, (char *) &sblock);
  360.                 return;
  361.             }
  362.             if (checktype(&spcl, TS_CLRI) == 1) {
  363.                 readbits(clrimap);
  364.                 for (ino = 1; ino <= maxi; ino++)
  365.                     if (BIT(ino, clrimap) == 0) {
  366.                         getdino(ino, &tino);
  367.                         if (tino.di_mode == 0)
  368.                             continue;
  369.                         itrunc(&tino);
  370.                         clri(&tino);
  371.                         putdino(ino, &tino);
  372.                     }
  373.                 dwrite( (daddr_t) 1, (char *) &sblock);
  374.                 goto ragain;
  375.             }
  376.             if (checktype(&spcl, TS_BITS) == 1) {
  377. #ifndef STANDALONE
  378.                 readbits(dumpmap);
  379. #else
  380.                 readbits(0);
  381. #endif
  382.                 goto ragain;
  383.             }
  384.             if (checktype(&spcl, TS_INODE) == 0) {
  385.                 printf("Unknown header type\n");
  386.                 eflag++;
  387.                 gethead(&spcl);
  388.                 goto ragain;
  389.             }
  390.             ino = spcl.c_inumber;
  391.             if (eflag)
  392.                 printf("Resynced at inode %u\n", ino);
  393.             eflag = 0;
  394.             if (ino > maxi) {
  395.                 printf("%u: ilist too small\n", ino);
  396.                 gethead(&spcl);
  397.                 goto ragain;
  398.             }
  399.             dino = spcl.c_dinode;
  400.             getdino(ino, &tino);
  401.             curbno = 0;
  402.             itrunc(&tino);
  403.             clri(&tino);
  404.             for (i = 0; i < NADDR; i++)
  405.                 taddr[i] = 0;
  406.             l3tol(taddr, dino.di_addr, 1);
  407.             getfile(ino, rstrfile, rstrskip, dino.di_size);
  408.             ip = &tino;
  409.             ltol3(ip->di_addr, taddr, NADDR);
  410.             ip1 = &dino;
  411.             ip->di_mode = ip1->di_mode;
  412.             ip->di_nlink = ip1->di_nlink;
  413.             ip->di_uid = ip1->di_uid;
  414.             ip->di_gid = ip1->di_gid;
  415.             ip->di_size = ip1->di_size;
  416.             ip->di_atime = ip1->di_atime;
  417.             ip->di_mtime = ip1->di_mtime;
  418.             ip->di_ctime = ip1->di_ctime;
  419.             putdino(ino, &tino);
  420.         }
  421.     }
  422. }
  423.  
  424. /*
  425.  * Read the tape, bulding up a directory structure for extraction
  426.  * by name
  427.  */
  428. #ifndef STANDALONE
  429. pass1()
  430. {
  431.     register i;
  432.     struct dinode *ip;
  433.     int    putdir(), null();
  434.  
  435.     while (gethead(&spcl) == 0) {
  436.         printf("Can't find directory header!\n");
  437.     }
  438.     for (;;) {
  439.         if (checktype(&spcl, TS_BITS) == 1) {
  440.             readbits(dumpmap);
  441.             continue;
  442.         }
  443.         if (checktype(&spcl, TS_CLRI) == 1) {
  444.             readbits(clrimap);
  445.             continue;
  446.         }
  447.         if (checktype(&spcl, TS_INODE) == 0) {
  448. finish:
  449.             flsh();
  450.             close(mt);
  451.             return;
  452.         }
  453.         ip = &spcl.c_dinode;
  454.         i = ip->di_mode & IFMT;
  455.         if (i != IFDIR) {
  456.             goto finish;
  457.         }
  458.         inotab[ipos].t_ino = spcl.c_inumber;
  459.         inotab[ipos++].t_seekpt = seekpt;
  460.         getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size);
  461.         putent("\000\000/");
  462.     }
  463. }
  464. #endif
  465.  
  466. /*
  467.  * Do the file extraction, calling the supplied functions
  468.  * with the blocks
  469.  */
  470. getfile(n, f1, f2, size)
  471. ino_t    n;
  472. int    (*f2)(), (*f1)();
  473. long    size;
  474. {
  475.     register i;
  476.     struct spcl addrblock;
  477.     char buf[BSIZE];
  478.  
  479.     addrblock = spcl;
  480.     curino = n;
  481.     goto start;
  482.     for (;;) {
  483.         if (gethead(&addrblock) == 0) {
  484.             printf("Missing address (header) block\n");
  485.             goto eloop;
  486.         }
  487.         if (checktype(&addrblock, TS_ADDR) == 0) {
  488.             spcl = addrblock;
  489.             curino = 0;
  490.             return;
  491.         }
  492. start:
  493.         for (i = 0; i < addrblock.c_count; i++) {
  494.             if (addrblock.c_addr[i]) {
  495.                 readtape(buf);
  496.                 (*f1)(buf, size > BSIZE ? (long) BSIZE : size);
  497.             }
  498.             else {
  499.                 clearbuf(buf);
  500.                 (*f2)(buf, size > BSIZE ? (long) BSIZE : size);
  501.             }
  502.             if ((size -= BSIZE) <= 0) {
  503. eloop:
  504.                 while (gethead(&spcl) == 0)
  505.                     ;
  506.                 if (checktype(&spcl, TS_ADDR) == 1)
  507.                     goto eloop;
  508.                 curino = 0;
  509.                 return;
  510.             }
  511.         }
  512.     }
  513. }
  514.  
  515. #ifdef GOO
  516. #define    MAXRX50    39
  517. long blkcnt = 0;
  518. #endif
  519. /*
  520.  * Do the tape i\/o, dealling with volume changes
  521.  * etc..
  522.  */
  523. readtape(b)
  524. char *b;
  525. {
  526.     register i;
  527.     struct spcl tmpbuf;
  528.  
  529.     if (bct >= NTREC) {
  530.         for (i = 0; i < NTREC; i++)
  531.             ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0;
  532.         bct = 0;
  533. #ifdef GOO
  534.         blkcnt++;
  535.         if (blkcnt <= MAXRX50) {
  536. #endif
  537.         if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) {
  538.             printf("Tape read error: inode %u\n", curino);
  539.             eflag++;
  540.             for (i = 0; i < NTREC; i++)
  541.                 clearbuf(&tbf[i*BSIZE]);
  542.         }
  543. #ifdef GOO
  544.         }
  545.         if (i == 0 || blkcnt > MAXRX50) {
  546.             blkcnt = 0;
  547. #else
  548.         if (i == 0) {
  549. #endif
  550.             bct = NTREC + 1;
  551.             volno++;
  552. loop:
  553.             flsht();
  554.             close(mt);
  555.             printf("Mount volume %d\n", volno);
  556.             while (getchar() != '\n')
  557.                 ;
  558.             if ((mt = open(magtape, 0)) == -1) {
  559.                 printf("Cannot open tape!\n");
  560.                 goto loop;
  561.             }
  562.             if (readhdr(&tmpbuf) == 0) {
  563.                 printf("Not a dump tape.Try again\n");
  564.                 goto loop;
  565.             }
  566.             if (checkvol(&tmpbuf, volno) == 0) {
  567.                 printf("Wrong tape. Try again\n");
  568.                 goto loop;
  569.             }
  570.             readtape(b);
  571.             return;
  572.         }
  573.     }
  574. #ifdef    STANDALONE
  575.     if(b)
  576. #endif
  577.     copy(&tbf[(bct++*BSIZE)], b, BSIZE);
  578. }
  579.  
  580. flsht()
  581. {
  582.     bct = NTREC+1;
  583. }
  584.  
  585. copy(f, t, s)
  586. register char *f, *t;
  587. {
  588.     register i;
  589.  
  590.     i = s;
  591.     do
  592.         *t++ = *f++;
  593.     while (--i);
  594. }
  595.  
  596. clearbuf(cp)
  597. register char *cp;
  598. {
  599.     register i;
  600.  
  601.     i = BSIZE;
  602.     do
  603.         *cp++ = 0;
  604.     while (--i);
  605. }
  606.  
  607. /*
  608.  * Put and get the directory entries from the compressed
  609.  * directory file
  610.  */
  611. #ifndef STANDALONE
  612. putent(cp)
  613. char    *cp;
  614. {
  615.     register i;
  616.  
  617.     for (i = 0; i < sizeof(ino_t); i++)
  618.         writec(*cp++);
  619.     for (i = 0; i < DIRSIZ; i++) {
  620.         writec(*cp);
  621.         if (*cp++ == 0)
  622.             return;
  623.     }
  624.     return;
  625. }
  626.  
  627. getent(bf)
  628. register char *bf;
  629. {
  630.     register i;
  631.  
  632.     for (i = 0; i < sizeof(ino_t); i++)
  633.         *bf++ = readc();
  634.     for (i = 0; i < DIRSIZ; i++)
  635.         if ((*bf++ = readc()) == 0)
  636.             return;
  637.     return;
  638. }
  639.  
  640. /*
  641.  * read/write te directory file
  642.  */
  643. writec(c)
  644. char c;
  645. {
  646.     drblock[bpt++] = c;
  647.     seekpt++;
  648.     if (bpt >= BSIZE) {
  649.         bpt = 0;
  650.         write(df, drblock, BSIZE);
  651.     }
  652. }
  653.  
  654. readc()
  655. {
  656.     if (bpt >= BSIZE) {
  657.         read(df, drblock, BSIZE);
  658.         bpt = 0;
  659.     }
  660.     return(drblock[bpt++]);
  661. }
  662.  
  663. mseek(pt)
  664. daddr_t pt;
  665. {
  666.     bpt = BSIZE;
  667.     lseek(df, pt, 0);
  668. }
  669.  
  670. flsh()
  671. {
  672.     write(df, drblock, bpt+1);
  673. }
  674.  
  675. #ifndef    STANDALONE
  676. /*
  677.  * search the directory inode ino
  678.  * looking for entry cp
  679.  */
  680. ino_t
  681. search(inum, cp)
  682. ino_t    inum;
  683. char    *cp;
  684. {
  685.     register i;
  686.     struct direct dir;
  687.  
  688.     for (i = 0; i < MAXINO; i++)
  689.         if (inotab[i].t_ino == inum) {
  690.             goto found;
  691.         }
  692.     return(0);
  693. found:
  694.     mseek(inotab[i].t_seekpt);
  695.     do {
  696.         getent((char *)&dir);
  697.         if (direq(dir.d_name, "/"))
  698.             return(0);
  699.     } while (direq(dir.d_name, cp) == 0);
  700.     return(dir.d_ino);
  701. }
  702.  
  703. /*
  704.  * Search the directory tree rooted at inode 2
  705.  * for the path pointed at by n
  706.  */
  707. psearch(n)
  708. char    *n;
  709. {
  710.     register char *cp, *cp1;
  711.     char c;
  712.  
  713.     ino = 2;
  714.     if (*(cp = n) == '/')
  715.         cp++;
  716. next:
  717.     cp1 = cp + 1;
  718.     while (*cp1 != '/' && *cp1)
  719.         cp1++;
  720.     c = *cp1;
  721.     *cp1 = 0;
  722.     ino = search(ino, cp);
  723.     if (ino == 0) {
  724.         *cp1 = c;
  725.         return(0);
  726.     }
  727.     *cp1 = c;
  728.     if (c == '/') {
  729.         cp = cp1+1;
  730.         goto next;
  731.     }
  732.     return(ino);
  733. }
  734. #endif    STANDALONE
  735.  
  736. direq(s1, s2)
  737. register char *s1, *s2;
  738. {
  739.     register i;
  740.  
  741.     for (i = 0; i < DIRSIZ; i++)
  742.         if (*s1++ == *s2) {
  743.             if (*s2++ == 0)
  744.                 return(1);
  745.         } else
  746.             return(0);
  747.     return(1);
  748. }
  749. #endif
  750.  
  751. /*
  752.  * read/write a disk block, be sure to update the buffer
  753.  * cache if needed.
  754.  */
  755. dwrite(bno, b)
  756. daddr_t    bno;
  757. char    *b;
  758. {
  759.     register i;
  760.  
  761.     for (i = 0; i < NCACHE; i++) {
  762.         if (cache[i].c_bno == bno) {
  763.             copy(b, cache[i].c_block, BSIZE);
  764.             cache[i].c_time = 0;
  765.             break;
  766.         }
  767.         else
  768.             cache[i].c_time++;
  769.     }
  770.     lseek(fi, bno*BSIZE, 0);
  771.     if(write(fi, b, BSIZE) != BSIZE) {
  772. #ifdef STANDALONE
  773.         printf("disk write error:  block %D\n", bno);
  774. #else
  775.         fprintf(stderr, "disk write error:  block %ld\n", bno);
  776. #endif
  777.         exit(1);
  778.     }
  779. }
  780.  
  781. dread(bno, buf, cnt)
  782. daddr_t bno;
  783. char *buf;
  784. {
  785.     register i, j;
  786.  
  787.     j = 0;
  788.     for (i = 0; i < NCACHE; i++) {
  789.         if (++curcache >= NCACHE)
  790.             curcache = 0;
  791.         if (cache[curcache].c_bno == bno) {
  792.             copy(cache[curcache].c_block, buf, cnt);
  793.             cache[curcache].c_time = 0;
  794.             return;
  795.         }
  796.         else {
  797.             cache[curcache].c_time++;
  798.             if (cache[j].c_time < cache[curcache].c_time)
  799.                 j = curcache;
  800.         }
  801.     }
  802.  
  803.     lseek(fi, bno*BSIZE, 0);
  804.     if (read(fi, cache[j].c_block, BSIZE) != BSIZE) {
  805. #ifdef STANDALONE
  806.         printf("read error:  block %D\n", bno);
  807. #else
  808.         printf("read error:  block %ld\n", bno);
  809. #endif
  810.         exit(1);
  811.     }
  812.     copy(cache[j].c_block, buf, cnt);
  813.     cache[j].c_time = 0;
  814.     cache[j].c_bno = bno;
  815. }
  816.  
  817. /*
  818.  * the inode manpulation routines. Like the system.
  819.  *
  820.  * clri zeros the inode
  821.  */
  822. clri(ip)
  823. struct dinode *ip;
  824. {
  825.     int i, *p;
  826.     if (ip->di_mode&IFMT)
  827.         sblock.s_tinode++;
  828.     i = sizeof(struct dinode)/sizeof(int);
  829.     p = (int *)ip;
  830.     do
  831.         *p++ = 0;
  832.     while(--i);
  833. }
  834.  
  835. /*
  836.  * itrunc/tloop/bfree free all of the blocks pointed at by the inode
  837.  */
  838. itrunc(ip)
  839. register struct dinode *ip;
  840. {
  841.     register i;
  842.     daddr_t bn, iaddr[NADDR];
  843.  
  844.     if (ip->di_mode == 0)
  845.         return;
  846.     i = ip->di_mode & IFMT;
  847.     if (i != IFDIR && i != IFREG)
  848.         return;
  849.     l3tol(iaddr, ip->di_addr, NADDR);
  850.     for(i=NADDR-1;i>=0;i--) {
  851.         bn = iaddr[i];
  852.         if(bn == 0) continue;
  853.         switch(i) {
  854.  
  855.         default:
  856.             bfree(bn);
  857.             break;
  858.  
  859.         case NADDR-3:
  860.             tloop(bn, 0, 0);
  861.             break;
  862.  
  863.         case NADDR-2:
  864.             tloop(bn, 1, 0);
  865.             break;
  866.  
  867.         case NADDR-1:
  868.             tloop(bn, 1, 1);
  869.         }
  870.     }
  871.     ip->di_size = 0;
  872. }
  873.  
  874. tloop(bn, f1, f2)
  875. daddr_t    bn;
  876. int    f1, f2;
  877. {
  878.     register i;
  879.     daddr_t nb;
  880.     union {
  881.         char    data[BSIZE];
  882.         daddr_t    indir[NINDIR];
  883.     } ibuf;
  884.  
  885.     dread(bn, ibuf.data, BSIZE);
  886.     for(i=NINDIR-1;i>=0;i--) {
  887.         nb = ibuf.indir[i];
  888.         if(nb) {
  889.             if(f1)
  890.                 tloop(nb, f2, 0);
  891.             else
  892.                 bfree(nb);
  893.         }
  894.     }
  895.     bfree(bn);
  896. }
  897.  
  898. bfree(bn)
  899. daddr_t    bn;
  900. {
  901.     register i;
  902.     union {
  903.         char    data[BSIZE];
  904.         struct    fblk frees;
  905.     } fbuf;
  906.  
  907.     if(sblock.s_nfree >= NICFREE) {
  908.         fbuf.df_nfree = sblock.s_nfree;
  909.         for(i=0;i<NICFREE;i++)
  910.             fbuf.df_free[i] = sblock.s_free[i];
  911.         sblock.s_nfree = 0;
  912.         dwrite(bn, fbuf.data);
  913.     }
  914.     sblock.s_free[sblock.s_nfree++] = bn;
  915.     sblock.s_tfree++;
  916. }
  917.  
  918. /*
  919.  * allocate a block off the free list.
  920.  */
  921. daddr_t
  922. balloc()
  923. {
  924.     daddr_t    bno;
  925.     register i;
  926.     static char zeroes[BSIZE];
  927.     union {
  928.         char    data[BSIZE];
  929.         struct    fblk frees;
  930.     } fbuf;
  931.  
  932.     if(sblock.s_nfree == 0 || (bno=sblock.s_free[--sblock.s_nfree]) == 0) {
  933. #ifdef STANDALONE
  934.         printf("Out of space\n");
  935. #else
  936.         fprintf(stderr, "Out of space.\n");
  937. #endif
  938.         exit(1);
  939.     }
  940.     if(sblock.s_nfree == 0) {
  941.         dread(bno, fbuf.data, BSIZE);
  942.         sblock.s_nfree = fbuf.df_nfree;
  943.         for(i=0;i<NICFREE;i++)
  944.             sblock.s_free[i] = fbuf.df_free[i];
  945.     }
  946.     dwrite(bno, zeroes);
  947.     sblock.s_tfree--;
  948.     return(bno);
  949. }
  950.  
  951. /*
  952.  * map a block number into a block address, ensuring
  953.  * all of the correct indirect blocks are around. Allocate
  954.  * the block requested.
  955.  */
  956. daddr_t
  957. bmap(iaddr, bn)
  958. daddr_t    iaddr[NADDR];
  959. daddr_t    bn;
  960. {
  961.     register i;
  962.     int j, sh;
  963.     daddr_t nb, nnb;
  964.     daddr_t indir[NINDIR];
  965.  
  966.     /*
  967.      * blocks 0..NADDR-4 are direct blocks
  968.      */
  969.     if(bn < NADDR-3) {
  970.         iaddr[bn] = nb = balloc();
  971.         return(nb);
  972.     }
  973.  
  974.     /*
  975.      * addresses NADDR-3, NADDR-2, and NADDR-1
  976.      * have single, double, triple indirect blocks.
  977.      * the first step is to determine
  978.      * how many levels of indirection.
  979.      */
  980.     sh = 0;
  981.     nb = 1;
  982.     bn -= NADDR-3;
  983.     for(j=3; j>0; j--) {
  984.         sh += NSHIFT;
  985.         nb <<= NSHIFT;
  986.         if(bn < nb)
  987.             break;
  988.         bn -= nb;
  989.     }
  990.     if(j == 0) {
  991.         return((daddr_t)0);
  992.     }
  993.  
  994.     /*
  995.      * fetch the address from the inode
  996.      */
  997.     if((nb = iaddr[NADDR-j]) == 0) {
  998.         iaddr[NADDR-j] = nb = balloc();
  999.     }
  1000.  
  1001.     /*
  1002.      * fetch through the indirect blocks
  1003.      */
  1004.     for(; j<=3; j++) {
  1005.         dread(nb, (char *)indir, BSIZE);
  1006.         sh -= NSHIFT;
  1007.         i = (bn>>sh) & NMASK;
  1008.         nnb = indir[i];
  1009.         if(nnb == 0) {
  1010.             nnb = balloc();
  1011.             indir[i] = nnb;
  1012.             dwrite(nb, (char *)indir);
  1013.         }
  1014.         nb = nnb;
  1015.     }
  1016.     return(nb);
  1017. }
  1018.  
  1019. /*
  1020.  * read the tape into buf, then return whether or
  1021.  * or not it is a header block.
  1022.  */
  1023. gethead(buf)
  1024. struct spcl *buf;
  1025. {
  1026.     readtape((char *)buf);
  1027.     if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
  1028.         return(0);
  1029.     return(1);
  1030. }
  1031.  
  1032. /*
  1033.  * return whether or not the buffer contains a header block
  1034.  */
  1035. ishead(buf)
  1036. struct spcl *buf;
  1037. {
  1038.     if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
  1039.         return(0);
  1040.     return(1);
  1041. }
  1042.  
  1043. checktype(b, t)
  1044. struct    spcl *b;
  1045. int    t;
  1046. {
  1047.     return(b->c_type == t);
  1048. }
  1049.  
  1050.  
  1051. checksum(b)
  1052. int *b;
  1053. {
  1054.     register i, j;
  1055.  
  1056.     j = BSIZE/sizeof(int);
  1057.     i = 0;
  1058.     do
  1059.         i += *b++;
  1060.     while (--j);
  1061.     if (i != CHECKSUM) {
  1062.         printf("Checksum error %o\n", i);
  1063.         return(0);
  1064.     }
  1065.     return(1);
  1066. }
  1067.  
  1068. checkvol(b, t)
  1069. struct spcl *b;
  1070. int t;
  1071. {
  1072.     if (b->c_volume == t)
  1073.         return(1);
  1074.     return(0);
  1075. }
  1076.  
  1077. readhdr(b)
  1078. struct    spcl *b;
  1079. {
  1080.     if (gethead(b) == 0)
  1081.         return(0);
  1082.     if (checktype(b, TS_TAPE) == 0)
  1083.         return(0);
  1084.     return(1);
  1085. }
  1086.  
  1087. /*
  1088.  * The next routines are called during file extraction to
  1089.  * put the data into the right form and place.
  1090.  */
  1091. #ifndef STANDALONE
  1092. xtrfile(b, size)
  1093. char    *b;
  1094. long    size;
  1095. {
  1096.     write(ofile, b, (int) size);
  1097. }
  1098.  
  1099. null() {;}
  1100.  
  1101. skip()
  1102. {
  1103.     lseek(ofile, (long) BSIZE, 1);
  1104. }
  1105. #endif
  1106.  
  1107.  
  1108. rstrfile(b, s)
  1109. char *b;
  1110. long s;
  1111. {
  1112.     daddr_t d;
  1113.  
  1114.     d = bmap(taddr, curbno);
  1115.     dwrite(d, b);
  1116.     curbno += 1;
  1117. }
  1118.  
  1119. rstrskip(b, s)
  1120. char *b;
  1121. long s;
  1122. {
  1123.     curbno += 1;
  1124. }
  1125.  
  1126. #ifndef STANDALONE
  1127. putdir(b)
  1128. char *b;
  1129. {
  1130.     register struct direct *dp;
  1131.     register i;
  1132.  
  1133.     for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) {
  1134.         if (dp->d_ino == 0)
  1135.             continue;
  1136.         putent((char *) dp);
  1137.     }
  1138. }
  1139. #endif
  1140.  
  1141. /*
  1142.  * read/write an inode from the disk
  1143.  */
  1144. getdino(inum, b)
  1145. ino_t    inum;
  1146. struct    dinode *b;
  1147. {
  1148.     daddr_t    bno;
  1149.     char buf[BSIZE];
  1150.  
  1151.     bno = (inum - 1)/INOPB;
  1152.     bno += 2;
  1153.     dread(bno, buf, BSIZE);
  1154.     copy(&buf[((inum-1)%INOPB)*sizeof(struct dinode)], (char *) b, sizeof(struct dinode));
  1155. }
  1156.  
  1157. putdino(inum, b)
  1158. ino_t    inum;
  1159. struct    dinode *b;
  1160. {
  1161.     daddr_t bno;
  1162.     char buf[BSIZE];
  1163.  
  1164.     if (b->di_mode&IFMT)
  1165.         sblock.s_tinode--;
  1166.     bno = ((inum - 1)/INOPB) + 2;
  1167.     dread(bno, buf, BSIZE);
  1168.     copy((char *) b, &buf[((inum-1)%INOPB)*sizeof(struct dinode)], sizeof(struct dinode));
  1169.     dwrite(bno, buf);
  1170. }
  1171.  
  1172. /*
  1173.  * read a bit mask from the tape into m.
  1174.  */
  1175. readbits(m)
  1176. short    *m;
  1177. {
  1178.     register i;
  1179.  
  1180.     i = spcl.c_count;
  1181.  
  1182.     while (i--) {
  1183.         readtape((char *) m);
  1184. #ifdef    STANDALONE
  1185.         if(m)
  1186. #endif
  1187.         m += (BSIZE/(MLEN/BITS));
  1188.     }
  1189.     while (gethead(&spcl) == 0)
  1190.         ;
  1191. }
  1192.  
  1193. done()
  1194. {
  1195. #ifndef STANDALONE
  1196.     unlink(dirfile);
  1197. #endif
  1198.     exit(0);
  1199. }
  1200.  
  1201.  
  1202.  
  1203.