# 2.11BSD#431 - /usr/src/sbin/restor/restor.c

##### Functions

    balloc            X
    bfree             X
    bmap              X
    checksum          X
    checktype         X
    checkvol          X
    clri              X
    dcvt              X
    doit              X
    done              X
    dread             X
    dwrite            X
    flushent          X
    futz              X
    getdino           X
    getfile           X
    gethead           X
    inidbuf           X
    ishead            X
    itrunc            X
    main              X
    null              X
    olddirect         X
    pass1             X
    psearch           X
    putdino           X
    putdir            X
    putent            X
    rddir             X
    readbits          X
    readhdr           X
    readtape          X
    rstrfile          X
    rstrskip          X
    search            X
    skip              X
    tloop             X
    xtrfile           X

##### Variables

    bct               X
    cache             X
    clrimap           X
    curbno            X
    curcache          X
    curino            X
    cvtflag           X
    df                X
    dino              X
    dirfile           X
    drblock           X
    dumpmap           X
    eflag             X
    fi                X
    ino               X
    ipos              X
    isdir             X
    magtape           X
    maxi              X
    mbuf              X
    module            X
    mt                X
    name              X
    ofile             X
    prev              X
    sblock            X
    seekpt            X
    taddr             X
    tapename          X
    tbf               X
    tino              X
    volno             X
    xtrlist           X

##### Macros

    BIC               X
    BIS               X
    BIT               X
    BITS              X
    MAXINO            X
    MAXXTR            X
    MBIT              X
    MWORD             X
    NCACHE            X
    ODIRSIZ           X
    ONTAPE            X
    XINUSE            X
    XTRACTD           X
    flsht             X

##### struct's

    cache             X
    odirect           X
    xtrlist           X

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

#### Defined functions

balloc defined in line 824; used 3 times

- in line 873, 901, 913

bfree defined in line 801; used 3 times

- in line 759, 795-798(2)

bmap defined in line 859; used 3 times

- in line 1030, 1157, 1174

checksum defined in line 965; used 1 times

- in line 954

checktype defined in line 957; used 14 times

- in line 254-258(2), 273, 281, 364, 370, 384, 392, 458-466(3), 518, 537, 996

checkvol defined in line 982; used 4 times

- in line 212, 247, 351, 583

clri defined in line 731; used 2 times

- in line 378, 411

dcvt defined in line 485; used 2 times

- in line 1056, 1152

doit defined in line 169; used 2 times

- in line 158, 165

done defined in line 1248; used 3 times

- in line 113, 147-149(2)

dread defined in line 690; used 6 times

- in line 345, 788, 843, 908, 1208, 1222

dwrite defined in line 664; used 9 times

- in line 367, 381, 815, 849, 915, 1031, 1158, 1175, 1224

flushent defined in line 1092; used 1 times

- in line 480

futz defined in line 1256; used 1 times

- in line 414

getdino defined in line 1199; used 2 times

- in line 374, 408

getfile defined in line 501; used 4 times

- in line 296, 303, 417, 478

gethead defined in line 926; used 12 times

- in line 252, 271, 282, 355-360(2), 395, 404, 450, 514, 535, 994, 1244

inidbuf defined in line 1181; used 2 times

- in line 1145, 1160

ishead defined in line 936; used 3 times

- in line 270, 358, 930

itrunc defined in line 742; used 2 times

- in line 377, 410

main defined in line 108; never used
null defined in line 1013; used 5 times

- in line 178, 303(2), 448, 478

olddirect defined in line 1134; used 1 times

- in line 1029

pass1 defined in line 443; used 1 times

- in line 217

psearch defined in line 631; used 1 times

- in line 220

putdino defined in line 1212; used 2 times

- in line 379, 432

putdir defined in line 1043; used 2 times

- in line 448, 478

putent defined in line 1076; used 3 times

- in line 479, 1057, 1072

rddir defined in line 1101; used 2 times

- in line 62, 620

readbits defined in line 1230; used 6 times

- in line 260, 371, 386-388(2), 459-463(2)

readhdr defined in line 991; used 5 times

- in line 199, 207, 243, 347, 579

readtape defined in line 550; used 4 times

- in line 526, 587, 929, 1238

rstrfile defined in line 1022; used 2 times

- in line 180, 417

rstrskip defined in line 1035; used 2 times

- in line 180, 417

search defined in line 602; used 1 times

- in line 646

skip defined in line 1015; used 2 times

- in line 178, 296

tloop defined in line 777; used 4 times

- in line 763-771(3), 793

xtrfile defined in line 1006; used 2 times

- in line 178, 296

#### Defined variables

bct defined in line 96; used 5 times

- in line 20, 556-559(2), 567, 594

cache defined in line 103; used 14 times

- in line 671-677(4), 700-707(6), 713, 721-723(3)

clrimap defined in line 93; used 3 times

- in line 371-373(2), 463

curbno defined in line 88; used 9 times

- in line 409, 425, 1030-1032(2), 1039, 1157-1159(2), 1174-1176(2)

curcache defined in line 104; used 8 times

- in line 698-708(8)

curino defined in line 47; used 4 times

- in line 511, 520, 539, 561

cvtflag defined in line 83; used 9 times

- in line 129, 413, 424, 942-949(4), 1028, 1052

df defined in line 60; used 7 times

- in line 152-153(2), 616, 1084, 1096-1098(2), 1108

dino defined in line 85; used 6 times

- in line 407, 414-419(5)

dirfile defined in line 61; used 7 times

- in line 116, 152-154(2), 160, 209-214(2), 1251

drblock defined in line 80; used 23 times

- in line 617, 1081-1089(8), 1095-1097(3), 1107-1125(11)

dumpmap defined in line 91; used 5 times

- in line 220, 260-263(2), 386, 459

eflag defined in line 83; used 5 times

- in line 362, 394-401(3), 562

fi defined in line 46; used 7 times

- in line 312, 322-323(2), 679-680(2), 712-713(2)

ino defined in line 47; used 18 times

- in line 372-379(6), 398-408(5), 417, 432, 637, 646-647(3), 656

ipos defined in line 68; used 2 times

- in line 476-477(2)

isdir defined in line 83; used 4 times

- in line 416, 424, 433, 1028

magtape defined in line 51; used 7 times

- in line 132, 164, 184-185(2), 194, 242, 575

maxi defined in line 47; used 3 times

- in line 346, 372, 402

mbuf defined in line 53; used 3 times

- in line 191-194(3)

module defined in line 54; used 1 times

- in line 163

mt defined in line 49; used 10 times

- in line 184, 192-193(2), 232, 242, 366, 468, 560, 571-575(2)

name defined in line 78; used 3 times

- in line 289-291(3)

ofile defined in line 60; used 5 times

- in line 290-299(3), 1010, 1017

prev defined in line 59; used 13 times

- in line 1082-1088(3), 1095-1097(3), 1143, 1149-1155(3), 1168-1173(3)

sblock defined in line 44; used 21 times

- in line 345-346(3), 367, 381, 735, 810-818(7), 834(3), 842-850(4), 1220

seekpt defined in line 58; used 2 times

- in line 477, 1098

taddr defined in line 86; used 6 times

- in line 412-415(2), 431, 1030, 1157, 1174

tapename defined in line 50; used 1 times

- in line 51

tbf defined in line 97; used 8 times

- in line 235-237(2), 328-333(2), 558-564(3), 594

tino defined in line 85; used 10 times

- in line 374-379(5), 408-411(3), 418, 432

volno defined in line 83; used 11 times

- in line 237-238(2), 247, 329-337(3), 351-352(2), 568-572(2), 583

xtrlist defined in line 76; used 12 times

- in line 224-225(2), 262-264(3), 276-277(2), 286-289(4), 298

#### Defined struct's

cache defined in line 99; never used
odirect defined in line 39; used 14 times

- in line 486(2), 1048-1054(6), 1141(2), 1147-1148(4)

xtrlist defined in line 73; never used

#### Defined macros

BIC defined in line 35; never used
BIS defined in line 34; never used
BIT defined in line 36; used 3 times

- in line 220, 263, 373

BITS defined in line 17; used 1 times

- in line 1242

MAXINO defined in line 15; used 2 times

- in line 67, 610

MAXXTR defined in line 18; used 2 times

- in line 76, 219

MBIT defined in line 33; used 3 times

- in line 34-36(3)

MWORD defined in line 32; used 3 times

- in line 34-36(3)

NCACHE defined in line 19; used 4 times

- in line 103, 670, 697-698(2)

ODIRSIZ defined in line 38; used 2 times

- in line 41, 492

ONTAPE defined in line 70; used 1 times

- in line 264

XINUSE defined in line 72; used 1 times

- in line 225

XTRACTD defined in line 71; used 2 times

- in line 277, 298

flsht defined in line 20; used 2 times

- in line 231, 570

Last modified: 1995-06-10 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 4150 |