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

Defined functions

balloc defined in line 927; used 3 times
bfree defined in line 905; used 3 times
bmap defined in line 961; used 1 times
checksum defined in line 1056; used 2 times
checktype defined in line 1048; used 14 times
checkvol defined in line 1073; used 4 times
clearbuf defined in line 606; used 2 times
clri defined in line 831; used 2 times
copy defined in line 595; used 6 times
direq defined in line 745; used 2 times
doit defined in line 190; used 2 times
done defined in line 1193; used 3 times
dread defined in line 790; used 6 times
dwrite defined in line 764; used 7 times
flsh defined in line 681; used 1 times
flsht defined in line 590; used 2 times
getdino defined in line 1149; used 2 times
getent defined in line 638; used 1 times
getfile defined in line 493; used 3 times
gethead defined in line 1028; used 13 times
ishead defined in line 1040; used 2 times
itrunc defined in line 845; used 2 times
main defined in line 131; never used
mseek defined in line 674; used 1 times
null defined in line 1104; used 2 times
pass1 defined in line 452; used 1 times
psearch defined in line 717; used 1 times
putdino defined in line 1162; used 2 times
putdir defined in line 1132; used 2 times
putent defined in line 623; used 2 times
readbits defined in line 1178; used 5 times
readc defined in line 665; used 2 times
readhdr defined in line 1082; used 5 times
readtape defined in line 547; used 5 times
rstrfile defined in line 1113; used 2 times
rstrskip defined in line 1124; used 2 times
search defined in line 690; used 1 times
skip defined in line 1106; used 2 times
tloop defined in line 881; used 4 times
writec defined in line 654; used 2 times
xtrfile defined in line 1097; used 2 times

Defined variables

bct defined in line 121; used 5 times
bpt defined in line 105; used 8 times
cache defined in line 128; used 14 times
clrimap defined in line 118; used 3 times
curbno defined in line 115; used 4 times
curcache defined in line 129; used 8 times
curino defined in line 74; used 5 times
df defined in line 85; used 8 times
dino defined in line 112; used 4 times
dirfile defined in line 86; used 6 times
drblock defined in line 104; used 5 times
dumpmap defined in line 117; used 5 times
eflag defined in line 108; used 5 times
fi defined in line 73; used 7 times
ino defined in line 74; used 20 times
ipos defined in line 92; used 2 times
magtape defined in line 78; used 7 times
maxi defined in line 74; used 3 times
mbuf defined in line 80; used 3 times
mt defined in line 76; used 10 times
name defined in line 102; used 4 times
ofile defined in line 85; used 4 times
sblock defined in line 71; used 17 times
seekpt defined in line 84; used 2 times
spcl defined in line 54; used 48 times
taddr defined in line 113; used 4 times
tapename defined in line 77; used 1 times
  • in line 78
tbf defined in line 122; used 7 times
tino defined in line 112; used 10 times
volno defined in line 110; used 11 times
xtrlist defined in line 100; used 12 times

Defined struct's

cache defined in line 124; never used
idates defined in line 56; never used
spcl defined in line 41; used 16 times
xtrlist defined in line 97; never used

Defined macros

BIC defined in line 68; never used
BIS defined in line 67; never used
BIT defined in line 69; used 3 times
BITS defined in line 7; used 1 times
CHECKSUM defined in line 40; used 1 times
MAGIC defined in line 39; used 2 times
MAXINO defined in line 5; used 2 times
MAXXTR defined in line 8; used 2 times
MBIT defined in line 66; used 3 times
MLEN defined in line 30; used 3 times
MSIZ defined in line 31; used 2 times
MWORD defined in line 65; used 3 times
NCACHE defined in line 9; used 4 times
NTREC defined in line 29; used 7 times
OBSIZE defined in line 22; used 14 times
OINOPB defined in line 26; never used
ONTAPE defined in line 94; used 1 times
TS_ADDR defined in line 36; used 2 times
TS_BITS defined in line 35; used 3 times
TS_CLRI defined in line 38; used 2 times
TS_END defined in line 37; used 2 times
TS_INODE defined in line 34; used 4 times
TS_TAPE defined in line 33; used 1 times
XINUSE defined in line 96; used 1 times
XTRACTD defined in line 95; used 2 times
Last modified: 1982-11-02
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3466
Valid CSS Valid XHTML 1.0 Strict