1: static  char *sccsid = "@(#)fsck.c	4.13 (Berkeley) 81/03/09";
   2: #include <stdio.h>
   3: #include <ctype.h>
   4: #include <sys/param.h>
   5: #include <sys/filsys.h>
   6: #include <sys/dir.h>
   7: #include <sys/fblk.h>
   8: #include <sys/ino.h>
   9: #include <sys/inode.h>
  10: #include <sys/stat.h>
  11: #include <fstab.h>
  12: 
  13: typedef int (*SIG_TYP)();
  14: 
  15: #define NDIRECT (BSIZE/sizeof(struct direct))
  16: #define SPERB   (BSIZE/sizeof(short))
  17: 
  18: #define NO  0
  19: #define YES 1
  20: 
  21: #define MAXDUP  10      /* limit on dup blks (per inode) */
  22: #define MAXBAD  10      /* limit on bad blks (per inode) */
  23: 
  24: #define STEPSIZE    9   /* default step for freelist spacing */
  25: #define CYLSIZE     400 /* default cyl size for spacing */
  26: #define MAXCYL      500 /* maximum cylinder size */
  27: 
  28: #define BITSPB  8       /* number bits per byte */
  29: #define BITSHIFT    3   /* log2(BITSPB) */
  30: #define BITMASK 07      /* BITSPB-1 */
  31: #define LSTATE  2       /* bits per inode state */
  32: #define STATEPB (BITSPB/LSTATE) /* inode states per byte */
  33: #define USTATE  0       /* inode not allocated */
  34: #define FSTATE  01      /* inode is file */
  35: #define DSTATE  02      /* inode is directory */
  36: #define CLEAR   03      /* inode is to be cleared */
  37: #define SMASK   03      /* mask for inode state */
  38: 
  39: typedef struct dinode   DINODE;
  40: typedef struct direct   DIRECT;
  41: 
  42: #define ALLOC   ((dp->di_mode & IFMT) != 0)
  43: #define DIR ((dp->di_mode & IFMT) == IFDIR)
  44: #define REG ((dp->di_mode & IFMT) == IFREG)
  45: #define BLK ((dp->di_mode & IFMT) == IFBLK)
  46: #define CHR ((dp->di_mode & IFMT) == IFCHR)
  47: #define MPC ((dp->di_mode & IFMT) == IFMPC)
  48: #define MPB ((dp->di_mode & IFMT) == IFMPB)
  49: #ifdef  UCB_SYMLINKS
  50: #define LNK ((dp->di_mode & IFMT) == IFLNK)
  51: #endif
  52: #ifdef  IFQUOT
  53: #define QUOT    ((dp->di_mode & IFQUOT) == IFQUOT)
  54: #ifdef  UCB_SYMLINKS
  55: #define SPECIAL (BLK || CHR || MPC || MPB || LNK || QUOT)
  56: #else
  57: #define SPECIAL (BLK || CHR || MPC || MPB || QUOT)
  58: #endif
  59: #else
  60: #ifdef  UCB_SYMLINKS
  61: #define SPECIAL (BLK || CHR || MPC || MPB || LNK)
  62: #else
  63: #define SPECIAL (BLK || CHR || MPC || MPB)
  64: #endif
  65: #endif	UCB_QUOTAS
  66: 
  67: #ifdef  NONSEPARATE
  68: #define NINOBLK 5       /* num blks for raw reading */
  69: #else
  70: #define NINOBLK 11      /* num blks for raw reading */
  71: #endif
  72: #define MAXRAW  55      /* largest raw read (in blks) */
  73: daddr_t startib;        /* blk num of first in raw area */
  74: unsigned niblk;         /* num of blks in raw area */
  75: 
  76: struct bufarea {
  77:     struct bufarea  *b_next;        /* must be first */
  78:     daddr_t b_bno;
  79:     union {
  80:         char    b_buf[BSIZE];       /* buffer space */
  81:         short   b_lnks[SPERB];      /* link counts */
  82:         daddr_t b_indir[NINDIR];    /* indirect block */
  83:         struct filsys b_fs;     /* super block */
  84:         struct fblk b_fb;       /* free block */
  85:         struct dinode b_dinode[INOPB];  /* inode block */
  86:         DIRECT b_dir[NDIRECT];      /* directory */
  87:     } b_un;
  88:     char    b_dirty;
  89: };
  90: 
  91: typedef struct bufarea BUFAREA;
  92: 
  93: BUFAREA inoblk;         /* inode blocks */
  94: BUFAREA fileblk;        /* other blks in filesys */
  95: BUFAREA sblk;           /* file system superblock */
  96: BUFAREA *poolhead;      /* ptr to first buffer in pool */
  97: 
  98: #define initbarea(x)    (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1
  99: #define dirty(x)    (x)->b_dirty = 1
 100: #define inodirty()  inoblk.b_dirty = 1
 101: #define fbdirty()   fileblk.b_dirty = 1
 102: #define sbdirty()   sblk.b_dirty = 1
 103: 
 104: #define freeblk     fileblk.b_un.b_fb
 105: #define dirblk      fileblk.b_un
 106: #define superblk    sblk.b_un.b_fs
 107: 
 108: struct filecntl {
 109:     int rfdes;
 110:     int wfdes;
 111:     int mod;
 112:     char    *fname;
 113: };
 114: 
 115: struct filecntl dfile;      /* file descriptors for filesys */
 116: struct filecntl sfile;      /* file descriptors for scratch file */
 117: 
 118: typedef unsigned MEMSIZE;
 119: 
 120: MEMSIZE memsize;        /* amt of memory we got */
 121: #ifdef pdp11
 122: #define MAXDATA ((MEMSIZE)56*1024)
 123: #define MEMUNIT 64          /* granule for sbrk */
 124: #endif
 125: #ifdef vax
 126: #define MAXDATA ((MEMSIZE)400*1024)
 127: #define MEMUNIT 1024            /* granule for sbrk */
 128: #endif
 129: 
 130: #define DUPTBLSIZE  100 /* num of dup blocks to remember */
 131: daddr_t duplist[DUPTBLSIZE];    /* dup block table */
 132: daddr_t *enddup;        /* next entry in dup table */
 133: daddr_t *muldup;        /* multiple dups part of table */
 134: 
 135: #define MAXLNCNT    50  /* num zero link cnts to remember */
 136: ino_t   badlncnt[MAXLNCNT]; /* table of inos with zero link cnts */
 137: ino_t   *badlnp;        /* next entry in table */
 138: 
 139: char    sflag;          /* salvage free block list */
 140: char    csflag;         /* salvage free block list (conditional) */
 141: char    nflag;          /* assume a no response */
 142: char    yflag;          /* assume a yes response */
 143: char    tflag;          /* scratch file specified */
 144: char    preen;          /* just fix normal inconsistencies */
 145: char    rplyflag;       /* any questions asked? */
 146: char    hotroot;        /* checking root device */
 147: char    rawflg;         /* read raw device */
 148: char    rmscr;          /* remove scratch file when done */
 149: char    fixfree;        /* corrupted free list */
 150: char    *membase;       /* base of memory we get */
 151: char    *blkmap;        /* ptr to primary blk allocation map */
 152: char    *freemap;       /* ptr to secondary blk allocation map */
 153: char    *statemap;      /* ptr to inode state table */
 154: char    *pathp;         /* pointer to pathname position */
 155: char    *thisname;      /* ptr to current pathname component */
 156: char    *srchname;      /* name being searched for in dir */
 157: char    pathname[200];
 158: char    scrfile[80];
 159: char    *lfname =   "lost+found";
 160: 
 161: short   *lncntp;        /* ptr to link count table */
 162: 
 163: int startpass = 1;      /* first pass for preen */
 164: int endpass = 30000;    /* last pass for preen */
 165: int cylsize;        /* num blocks per cylinder */
 166: int stepsize;       /* num blocks for spacing purposes */
 167: int badblk;         /* num of bad blks seen (per inode) */
 168: int dupblk;         /* num of dup blks seen (per inode) */
 169: int (*pfunc)();     /* function to call to chk blk */
 170: 
 171: ino_t   inum;           /* inode we are currently working on */
 172: ino_t   imax;           /* number of inodes */
 173: ino_t   parentdir;      /* i number of parent directory */
 174: ino_t   lastino;        /* hiwater mark of inodes */
 175: ino_t   lfdir;          /* lost & found directory */
 176: ino_t   orphan;         /* orphaned inode */
 177: 
 178: off_t   filsize;        /* num blks seen in file */
 179: off_t   maxblk;         /* largest logical blk in file */
 180: off_t   bmapsz;         /* num chars in blkmap */
 181: 
 182: daddr_t tempbase;       /* starting blk of temp file for this pass */
 183: daddr_t bmapblk;        /* starting blk of block map */
 184: daddr_t smapblk;        /* starting blk of state map */
 185: daddr_t lncntblk;       /* starting blk of link cnt table */
 186: daddr_t fmapblk;        /* starting blk of free map */
 187: daddr_t n_free;         /* number of free blocks */
 188: daddr_t n_blks;         /* number of blocks used */
 189: daddr_t n_files;        /* number of files seen */
 190: daddr_t fmin;           /* block number of the first data block */
 191: daddr_t fmax;           /* number of blocks in the volume */
 192: 
 193: #define howmany(x,y)    (((x)+((y)-1))/(y))
 194: #define roundup(x,y)    ((((x)+((y)-1))/(y))*(y))
 195: #define outrange(x) (x < fmin || x >= fmax)
 196: #define zapino(x)   clear((char *)(x),sizeof(DINODE))
 197: 
 198: #define setlncnt(x) dolncnt(x,0)
 199: #define getlncnt()  dolncnt(0,1)
 200: #define declncnt()  dolncnt(0,2)
 201: 
 202: #define setbmap(x)  domap(x,0)
 203: #define getbmap(x)  domap(x,1)
 204: #define clrbmap(x)  domap(x,2)
 205: 
 206: #define setfmap(x)  domap(x,0+4)
 207: #define getfmap(x)  domap(x,1+4)
 208: #define clrfmap(x)  domap(x,2+4)
 209: 
 210: #define setstate(x) dostate(x,0)
 211: #define getstate()  dostate(0,1)
 212: 
 213: #define DATA    1
 214: #define ADDR    0
 215: #define ALTERD  010
 216: #define KEEPON  04
 217: #define SKIP    02
 218: #define STOP    01
 219: 
 220: int (*signal())();
 221: long    lseek();
 222: long    time();
 223: DINODE  *ginode();
 224: BUFAREA *getblk();
 225: BUFAREA *search();
 226: int dirscan();
 227: int findino();
 228: int catch();
 229: int mkentry();
 230: int chgdd();
 231: int pass1();
 232: int pass1b();
 233: int pass2();
 234: int pass3();
 235: int pass4();
 236: int pass5();
 237: 
 238: char    *devname;
 239: 
 240: main(argc,argv)
 241: int argc;
 242: char    *argv[];
 243: {
 244:     register char *p;
 245:     char *sbrk();
 246: 
 247:     sync();
 248:     while(--argc > 0 && **++argv == '-') {
 249:         switch(*++*argv) {
 250:             case 'p':
 251:                 preen++;
 252:                 getpasses(*argv+1);
 253:                 break;
 254:             case 't':
 255:             case 'T':
 256:                 tflag++;
 257:                 if(**++argv == '-' || --argc <= 0)
 258:                     errexit("Bad -t option\n");
 259:                 p = scrfile;
 260:                 while(*p++ = **argv)
 261:                     (*argv)++;
 262:                 break;
 263:             case 's':   /* salvage flag */
 264:                 stype(++*argv);
 265:                 sflag++;
 266:                 break;
 267:             case 'S':   /* conditional salvage */
 268:                 stype(++*argv);
 269:                 csflag++;
 270:                 break;
 271:             case 'n':   /* default no answer flag */
 272:             case 'N':
 273:                 nflag++;
 274:                 yflag = 0;
 275:                 break;
 276:             case 'y':   /* default yes answer flag */
 277:             case 'Y':
 278:                 yflag++;
 279:                 nflag = 0;
 280:                 break;
 281:             default:
 282:                 errexit("%c option?\n",**argv);
 283:         }
 284:     }
 285:     if(nflag && (sflag || csflag))
 286:         errexit("Incompatible options: -n and -%s\n",sflag?"s":"S");
 287:     if(sflag && csflag)
 288:         sflag = 0;
 289:     memsize = (MEMSIZE)sbrk(0);
 290:     memsize = MAXDATA - memsize - sizeof(int);
 291:     while(memsize >= 2*sizeof(BUFAREA) &&
 292:         (membase = sbrk(memsize)) == (char *)-1)
 293:         memsize -= MEMUNIT;
 294:     if(memsize < 2*sizeof(BUFAREA))
 295:         errexit("Can't get memory\n");
 296:     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 297:         signal(SIGINT, catch);
 298:     if(argc) {      /* arg list has file names */
 299:         while(argc-- > 0){
 300:             tempbase = 0;
 301:             hotroot = 0;
 302:             check(*argv++);
 303:         }
 304:     }
 305:     else {          /* use default checklist */
 306:         struct fstab *fsp;
 307:         int pid, passno, anygtr, sumstatus = 0;
 308:         passno = startpass;
 309:         do {
 310:             anygtr = 0;
 311:             tempbase = 0;
 312:             if (setfsent() == 0)
 313:                 errexit("Can't open checklist file: %s\n",
 314:                     FSTAB);
 315:             while ( (fsp = getfsent()) != 0){
 316:                 if (strcmp(fsp->fs_type, FSTAB_RW) &&
 317:                     strcmp(fsp->fs_type, FSTAB_RO))
 318:                     continue;
 319:                 if (preen == 0 ||
 320:                     passno == 1 && fsp->fs_passno == passno) {
 321:                     tempbase = 0;
 322:                     if (blockcheck(fsp->fs_spec) == NO &&
 323:                         preen)
 324:                         exit(8);
 325:                 } else if (fsp->fs_passno > passno)
 326:                     anygtr = 1;
 327:                 else if (fsp->fs_passno == passno) {
 328:                     if (((devname=namecheck(fsp->fs_spec))==NO)
 329:                       || (setup(devname)==NO)) {
 330:                         sumstatus |=8;
 331:                         continue;
 332:                     }
 333:                     pid = fork();
 334:                     if (pid < 0) {
 335:                         perror("fork");
 336:                         closefils();
 337:                         sumstatus |=8;
 338:                         continue;
 339:                     }
 340:                     if (pid == 0) {
 341:                         check1(devname);
 342:                         exit(0);
 343:                     }
 344:                     closefils();
 345:                 }
 346:             }
 347:             if (preen) {
 348:                 int status;
 349:                 while (wait(&status) != -1)
 350:                     sumstatus |= status;
 351:             }
 352:             passno++;
 353:         } while (anygtr && passno<=endpass);
 354:         if(rmscr) {
 355:             unlink(scrfile);
 356:             rmscr = 0;
 357:         }
 358:         if (sumstatus)
 359:             exit(8);
 360:         endfsent();
 361:     }
 362:     exit(0);
 363: }
 364: 
 365: getpasses(s)
 366: char *s;
 367: {
 368:     register char *p;
 369: 
 370:     for (p = s; *p; p++)
 371:         if (*p == '-')
 372:             break;
 373:     if (*p == '-') {
 374:         *p = '\0';
 375:         if (*(p+1))
 376:             endpass = atoi(p+1);
 377:         if (*s)
 378:             startpass = atoi(s);
 379:         *p = '-';
 380:     } else if (*s)
 381:         startpass = atoi(s);
 382:     if (startpass <= 0 || startpass > endpass)
 383:         errexit("-p: invalid pass numbers\n");
 384: }
 385: 
 386: char *namecheck(), *rawname(), *rindex(), *unrawname();
 387: 
 388: blockcheck(name)
 389:     char    *name;
 390: {
 391:     char *dev;
 392:     if (dev = namecheck(name)) {
 393:         check(dev);
 394:         return(YES);
 395:     } else
 396:         return(NO);
 397: }
 398: 
 399: char *
 400: namecheck(name)
 401:     char    *name;
 402: {
 403:     struct  stat    stat_slash, stat_block, stat_char;
 404:     char    *raw;
 405:     int looped = 0;
 406: 
 407:     hotroot = 0;
 408:     if (stat("/", &stat_slash) < 0){
 409:         error("Can't stat root\n");
 410:         return(NULL);
 411:     }
 412:   retry:
 413:     if (stat(name, &stat_block) < 0){
 414:         error("Can't stat %s\n", name);
 415:         return(NULL);
 416:     }
 417:     if (stat_block.st_mode & S_IFBLK){
 418:         raw = rawname(name);
 419:         if (stat(raw, &stat_char) < 0){
 420:             error("Can't stat %s\n", raw);
 421:             return(NULL);
 422:         }
 423:         if (stat_char.st_mode & S_IFCHR){
 424:             if (stat_slash.st_dev == stat_block.st_rdev) {
 425:                 hotroot++;
 426:                 raw = unrawname(name);
 427:             }
 428:             return(raw);
 429:         } else {
 430:             error("%s is not a character device\n", raw);
 431:             return(NULL);
 432:         }
 433:     } else
 434:     if (stat_block.st_mode & S_IFCHR){
 435:         if (looped) {
 436:             error("Can't make sense out of name %s\n", name);
 437:             return(NULL);
 438:         }
 439:         name = unrawname(name);
 440:         looped++;
 441:         goto retry;
 442:     }
 443:     error("Can't make sense out of name %s\n", name);
 444:     return(NULL);
 445: }
 446: 
 447: char *
 448: unrawname(cp)
 449:     char    *cp;
 450: {
 451:     char    *dp = rindex(cp, '/');
 452:     struct stat stb;
 453:     if (dp == 0)
 454:         return(cp);
 455:     if (stat(cp, &stb) < 0)
 456:         return(cp);
 457:     if ((stb.st_mode&S_IFMT) != S_IFCHR)
 458:         return(cp);
 459:     if (*(dp+1) != 'r')
 460:         return(cp);
 461:     strcpy(dp+1, dp+2);
 462:     return(cp);
 463: }
 464: 
 465: char *
 466: rawname(cp)
 467:     char *cp;
 468: {
 469:     static char rawbuf[32];
 470:     char *dp = rindex(cp, '/');
 471: 
 472:     if (dp == 0)
 473:         return (0);
 474:     *dp = 0;
 475:     strcpy(rawbuf, cp);
 476:     *dp = '/';
 477:     strcat(rawbuf, "/r");
 478:     strcat(rawbuf, dp+1);
 479:     return (rawbuf);
 480: }
 481: 
 482: check(dev)
 483: char *dev;
 484: {
 485: 
 486:     devname = dev;
 487:     if(setup(dev) == NO)
 488:         return;
 489:     check1(dev);
 490:     if(rmscr) {
 491:         unlink(scrfile);
 492:         rmscr = 0;
 493:     }
 494:     devname = 0;
 495: }
 496: 
 497: check1(dev)
 498: char *dev;
 499: {
 500:     register DINODE *dp;
 501:     register n;
 502:     register ino_t *blp;
 503:     ino_t savino;
 504:     daddr_t blk;
 505:     BUFAREA *bp1, *bp2;
 506: 
 507:     if (preen==0) {
 508:         printf("** Checking %s\n", dev);
 509:         printf("** Phase 1 - Check Blocks and Sizes\n");
 510:     }
 511:     pfunc = pass1;
 512:     for(inum = 1; inum <= imax; inum++) {
 513:         if((dp = ginode()) == NULL)
 514:             continue;
 515:         if(ALLOC) {
 516:             lastino = inum;
 517:             if(ftypeok(dp) == NO) {
 518:                 pfatal("UNKNOWN FILE TYPE I=%u",inum);
 519:                 if(reply("CLEAR") == YES) {
 520:                     zapino(dp);
 521:                     inodirty();
 522:                 }
 523:                 continue;
 524:             }
 525:             n_files++;
 526:             if(setlncnt(dp->di_nlink) <= 0) {
 527:                 if(badlnp < &badlncnt[MAXLNCNT])
 528:                     *badlnp++ = inum;
 529:                 else {
 530:                     pfatal("LINK COUNT TABLE OVERFLOW");
 531:                     if(reply("CONTINUE") == NO)
 532:                         errexit("");
 533:                 }
 534:             }
 535:             setstate(DIR ? DSTATE : FSTATE);
 536:             badblk = dupblk = 0;
 537:             filsize = 0;
 538:             maxblk = 0;
 539:             ckinode(dp,ADDR);
 540:             if((n = getstate()) == DSTATE || n == FSTATE)
 541:                 sizechk(dp);
 542:         }
 543:         else if(dp->di_mode != 0) {
 544:             pfatal("PARTIALLY ALLOCATED INODE I=%u",inum);
 545:             if(reply("CLEAR") == YES) {
 546:                 zapino(dp);
 547:                 inodirty();
 548:             }
 549:         }
 550:     }
 551: 
 552: 
 553:     if(enddup != &duplist[0]) {
 554:         if (preen)
 555:             pfatal("INTERNAL ERROR: dups with -p");
 556:         printf("** Phase 1b - Rescan For More DUPS\n");
 557:         pfunc = pass1b;
 558:         for(inum = 1; inum <= lastino; inum++) {
 559:             if(getstate() != USTATE && (dp = ginode()) != NULL)
 560:                 if(ckinode(dp,ADDR) & STOP)
 561:                     break;
 562:         }
 563:     }
 564:     if(rawflg) {
 565:         if(inoblk.b_dirty)
 566:             bwrite(&dfile,membase,startib,(int)niblk*BSIZE);
 567:         inoblk.b_dirty = 0;
 568:         if(poolhead) {
 569:             clear(membase,niblk*BSIZE);
 570:             for(bp1 = poolhead;bp1->b_next;bp1 = bp1->b_next);
 571:             bp2 = &((BUFAREA *)membase)[(niblk*BSIZE)/sizeof(BUFAREA)];
 572:             while(--bp2 >= (BUFAREA *)membase) {
 573:                 initbarea(bp2);
 574:                 bp2->b_next = bp1->b_next;
 575:                 bp1->b_next = bp2;
 576:             }
 577:         }
 578:         rawflg = 0;
 579: 
 580:     }
 581: 
 582: 
 583:     if (preen == 0)
 584:         printf("** Phase 2 - Check Pathnames\n");
 585:     inum = ROOTINO;
 586:     thisname = pathp = pathname;
 587:     pfunc = pass2;
 588:     switch(getstate()) {
 589:         case USTATE:
 590:             errexit("ROOT INODE UNALLOCATED. TERMINATING.\n");
 591:         case FSTATE:
 592:             pfatal("ROOT INODE NOT DIRECTORY");
 593:             if(reply("FIX") == NO || (dp = ginode()) == NULL)
 594:                 errexit("");
 595:             dp->di_mode &= ~IFMT;
 596:             dp->di_mode |= IFDIR;
 597:             inodirty();
 598:             setstate(DSTATE);
 599:         case DSTATE:
 600:             descend();
 601:             break;
 602:         case CLEAR:
 603:             pfatal("DUPS/BAD IN ROOT INODE");
 604:             printf("\n");
 605:             if(reply("CONTINUE") == NO)
 606:                 errexit("");
 607:             setstate(DSTATE);
 608:             descend();
 609:     }
 610: 
 611: 
 612:     if (preen == 0)
 613:         printf("** Phase 3 - Check Connectivity\n");
 614:     for(inum = ROOTINO; inum <= lastino; inum++) {
 615:         if(getstate() == DSTATE) {
 616:             pfunc = findino;
 617:             srchname = "..";
 618:             savino = inum;
 619:             do {
 620:                 orphan = inum;
 621:                 if((dp = ginode()) == NULL)
 622:                     break;
 623:                 filsize = dp->di_size;
 624:                 parentdir = 0;
 625:                 ckinode(dp,DATA);
 626:                 if((inum = parentdir) == 0)
 627:                     break;
 628:             } while(getstate() == DSTATE);
 629:             inum = orphan;
 630:             if(linkup() == YES) {
 631:                 thisname = pathp = pathname;
 632:                 *pathp++ = '?';
 633:                 pfunc = pass2;
 634:                 descend();
 635:             }
 636:             inum = savino;
 637:         }
 638:     }
 639: 
 640: 
 641:     if (preen == 0)
 642:         printf("** Phase 4 - Check Reference Counts\n");
 643:     pfunc = pass4;
 644:     for(inum = ROOTINO; inum <= lastino; inum++) {
 645:         switch(getstate()) {
 646:             case FSTATE:
 647:                 if(n = getlncnt())
 648:                     adjust((short)n);
 649:                 else {
 650:                     for(blp = badlncnt;blp < badlnp; blp++)
 651:                         if(*blp == inum) {
 652:                             clri("UNREF",YES);
 653:                             break;
 654:                         }
 655:                 }
 656:                 break;
 657:             case DSTATE:
 658:                 clri("UNREF",YES);
 659:                 break;
 660:             case CLEAR:
 661:                 clri("BAD/DUP",YES);
 662:         }
 663:     }
 664:     if(imax - n_files != superblk.s_tinode) {
 665:         pwarn("FREE INODE COUNT WRONG IN SUPERBLK");
 666:         if (preen)
 667:             printf(" (FIXED)\n");
 668:         if (preen || reply("FIX") == YES) {
 669:             superblk.s_tinode = imax - n_files;
 670:             sbdirty();
 671:         }
 672:     }
 673:     flush(&dfile,&fileblk);
 674: 
 675: 
 676:     if (preen == 0)
 677:         printf("** Phase 5 - Check Free List ");
 678:     if(sflag || (csflag && rplyflag == 0)) {
 679:         if (preen == 0)
 680:             printf("(Ignored)\n");
 681:         fixfree = 1;
 682:     }
 683:     else {
 684:         if (preen == 0)
 685:             printf("\n");
 686:         ifreechk();
 687:         if(freemap)
 688:             copy(blkmap,freemap,(MEMSIZE)bmapsz);
 689:         else {
 690:             for(blk = 0; blk < fmapblk-bmapblk; blk++) {
 691:                 bp1 = getblk((BUFAREA *)NULL,blk+bmapblk);
 692:                 bp2 = getblk((BUFAREA *)NULL,blk+fmapblk);
 693:                 copy(bp1->b_un.b_buf,bp2->b_un.b_buf,BSIZE);
 694:                 dirty(bp2);
 695:             }
 696:         }
 697:         badblk = dupblk = 0;
 698:         freeblk.df_nfree = superblk.s_nfree;
 699:         for(n = 0; n < NICFREE; n++)
 700:             freeblk.df_free[n] = superblk.s_free[n];
 701:         freechk();
 702:         if(badblk) {
 703:             pfatal("%d BAD BLKS IN FREE LIST",badblk);
 704:             printf("\n");
 705:         }
 706:         if(dupblk)
 707:             pwarn("%d DUP BLKS IN FREE LIST\n",dupblk);
 708:         if(fixfree == 0) {
 709:             if((n_blks+n_free) != (fmax-fmin)) {
 710:                 pwarn("%ld BLK(S) MISSING\n",
 711:                     fmax-fmin-n_blks-n_free);
 712:                 fixfree = 1;
 713:             }
 714:             else if(n_free != superblk.s_tfree) {
 715:                 pwarn("FREE BLK COUNT WRONG IN SUPERBLK");
 716:                 if (preen)
 717:                     printf(" (FIXED)\n");
 718:                 if(preen || reply("FIX") == YES) {
 719:                     superblk.s_tfree = n_free;
 720:                     sbdirty();
 721:                 }
 722:             }
 723:         }
 724:         if(fixfree) {
 725:             pwarn("BAD FREE LIST");
 726:             if (preen)
 727:                 printf(" (SALVAGED)\n");
 728:             else if(reply("SALVAGE") == NO)
 729:                 fixfree = 0;
 730:         }
 731:     }
 732: 
 733: 
 734:     if(fixfree) {
 735:         if (preen == 0)
 736:             printf("** Phase 6 - Salvage Free List\n");
 737:         makefree();
 738:         n_free = superblk.s_tfree;
 739:     }
 740: 
 741: 
 742:     pwarn("%ld files %ld blocks %ld free\n", n_files,n_blks,n_free);
 743:     if(dfile.mod) {
 744:         time(&superblk.s_time);
 745:         sbdirty();
 746:     }
 747:     ckfini();
 748: #ifndef VMUNIX
 749:     if(dfile.mod && hotroot) {
 750:         if (preen)
 751:             exit(4);
 752:         else {
 753:             printf("\n***** BOOT UNIX (NO SYNC!) *****\n");
 754:             for(;;);
 755:         }
 756:     }
 757: #endif
 758:     sync();
 759:     if(dfile.mod && preen == 0)
 760:         printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
 761: }
 762: 
 763: /* VARARGS1 */
 764: error(s1,s2,s3,s4)
 765: char *s1;
 766: {
 767:     printf(s1,s2,s3,s4);
 768: }
 769: 
 770: /* VARARGS1 */
 771: errexit(s1,s2,s3,s4)
 772: char *s1;
 773: {
 774:     error(s1,s2,s3,s4);
 775:     exit(8);
 776: }
 777: 
 778: /*
 779:  * Pfatal is called when an inconsistency occurs
 780:  * which should not happen during normal operations.
 781:  * It prints a message and then dies.
 782:  * When not preening, this is just a printf.
 783:  */
 784: /* VARARGS1 */
 785: pfatal(s,a1,a2,a3,a4)
 786: {
 787: 
 788:     if (preen) {
 789:         printf("%s: ", devname);
 790:         printf(s, a1, a2, a3, a4);
 791:         printf("\n");
 792:         preendie();
 793:     }
 794:     printf(s, a1, a2, a3, a4);
 795: }
 796: 
 797: /*
 798:  * Fatal is called to terminate preening
 799:  * due to unexplainable inconsistency.
 800:  */
 801: preendie()
 802: {
 803: 
 804:     printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname);
 805:     exit(8);
 806: }
 807: 
 808: /*
 809:  * Pwarn is like printf when not preening,
 810:  * or a warning (preceded by filename) when preening.
 811:  */
 812: /* VARARGS1 */
 813: pwarn(s,a1,a2,a3,a4,a5,a6)
 814: {
 815: 
 816:     if (preen)
 817:         printf("%s: ", devname);
 818:     printf(s, a1, a2, a3, a4, a5, a6);
 819: }
 820: 
 821: ckinode(dp,flg)
 822: DINODE *dp;
 823: register flg;
 824: {
 825:     register daddr_t *ap;
 826:     register ret;
 827:     int (*func)(), n;
 828:     daddr_t iaddrs[NADDR];
 829: 
 830:     if(SPECIAL)
 831:         return(KEEPON);
 832:     l3tol(iaddrs,dp->di_addr,NADDR);
 833:     func = (flg == ADDR) ? pfunc : dirscan;
 834:     for(ap = iaddrs; ap < &iaddrs[NADDR-3]; ap++) {
 835:         if(*ap && (ret = (*func)(*ap)) & STOP)
 836:             return(ret);
 837:     }
 838:     for(n = 1; n < 4; n++) {
 839:         if(*ap && (ret = iblock(*ap,n,flg)) & STOP)
 840:             return(ret);
 841:         ap++;
 842:     }
 843:     return(KEEPON);
 844: }
 845: 
 846: 
 847: iblock(blk,ilevel,flg)
 848: daddr_t blk;
 849: register ilevel;
 850: {
 851:     register daddr_t *ap;
 852:     register n;
 853:     int (*func)();
 854:     BUFAREA ib;
 855: 
 856:     if(flg == ADDR) {
 857:         func = pfunc;
 858:         if(((n = (*func)(blk)) & KEEPON) == 0)
 859:             return(n);
 860:     }
 861:     else
 862:         func = dirscan;
 863:     if(outrange(blk))       /* protect thyself */
 864:         return(SKIP);
 865:     initbarea(&ib);
 866:     if(getblk(&ib,blk) == NULL)
 867:         return(SKIP);
 868:     ilevel--;
 869:     for(ap = ib.b_un.b_indir; ap < &ib.b_un.b_indir[NINDIR]; ap++) {
 870:         if(*ap) {
 871:             if(ilevel > 0) {
 872:                 n = iblock(*ap,ilevel,flg);
 873:             }
 874:             else
 875:                 n = (*func)(*ap);
 876:             if(n & STOP)
 877:                 return(n);
 878:         }
 879:     }
 880:     return(KEEPON);
 881: }
 882: 
 883: 
 884: pass1(blk)
 885: daddr_t blk;
 886: {
 887:     register daddr_t *dlp;
 888: 
 889:     if(outrange(blk)) {
 890:         blkerr("BAD",blk);
 891:         if(++badblk >= MAXBAD) {
 892:             printf("EXCESSIVE BAD BLKS I=%u",inum);
 893:             if(reply("CONTINUE") == NO)
 894:                 errexit("");
 895:             return(STOP);
 896:         }
 897:         return(SKIP);
 898:     }
 899:     if(getbmap(blk)) {
 900:         blkerr("DUP",blk);
 901:         if(++dupblk >= MAXDUP) {
 902:             printf("EXCESSIVE DUP BLKS I=%u",inum);
 903:             if(reply("CONTINUE") == NO)
 904:                 errexit("");
 905:             return(STOP);
 906:         }
 907:         if(enddup >= &duplist[DUPTBLSIZE]) {
 908:             printf("DUP TABLE OVERFLOW.");
 909:             if(reply("CONTINUE") == NO)
 910:                 errexit("");
 911:             return(STOP);
 912:         }
 913:         for(dlp = duplist; dlp < muldup; dlp++) {
 914:             if(*dlp == blk) {
 915:                 *enddup++ = blk;
 916:                 break;
 917:             }
 918:         }
 919:         if(dlp >= muldup) {
 920:             *enddup++ = *muldup;
 921:             *muldup++ = blk;
 922:         }
 923:     }
 924:     else {
 925:         n_blks++;
 926:         setbmap(blk);
 927:     }
 928:     filsize++;
 929:     return(KEEPON);
 930: }
 931: 
 932: 
 933: pass1b(blk)
 934: daddr_t blk;
 935: {
 936:     register daddr_t *dlp;
 937: 
 938:     if(outrange(blk))
 939:         return(SKIP);
 940:     for(dlp = duplist; dlp < muldup; dlp++) {
 941:         if(*dlp == blk) {
 942:             blkerr("DUP",blk);
 943:             *dlp = *--muldup;
 944:             *muldup = blk;
 945:             return(muldup == duplist ? STOP : KEEPON);
 946:         }
 947:     }
 948:     return(KEEPON);
 949: }
 950: 
 951: 
 952: pass2(dirp)
 953: register DIRECT *dirp;
 954: {
 955:     register char *p;
 956:     register n;
 957:     DINODE *dp;
 958: 
 959:     if((inum = dirp->d_ino) == 0)
 960:         return(KEEPON);
 961:     thisname = pathp;
 962:     for(p = dirp->d_name; p < &dirp->d_name[DIRSIZ]; )
 963:         if((*pathp++ = *p++) == 0) {
 964:             --pathp;
 965:             break;
 966:         }
 967:     *pathp = 0;
 968:     n = NO;
 969:     if(inum > imax || inum < ROOTINO)
 970:         n = direrr("I OUT OF RANGE");
 971:     else {
 972:     again:
 973:         switch(getstate()) {
 974:             case USTATE:
 975:                 n = direrr("UNALLOCATED");
 976:                 break;
 977:             case CLEAR:
 978:                 if((n = direrr("DUP/BAD")) == YES)
 979:                     break;
 980:                 if((dp = ginode()) == NULL)
 981:                     break;
 982:                 setstate(DIR ? DSTATE : FSTATE);
 983:                 goto again;
 984:             case FSTATE:
 985:                 declncnt();
 986:                 break;
 987:             case DSTATE:
 988:                 declncnt();
 989:                 descend();
 990:         }
 991:     }
 992:     pathp = thisname;
 993:     if(n == NO)
 994:         return(KEEPON);
 995:     dirp->d_ino = 0;
 996:     return(KEEPON|ALTERD);
 997: }
 998: 
 999: 
1000: pass4(blk)
1001: daddr_t blk;
1002: {
1003:     register daddr_t *dlp;
1004: 
1005:     if(outrange(blk))
1006:         return(SKIP);
1007:     if(getbmap(blk)) {
1008:         for(dlp = duplist; dlp < enddup; dlp++)
1009:             if(*dlp == blk) {
1010:                 *dlp = *--enddup;
1011:                 return(KEEPON);
1012:             }
1013:         clrbmap(blk);
1014:         n_blks--;
1015:     }
1016:     return(KEEPON);
1017: }
1018: 
1019: 
1020: pass5(blk)
1021: daddr_t blk;
1022: {
1023:     if(outrange(blk)) {
1024:         fixfree = 1;
1025:         if (preen)
1026:             pfatal("BAD BLOCKS IN FREE LIST.");
1027:         if(++badblk >= MAXBAD) {
1028:             printf("EXCESSIVE BAD BLKS IN FREE LIST.");
1029:             if(reply("CONTINUE") == NO)
1030:                 errexit("");
1031:             return(STOP);
1032:         }
1033:         return(SKIP);
1034:     }
1035:     if(getfmap(blk)) {
1036:         fixfree = 1;
1037:         if(++dupblk >= DUPTBLSIZE) {
1038:             printf("EXCESSIVE DUP BLKS IN FREE LIST.");
1039:             if(reply("CONTINUE") == NO)
1040:                 errexit("");
1041:             return(STOP);
1042:         }
1043:     }
1044:     else {
1045:         n_free++;
1046:         setfmap(blk);
1047:     }
1048:     return(KEEPON);
1049: }
1050: 
1051: 
1052: blkerr(s,blk)
1053: daddr_t blk;
1054: char *s;
1055: {
1056:     pfatal("%ld %s I=%u",blk,s,inum);
1057:     printf("\n");
1058:     setstate(CLEAR);    /* mark for possible clearing */
1059: }
1060: 
1061: 
1062: descend()
1063: {
1064:     register DINODE *dp;
1065:     register char *savname;
1066:     off_t savsize;
1067: 
1068:     setstate(FSTATE);
1069:     if((dp = ginode()) == NULL)
1070:         return;
1071:     savname = thisname;
1072:     *pathp++ = '/';
1073:     savsize = filsize;
1074:     filsize = dp->di_size;
1075:     ckinode(dp,DATA);
1076:     thisname = savname;
1077:     *--pathp = 0;
1078:     filsize = savsize;
1079: }
1080: 
1081: 
1082: dirscan(blk)
1083: daddr_t blk;
1084: {
1085:     register DIRECT *dirp;
1086:     register char *p1, *p2;
1087:     register n;
1088:     DIRECT direntry;
1089: 
1090:     if(outrange(blk)) {
1091:         filsize -= BSIZE;
1092:         return(SKIP);
1093:     }
1094:     for(dirp = dirblk.b_dir; dirp < &dirblk.b_dir[NDIRECT] &&
1095:         filsize > 0; dirp++, filsize -= sizeof(DIRECT)) {
1096:         if(getblk(&fileblk,blk) == NULL) {
1097:             filsize -= (&dirblk.b_dir[NDIRECT]-dirp)*sizeof(DIRECT);
1098:             return(SKIP);
1099:         }
1100:         p1 = &dirp->d_name[DIRSIZ];
1101:         p2 = &direntry.d_name[DIRSIZ];
1102:         while(p1 > (char *)dirp)
1103:             *--p2 = *--p1;
1104:         if((n = (*pfunc)(&direntry)) & ALTERD) {
1105:             if(getblk(&fileblk,blk) != NULL) {
1106:                 p1 = &dirp->d_name[DIRSIZ];
1107:                 p2 = &direntry.d_name[DIRSIZ];
1108:                 while(p1 > (char *)dirp)
1109:                     *--p1 = *--p2;
1110:                 fbdirty();
1111:             }
1112:             else
1113:                 n &= ~ALTERD;
1114:         }
1115:         if(n & STOP)
1116:             return(n);
1117:     }
1118:     return(filsize > 0 ? KEEPON : STOP);
1119: }
1120: 
1121: 
1122: direrr(s)
1123: char *s;
1124: {
1125:     register DINODE *dp;
1126: 
1127:     pwarn("%s ",s);
1128:     pinode();
1129:     printf("\n");
1130:     if((dp = ginode()) != NULL && ftypeok(dp))
1131:         pfatal("%s=%s",DIR?"DIR":"FILE",pathname);
1132:     else
1133:         pfatal("NAME=%s",pathname);
1134:     return(reply("REMOVE"));
1135: }
1136: 
1137: 
1138: adjust(lcnt)
1139: register short lcnt;
1140: {
1141:     register DINODE *dp;
1142: 
1143:     if((dp = ginode()) == NULL)
1144:         return;
1145:     if(dp->di_nlink == lcnt) {
1146:         if(linkup() == NO)
1147:             clri("UNREF",NO);
1148:     }
1149:     else {
1150:         pwarn("LINK COUNT %s",
1151:             (lfdir==inum)?lfname:(DIR?"DIR":"FILE"));
1152:         pinode();
1153:         printf(" COUNT %d SHOULD BE %d",
1154:             dp->di_nlink,dp->di_nlink-lcnt);
1155:         if (preen) {
1156:             if (lcnt < 0) {
1157:                 printf("\n");
1158:                 preendie();
1159:             }
1160:             printf(" (ADJUSTED)\n");
1161:         }
1162:         if(preen || reply("ADJUST") == YES) {
1163:             dp->di_nlink -= lcnt;
1164:             inodirty();
1165:         }
1166:     }
1167: }
1168: 
1169: 
1170: clri(s,flg)
1171: char *s;
1172: {
1173:     register DINODE *dp;
1174: 
1175:     if((dp = ginode()) == NULL)
1176:         return;
1177:     if(flg == YES) {
1178:         pwarn("%s %s",s,DIR?"DIR":"FILE");
1179:         pinode();
1180:     }
1181:     if(preen || reply("CLEAR") == YES) {
1182:         if (preen)
1183:             printf(" (CLEARED)\n");
1184:         n_files--;
1185:         pfunc = pass4;
1186:         ckinode(dp,ADDR);
1187:         zapino(dp);
1188:         inodirty();
1189:     }
1190: }
1191: 
1192: 
1193: setup(dev)
1194: char *dev;
1195: {
1196:     register n;
1197:     register BUFAREA *bp;
1198:     register MEMSIZE msize;
1199:     char *mbase;
1200:     daddr_t bcnt, nscrblk;
1201:     dev_t rootdev;
1202:     off_t smapsz, lncntsz, totsz;
1203:     struct stat statarea;
1204: 
1205:     if(stat("/",&statarea) < 0)
1206:         errexit("Can't stat root\n");
1207:     rootdev = statarea.st_dev;
1208:     if(stat(dev,&statarea) < 0) {
1209:         error("Can't stat %s\n",dev);
1210:         return(NO);
1211:     }
1212:     rawflg = 0;
1213:     if((statarea.st_mode & S_IFMT) == S_IFBLK)
1214:         ;
1215:     else if((statarea.st_mode & S_IFMT) == S_IFCHR)
1216:         rawflg++;
1217:     else {
1218:         pfatal("file is not a block or character device");
1219:         if (reply("OK") == NO)
1220:             return(NO);
1221:     }
1222:     if(rootdev == statarea.st_rdev)
1223:         hotroot++;
1224:     if((dfile.rfdes = open(dev,0)) < 0) {
1225:         error("Can't open %s\n",dev);
1226:         return(NO);
1227:     }
1228:     if (preen == 0)
1229:         printf("\n%s",dev);
1230:     if(nflag || (dfile.wfdes = open(dev,1)) < 0) {
1231:         dfile.wfdes = -1;
1232:         if (preen)
1233:             pfatal("NO WRITE ACCESS");
1234:         printf(" (NO WRITE)");
1235:     }
1236:     dfile.fname = dev;
1237:     if (preen == 0)
1238:         printf("\n");
1239:     fixfree = 0;
1240:     dfile.mod = 0;
1241:     n_files = n_blks = n_free = 0;
1242:     muldup = enddup = &duplist[0];
1243:     badlnp = &badlncnt[0];
1244:     lfdir = 0;
1245:     rplyflag = 0;
1246:     initbarea(&sblk);
1247:     initbarea(&fileblk);
1248:     initbarea(&inoblk);
1249:     sfile.wfdes = sfile.rfdes = -1;
1250:     if(getblk(&sblk,SUPERB) == NULL) {
1251:         ckfini();
1252:         return(NO);
1253:     }
1254:     imax = ((ino_t)superblk.s_isize - (SUPERB+1)) * INOPB;
1255:     fmin = (daddr_t)superblk.s_isize;   /* first data blk num */
1256:     fmax = superblk.s_fsize;        /* first invalid blk num */
1257:     if(fmin >= fmax ||
1258:         (imax/INOPB) != ((ino_t)superblk.s_isize-(SUPERB+1))) {
1259:         pfatal("Size check: fsize %ld isize %d",
1260:             superblk.s_fsize,superblk.s_isize);
1261:         printf("\n");
1262:         ckfini();
1263:         return(NO);
1264:     }
1265:     if (preen == 0)
1266:         printf("File System: %.12s\n\n", superblk.s_fsmnt);
1267:     bmapsz = roundup(howmany(fmax,BITSPB),sizeof(*lncntp));
1268:     smapsz = roundup(howmany((long)(imax+1),STATEPB),sizeof(*lncntp));
1269:     lncntsz = (long)(imax+1) * sizeof(*lncntp);
1270:     if(bmapsz > smapsz+lncntsz)
1271:         smapsz = bmapsz-lncntsz;
1272:     totsz = bmapsz+smapsz+lncntsz;
1273:     msize = memsize;
1274:     mbase = membase;
1275:     if(rawflg) {
1276:         if(msize < (MEMSIZE)(NINOBLK*BSIZE) + 2*sizeof(BUFAREA))
1277:             rawflg = 0;
1278:         else {
1279:             msize -= (MEMSIZE)NINOBLK*BSIZE;
1280:             mbase += (MEMSIZE)NINOBLK*BSIZE;
1281:             niblk = NINOBLK;
1282:             startib = fmax;
1283:         }
1284:     }
1285:     clear(mbase,msize);
1286:     if((off_t)msize < totsz) {
1287:         bmapsz = roundup(bmapsz,BSIZE);
1288:         smapsz = roundup(smapsz,BSIZE);
1289:         lncntsz = roundup(lncntsz,BSIZE);
1290:         nscrblk = (bmapsz+smapsz+lncntsz)>>BSHIFT;
1291:         if(tflag == 0) {
1292:             pfatal("\nNEED SCRATCH FILE (%ld BLKS)\n",nscrblk);
1293:             do {
1294:                 printf("ENTER FILENAME:  ");
1295:                 if((n = getline(stdin,scrfile,sizeof(scrfile))) == EOF)
1296:                     errexit("\n");
1297:             } while(n == 0);
1298:         }
1299:         if(stat(scrfile,&statarea) < 0 ||
1300:             (statarea.st_mode & S_IFMT) == S_IFREG)
1301:             rmscr++;
1302:         if (tempbase == 0)
1303:             sfile.wfdes=creat(scrfile,0666);
1304:         else
1305:             sfile.wfdes=open(scrfile,1);
1306:         if ((sfile.wfdes < 0)
1307:             || ((sfile.rfdes = open(scrfile,0)) < 0)) {
1308:             error("Can't create %s\n",scrfile);
1309:             ckfini();
1310:             return(NO);
1311:         }
1312:         if (hotroot && (stat(scrfile,&statarea)==0)
1313:             && ((statarea.st_mode & S_IFMT) == S_IFREG)
1314:             && (statarea.st_dev==rootdev))
1315:              pfatal("TMP FILE (%s) ON ROOT WHEN CHECKING ROOT",scrfile);
1316:         sfile.fname = scrfile;
1317:         bp = &((BUFAREA *)mbase)[(msize/sizeof(BUFAREA))];
1318:         poolhead = NULL;
1319:         while(--bp >= (BUFAREA *)mbase) {
1320:             initbarea(bp);
1321:             bp->b_next = poolhead;
1322:             poolhead = bp;
1323:         }
1324:         bp = poolhead;
1325:         for(bcnt = tempbase; bcnt < tempbase+nscrblk; bcnt++) {
1326:             bp->b_bno = bcnt;
1327:             dirty(bp);
1328:             flush(&sfile,bp);
1329:         }
1330:         blkmap = freemap = statemap = (char *) NULL;
1331:         lncntp = (short *) NULL;
1332:         bmapblk = tempbase;
1333:         tempbase += nscrblk;
1334:         smapblk = bmapblk + bmapsz / BSIZE;
1335:         lncntblk = smapblk + smapsz / BSIZE;
1336:         fmapblk = smapblk;
1337:     }
1338:     else {
1339:         if(rawflg && (off_t)msize > totsz+BSIZE) {
1340:             niblk += (unsigned)((off_t)msize-totsz)>>BSHIFT;
1341:             if(niblk > MAXRAW)
1342:                 niblk = MAXRAW;
1343:             msize = memsize - (niblk*BSIZE);
1344:             mbase = membase + (niblk*BSIZE);
1345:         }
1346:         poolhead = NULL;
1347:         blkmap = mbase;
1348:         statemap = &mbase[(MEMSIZE)bmapsz];
1349:         freemap = statemap;
1350:         lncntp = (short *)&statemap[(MEMSIZE)smapsz];
1351:     }
1352:     return(YES);
1353: }
1354: 
1355: 
1356: DINODE *
1357: ginode()
1358: {
1359:     register DINODE *dp;
1360:     register char *mbase;
1361:     daddr_t iblk;
1362: 
1363:     if(inum > imax)
1364:         return(NULL);
1365:     iblk = itod(inum);
1366:     if(rawflg) {
1367:         mbase = membase;
1368:         if(iblk < startib || iblk >= startib+niblk) {
1369:             if(inoblk.b_dirty)
1370:                 bwrite(&dfile,mbase,startib,(int)niblk*BSIZE);
1371:             inoblk.b_dirty = 0;
1372:             if(bread(&dfile,mbase,iblk,(int)niblk*BSIZE) == NO) {
1373:                 startib = fmax;
1374:                 return(NULL);
1375:             }
1376:             startib = iblk;
1377:         }
1378:         dp = (DINODE *)&mbase[(unsigned)((iblk-startib)<<BSHIFT)];
1379:     }
1380:     else if(getblk(&inoblk,iblk) != NULL)
1381:         dp = inoblk.b_un.b_dinode;
1382:     else
1383:         return(NULL);
1384:     return(dp + itoo(inum));
1385: }
1386: 
1387: 
1388: ftypeok(dp)
1389: DINODE *dp;
1390: {
1391:     switch(dp->di_mode & IFMT) {
1392:         case IFDIR:
1393:         case IFREG:
1394:         case IFBLK:
1395:         case IFCHR:
1396:         case IFMPC:
1397:         case IFMPB:
1398: #ifdef  IFQUOT
1399:         case IFQUOT:
1400: #endif
1401: #ifdef  UCB_SYMLINKS
1402:         case IFLNK:
1403: #endif
1404:             return(YES);
1405:         default:
1406:             return(NO);
1407:     }
1408: }
1409: 
1410: 
1411: reply(s)
1412: char *s;
1413: {
1414:     char line[80];
1415: 
1416:     if (preen)
1417:         pfatal("INTERNAL ERROR: GOT TO reply()");
1418:     rplyflag = 1;
1419:     printf("\n%s? ",s);
1420:     if(nflag || csflag || dfile.wfdes < 0) {
1421:         printf(" no\n\n");
1422:         return(NO);
1423:     }
1424:     if(yflag) {
1425:         printf(" yes\n\n");
1426:         return(YES);
1427:     }
1428:     if(getline(stdin,line,sizeof(line)) == EOF)
1429:         errexit("\n");
1430:     printf("\n");
1431:     if(line[0] == 'y' || line[0] == 'Y')
1432:         return(YES);
1433:     else
1434:         return(NO);
1435: }
1436: 
1437: 
1438: getline(fp,loc,maxlen)
1439: FILE *fp;
1440: char *loc;
1441: {
1442:     register n;
1443:     register char *p, *lastloc;
1444: 
1445:     p = loc;
1446:     lastloc = &p[maxlen-1];
1447:     while((n = getc(fp)) != '\n') {
1448:         if(n == EOF)
1449:             return(EOF);
1450:         if(!isspace(n) && p < lastloc)
1451:             *p++ = n;
1452:     }
1453:     *p = 0;
1454:     return(p - loc);
1455: }
1456: 
1457: 
1458: stype(p)
1459: register char *p;
1460: {
1461:     if(*p == 0)
1462:         return;
1463:     if (*(p+1) == 0) {
1464:         if (*p == '3') {
1465:             cylsize = 200;
1466:             stepsize = 5;
1467:             return;
1468:         }
1469:         if (*p == '4') {
1470:             cylsize = 418;
1471:             stepsize = 9;
1472:             return;
1473:         }
1474:     }
1475:     cylsize = atoi(p);
1476:     while(*p && *p != ':')
1477:         p++;
1478:     if(*p)
1479:         p++;
1480:     stepsize = atoi(p);
1481:     if(stepsize <= 0 || stepsize > cylsize ||
1482:     cylsize <= 0 || cylsize > MAXCYL) {
1483:         error("Invalid -s argument, defaults assumed\n");
1484:         cylsize = stepsize = 0;
1485:     }
1486: }
1487: 
1488: 
1489: dostate(s,flg)
1490: {
1491:     register char *p;
1492:     register unsigned byte, shift;
1493:     BUFAREA *bp;
1494: 
1495:     byte = (inum)/STATEPB;
1496:     shift = LSTATE * ((inum)%STATEPB);
1497:     if(statemap != NULL) {
1498:         bp = NULL;
1499:         p = &statemap[byte];
1500:     }
1501:     else if((bp = getblk((BUFAREA *)NULL,(daddr_t)(smapblk+(byte/BSIZE)))) == NULL)
1502:         errexit("Fatal I/O error\n");
1503:     else
1504:         p = &bp->b_un.b_buf[byte%BSIZE];
1505:     switch(flg) {
1506:         case 0:
1507:             *p &= ~(SMASK<<(shift));
1508:             *p |= s<<(shift);
1509:             if(bp != NULL)
1510:                 dirty(bp);
1511:             return(s);
1512:         case 1:
1513:             return((*p>>(shift)) & SMASK);
1514:     }
1515:     return(USTATE);
1516: }
1517: 
1518: 
1519: domap(blk,flg)
1520: daddr_t blk;
1521: {
1522:     register char *p;
1523:     register unsigned n;
1524:     register BUFAREA *bp;
1525:     off_t byte;
1526: 
1527:     byte = blk >> BITSHIFT;
1528:     n = 1<<((unsigned)(blk & BITMASK));
1529:     if(flg & 04) {
1530:         p = freemap;
1531:         blk = fmapblk;
1532:     }
1533:     else {
1534:         p = blkmap;
1535:         blk = bmapblk;
1536:     }
1537:     if(p != NULL) {
1538:         bp = NULL;
1539:         p += (unsigned)byte;
1540:     }
1541:     else if((bp = getblk((BUFAREA *)NULL,blk+(byte>>BSHIFT))) == NULL)
1542:         errexit("Fatal I/O error\n");
1543:     else
1544:         p = &bp->b_un.b_buf[(unsigned)(byte&BMASK)];
1545:     switch(flg&03) {
1546:         case 0:
1547:             *p |= n;
1548:             break;
1549:         case 1:
1550:             n &= *p;
1551:             bp = NULL;
1552:             break;
1553:         case 2:
1554:             *p &= ~n;
1555:     }
1556:     if(bp != NULL)
1557:         dirty(bp);
1558:     return(n);
1559: }
1560: 
1561: 
1562: dolncnt(val,flg)
1563: short val;
1564: {
1565:     register short *sp;
1566:     register BUFAREA *bp;
1567: 
1568:     if(lncntp != NULL) {
1569:         bp = NULL;
1570:         sp = &lncntp[inum];
1571:     }
1572:     else if((bp = getblk((BUFAREA *)NULL,(daddr_t)(lncntblk+(inum/SPERB)))) == NULL)
1573:         errexit("Fatal I/O error\n");
1574:     else
1575:         sp = &bp->b_un.b_lnks[inum%SPERB];
1576:     switch(flg) {
1577:         case 0:
1578:             *sp = val;
1579:             break;
1580:         case 1:
1581:             bp = NULL;
1582:             break;
1583:         case 2:
1584:             (*sp)--;
1585:     }
1586:     if(bp != NULL)
1587:         dirty(bp);
1588:     return(*sp);
1589: }
1590: 
1591: 
1592: BUFAREA *
1593: getblk(bp,blk)
1594: daddr_t blk;
1595: register BUFAREA *bp;
1596: {
1597:     register struct filecntl *fcp;
1598: 
1599:     if(bp == NULL) {
1600:         bp = search(blk);
1601:         fcp = &sfile;
1602:     }
1603:     else
1604:         fcp = &dfile;
1605:     if(bp->b_bno == blk)
1606:         return(bp);
1607:     flush(fcp,bp);
1608:     if(bread(fcp,bp->b_un.b_buf,blk,BSIZE) != NO) {
1609:         bp->b_bno = blk;
1610:         return(bp);
1611:     }
1612:     bp->b_bno = (daddr_t)-1;
1613:     return(NULL);
1614: }
1615: 
1616: 
1617: flush(fcp,bp)
1618: struct filecntl *fcp;
1619: register BUFAREA *bp;
1620: {
1621:     if(bp->b_dirty) {
1622:         bwrite(fcp,bp->b_un.b_buf,bp->b_bno,BSIZE);
1623:     }
1624:     bp->b_dirty = 0;
1625: }
1626: 
1627: 
1628: rwerr(s,blk,name,fd)
1629: char *s;
1630: daddr_t blk;
1631: char *name;
1632: {
1633:     if (preen == 0)
1634:         printf("\n");
1635:     pfatal("CAN NOT %s: BLK %ld of %s",s,blk,name);
1636:     if(reply("CONTINUE") == NO)
1637:         errexit("Program terminated\n");
1638: }
1639: 
1640: 
1641: sizechk(dp)
1642: register DINODE *dp;
1643: {
1644: /*
1645: 	if (maxblk != howmany(dp->di_size, BSIZE))
1646: 		printf("POSSIBLE FILE SIZE ERROR I=%u (%ld,%ld)\n\n",
1647: 		    inum, maxblk, howmany(dp->di_size,BSIZE));
1648: */
1649:     if(DIR && (dp->di_size % sizeof(DIRECT)) != 0) {
1650:         pwarn("DIRECTORY MISALIGNED I=%u\n",inum);
1651:         if (preen == 0)
1652:             printf("\n");
1653:     }
1654: }
1655: 
1656: 
1657: ckfini()
1658: {
1659:     flush(&dfile,&fileblk);
1660:     flush(&dfile,&sblk);
1661:     flush(&dfile,&inoblk);
1662:     closefils();
1663: }
1664: 
1665: closefils()
1666: {
1667:     close(dfile.rfdes);
1668:     close(dfile.wfdes);
1669:     close(sfile.rfdes);
1670:     close(sfile.wfdes);
1671: }
1672: 
1673: 
1674: pinode()
1675: {
1676:     register DINODE *dp;
1677:     register char *p;
1678:     char uidbuf[200];
1679:     char *ctime();
1680: 
1681:     printf(" I=%u ",inum);
1682:     if((dp = ginode()) == NULL)
1683:         return;
1684:     printf(" OWNER=");
1685:     if(getpw((int)dp->di_uid,uidbuf) == 0) {
1686:         for(p = uidbuf; *p != ':'; p++);
1687:         *p = 0;
1688:         printf("%s ",uidbuf);
1689:     }
1690:     else {
1691:         printf("%d ",dp->di_uid);
1692:     }
1693:     printf("MODE=%o\n",dp->di_mode);
1694:     if (preen)
1695:         printf("%s: ", devname);
1696:     printf("SIZE=%ld ",dp->di_size);
1697:     p = ctime(&dp->di_mtime);
1698:     printf("MTIME=%12.12s %4.4s ",p+4,p+20);
1699: }
1700: 
1701: 
1702: copy(fp,tp,size)
1703: register char *tp, *fp;
1704: MEMSIZE size;
1705: {
1706:     while(size--)
1707:         *tp++ = *fp++;
1708: }
1709: 
1710: ifreechk() {
1711:     register i;
1712: 
1713:     for (i=0; i<superblk.s_ninode; i++) {
1714:         inum = superblk.s_inode[i];
1715:         switch (getstate()) {
1716: 
1717:         case USTATE:
1718:             continue;
1719:         default:
1720:             pwarn("ALLOCATED INODE(S) IN IFREE LIST");
1721:             if (preen)
1722:                 printf(" (FIXED)\n");
1723:             if (preen || reply("FIX") == YES) {
1724:                 superblk.s_ninode = i-1;
1725:                 sbdirty();
1726:             }
1727:             return;
1728:         }
1729:     }
1730: }
1731: 
1732: freechk()
1733: {
1734:     register daddr_t *ap;
1735: 
1736:     if(freeblk.df_nfree == 0)
1737:         return;
1738:     do {
1739:         if(freeblk.df_nfree <= 0 || freeblk.df_nfree > NICFREE) {
1740:             pfatal("BAD FREEBLK COUNT");
1741:             printf("\n");
1742:             fixfree = 1;
1743:             return;
1744:         }
1745:         ap = &freeblk.df_free[freeblk.df_nfree];
1746:         while(--ap > &freeblk.df_free[0]) {
1747:             if(pass5(*ap) == STOP)
1748:                 return;
1749:         }
1750:         if(*ap == (daddr_t)0 || pass5(*ap) != KEEPON)
1751:             return;
1752:     } while(getblk(&fileblk,*ap) != NULL);
1753: }
1754: 
1755: 
1756: makefree()
1757: {
1758:     register i, cyl, step;
1759:     int j;
1760:     char flg[MAXCYL];
1761:     short addr[MAXCYL];
1762:     daddr_t blk, baseblk;
1763: 
1764:     superblk.s_nfree = 0;
1765:     superblk.s_flock = 0;
1766:     superblk.s_fmod = 0;
1767:     superblk.s_tfree = 0;
1768:     superblk.s_ninode = 0;
1769:     superblk.s_ilock = 0;
1770:     superblk.s_ronly = 0;
1771:     if(cylsize == 0 || stepsize == 0) {
1772:         step = superblk.s_dinfo[0];
1773:         cyl = superblk.s_dinfo[1];
1774:     }
1775:     else {
1776:         step = stepsize;
1777:         cyl = cylsize;
1778:     }
1779:     if(step > cyl || step <= 0 || cyl <= 0 || cyl > MAXCYL) {
1780:         error("Default free list spacing assumed\n");
1781:         step = STEPSIZE;
1782:         cyl = CYLSIZE;
1783:     }
1784:     superblk.s_dinfo[0] = step;
1785:     superblk.s_dinfo[1] = cyl;
1786:     clear(flg,sizeof(flg));
1787:     i = 0;
1788:     for(j = 0; j < cyl; j++) {
1789:         while(flg[i])
1790:             i = (i + 1) % cyl;
1791:         addr[j] = i + 1;
1792:         flg[i]++;
1793:         i = (i + step) % cyl;
1794:     }
1795:     baseblk = (daddr_t)roundup(fmax,cyl);
1796:     clear((char *)&freeblk,BSIZE);
1797:     freeblk.df_nfree++;
1798:     for( ; baseblk > 0; baseblk -= cyl)
1799:         for(i = 0; i < cyl; i++) {
1800:             blk = baseblk - addr[i];
1801:             if(!outrange(blk) && !getbmap(blk)) {
1802:                 superblk.s_tfree++;
1803:                 if(freeblk.df_nfree >= NICFREE) {
1804:                     fbdirty();
1805:                     fileblk.b_bno = blk;
1806:                     flush(&dfile,&fileblk);
1807:                     clear((char *)&freeblk,BSIZE);
1808:                 }
1809:                 freeblk.df_free[freeblk.df_nfree] = blk;
1810:                 freeblk.df_nfree++;
1811:             }
1812:         }
1813:     superblk.s_nfree = freeblk.df_nfree;
1814:     for(i = 0; i < NICFREE; i++)
1815:         superblk.s_free[i] = freeblk.df_free[i];
1816:     sbdirty();
1817: }
1818: 
1819: 
1820: clear(p,cnt)
1821: register char *p;
1822: MEMSIZE cnt;
1823: {
1824:     while(cnt--)
1825:         *p++ = 0;
1826: }
1827: 
1828: 
1829: BUFAREA *
1830: search(blk)
1831: daddr_t blk;
1832: {
1833:     register BUFAREA *pbp, *bp;
1834: 
1835:     for(bp = (BUFAREA *) &poolhead; bp->b_next; ) {
1836:         pbp = bp;
1837:         bp = pbp->b_next;
1838:         if(bp->b_bno == blk)
1839:             break;
1840:     }
1841:     pbp->b_next = bp->b_next;
1842:     bp->b_next = poolhead;
1843:     poolhead = bp;
1844:     return(bp);
1845: }
1846: 
1847: 
1848: findino(dirp)
1849: register DIRECT *dirp;
1850: {
1851:     register char *p1, *p2;
1852: 
1853:     if(dirp->d_ino == 0)
1854:         return(KEEPON);
1855:     for(p1 = dirp->d_name,p2 = srchname;*p2++ == *p1; p1++) {
1856:         if(*p1 == 0 || p1 == &dirp->d_name[DIRSIZ-1]) {
1857:             if(dirp->d_ino >= ROOTINO && dirp->d_ino <= imax)
1858:                 parentdir = dirp->d_ino;
1859:             return(STOP);
1860:         }
1861:     }
1862:     return(KEEPON);
1863: }
1864: 
1865: 
1866: mkentry(dirp)
1867: register DIRECT *dirp;
1868: {
1869:     register ino_t in;
1870:     register char *p;
1871: 
1872:     if(dirp->d_ino)
1873:         return(KEEPON);
1874:     dirp->d_ino = orphan;
1875:     in = orphan;
1876:     p = &dirp->d_name[DIRSIZ];
1877:     while (p >=  &dirp->d_name[8])
1878:         *--p = 0;
1879:     while(p > dirp->d_name) {
1880:         *--p = (in % 10) + '0';
1881:         in /= 10;
1882:     }
1883:     *p = '#';
1884:     return(ALTERD|STOP);
1885: }
1886: 
1887: 
1888: chgdd(dirp)
1889: register DIRECT *dirp;
1890: {
1891:     if(dirp->d_name[0] == '.' && dirp->d_name[1] == '.' &&
1892:     dirp->d_name[2] == 0) {
1893:         dirp->d_ino = lfdir;
1894:         return(ALTERD|STOP);
1895:     }
1896:     return(KEEPON);
1897: }
1898: 
1899: 
1900: linkup()
1901: {
1902:     register DINODE *dp;
1903:     register lostdir;
1904:     register ino_t pdir;
1905: 
1906:     if((dp = ginode()) == NULL)
1907:         return(NO);
1908:     lostdir = DIR;
1909:     pdir = parentdir;
1910:     pwarn("UNREF %s ",lostdir ? "DIR" : "FILE");
1911:     pinode();
1912:     if (preen && dp->di_size == 0)
1913:         return(NO);
1914:     if (preen)
1915:         printf(" (RECONNECTED)\n");
1916:     else
1917:         if (reply("RECONNECT") == NO)
1918:             return(NO);
1919:     orphan = inum;
1920:     if(lfdir == 0) {
1921:         inum = ROOTINO;
1922:         if((dp = ginode()) == NULL) {
1923:             inum = orphan;
1924:             return(NO);
1925:         }
1926:         pfunc = findino;
1927:         srchname = lfname;
1928:         filsize = dp->di_size;
1929:         parentdir = 0;
1930:         ckinode(dp,DATA);
1931:         inum = orphan;
1932:         if((lfdir = parentdir) == 0) {
1933:             pfatal("SORRY. NO lost+found DIRECTORY");
1934:             printf("\n\n");
1935:             return(NO);
1936:         }
1937:     }
1938:     inum = lfdir;
1939:     if((dp = ginode()) == NULL || !DIR || getstate() != FSTATE) {
1940:         inum = orphan;
1941:         pfatal("SORRY. NO lost+found DIRECTORY");
1942:         printf("\n\n");
1943:         return(NO);
1944:     }
1945:     if(dp->di_size & BMASK) {
1946:         dp->di_size = roundup(dp->di_size,BSIZE);
1947:         inodirty();
1948:     }
1949:     filsize = dp->di_size;
1950:     inum = orphan;
1951:     pfunc = mkentry;
1952:     if((ckinode(dp,DATA) & ALTERD) == 0) {
1953:         pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
1954:         printf("\n\n");
1955:         return(NO);
1956:     }
1957:     declncnt();
1958:     if(lostdir) {
1959:         pfunc = chgdd;
1960:         dp = ginode();
1961:         filsize = dp->di_size;
1962:         ckinode(dp,DATA);
1963:         inum = lfdir;
1964:         if((dp = ginode()) != NULL) {
1965:             dp->di_nlink++;
1966:             inodirty();
1967:             setlncnt(getlncnt()+1);
1968:         }
1969:         inum = orphan;
1970:         pwarn("DIR I=%u CONNECTED. ",orphan);
1971:         printf("PARENT WAS I=%u\n",pdir);
1972:         if (preen == 0)
1973:             printf("\n");
1974:     }
1975:     return(YES);
1976: }
1977: 
1978: 
1979: bread(fcp,buf,blk,size)
1980: daddr_t blk;
1981: register struct filecntl *fcp;
1982: register size;
1983: char *buf;
1984: {
1985:     if(lseek(fcp->rfdes,blk<<BSHIFT,0) < 0)
1986:         rwerr("SEEK",blk,fcp->fname);
1987:     else if(read(fcp->rfdes,buf,size) == size)
1988:         return(YES);
1989:     rwerr("READ",blk,fcp->fname);
1990:     return(NO);
1991: }
1992: 
1993: 
1994: bwrite(fcp,buf,blk,size)
1995: daddr_t blk;
1996: register struct filecntl *fcp;
1997: register size;
1998: char *buf;
1999: {
2000:     if(fcp->wfdes < 0)
2001:         return(NO);
2002:     if(lseek(fcp->wfdes,blk<<BSHIFT,0) < 0)
2003:         rwerr("SEEK",blk,fcp->fname);
2004:     else if(write(fcp->wfdes,buf,size) == size) {
2005:         fcp->mod = 1;
2006:         return(YES);
2007:     }
2008:     rwerr("WRITE",blk,fcp->fname);
2009:     return(NO);
2010: }
2011: 
2012: catch()
2013: {
2014:     ckfini();
2015:     if(rmscr)
2016:         unlink(scrfile);
2017:     exit(12);
2018: }

Defined functions

adjust defined in line 1138; used 1 times
blkerr defined in line 1052; used 3 times
blockcheck defined in line 388; used 1 times
bread defined in line 1979; used 2 times
bwrite defined in line 1994; used 3 times
catch defined in line 2012; used 2 times
check defined in line 482; used 2 times
check1 defined in line 497; used 2 times
chgdd defined in line 1888; used 2 times
ckfini defined in line 1657; used 5 times
ckinode defined in line 821; used 8 times
clear defined in line 1820; used 6 times
closefils defined in line 1665; used 3 times
clri defined in line 1170; used 4 times
copy defined in line 1702; used 2 times
descend defined in line 1062; used 4 times
direrr defined in line 1122; used 3 times
dirscan defined in line 1082; used 3 times
dolncnt defined in line 1562; used 3 times
domap defined in line 1519; used 6 times
dostate defined in line 1489; used 2 times
errexit defined in line 771; used 22 times
error defined in line 764; used 12 times
findino defined in line 1848; used 3 times
flush defined in line 1617; used 7 times
freechk defined in line 1732; used 1 times
ftypeok defined in line 1388; used 2 times
getblk defined in line 1592; used 12 times
getline defined in line 1438; used 2 times
getpasses defined in line 365; used 1 times
ginode defined in line 1356; used 16 times
iblock defined in line 847; used 2 times
ifreechk defined in line 1710; used 1 times
linkup defined in line 1900; used 2 times
main defined in line 240; never used
makefree defined in line 1756; used 1 times
mkentry defined in line 1866; used 2 times
namecheck defined in line 399; used 3 times
pass1 defined in line 884; used 2 times
pass1b defined in line 933; used 2 times
pass2 defined in line 952; used 3 times
pass4 defined in line 1000; used 3 times
pass5 defined in line 1020; used 3 times
pfatal defined in line 785; used 22 times
pinode defined in line 1674; used 4 times
preendie defined in line 801; used 2 times
pwarn defined in line 813; used 13 times
rawname defined in line 465; used 2 times
reply defined in line 1411; used 20 times
rwerr defined in line 1628; used 4 times
search defined in line 1829; used 2 times
setup defined in line 1193; used 2 times
sizechk defined in line 1641; used 1 times
stype defined in line 1458; used 2 times
unrawname defined in line 447; used 3 times

Defined variables

badblk defined in line 167; used 6 times
badlncnt defined in line 136; used 3 times
badlnp defined in line 137; used 4 times
blkmap defined in line 151; used 4 times
bmapblk defined in line 183; used 5 times
bmapsz defined in line 180; used 10 times
csflag defined in line 140; used 5 times
cylsize defined in line 165; used 9 times
devname defined in line 238; used 9 times
dfile defined in line 115; used 20 times
dupblk defined in line 168; used 6 times
duplist defined in line 131; used 7 times
enddup defined in line 132; used 7 times
endpass defined in line 164; used 3 times
fileblk defined in line 94; used 11 times
filsize defined in line 178; used 14 times
fixfree defined in line 149; used 10 times
fmapblk defined in line 186; used 4 times
fmax defined in line 191; used 9 times
fmin defined in line 190; used 5 times
freemap defined in line 152; used 5 times
hotroot defined in line 146; used 6 times
imax defined in line 172; used 10 times
inoblk defined in line 93; used 9 times
inum defined in line 171; used 50 times
lastino defined in line 174; used 4 times
lfdir defined in line 175; used 7 times
lfname defined in line 159; used 2 times
lncntblk defined in line 185; used 2 times
lncntp defined in line 161; used 7 times
maxblk defined in line 179; used 1 times
membase defined in line 150; used 8 times
memsize defined in line 120; used 9 times
muldup defined in line 133; used 9 times
n_blks defined in line 188; used 6 times
n_files defined in line 189; used 6 times
n_free defined in line 187; used 8 times
nflag defined in line 141; used 5 times
niblk defined in line 74; used 12 times
orphan defined in line 176; used 11 times
parentdir defined in line 173; used 6 times
pathname defined in line 157; used 4 times
pathp defined in line 154; used 10 times
poolhead defined in line 96; used 10 times
preen defined in line 144; used 40 times
rawflg defined in line 147; used 8 times
rmscr defined in line 148; used 6 times
rplyflag defined in line 145; used 3 times
sblk defined in line 95; used 5 times
sccsid defined in line 1; never used
scrfile defined in line 158; used 14 times
sfile defined in line 116; used 11 times
sflag defined in line 139; used 6 times
smapblk defined in line 184; used 4 times
srchname defined in line 156; used 3 times
startib defined in line 73; used 8 times
startpass defined in line 163; used 5 times
statemap defined in line 153; used 6 times
stepsize defined in line 166; used 8 times
tempbase defined in line 182; used 8 times
tflag defined in line 143; used 2 times
thisname defined in line 155; used 6 times
yflag defined in line 142; used 3 times

Defined struct's

bufarea defined in line 76; used 4 times
  • in line 77(2), 91(2)
filecntl defined in line 108; used 12 times

Defined typedef's

BUFAREA defined in line 91; used 32 times
DINODE defined in line 39; used 16 times
DIRECT defined in line 40; used 10 times
MEMSIZE defined in line 118; used 13 times

Defined macros

ADDR defined in line 214; used 5 times
ALLOC defined in line 42; used 1 times
ALTERD defined in line 215; used 6 times
BITMASK defined in line 30; used 1 times
BITSHIFT defined in line 29; used 1 times
BITSPB defined in line 28; used 2 times
BLK defined in line 45; used 4 times
CHR defined in line 46; used 4 times
CLEAR defined in line 36; used 1 times
CYLSIZE defined in line 25; used 1 times
DATA defined in line 213; used 5 times
DIR defined in line 43; used 8 times
DSTATE defined in line 35; used 7 times
DUPTBLSIZE defined in line 130; used 3 times
FSTATE defined in line 34; used 5 times
KEEPON defined in line 216; used 19 times
LNK defined in line 50; used 2 times
LSTATE defined in line 31; used 2 times
MAXBAD defined in line 22; used 2 times
MAXCYL defined in line 26; used 4 times
MAXDATA defined in line 126; used 1 times
MAXDUP defined in line 21; used 1 times
MAXLNCNT defined in line 135; used 2 times
MAXRAW defined in line 72; used 2 times
MEMUNIT defined in line 127; used 1 times
MPB defined in line 48; used 4 times
MPC defined in line 47; used 4 times
NDIRECT defined in line 15; used 3 times
NINOBLK defined in line 70; used 4 times
NO defined in line 18; used 43 times
QUOT defined in line 53; used 2 times
REG defined in line 44; never used
SKIP defined in line 217; used 8 times
SMASK defined in line 37; used 2 times
SPECIAL defined in line 63; used 1 times
SPERB defined in line 16; used 3 times
STATEPB defined in line 32; used 3 times
STEPSIZE defined in line 24; used 1 times
STOP defined in line 218; used 16 times
USTATE defined in line 33; used 2 times
YES defined in line 19; used 21 times
clrbmap defined in line 204; used 1 times
clrfmap defined in line 208; never used
declncnt defined in line 200; used 3 times
dirblk defined in line 105; used 3 times
dirty defined in line 99; used 5 times
fbdirty defined in line 101; used 2 times
freeblk defined in line 104; used 17 times
getbmap defined in line 203; used 3 times
getfmap defined in line 207; used 1 times
getlncnt defined in line 199; used 2 times
getstate defined in line 211; used 9 times
howmany defined in line 193; used 2 times
initbarea defined in line 98; used 6 times
inodirty defined in line 100; used 7 times
outrange defined in line 195; used 7 times
roundup defined in line 194; used 7 times
sbdirty defined in line 102; used 5 times
setbmap defined in line 202; used 1 times
setfmap defined in line 206; used 1 times
setlncnt defined in line 198; used 2 times
setstate defined in line 210; used 6 times
superblk defined in line 106; used 32 times
zapino defined in line 196; used 3 times
Last modified: 1983-05-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 8058
Valid CSS Valid XHTML 1.0 Strict