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

Defined functions

balloc defined in line 1018; used 3 times
bfree defined in line 996; used 3 times
bmap defined in line 1052; used 1 times
checksum defined in line 1147; used 2 times
checktype defined in line 1139; used 14 times
checkvol defined in line 1164; used 4 times
clearbuf defined in line 697; used 2 times
clri defined in line 922; used 2 times
copy defined in line 686; used 6 times
direq defined in line 836; used 2 times
doit defined in line 281; used 2 times
done defined in line 1284; used 3 times
dread defined in line 881; used 6 times
dwrite defined in line 855; used 7 times
flsh defined in line 772; used 1 times
flsht defined in line 681; used 2 times
getdino defined in line 1240; used 2 times
getent defined in line 729; used 1 times
getfile defined in line 584; used 3 times
gethead defined in line 1119; used 13 times
ishead defined in line 1131; used 2 times
itrunc defined in line 936; used 2 times
main defined in line 222; never used
mseek defined in line 765; used 1 times
null defined in line 1195; used 2 times
pass1 defined in line 543; used 1 times
psearch defined in line 808; used 1 times
putdino defined in line 1253; used 2 times
putdir defined in line 1223; used 2 times
putent defined in line 714; used 2 times
readbits defined in line 1269; used 5 times
readc defined in line 756; used 2 times
readhdr defined in line 1173; used 5 times
readtape defined in line 638; used 5 times
rstrfile defined in line 1204; used 2 times
rstrskip defined in line 1215; used 2 times
search defined in line 781; used 1 times
skip defined in line 1197; used 2 times
tloop defined in line 972; used 4 times
writec defined in line 745; used 2 times
xtrfile defined in line 1188; used 2 times

Defined variables

bct defined in line 212; used 5 times
bpt defined in line 196; used 8 times
cache defined in line 219; used 14 times
clrimap defined in line 209; used 3 times
curbno defined in line 206; used 4 times
curcache defined in line 220; used 8 times
curino defined in line 165; used 5 times
df defined in line 176; used 8 times
dino defined in line 203; used 4 times
dirfile defined in line 177; used 6 times
drblock defined in line 195; used 5 times
dumpmap defined in line 208; used 5 times
eflag defined in line 199; used 5 times
fi defined in line 164; used 7 times
ino defined in line 165; used 20 times
ipos defined in line 183; used 2 times
magtape defined in line 169; used 7 times
maxi defined in line 165; used 3 times
mbuf defined in line 171; used 3 times
mt defined in line 167; used 10 times
name defined in line 193; used 4 times
ofile defined in line 176; used 4 times
sblock defined in line 162; used 17 times
seekpt defined in line 175; used 2 times
spcl defined in line 136; used 48 times
taddr defined in line 204; used 4 times
tapename defined in line 168; used 1 times
tbf defined in line 213; used 7 times
tino defined in line 203; used 10 times
volno defined in line 201; used 11 times
xtrlist defined in line 191; used 12 times

Defined struct's

cache defined in line 215; never used
dinode defined in line 44; used 26 times
direct defined in line 100; used 6 times
fblk defined in line 64; used 4 times
filsys defined in line 74; used 2 times
  • in line 162(2)
idates defined in line 138; never used
spcl defined in line 123; used 16 times
xtrlist defined in line 188; never used

Defined macros

BIC defined in line 159; never used
BIS defined in line 158; never used
BIT defined in line 160; used 3 times
BITS defined in line 152; used 1 times
BSIZE defined in line 8; used 33 times
CHECKSUM defined in line 122; used 1 times
DIRSIZ defined in line 98; used 4 times
IEXEC defined in line 37; never used
IFBLK defined in line 27; never used
IFCHR defined in line 25; never used
IFDIR defined in line 24; used 2 times
IFLNK defined in line 30; never used
IFMPB defined in line 28; never used
IFMPC defined in line 26; never used
IFMT defined in line 23; used 2 times
IFQUOT defined in line 31; never used
IFREG defined in line 29; used 1 times
INOPB defined in line 57; used 5 times
IREAD defined in line 35; never used
ISGID defined in line 33; never used
ISUID defined in line 32; never used
ISVTX defined in line 34; never used
IWRITE defined in line 36; never used
MAGIC defined in line 121; used 2 times
MAXINO defined in line 150; used 2 times
MAXXTR defined in line 153; used 2 times
MBIT defined in line 157; used 3 times
MLEN defined in line 112; used 3 times
MSIZ defined in line 113; used 2 times
MWORD defined in line 156; used 3 times
NADDR defined in line 20; used 14 times
NCACHE defined in line 154; used 4 times
NICFREE defined in line 14; used 5 times
NICINOD defined in line 13; used 1 times
  • in line 81
NINDIR defined in line 9; used 3 times
NMASK defined in line 10; used 1 times
NSHIFT defined in line 11; used 3 times
NTREC defined in line 111; used 7 times
OBSIZE defined in line 17; used 14 times
OINOPB defined in line 108; never used
ONTAPE defined in line 185; used 1 times
TS_ADDR defined in line 118; used 2 times
TS_BITS defined in line 117; used 3 times
TS_CLRI defined in line 120; used 2 times
TS_END defined in line 119; used 2 times
TS_INODE defined in line 116; used 4 times
TS_TAPE defined in line 115; used 1 times
XINUSE defined in line 187; used 1 times
XTRACTD defined in line 186; used 2 times
s_m defined in line 90; never used
s_n defined in line 91; never used
Last modified: 1987-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 8303
Valid CSS Valid XHTML 1.0 Strict