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  1000
  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/rmt1";
  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: /*
 516:  * Do the tape i\/o, dealling with volume changes
 517:  * etc..
 518:  */
 519: readtape(b)
 520: char *b;
 521: {
 522:     register i;
 523:     struct spcl tmpbuf;
 524: 
 525:     if (bct >= NTREC) {
 526:         for (i = 0; i < NTREC; i++)
 527:             ((struct spcl *)&tbf[i*BSIZE])->c_magic = 0;
 528:         bct = 0;
 529:         if ((i = read(mt, tbf, NTREC*BSIZE)) < 0) {
 530:             printf("Tape read error: inode %u\n", curino);
 531:             eflag++;
 532:             for (i = 0; i < NTREC; i++)
 533:                 clearbuf(&tbf[i*BSIZE]);
 534:         }
 535:         if (i == 0) {
 536:             bct = NTREC + 1;
 537:             volno++;
 538: loop:
 539:             flsht();
 540:             close(mt);
 541:             printf("Mount volume %d\n", volno);
 542:             while (getchar() != '\n')
 543:                 ;
 544:             if ((mt = open(magtape, 0)) == -1) {
 545:                 printf("Cannot open tape!\n");
 546:                 goto loop;
 547:             }
 548:             if (readhdr(&tmpbuf) == 0) {
 549:                 printf("Not a dump tape.Try again\n");
 550:                 goto loop;
 551:             }
 552:             if (checkvol(&tmpbuf, volno) == 0) {
 553:                 printf("Wrong tape. Try again\n");
 554:                 goto loop;
 555:             }
 556:             readtape(b);
 557:             return;
 558:         }
 559:     }
 560: #ifdef  STANDALONE
 561:     if(b)
 562: #endif
 563:     copy(&tbf[(bct++*BSIZE)], b, BSIZE);
 564: }
 565: 
 566: flsht()
 567: {
 568:     bct = NTREC+1;
 569: }
 570: 
 571: copy(f, t, s)
 572: register char *f, *t;
 573: {
 574:     register i;
 575: 
 576:     i = s;
 577:     do
 578:         *t++ = *f++;
 579:     while (--i);
 580: }
 581: 
 582: clearbuf(cp)
 583: register char *cp;
 584: {
 585:     register i;
 586: 
 587:     i = BSIZE;
 588:     do
 589:         *cp++ = 0;
 590:     while (--i);
 591: }
 592: 
 593: /*
 594:  * Put and get the directory entries from the compressed
 595:  * directory file
 596:  */
 597: #ifndef STANDALONE
 598: putent(cp)
 599: char    *cp;
 600: {
 601:     register i;
 602: 
 603:     for (i = 0; i < sizeof(ino_t); i++)
 604:         writec(*cp++);
 605:     for (i = 0; i < DIRSIZ; i++) {
 606:         writec(*cp);
 607:         if (*cp++ == 0)
 608:             return;
 609:     }
 610:     return;
 611: }
 612: 
 613: getent(bf)
 614: register char *bf;
 615: {
 616:     register i;
 617: 
 618:     for (i = 0; i < sizeof(ino_t); i++)
 619:         *bf++ = readc();
 620:     for (i = 0; i < DIRSIZ; i++)
 621:         if ((*bf++ = readc()) == 0)
 622:             return;
 623:     return;
 624: }
 625: 
 626: /*
 627:  * read/write te directory file
 628:  */
 629: writec(c)
 630: char c;
 631: {
 632:     drblock[bpt++] = c;
 633:     seekpt++;
 634:     if (bpt >= BSIZE) {
 635:         bpt = 0;
 636:         write(df, drblock, BSIZE);
 637:     }
 638: }
 639: 
 640: readc()
 641: {
 642:     if (bpt >= BSIZE) {
 643:         read(df, drblock, BSIZE);
 644:         bpt = 0;
 645:     }
 646:     return(drblock[bpt++]);
 647: }
 648: 
 649: mseek(pt)
 650: daddr_t pt;
 651: {
 652:     bpt = BSIZE;
 653:     lseek(df, pt, 0);
 654: }
 655: 
 656: flsh()
 657: {
 658:     write(df, drblock, bpt+1);
 659: }
 660: 
 661: #ifndef STANDALONE
 662: /*
 663:  * search the directory inode ino
 664:  * looking for entry cp
 665:  */
 666: ino_t
 667: search(inum, cp)
 668: ino_t   inum;
 669: char    *cp;
 670: {
 671:     register i;
 672:     struct direct dir;
 673: 
 674:     for (i = 0; i < MAXINO; i++)
 675:         if (inotab[i].t_ino == inum) {
 676:             goto found;
 677:         }
 678:     return(0);
 679: found:
 680:     mseek(inotab[i].t_seekpt);
 681:     do {
 682:         getent((char *)&dir);
 683:         if (direq(dir.d_name, "/"))
 684:             return(0);
 685:     } while (direq(dir.d_name, cp) == 0);
 686:     return(dir.d_ino);
 687: }
 688: 
 689: /*
 690:  * Search the directory tree rooted at inode 2
 691:  * for the path pointed at by n
 692:  */
 693: psearch(n)
 694: char    *n;
 695: {
 696:     register char *cp, *cp1;
 697:     char c;
 698: 
 699:     ino = 2;
 700:     if (*(cp = n) == '/')
 701:         cp++;
 702: next:
 703:     cp1 = cp + 1;
 704:     while (*cp1 != '/' && *cp1)
 705:         cp1++;
 706:     c = *cp1;
 707:     *cp1 = 0;
 708:     ino = search(ino, cp);
 709:     if (ino == 0) {
 710:         *cp1 = c;
 711:         return(0);
 712:     }
 713:     *cp1 = c;
 714:     if (c == '/') {
 715:         cp = cp1+1;
 716:         goto next;
 717:     }
 718:     return(ino);
 719: }
 720: #endif	STANDALONE
 721: 
 722: direq(s1, s2)
 723: register char *s1, *s2;
 724: {
 725:     register i;
 726: 
 727:     for (i = 0; i < DIRSIZ; i++)
 728:         if (*s1++ == *s2) {
 729:             if (*s2++ == 0)
 730:                 return(1);
 731:         } else
 732:             return(0);
 733:     return(1);
 734: }
 735: #endif
 736: 
 737: /*
 738:  * read/write a disk block, be sure to update the buffer
 739:  * cache if needed.
 740:  */
 741: dwrite(bno, b)
 742: daddr_t bno;
 743: char    *b;
 744: {
 745:     register i;
 746: 
 747:     for (i = 0; i < NCACHE; i++) {
 748:         if (cache[i].c_bno == bno) {
 749:             copy(b, cache[i].c_block, BSIZE);
 750:             cache[i].c_time = 0;
 751:             break;
 752:         }
 753:         else
 754:             cache[i].c_time++;
 755:     }
 756:     lseek(fi, bno*BSIZE, 0);
 757:     if(write(fi, b, BSIZE) != BSIZE) {
 758: #ifdef STANDALONE
 759:         printf("disk write error:  block %D\n", bno);
 760: #else
 761:         fprintf(stderr, "disk write error:  block %ld\n", bno);
 762: #endif
 763:         exit(1);
 764:     }
 765: }
 766: 
 767: dread(bno, buf, cnt)
 768: daddr_t bno;
 769: char *buf;
 770: {
 771:     register i, j;
 772: 
 773:     j = 0;
 774:     for (i = 0; i < NCACHE; i++) {
 775:         if (++curcache >= NCACHE)
 776:             curcache = 0;
 777:         if (cache[curcache].c_bno == bno) {
 778:             copy(cache[curcache].c_block, buf, cnt);
 779:             cache[curcache].c_time = 0;
 780:             return;
 781:         }
 782:         else {
 783:             cache[curcache].c_time++;
 784:             if (cache[j].c_time < cache[curcache].c_time)
 785:                 j = curcache;
 786:         }
 787:     }
 788: 
 789:     lseek(fi, bno*BSIZE, 0);
 790:     if (read(fi, cache[j].c_block, BSIZE) != BSIZE) {
 791: #ifdef STANDALONE
 792:         printf("read error:  block %D\n", bno);
 793: #else
 794:         printf("read error:  block %ld\n", bno);
 795: #endif
 796:         exit(1);
 797:     }
 798:     copy(cache[j].c_block, buf, cnt);
 799:     cache[j].c_time = 0;
 800:     cache[j].c_bno = bno;
 801: }
 802: 
 803: /*
 804:  * the inode manpulation routines. Like the system.
 805:  *
 806:  * clri zeros the inode
 807:  */
 808: clri(ip)
 809: struct dinode *ip;
 810: {
 811:     int i, *p;
 812:     if (ip->di_mode&IFMT)
 813:         sblock.s_tinode++;
 814:     i = sizeof(struct dinode)/sizeof(int);
 815:     p = (int *)ip;
 816:     do
 817:         *p++ = 0;
 818:     while(--i);
 819: }
 820: 
 821: /*
 822:  * itrunc/tloop/bfree free all of the blocks pointed at by the inode
 823:  */
 824: itrunc(ip)
 825: register struct dinode *ip;
 826: {
 827:     register i;
 828:     daddr_t bn, iaddr[NADDR];
 829: 
 830:     if (ip->di_mode == 0)
 831:         return;
 832:     i = ip->di_mode & IFMT;
 833:     if (i != IFDIR && i != IFREG)
 834:         return;
 835:     l3tol(iaddr, ip->di_addr, NADDR);
 836:     for(i=NADDR-1;i>=0;i--) {
 837:         bn = iaddr[i];
 838:         if(bn == 0) continue;
 839:         switch(i) {
 840: 
 841:         default:
 842:             bfree(bn);
 843:             break;
 844: 
 845:         case NADDR-3:
 846:             tloop(bn, 0, 0);
 847:             break;
 848: 
 849:         case NADDR-2:
 850:             tloop(bn, 1, 0);
 851:             break;
 852: 
 853:         case NADDR-1:
 854:             tloop(bn, 1, 1);
 855:         }
 856:     }
 857:     ip->di_size = 0;
 858: }
 859: 
 860: tloop(bn, f1, f2)
 861: daddr_t bn;
 862: int f1, f2;
 863: {
 864:     register i;
 865:     daddr_t nb;
 866:     union {
 867:         char    data[BSIZE];
 868:         daddr_t indir[NINDIR];
 869:     } ibuf;
 870: 
 871:     dread(bn, ibuf.data, BSIZE);
 872:     for(i=NINDIR-1;i>=0;i--) {
 873:         nb = ibuf.indir[i];
 874:         if(nb) {
 875:             if(f1)
 876:                 tloop(nb, f2, 0);
 877:             else
 878:                 bfree(nb);
 879:         }
 880:     }
 881:     bfree(bn);
 882: }
 883: 
 884: bfree(bn)
 885: daddr_t bn;
 886: {
 887:     register i;
 888:     union {
 889:         char    data[BSIZE];
 890:         struct  fblk frees;
 891:     } fbuf;
 892: 
 893:     if(sblock.s_nfree >= NICFREE) {
 894:         fbuf.df_nfree = sblock.s_nfree;
 895:         for(i=0;i<NICFREE;i++)
 896:             fbuf.df_free[i] = sblock.s_free[i];
 897:         sblock.s_nfree = 0;
 898:         dwrite(bn, fbuf.data);
 899:     }
 900:     sblock.s_free[sblock.s_nfree++] = bn;
 901:     sblock.s_tfree++;
 902: }
 903: 
 904: /*
 905:  * allocate a block off the free list.
 906:  */
 907: daddr_t
 908: balloc()
 909: {
 910:     daddr_t bno;
 911:     register i;
 912:     static char zeroes[BSIZE];
 913:     union {
 914:         char    data[BSIZE];
 915:         struct  fblk frees;
 916:     } fbuf;
 917: 
 918:     if(sblock.s_nfree == 0 || (bno=sblock.s_free[--sblock.s_nfree]) == 0) {
 919: #ifdef STANDALONE
 920:         printf("Out of space\n");
 921: #else
 922:         fprintf(stderr, "Out of space.\n");
 923: #endif
 924:         exit(1);
 925:     }
 926:     if(sblock.s_nfree == 0) {
 927:         dread(bno, fbuf.data, BSIZE);
 928:         sblock.s_nfree = fbuf.df_nfree;
 929:         for(i=0;i<NICFREE;i++)
 930:             sblock.s_free[i] = fbuf.df_free[i];
 931:     }
 932:     dwrite(bno, zeroes);
 933:     sblock.s_tfree--;
 934:     return(bno);
 935: }
 936: 
 937: /*
 938:  * map a block number into a block address, ensuring
 939:  * all of the correct indirect blocks are around. Allocate
 940:  * the block requested.
 941:  */
 942: daddr_t
 943: bmap(iaddr, bn)
 944: daddr_t iaddr[NADDR];
 945: daddr_t bn;
 946: {
 947:     register i;
 948:     int j, sh;
 949:     daddr_t nb, nnb;
 950:     daddr_t indir[NINDIR];
 951: 
 952:     /*
 953: 	 * blocks 0..NADDR-4 are direct blocks
 954: 	 */
 955:     if(bn < NADDR-3) {
 956:         iaddr[bn] = nb = balloc();
 957:         return(nb);
 958:     }
 959: 
 960:     /*
 961: 	 * addresses NADDR-3, NADDR-2, and NADDR-1
 962: 	 * have single, double, triple indirect blocks.
 963: 	 * the first step is to determine
 964: 	 * how many levels of indirection.
 965: 	 */
 966:     sh = 0;
 967:     nb = 1;
 968:     bn -= NADDR-3;
 969:     for(j=3; j>0; j--) {
 970:         sh += NSHIFT;
 971:         nb <<= NSHIFT;
 972:         if(bn < nb)
 973:             break;
 974:         bn -= nb;
 975:     }
 976:     if(j == 0) {
 977:         return((daddr_t)0);
 978:     }
 979: 
 980:     /*
 981: 	 * fetch the address from the inode
 982: 	 */
 983:     if((nb = iaddr[NADDR-j]) == 0) {
 984:         iaddr[NADDR-j] = nb = balloc();
 985:     }
 986: 
 987:     /*
 988: 	 * fetch through the indirect blocks
 989: 	 */
 990:     for(; j<=3; j++) {
 991:         dread(nb, (char *)indir, BSIZE);
 992:         sh -= NSHIFT;
 993:         i = (bn>>sh) & NMASK;
 994:         nnb = indir[i];
 995:         if(nnb == 0) {
 996:             nnb = balloc();
 997:             indir[i] = nnb;
 998:             dwrite(nb, (char *)indir);
 999:         }
1000:         nb = nnb;
1001:     }
1002:     return(nb);
1003: }
1004: 
1005: /*
1006:  * read the tape into buf, then return whether or
1007:  * or not it is a header block.
1008:  */
1009: gethead(buf)
1010: struct spcl *buf;
1011: {
1012:     readtape((char *)buf);
1013:     if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
1014:         return(0);
1015:     return(1);
1016: }
1017: 
1018: /*
1019:  * return whether or not the buffer contains a header block
1020:  */
1021: ishead(buf)
1022: struct spcl *buf;
1023: {
1024:     if (buf->c_magic != MAGIC || checksum((int *) buf) == 0)
1025:         return(0);
1026:     return(1);
1027: }
1028: 
1029: checktype(b, t)
1030: struct  spcl *b;
1031: int t;
1032: {
1033:     return(b->c_type == t);
1034: }
1035: 
1036: 
1037: checksum(b)
1038: int *b;
1039: {
1040:     register i, j;
1041: 
1042:     j = BSIZE/sizeof(int);
1043:     i = 0;
1044:     do
1045:         i += *b++;
1046:     while (--j);
1047:     if (i != CHECKSUM) {
1048:         printf("Checksum error %o\n", i);
1049:         return(0);
1050:     }
1051:     return(1);
1052: }
1053: 
1054: checkvol(b, t)
1055: struct spcl *b;
1056: int t;
1057: {
1058:     if (b->c_volume == t)
1059:         return(1);
1060:     return(0);
1061: }
1062: 
1063: readhdr(b)
1064: struct  spcl *b;
1065: {
1066:     if (gethead(b) == 0)
1067:         return(0);
1068:     if (checktype(b, TS_TAPE) == 0)
1069:         return(0);
1070:     return(1);
1071: }
1072: 
1073: /*
1074:  * The next routines are called during file extraction to
1075:  * put the data into the right form and place.
1076:  */
1077: #ifndef STANDALONE
1078: xtrfile(b, size)
1079: char    *b;
1080: long    size;
1081: {
1082:     write(ofile, b, (int) size);
1083: }
1084: 
1085: null() {;}
1086: 
1087: skip()
1088: {
1089:     lseek(ofile, (long) BSIZE, 1);
1090: }
1091: #endif
1092: 
1093: 
1094: rstrfile(b, s)
1095: char *b;
1096: long s;
1097: {
1098:     daddr_t d;
1099: 
1100:     d = bmap(taddr, curbno);
1101:     dwrite(d, b);
1102:     curbno += 1;
1103: }
1104: 
1105: rstrskip(b, s)
1106: char *b;
1107: long s;
1108: {
1109:     curbno += 1;
1110: }
1111: 
1112: #ifndef STANDALONE
1113: putdir(b)
1114: char *b;
1115: {
1116:     register struct direct *dp;
1117:     register i;
1118: 
1119:     for (dp = (struct direct *) b, i = 0; i < BSIZE; dp++, i += sizeof(*dp)) {
1120:         if (dp->d_ino == 0)
1121:             continue;
1122:         putent((char *) dp);
1123:     }
1124: }
1125: #endif
1126: 
1127: /*
1128:  * read/write an inode from the disk
1129:  */
1130: getdino(inum, b)
1131: ino_t   inum;
1132: struct  dinode *b;
1133: {
1134:     daddr_t bno;
1135:     char buf[BSIZE];
1136: 
1137:     bno = (inum - 1)/INOPB;
1138:     bno += 2;
1139:     dread(bno, buf, BSIZE);
1140:     copy(&buf[((inum-1)%INOPB)*sizeof(struct dinode)], (char *) b, sizeof(struct dinode));
1141: }
1142: 
1143: putdino(inum, b)
1144: ino_t   inum;
1145: struct  dinode *b;
1146: {
1147:     daddr_t bno;
1148:     char buf[BSIZE];
1149: 
1150:     if (b->di_mode&IFMT)
1151:         sblock.s_tinode--;
1152:     bno = ((inum - 1)/INOPB) + 2;
1153:     dread(bno, buf, BSIZE);
1154:     copy((char *) b, &buf[((inum-1)%INOPB)*sizeof(struct dinode)], sizeof(struct dinode));
1155:     dwrite(bno, buf);
1156: }
1157: 
1158: /*
1159:  * read a bit mask from the tape into m.
1160:  */
1161: readbits(m)
1162: short   *m;
1163: {
1164:     register i;
1165: 
1166:     i = spcl.c_count;
1167: 
1168:     while (i--) {
1169:         readtape((char *) m);
1170: #ifdef  STANDALONE
1171:         if(m)
1172: #endif
1173:         m += (BSIZE/(MLEN/BITS));
1174:     }
1175:     while (gethead(&spcl) == 0)
1176:         ;
1177: }
1178: 
1179: done()
1180: {
1181: #ifndef STANDALONE
1182:     unlink(dirfile);
1183: #endif
1184:     exit(0);
1185: }

Defined functions

balloc defined in line 907; used 3 times
bfree defined in line 884; used 3 times
bmap defined in line 942; used 1 times
checksum defined in line 1037; used 2 times
checktype defined in line 1029; used 14 times
checkvol defined in line 1054; used 4 times
clearbuf defined in line 582; used 2 times
clri defined in line 808; used 2 times
copy defined in line 571; used 6 times
direq defined in line 722; used 2 times
doit defined in line 163; used 2 times
done defined in line 1179; used 3 times
dread defined in line 767; used 6 times
dwrite defined in line 741; used 7 times
flsh defined in line 656; used 1 times
flsht defined in line 566; used 2 times
getdino defined in line 1130; used 2 times
getent defined in line 613; used 1 times
getfile defined in line 470; used 4 times
gethead defined in line 1009; used 12 times
ishead defined in line 1021; used 2 times
itrunc defined in line 824; used 2 times
main defined in line 103; never used
mseek defined in line 649; used 1 times
null defined in line 1085; used 5 times
pass1 defined in line 429; used 1 times
psearch defined in line 693; used 1 times
putdino defined in line 1143; used 2 times
putdir defined in line 1113; used 2 times
putent defined in line 598; used 2 times
readbits defined in line 1161; used 6 times
readc defined in line 640; used 2 times
readhdr defined in line 1063; used 5 times
readtape defined in line 519; used 4 times
rstrfile defined in line 1094; used 2 times
rstrskip defined in line 1105; used 2 times
search defined in line 666; used 1 times
skip defined in line 1087; used 2 times
tloop defined in line 860; used 4 times
writec defined in line 629; used 2 times
xtrfile defined in line 1078; used 2 times

Defined variables

bct defined in line 93; used 5 times
bpt defined in line 75; used 8 times
cache defined in line 100; used 14 times
clrimap defined in line 90; used 3 times
curbno defined in line 85; used 4 times
curcache defined in line 101; used 8 times
curino defined in line 43; used 4 times
df defined in line 55; used 8 times
dino defined in line 82; used 4 times
dirfile defined in line 56; used 6 times
drblock defined in line 74; used 5 times
dumpmap defined in line 88; used 5 times
eflag defined in line 78; used 5 times
fi defined in line 42; used 7 times
ino defined in line 43; used 18 times
ipos defined in line 62; used 2 times
magtape defined in line 47; used 7 times
maxi defined in line 43; used 3 times
mbuf defined in line 49; used 3 times
module defined in line 50; used 1 times
mt defined in line 45; used 10 times
name defined in line 72; used 4 times
ofile defined in line 55; used 4 times
sblock defined in line 40; used 21 times
seekpt defined in line 54; used 2 times
taddr defined in line 83; used 4 times
tapename defined in line 46; used 1 times
  • in line 47
tbf defined in line 94; used 8 times
tino defined in line 82; used 10 times
volno defined in line 80; used 11 times
xtrlist defined in line 70; used 12 times

Defined struct's

cache defined in line 96; never used
xtrlist defined in line 67; never used

Defined macros

BIC defined in line 37; never used
BIS defined in line 36; never used
BIT defined in line 38; used 3 times
BITS defined in line 14; used 1 times
MAXINO defined in line 12; used 2 times
MAXXTR defined in line 15; used 2 times
MBIT defined in line 35; used 3 times
MWORD defined in line 34; used 3 times
NCACHE defined in line 19; used 4 times
ONTAPE defined in line 64; used 1 times
XINUSE defined in line 66; used 1 times
XTRACTD defined in line 65; used 2 times
Last modified: 1983-06-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3300
Valid CSS Valid XHTML 1.0 Strict