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

Defined functions

balloc defined in line 875; used 3 times
bfree defined in line 853; used 3 times
bmap defined in line 909; used 1 times
checksum defined in line 1004; used 2 times
checktype defined in line 996; used 14 times
checkvol defined in line 1021; used 4 times
clearbuf defined in line 555; used 2 times
clri defined in line 779; used 2 times
copy defined in line 544; used 6 times
direq defined in line 693; used 2 times
doit defined in line 143; used 2 times
done defined in line 1141; used 3 times
dread defined in line 738; used 6 times
dwrite defined in line 712; used 7 times
flsh defined in line 629; used 1 times
flsht defined in line 539; used 2 times
getdino defined in line 1097; used 2 times
getent defined in line 586; used 1 times
getfile defined in line 446; used 3 times
gethead defined in line 976; used 13 times
ishead defined in line 988; used 2 times
itrunc defined in line 793; used 2 times
main defined in line 84; never used
mseek defined in line 622; used 1 times
null defined in line 1052; used 2 times
pass1 defined in line 405; used 1 times
psearch defined in line 665; used 1 times
putdino defined in line 1110; used 2 times
putdir defined in line 1080; used 2 times
putent defined in line 571; used 2 times
readbits defined in line 1126; used 5 times
readc defined in line 613; used 2 times
readhdr defined in line 1030; used 5 times
readtape defined in line 495; used 4 times
rstrfile defined in line 1061; used 2 times
rstrskip defined in line 1072; used 2 times
search defined in line 638; used 1 times
skip defined in line 1054; used 2 times
tloop defined in line 829; used 4 times
writec defined in line 602; used 2 times
xtrfile defined in line 1045; used 2 times

Defined variables

bct defined in line 74; used 5 times
bpt defined in line 58; used 8 times
cache defined in line 81; used 14 times
clrimap defined in line 71; used 3 times
curbno defined in line 68; used 4 times
curcache defined in line 82; used 8 times
curino defined in line 27; used 4 times
df defined in line 38; used 8 times
dino defined in line 65; used 4 times
dirfile defined in line 39; used 6 times
drblock defined in line 57; used 5 times
dumpmap defined in line 70; used 5 times
eflag defined in line 61; used 5 times
fi defined in line 26; used 7 times
ino defined in line 27; used 21 times
ipos defined in line 45; used 2 times
magtape defined in line 31; used 7 times
maxi defined in line 27; used 3 times
mbuf defined in line 33; used 3 times
mt defined in line 29; used 10 times
name defined in line 55; used 4 times
ofile defined in line 38; used 4 times
sblock defined in line 24; used 17 times
seekpt defined in line 37; used 2 times
taddr defined in line 66; used 4 times
tapename defined in line 30; used 1 times
  • in line 31
tbf defined in line 75; used 8 times
tino defined in line 65; used 10 times
volno defined in line 63; used 11 times
xtrlist defined in line 53; used 12 times

Defined struct's

cache defined in line 77; never used
xtrlist defined in line 50; never used

Defined macros

BIC defined in line 21; never used
BIS defined in line 20; never used
BIT defined in line 22; used 3 times
BITS defined in line 2; used 1 times
MAXINO defined in line 1; used 2 times
MAXXTR defined in line 3; used 2 times
MBIT defined in line 19; used 3 times
MWORD defined in line 18; used 3 times
NCACHE defined in line 4; used 4 times
ONTAPE defined in line 47; used 1 times
XINUSE defined in line 49; used 1 times
XTRACTD defined in line 48; used 2 times
Last modified: 1979-05-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2943
Valid CSS Valid XHTML 1.0 Strict