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

Defined functions

balloc defined in line 824; used 3 times
bfree defined in line 801; used 3 times
bmap defined in line 859; used 3 times
checksum defined in line 965; used 1 times
checktype defined in line 957; used 14 times
checkvol defined in line 982; used 4 times
clri defined in line 731; used 2 times
dcvt defined in line 485; used 2 times
doit defined in line 169; used 2 times
done defined in line 1248; used 3 times
dread defined in line 690; used 6 times
dwrite defined in line 664; used 9 times
flushent defined in line 1092; used 1 times
futz defined in line 1256; used 1 times
getdino defined in line 1199; used 2 times
getfile defined in line 501; used 4 times
gethead defined in line 926; used 12 times
inidbuf defined in line 1181; used 2 times
ishead defined in line 936; used 3 times
itrunc defined in line 742; used 2 times
main defined in line 108; never used
null defined in line 1013; used 5 times
olddirect defined in line 1134; used 1 times
pass1 defined in line 443; used 1 times
psearch defined in line 631; used 1 times
putdino defined in line 1212; used 2 times
putdir defined in line 1043; used 2 times
putent defined in line 1076; used 3 times
rddir defined in line 1101; used 2 times
readbits defined in line 1230; used 6 times
readhdr defined in line 991; used 5 times
readtape defined in line 550; used 4 times
rstrfile defined in line 1022; used 2 times
rstrskip defined in line 1035; used 2 times
search defined in line 602; used 1 times
skip defined in line 1015; used 2 times
tloop defined in line 777; used 4 times
xtrfile defined in line 1006; used 2 times

Defined variables

bct defined in line 96; used 5 times
cache defined in line 103; used 14 times
clrimap defined in line 93; used 3 times
curbno defined in line 88; used 9 times
curcache defined in line 104; used 8 times
curino defined in line 47; used 4 times
cvtflag defined in line 83; used 9 times
df defined in line 60; used 7 times
dino defined in line 85; used 6 times
dirfile defined in line 61; used 7 times
drblock defined in line 80; used 23 times
dumpmap defined in line 91; used 5 times
eflag defined in line 83; used 5 times
fi defined in line 46; used 7 times
ino defined in line 47; used 18 times
ipos defined in line 68; used 2 times
isdir defined in line 83; used 4 times
magtape defined in line 51; used 7 times
maxi defined in line 47; used 3 times
mbuf defined in line 53; used 3 times
module defined in line 54; used 1 times
mt defined in line 49; used 10 times
name defined in line 78; used 3 times
ofile defined in line 60; used 5 times
prev defined in line 59; used 13 times
sblock defined in line 44; used 21 times
seekpt defined in line 58; used 2 times
taddr defined in line 86; used 6 times
tapename defined in line 50; used 1 times
  • in line 51
tbf defined in line 97; used 8 times
tino defined in line 85; used 10 times
volno defined in line 83; used 11 times
xtrlist defined in line 76; used 12 times

Defined struct's

cache defined in line 99; never used
odirect defined in line 39; used 14 times
xtrlist defined in line 73; never used

Defined macros

BIC defined in line 35; never used
BIS defined in line 34; never used
BIT defined in line 36; used 3 times
BITS defined in line 17; used 1 times
MAXINO defined in line 15; used 2 times
MAXXTR defined in line 18; used 2 times
MBIT defined in line 33; used 3 times
MWORD defined in line 32; used 3 times
NCACHE defined in line 19; used 4 times
ODIRSIZ defined in line 38; used 2 times
ONTAPE defined in line 70; used 1 times
XINUSE defined in line 72; used 1 times
XTRACTD defined in line 71; used 2 times
flsht defined in line 20; used 2 times
Last modified: 1995-06-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 7648
Valid CSS Valid XHTML 1.0 Strict