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

Defined functions

balloc defined in line 923; used 3 times
bfree defined in line 901; used 3 times
bmap defined in line 957; used 1 times
checksum defined in line 1052; used 2 times
checktype defined in line 1044; used 14 times
checkvol defined in line 1069; used 4 times
clearbuf defined in line 602; used 2 times
clri defined in line 827; used 2 times
copy defined in line 591; used 6 times
direq defined in line 741; used 2 times
doit defined in line 186; used 2 times
done defined in line 1189; used 3 times
dread defined in line 786; used 6 times
dwrite defined in line 760; used 7 times
flsh defined in line 677; used 1 times
flsht defined in line 586; used 2 times
getdino defined in line 1145; used 2 times
getent defined in line 634; used 1 times
getfile defined in line 489; used 3 times
gethead defined in line 1024; used 13 times
ishead defined in line 1036; used 2 times
itrunc defined in line 841; used 2 times
main defined in line 127; never used
mseek defined in line 670; used 1 times
null defined in line 1100; used 2 times
pass1 defined in line 448; used 1 times
psearch defined in line 713; used 1 times
putdino defined in line 1158; used 2 times
putdir defined in line 1128; used 2 times
putent defined in line 619; used 2 times
readbits defined in line 1174; used 5 times
readc defined in line 661; used 2 times
readhdr defined in line 1078; used 5 times
readtape defined in line 543; used 5 times
rstrfile defined in line 1109; used 2 times
rstrskip defined in line 1120; used 2 times
search defined in line 686; used 1 times
skip defined in line 1102; used 2 times
tloop defined in line 877; used 4 times
writec defined in line 650; used 2 times
xtrfile defined in line 1093; used 2 times

Defined variables

bct defined in line 117; used 5 times
bpt defined in line 101; used 8 times
cache defined in line 124; used 14 times
clrimap defined in line 114; used 3 times
curcache defined in line 125; used 8 times
df defined in line 81; used 8 times
dino defined in line 108; used 4 times
dirfile defined in line 82; used 6 times
drblock defined in line 100; used 5 times
dumpmap defined in line 113; used 5 times
eflag defined in line 104; used 5 times
fi defined in line 69; used 7 times
ipos defined in line 88; used 2 times
magtape defined in line 74; used 7 times
mbuf defined in line 76; used 3 times
mt defined in line 72; used 10 times
name defined in line 98; used 4 times
ofile defined in line 81; used 4 times
sblock defined in line 67; used 17 times
sccsid defined in line 1; never used
spcl defined in line 50; used 48 times
tapename defined in line 73; used 1 times
  • in line 74
tbf defined in line 118; used 7 times
tino defined in line 108; used 10 times
volno defined in line 106; used 11 times
xtrlist defined in line 96; used 12 times

Defined struct's

cache defined in line 120; never used
idates defined in line 52; never used
spcl defined in line 37; used 16 times
xtrlist defined in line 93; never used

Defined macros

BIC defined in line 64; never used
BIS defined in line 63; never used
BIT defined in line 65; used 3 times
BITS defined in line 3; used 1 times
CHECKSUM defined in line 36; used 1 times
MAGIC defined in line 35; used 2 times
MAXINO defined in line 2; used 2 times
MAXXTR defined in line 4; used 2 times
MBIT defined in line 62; used 3 times
MLEN defined in line 26; used 3 times
MSIZ defined in line 27; used 2 times
MWORD defined in line 61; used 3 times
NCACHE defined in line 5; used 4 times
NTREC defined in line 25; used 7 times
OBSIZE defined in line 18; used 14 times
OINOPB defined in line 22; never used
ONTAPE defined in line 90; used 1 times
TS_ADDR defined in line 32; used 2 times
TS_BITS defined in line 31; used 3 times
TS_CLRI defined in line 34; used 2 times
TS_END defined in line 33; used 2 times
TS_INODE defined in line 30; used 4 times
TS_TAPE defined in line 29; used 1 times
XINUSE defined in line 92; used 1 times
XTRACTD defined in line 91; used 2 times
Last modified: 1982-10-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4649
Valid CSS Valid XHTML 1.0 Strict