1*9255Smckusick char version[] = "@(#)main.c 2.17 (Berkeley) 11/15/82"; 24428Smckusic 34236Smckusick #include <stdio.h> 44236Smckusick #include <ctype.h> 56489Smckusick #include <sys/param.h> 66489Smckusick #include <sys/fs.h> 76489Smckusick #include <sys/inode.h> 86634Smckusick #include <dir.h> 96489Smckusick #include <sys/stat.h> 104236Smckusick #include <fstab.h> 114236Smckusick 12*9255Smckusick /* RECONSTRUCT ONLY BAD CG IN PASS 6 */ 13*9255Smckusick 144236Smckusick typedef int (*SIG_TYP)(); 154236Smckusick 165347Smckusic #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 175347Smckusic #define MAXINOPB (MAXBSIZE / sizeof (struct dinode)) 185325Smckusic #define SPERB (MAXBSIZE / sizeof(short)) 194236Smckusick 204236Smckusick #define MAXDUP 10 /* limit on dup blks (per inode) */ 214236Smckusick #define MAXBAD 10 /* limit on bad blks (per inode) */ 224236Smckusick 234236Smckusick #define USTATE 0 /* inode not allocated */ 244236Smckusick #define FSTATE 01 /* inode is file */ 254236Smckusick #define DSTATE 02 /* inode is directory */ 264236Smckusick #define CLEAR 03 /* inode is to be cleared */ 274236Smckusick 284236Smckusick typedef struct dinode DINODE; 294236Smckusick typedef struct direct DIRECT; 304236Smckusick 314236Smckusick #define ALLOC ((dp->di_mode & IFMT) != 0) 325877Smckusic #define DIRCT ((dp->di_mode & IFMT) == IFDIR) 334236Smckusick #define REG ((dp->di_mode & IFMT) == IFREG) 344236Smckusick #define BLK ((dp->di_mode & IFMT) == IFBLK) 354236Smckusick #define CHR ((dp->di_mode & IFMT) == IFCHR) 366837Smckusick #define LNK ((dp->di_mode & IFMT) == IFLNK) 376285Smckusick #define SPECIAL (BLK || CHR) 384236Smckusick 394465Smckusic ino_t startinum; /* blk num of first in raw area */ 404236Smckusick 414236Smckusick struct bufarea { 424236Smckusick struct bufarea *b_next; /* must be first */ 434236Smckusick daddr_t b_bno; 444236Smckusick int b_size; 454236Smckusick union { 465325Smckusic char b_buf[MAXBSIZE]; /* buffer space */ 474236Smckusick short b_lnks[SPERB]; /* link counts */ 485325Smckusic daddr_t b_indir[MAXNINDIR]; /* indirect block */ 494236Smckusick struct fs b_fs; /* super block */ 504236Smckusick struct cg b_cg; /* cylinder group */ 515325Smckusic struct dinode b_dinode[MAXINOPB]; /* inode block */ 524236Smckusick } b_un; 534236Smckusick char b_dirty; 544236Smckusick }; 554236Smckusick 564236Smckusick typedef struct bufarea BUFAREA; 574236Smckusick 584236Smckusick BUFAREA inoblk; /* inode blocks */ 594236Smckusick BUFAREA fileblk; /* other blks in filesys */ 604236Smckusick BUFAREA sblk; /* file system superblock */ 614236Smckusick BUFAREA cgblk; 624236Smckusick 634236Smckusick #define initbarea(x) (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1 644236Smckusick #define dirty(x) (x)->b_dirty = 1 654236Smckusick #define inodirty() inoblk.b_dirty = 1 664236Smckusick #define sbdirty() sblk.b_dirty = 1 674236Smckusick #define cgdirty() cgblk.b_dirty = 1 684236Smckusick 694236Smckusick #define dirblk fileblk.b_un 704236Smckusick #define sblock sblk.b_un.b_fs 714236Smckusick #define cgrp cgblk.b_un.b_cg 724236Smckusick 734236Smckusick struct filecntl { 744236Smckusick int rfdes; 754236Smckusick int wfdes; 764236Smckusick int mod; 774236Smckusick } dfile; /* file descriptors for filesys */ 784236Smckusick 794236Smckusick #define DUPTBLSIZE 100 /* num of dup blocks to remember */ 804236Smckusick daddr_t duplist[DUPTBLSIZE]; /* dup block table */ 814236Smckusick daddr_t *enddup; /* next entry in dup table */ 824236Smckusick daddr_t *muldup; /* multiple dups part of table */ 834236Smckusick 846837Smckusick #define MAXLNCNT 50 /* num zero link cnts to remember */ 854236Smckusick ino_t badlncnt[MAXLNCNT]; /* table of inos with zero link cnts */ 864236Smckusick ino_t *badlnp; /* next entry in table */ 874236Smckusick 884236Smckusick char rawflg; 894236Smckusick char nflag; /* assume a no response */ 904236Smckusick char yflag; /* assume a yes response */ 914236Smckusick int bflag; /* location of alternate super block */ 925381Smckusic int debug; /* output debugging info */ 934236Smckusick char preen; /* just fix normal inconsistencies */ 944236Smckusick char rplyflag; /* any questions asked? */ 954236Smckusick char hotroot; /* checking root device */ 964236Smckusick char fixcg; /* corrupted free list bit maps */ 974236Smckusick 986314Smckusick char *blockmap; /* ptr to primary blk allocation map */ 994236Smckusick char *freemap; /* ptr to secondary blk allocation map */ 1004236Smckusick char *statemap; /* ptr to inode state table */ 1014236Smckusick short *lncntp; /* ptr to link count table */ 1024236Smckusick 1034236Smckusick char *pathp; /* pointer to pathname position */ 1044236Smckusick char *thisname; /* ptr to current pathname component */ 1054236Smckusick char *srchname; /* name being searched for in dir */ 1065877Smckusic char pathname[BUFSIZ]; 1074236Smckusick 1084236Smckusick char *lfname = "lost+found"; 1094236Smckusick 1104236Smckusick ino_t inum; /* inode we are currently working on */ 1116634Smckusick ino_t dnum; /* directory inode currently being worked on */ 1124236Smckusick ino_t imax; /* number of inodes */ 1134236Smckusick ino_t parentdir; /* i number of parent directory */ 1144236Smckusick ino_t lastino; /* hiwater mark of inodes */ 1154236Smckusick ino_t lfdir; /* lost & found directory */ 1164236Smckusick ino_t orphan; /* orphaned inode */ 1174236Smckusick 1184236Smckusick off_t filsize; /* num blks seen in file */ 1194236Smckusick off_t maxblk; /* largest logical blk in file */ 1206314Smckusick off_t bmapsz; /* num chars in blockmap */ 1214236Smckusick 1224236Smckusick daddr_t n_ffree; /* number of small free blocks */ 1234236Smckusick daddr_t n_bfree; /* number of large free blocks */ 1244236Smckusick daddr_t n_blks; /* number of blocks used */ 1254236Smckusick daddr_t n_files; /* number of files seen */ 1264236Smckusick daddr_t n_index; 1274236Smckusick daddr_t n_bad; 1284236Smckusick daddr_t fmax; /* number of blocks in the volume */ 1294236Smckusick 1304236Smckusick daddr_t badblk; 1314236Smckusick daddr_t dupblk; 1324236Smckusick 1334236Smckusick int inosumbad; 1344236Smckusick int offsumbad; 1354465Smckusic int frsumbad; 1366491Smckusick int sbsumbad; 1374236Smckusick 1384236Smckusick #define zapino(x) (*(x) = zino) 1394236Smckusick struct dinode zino; 1404236Smckusick 1416314Smckusick #define setbmap(x) setbit(blockmap, x) 1426314Smckusick #define getbmap(x) isset(blockmap, x) 1436314Smckusick #define clrbmap(x) clrbit(blockmap, x) 1444236Smckusick 1454236Smckusick #define setfmap(x) setbit(freemap, x) 1464236Smckusick #define getfmap(x) isset(freemap, x) 1474236Smckusick #define clrfmap(x) clrbit(freemap, x) 1484236Smckusick 1494236Smckusick #define DATA 1 1504236Smckusick #define ADDR 0 1514236Smckusick 1524236Smckusick #define ALTERD 010 1534236Smckusick #define KEEPON 04 1544236Smckusick #define SKIP 02 1554236Smckusick #define STOP 01 1564236Smckusick 1574236Smckusick int (*signal())(); 1584236Smckusick long lseek(); 1594236Smckusick time_t time(); 1604236Smckusick DINODE *ginode(); 1614236Smckusick BUFAREA *getblk(); 1624236Smckusick int dirscan(); 1634236Smckusick int findino(); 1644236Smckusick int catch(); 1654236Smckusick int mkentry(); 1664236Smckusick int chgdd(); 167*9255Smckusick int pass1check(), pass1bcheck(), pass2check(), pass4check(), pass5check(); 1684236Smckusick int (*pfunc)(); 1694236Smckusick char *rawname(), *rindex(), *unrawname(); 1704606Smckusic extern int inside[], around[]; 1715325Smckusic extern unsigned char *fragtbl[]; 1724236Smckusick 1734236Smckusick char *devname; 1744236Smckusick 1754236Smckusick main(argc, argv) 1764715Smckusic int argc; 1774715Smckusic char *argv[]; 1784236Smckusick { 1794236Smckusick struct fstab *fsp; 1804236Smckusick int pid, passno, anygtr, sumstatus; 1814236Smckusick 1824236Smckusick sync(); 1834236Smckusick while (--argc > 0 && **++argv == '-') { 1844236Smckusick switch (*++*argv) { 1854236Smckusick 1864236Smckusick case 'p': 1874236Smckusick preen++; 1884236Smckusick break; 1894236Smckusick 1904236Smckusick case 'b': 1914236Smckusick bflag = atoi(argv[0]+1); 1924236Smckusick printf("Alternate super block location: %d\n", bflag); 1934236Smckusick break; 1944236Smckusick 1955381Smckusic case 'd': 1965381Smckusic debug++; 1975381Smckusic break; 1985381Smckusic 1994236Smckusick case 'n': /* default no answer flag */ 2004236Smckusick case 'N': 2014236Smckusick nflag++; 2024236Smckusick yflag = 0; 2034236Smckusick break; 2044236Smckusick 2054236Smckusick case 'y': /* default yes answer flag */ 2064236Smckusick case 'Y': 2074236Smckusick yflag++; 2084236Smckusick nflag = 0; 2094236Smckusick break; 2104236Smckusick 2114236Smckusick default: 2124236Smckusick errexit("%c option?\n", **argv); 2134236Smckusick } 2144236Smckusick } 2154236Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2164236Smckusick signal(SIGINT, catch); 2174236Smckusick if (argc) { 2184236Smckusick while (argc-- > 0) { 2194236Smckusick hotroot = 0; 220*9255Smckusick checkfilesys(*argv++); 2214236Smckusick } 2224236Smckusick exit(0); 2234236Smckusick } 2244236Smckusick sumstatus = 0; 2254236Smckusick passno = 1; 2264236Smckusick do { 2274236Smckusick anygtr = 0; 2284236Smckusick if (setfsent() == 0) 2294236Smckusick errexit("Can't open checklist file: %s\n", FSTAB); 2304236Smckusick while ((fsp = getfsent()) != 0) { 2314236Smckusick if (strcmp(fsp->fs_type, FSTAB_RW) && 2324236Smckusick strcmp(fsp->fs_type, FSTAB_RO)) 2334236Smckusick continue; 2344236Smckusick if (preen == 0 || 2354236Smckusick passno == 1 && fsp->fs_passno == passno) { 2364236Smckusick if (blockcheck(fsp->fs_spec) == 0 && preen) 2374236Smckusick exit(8); 2384236Smckusick } else if (fsp->fs_passno > passno) 2394236Smckusick anygtr = 1; 2404236Smckusick else if (fsp->fs_passno == passno) { 2414236Smckusick pid = fork(); 2424236Smckusick if (pid < 0) { 2434236Smckusick perror("fork"); 2444236Smckusick exit(8); 2454236Smckusick } 2464236Smckusick if (pid == 0) 2474236Smckusick if (blockcheck(fsp->fs_spec)==0) 2484236Smckusick exit(8); 2494236Smckusick else 2504236Smckusick exit(0); 2514236Smckusick } 2524236Smckusick } 2534236Smckusick if (preen) { 2544236Smckusick int status; 2554236Smckusick while (wait(&status) != -1) 2564236Smckusick sumstatus |= status; 2574236Smckusick } 2584236Smckusick passno++; 2594236Smckusick } while (anygtr); 2604236Smckusick if (sumstatus) 2614236Smckusick exit(8); 2624236Smckusick endfsent(); 2634236Smckusick exit(0); 2644236Smckusick } 2654236Smckusick 2664236Smckusick blockcheck(name) 2674236Smckusick char *name; 2684236Smckusick { 2696489Smckusick struct stat stslash, stblock, stchar; 2704236Smckusick char *raw; 2714236Smckusick int looped = 0; 2724236Smckusick 2734236Smckusick hotroot = 0; 2744236Smckusick if (stat("/", &stslash) < 0){ 2754236Smckusick error("Can't stat root\n"); 2764236Smckusick return (0); 2774236Smckusick } 2784236Smckusick retry: 2794236Smckusick if (stat(name, &stblock) < 0){ 2804236Smckusick error("Can't stat %s\n", name); 2814236Smckusick return (0); 2824236Smckusick } 2834236Smckusick if (stblock.st_mode & S_IFBLK) { 2844236Smckusick raw = rawname(name); 2854236Smckusick if (stat(raw, &stchar) < 0){ 2864236Smckusick error("Can't stat %s\n", raw); 2874236Smckusick return (0); 2884236Smckusick } 2894236Smckusick if (stchar.st_mode & S_IFCHR) { 2904236Smckusick if (stslash.st_dev == stblock.st_rdev) { 2914236Smckusick hotroot++; 2924236Smckusick raw = unrawname(name); 2934236Smckusick } 294*9255Smckusick checkfilesys(raw); 2954236Smckusick return (1); 2964236Smckusick } else { 2974236Smckusick error("%s is not a character device\n", raw); 2984236Smckusick return (0); 2994236Smckusick } 3004236Smckusick } else if (stblock.st_mode & S_IFCHR) { 3014236Smckusick if (looped) { 3024236Smckusick error("Can't make sense out of name %s\n", name); 3034236Smckusick return (0); 3044236Smckusick } 3054236Smckusick name = unrawname(name); 3064236Smckusick looped++; 3074236Smckusick goto retry; 3084236Smckusick } 3094236Smckusick error("Can't make sense out of name %s\n", name); 3104236Smckusick return (0); 3114236Smckusick } 3124236Smckusick 313*9255Smckusick checkfilesys(filesys) 314*9255Smckusick char *filesys; 3154236Smckusick { 3164236Smckusick register DINODE *dp; 3174236Smckusick register ino_t *blp; 3184236Smckusick register int i, n; 3194236Smckusick ino_t savino; 3207140Smckusick int b, c, j, partial, ndb; 3214236Smckusick daddr_t d, s; 3224236Smckusick 323*9255Smckusick devname = filesys; 324*9255Smckusick if (setup(filesys) == 0) { 3254236Smckusick if (preen) 326*9255Smckusick pfatal("CAN'T CHECK FILE SYSTEM."); 3274236Smckusick return; 3284236Smckusick } 329*9255Smckusick /* 1: scan inodes tallying blocks used */ 3306837Smckusick if (preen == 0) { 3316837Smckusick printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 3324236Smckusick if (hotroot) 3334236Smckusick printf("** Root file system\n"); 3344236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 3354236Smckusick } 336*9255Smckusick pass1(); 337*9255Smckusick 338*9255Smckusick /* 1b: locate first references to duplicates, if any */ 339*9255Smckusick if (enddup != &duplist[0]) { 340*9255Smckusick if (preen) 341*9255Smckusick pfatal("INTERNAL ERROR: dups with -p"); 342*9255Smckusick printf("** Phase 1b - Rescan For More DUPS\n"); 343*9255Smckusick pass1b(); 344*9255Smckusick } 345*9255Smckusick 346*9255Smckusick /* 2: traverse directories to check reference counts */ 347*9255Smckusick if (preen == 0) 348*9255Smckusick printf("** Phase 2 - Check Pathnames\n"); 349*9255Smckusick pass2(); 350*9255Smckusick 351*9255Smckusick /* 3 */ 352*9255Smckusick if (preen == 0) 353*9255Smckusick printf("** Phase 3 - Check Connectivity\n"); 354*9255Smckusick pass3(); 355*9255Smckusick 356*9255Smckusick /* 4 */ 357*9255Smckusick if (preen == 0) 358*9255Smckusick printf("** Phase 4 - Check Reference Counts\n"); 359*9255Smckusick pass4(); 360*9255Smckusick 361*9255Smckusick /* 5 */ 362*9255Smckusick if (preen == 0) 363*9255Smckusick printf("** Phase 5 - Check Cyl groups\n"); 364*9255Smckusick pass5(); 365*9255Smckusick 366*9255Smckusick if (fixcg) { 367*9255Smckusick if (preen == 0) 368*9255Smckusick printf("** Phase 6 - Salvage Cylinder Groups\n"); 369*9255Smckusick makecg(); 370*9255Smckusick n_ffree = sblock.fs_cstotal.cs_nffree; 371*9255Smckusick n_bfree = sblock.fs_cstotal.cs_nbfree; 372*9255Smckusick } 373*9255Smckusick 374*9255Smckusick pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n", 375*9255Smckusick n_files, n_blks - howmany(sblock.fs_cssize, sblock.fs_fsize), 376*9255Smckusick n_ffree + sblock.fs_frag * n_bfree, n_ffree, n_bfree); 377*9255Smckusick if (dfile.mod) { 378*9255Smckusick time(&sblock.fs_time); 379*9255Smckusick sbdirty(); 380*9255Smckusick } 381*9255Smckusick ckfini(); 382*9255Smckusick free(blockmap); 383*9255Smckusick free(freemap); 384*9255Smckusick free(statemap); 385*9255Smckusick free(lncntp); 386*9255Smckusick if (dfile.mod) { 387*9255Smckusick if (preen) { 388*9255Smckusick if (hotroot) 389*9255Smckusick exit(4); 390*9255Smckusick } else { 391*9255Smckusick printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 392*9255Smckusick if (hotroot) { 393*9255Smckusick printf("\n***** BOOT UNIX (NO SYNC!) *****\n"); 394*9255Smckusick exit(4); 395*9255Smckusick } 396*9255Smckusick } 397*9255Smckusick } 398*9255Smckusick sync(); /* ??? */ 399*9255Smckusick } 400*9255Smckusick 401*9255Smckusick setup(dev) 402*9255Smckusick char *dev; 403*9255Smckusick { 404*9255Smckusick dev_t rootdev; 405*9255Smckusick struct stat statb; 406*9255Smckusick int super = bflag ? bflag : SBLOCK; 407*9255Smckusick int i, j, size; 408*9255Smckusick int c, d, cgd; 409*9255Smckusick 410*9255Smckusick bflag = 0; 411*9255Smckusick if (stat("/", &statb) < 0) 412*9255Smckusick errexit("Can't stat root\n"); 413*9255Smckusick rootdev = statb.st_dev; 414*9255Smckusick if (stat(dev, &statb) < 0) { 415*9255Smckusick error("Can't stat %s\n", dev); 416*9255Smckusick return (0); 417*9255Smckusick } 418*9255Smckusick rawflg = 0; 419*9255Smckusick if ((statb.st_mode & S_IFMT) == S_IFBLK) 420*9255Smckusick ; 421*9255Smckusick else if ((statb.st_mode & S_IFMT) == S_IFCHR) 422*9255Smckusick rawflg++; 423*9255Smckusick else { 424*9255Smckusick if (reply("file is not a block or character device; OK") == 0) 425*9255Smckusick return (0); 426*9255Smckusick } 427*9255Smckusick if (rootdev == statb.st_rdev) 428*9255Smckusick hotroot++; 429*9255Smckusick if ((dfile.rfdes = open(dev, 0)) < 0) { 430*9255Smckusick error("Can't open %s\n", dev); 431*9255Smckusick return (0); 432*9255Smckusick } 433*9255Smckusick if (preen == 0) 434*9255Smckusick printf("** %s", dev); 435*9255Smckusick if (nflag || (dfile.wfdes = open(dev, 1)) < 0) { 436*9255Smckusick dfile.wfdes = -1; 437*9255Smckusick if (preen) 438*9255Smckusick pfatal("NO WRITE ACCESS"); 439*9255Smckusick printf(" (NO WRITE)"); 440*9255Smckusick } 441*9255Smckusick if (preen == 0) 442*9255Smckusick printf("\n"); 443*9255Smckusick fixcg = 0; inosumbad = 0; offsumbad = 0; frsumbad = 0; sbsumbad = 0; 444*9255Smckusick dfile.mod = 0; 445*9255Smckusick n_files = n_blks = n_ffree = n_bfree = 0; 446*9255Smckusick muldup = enddup = &duplist[0]; 447*9255Smckusick badlnp = &badlncnt[0]; 448*9255Smckusick lfdir = 0; 449*9255Smckusick rplyflag = 0; 450*9255Smckusick initbarea(&sblk); 451*9255Smckusick initbarea(&fileblk); 452*9255Smckusick initbarea(&inoblk); 453*9255Smckusick initbarea(&cgblk); 454*9255Smckusick /* 455*9255Smckusick * Read in the super block and its summary info. 456*9255Smckusick */ 457*9255Smckusick if (bread(&dfile, &sblock, super, SBSIZE) == 0) 458*9255Smckusick return (0); 459*9255Smckusick sblk.b_bno = super; 460*9255Smckusick sblk.b_size = SBSIZE; 461*9255Smckusick /* 462*9255Smckusick * run a few consistency checks of the super block 463*9255Smckusick */ 464*9255Smckusick if (sblock.fs_magic != FS_MAGIC) 465*9255Smckusick { badsb("MAGIC NUMBER WRONG"); return (0); } 466*9255Smckusick if (sblock.fs_ncg < 1) 467*9255Smckusick { badsb("NCG OUT OF RANGE"); return (0); } 468*9255Smckusick if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG) 469*9255Smckusick { badsb("CPG OUT OF RANGE"); return (0); } 470*9255Smckusick if (sblock.fs_nsect < 1) 471*9255Smckusick { badsb("NSECT < 1"); return (0); } 472*9255Smckusick if (sblock.fs_ntrak < 1) 473*9255Smckusick { badsb("NTRAK < 1"); return (0); } 474*9255Smckusick if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak) 475*9255Smckusick { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); } 476*9255Smckusick if (sblock.fs_ipg % INOPB(&sblock)) 477*9255Smckusick { badsb("INODES NOT MULTIPLE OF A BLOCK"); return (0); } 478*9255Smckusick if (cgdmin(&sblock, 0) >= sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock)) 479*9255Smckusick { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); } 480*9255Smckusick if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl || 481*9255Smckusick (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) 482*9255Smckusick { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); } 483*9255Smckusick if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock)) 484*9255Smckusick { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); } 485*9255Smckusick if (sblock.fs_size * NSPF(&sblock) <= 486*9255Smckusick (sblock.fs_ncyl - 1) * sblock.fs_spc) 487*9255Smckusick { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); } 488*9255Smckusick if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) 489*9255Smckusick { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); } 490*9255Smckusick /* rest we COULD repair... */ 491*9255Smckusick if (sblock.fs_cgsize != fragroundup(&sblock, 492*9255Smckusick sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY))) 493*9255Smckusick { badsb("CGSIZE INCORRECT"); return (0); } 494*9255Smckusick if (sblock.fs_cssize != 495*9255Smckusick fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum))) 496*9255Smckusick { badsb("CSSIZE INCORRECT"); return (0); } 497*9255Smckusick fmax = sblock.fs_size; 498*9255Smckusick imax = sblock.fs_ncg * sblock.fs_ipg; 499*9255Smckusick n_bad = cgsblock(&sblock, 0); /* boot block plus dedicated sblock */ 500*9255Smckusick /* 501*9255Smckusick * read in the summary info. 502*9255Smckusick */ 503*9255Smckusick for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 504*9255Smckusick size = sblock.fs_cssize - i < sblock.fs_bsize ? 505*9255Smckusick sblock.fs_cssize - i : sblock.fs_bsize; 506*9255Smckusick sblock.fs_csp[j] = (struct csum *)calloc(1, size); 507*9255Smckusick bread(&dfile, (char *)sblock.fs_csp[j], 508*9255Smckusick fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 509*9255Smckusick size); 510*9255Smckusick } 511*9255Smckusick /* 512*9255Smckusick * allocate and initialize the necessary maps 513*9255Smckusick */ 514*9255Smckusick bmapsz = roundup(howmany(fmax, NBBY), sizeof(short)); 515*9255Smckusick blockmap = (char *)calloc(bmapsz, sizeof (char)); 516*9255Smckusick if (blockmap == NULL) { 517*9255Smckusick printf("cannot alloc %d bytes for blockmap\n", bmapsz); 518*9255Smckusick exit(1); 519*9255Smckusick } 520*9255Smckusick freemap = (char *)calloc(bmapsz, sizeof (char)); 521*9255Smckusick if (freemap == NULL) { 522*9255Smckusick printf("cannot alloc %d bytes for freemap\n", bmapsz); 523*9255Smckusick exit(1); 524*9255Smckusick } 525*9255Smckusick statemap = (char *)calloc(imax+1, sizeof(char)); 526*9255Smckusick if (statemap == NULL) { 527*9255Smckusick printf("cannot alloc %d bytes for statemap\n", imax + 1); 528*9255Smckusick exit(1); 529*9255Smckusick } 530*9255Smckusick lncntp = (short *)calloc(imax+1, sizeof(short)); 531*9255Smckusick if (lncntp == NULL) { 532*9255Smckusick printf("cannot alloc %d bytes for lncntp\n", 533*9255Smckusick (imax + 1) * sizeof(short)); 534*9255Smckusick exit(1); 535*9255Smckusick } 536*9255Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 537*9255Smckusick cgd = cgdmin(&sblock, c); 538*9255Smckusick if (c == 0) { 539*9255Smckusick d = cgbase(&sblock, c); 540*9255Smckusick cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); 541*9255Smckusick } else 542*9255Smckusick d = cgsblock(&sblock, c); 543*9255Smckusick for (; d < cgd; d++) 544*9255Smckusick setbmap(d); 545*9255Smckusick } 546*9255Smckusick 547*9255Smckusick startinum = imax + 1; 548*9255Smckusick return (1); 549*9255Smckusick 550*9255Smckusick badsb: 551*9255Smckusick ckfini(); 552*9255Smckusick return (0); 553*9255Smckusick } 554*9255Smckusick 555*9255Smckusick pass1() 556*9255Smckusick { 557*9255Smckusick register int c, i, n, j; 558*9255Smckusick register DINODE *dp; 559*9255Smckusick int savino, ndb, partial; 560*9255Smckusick 561*9255Smckusick pfunc = pass1check; 5624236Smckusick inum = 0; 5636533Smckusick n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 5644236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 5655381Smckusic if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0) 5664236Smckusick continue; 567*9255Smckusick if (cgrp.cg_magic != CG_MAGIC) { 568*9255Smckusick pfatal("cg %d: bad magic number\n", c); 569*9255Smckusick bzero((caddr_t)&cgrp, sblock.fs_cgsize); 570*9255Smckusick } 5714236Smckusick n = 0; 5724465Smckusic for (i = 0; i < sblock.fs_ipg; i++, inum++) { 5734465Smckusic dp = ginode(); 5744465Smckusic if (dp == NULL) 5754465Smckusic continue; 5765944Smckusic n++; 5774236Smckusick if (ALLOC) { 5784236Smckusick if (!isset(cgrp.cg_iused, i)) { 5795381Smckusic if (debug) 5805381Smckusic printf("%d bad, not used\n", 5815381Smckusic inum); 5824236Smckusick inosumbad++; 5834236Smckusick } 5845944Smckusic n--; 5854236Smckusick lastino = inum; 5867140Smckusick if (ftypeok(dp) == 0) 5877140Smckusick goto unknown; 5889235Smckusick if (dp->di_size < 0) { 5899235Smckusick if (debug) 5909235Smckusick printf("bad size %d:", 5919235Smckusick dp->di_size); 5927140Smckusick goto unknown; 5939235Smckusick } 5947140Smckusick ndb = howmany(dp->di_size, sblock.fs_bsize); 5957140Smckusick if (SPECIAL) 5967140Smckusick ndb++; 5977140Smckusick for (j = ndb; j < NDADDR; j++) 5989235Smckusick if (dp->di_db[j] != 0) { 5999235Smckusick if (debug) 6009235Smckusick printf("bad direct addr:"); 6017140Smckusick goto unknown; 6029235Smckusick } 6037140Smckusick for (j = 0, ndb -= NDADDR; ndb > 0; j++) 6047140Smckusick ndb /= NINDIR(&sblock); 6057140Smckusick for (; j < NIADDR; j++) 6069235Smckusick if (dp->di_ib[j] != 0) { 6079235Smckusick if (debug) 6089235Smckusick printf("bad indirect addr:"); 6097140Smckusick goto unknown; 6109235Smckusick } 6114236Smckusick n_files++; 612*9255Smckusick lncntp[inum] = dp->di_nlink; 613*9255Smckusick if (dp->di_nlink <= 0) { 6144236Smckusick if (badlnp < &badlncnt[MAXLNCNT]) 6154236Smckusick *badlnp++ = inum; 6164236Smckusick else { 6174236Smckusick pfatal("LINK COUNT TABLE OVERFLOW"); 6184236Smckusick if (reply("CONTINUE") == 0) 6194236Smckusick errexit(""); 6204236Smckusick } 6214236Smckusick } 622*9255Smckusick statemap[inum] = DIRCT ? DSTATE : FSTATE; 6234236Smckusick badblk = dupblk = 0; filsize = 0; maxblk = 0; 6244236Smckusick ckinode(dp, ADDR); 6257140Smckusick continue; 6267140Smckusick unknown: 6277140Smckusick pfatal("UNKNOWN FILE TYPE I=%u", inum); 6287140Smckusick if (reply("CLEAR") == 1) { 6297140Smckusick zapino(dp); 6307140Smckusick inodirty(); 6317140Smckusick inosumbad++; 6327140Smckusick } 6334236Smckusick } else { 6344236Smckusick if (isset(cgrp.cg_iused, i)) { 6355381Smckusic if (debug) 6365381Smckusic printf("%d bad, marked used\n", 6375381Smckusic inum); 6384236Smckusick inosumbad++; 6394465Smckusic n--; 6404236Smckusick } 6417140Smckusick partial = 0; 6427140Smckusick for (j = 0; j < NDADDR; j++) 6437140Smckusick if (dp->di_db[j] != 0) 6447140Smckusick partial++; 6457140Smckusick for (j = 0; j < NIADDR; j++) 6467140Smckusick if (dp->di_ib[j] != 0) 6477140Smckusick partial++; 6487140Smckusick if (partial || dp->di_mode != 0 || 6497140Smckusick dp->di_size != 0) { 6504236Smckusick pfatal("PARTIALLY ALLOCATED INODE I=%u", inum); 6514236Smckusick if (reply("CLEAR") == 1) { 6524236Smckusick zapino(dp); 6534236Smckusick inodirty(); 6544236Smckusick inosumbad++; 6554236Smckusick } 6564236Smckusick } 6574236Smckusick } 6584236Smckusick } 6594789Smckusic if (n != cgrp.cg_cs.cs_nifree) { 6605381Smckusic if (debug) 6615944Smckusic printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n", 6625381Smckusic c, cgrp.cg_cs.cs_nifree, n); 6634236Smckusick inosumbad++; 6644236Smckusick } 6656491Smckusick if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree 6666491Smckusick || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree 6676491Smckusick || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree 6686491Smckusick || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir) 6696491Smckusick sbsumbad++; 6704236Smckusick } 671*9255Smckusick } 672*9255Smckusick 673*9255Smckusick pass1check(blk, size) 674*9255Smckusick daddr_t blk; 675*9255Smckusick int size; 676*9255Smckusick { 677*9255Smckusick register daddr_t *dlp; 678*9255Smckusick int res = KEEPON; 679*9255Smckusick int anyout; 680*9255Smckusick 681*9255Smckusick anyout = outrange(blk, size); 682*9255Smckusick for (; size > 0; blk++, size--) { 683*9255Smckusick if (anyout && outrange(blk, 1)) { 684*9255Smckusick blkerr("BAD", blk); 685*9255Smckusick if (++badblk >= MAXBAD) { 686*9255Smckusick pwarn("EXCESSIVE BAD BLKS I=%u", inum); 687*9255Smckusick if (preen) 688*9255Smckusick printf(" (SKIPPING)\n"); 689*9255Smckusick else if (reply("CONTINUE") == 0) 690*9255Smckusick errexit(""); 691*9255Smckusick return (STOP); 6924465Smckusic } 693*9255Smckusick res = SKIP; 694*9255Smckusick } else if (getbmap(blk)) { 695*9255Smckusick blkerr("DUP", blk); 696*9255Smckusick if (++dupblk >= MAXDUP) { 697*9255Smckusick pwarn("EXCESSIVE DUP BLKS I=%u", inum); 698*9255Smckusick if (preen) 699*9255Smckusick printf(" (SKIPPING)\n"); 700*9255Smckusick else if (reply("CONTINUE") == 0) 701*9255Smckusick errexit(""); 702*9255Smckusick return (STOP); 703*9255Smckusick } 704*9255Smckusick if (enddup >= &duplist[DUPTBLSIZE]) { 705*9255Smckusick pfatal("DUP TABLE OVERFLOW."); 706*9255Smckusick if (reply("CONTINUE") == 0) 707*9255Smckusick errexit(""); 708*9255Smckusick return (STOP); 709*9255Smckusick } 710*9255Smckusick for (dlp = duplist; dlp < muldup; dlp++) 711*9255Smckusick if (*dlp == blk) { 712*9255Smckusick *enddup++ = blk; 713*9255Smckusick break; 714*9255Smckusick } 715*9255Smckusick if (dlp >= muldup) { 716*9255Smckusick *enddup++ = *muldup; 717*9255Smckusick *muldup++ = blk; 718*9255Smckusick } 719*9255Smckusick } else { 720*9255Smckusick n_blks++; 721*9255Smckusick setbmap(blk); 7224236Smckusick } 723*9255Smckusick filsize++; 7244236Smckusick } 725*9255Smckusick return (res); 726*9255Smckusick } 727*9255Smckusick 728*9255Smckusick pass1b() 729*9255Smckusick { 730*9255Smckusick register int c, i; 731*9255Smckusick register DINODE *dp; 732*9255Smckusick 733*9255Smckusick pfunc = pass1bcheck; 734*9255Smckusick inum = 0; 735*9255Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 736*9255Smckusick for (i = 0; i < sblock.fs_ipg; i++, inum++) { 737*9255Smckusick dp = ginode(); 738*9255Smckusick if (dp == NULL) 739*9255Smckusick continue; 740*9255Smckusick if (statemap[inum] != USTATE && 741*9255Smckusick (ckinode(dp, ADDR) & STOP)) 742*9255Smckusick goto out1b; 743*9255Smckusick } 744*9255Smckusick } 7454236Smckusick out1b: 7464465Smckusic flush(&dfile, &inoblk); 747*9255Smckusick } 748*9255Smckusick 749*9255Smckusick pass1bcheck(blk, size) 750*9255Smckusick daddr_t blk; 751*9255Smckusick int size; 752*9255Smckusick { 753*9255Smckusick register daddr_t *dlp; 754*9255Smckusick int res = KEEPON; 755*9255Smckusick 756*9255Smckusick for (; size > 0; blk++, size--) { 757*9255Smckusick if (outrange(blk, 1)) 758*9255Smckusick res = SKIP; 759*9255Smckusick for (dlp = duplist; dlp < muldup; dlp++) 760*9255Smckusick if (*dlp == blk) { 761*9255Smckusick blkerr("DUP", blk); 762*9255Smckusick *dlp = *--muldup; 763*9255Smckusick *muldup = blk; 764*9255Smckusick if (muldup == duplist) 765*9255Smckusick return (STOP); 766*9255Smckusick } 767*9255Smckusick } 768*9255Smckusick return (res); 769*9255Smckusick } 770*9255Smckusick 771*9255Smckusick pass2() 772*9255Smckusick { 773*9255Smckusick register DINODE *dp; 774*9255Smckusick 7754236Smckusick inum = ROOTINO; 7764236Smckusick thisname = pathp = pathname; 777*9255Smckusick pfunc = pass2check; 778*9255Smckusick switch (statemap[inum]) { 7794236Smckusick 7804236Smckusick case USTATE: 7814236Smckusick errexit("ROOT INODE UNALLOCATED. TERMINATING.\n"); 7824236Smckusick 7834236Smckusick case FSTATE: 7844236Smckusick pfatal("ROOT INODE NOT DIRECTORY"); 7854236Smckusick if (reply("FIX") == 0 || (dp = ginode()) == NULL) 7864236Smckusick errexit(""); 7874236Smckusick dp->di_mode &= ~IFMT; 7884236Smckusick dp->di_mode |= IFDIR; 7894236Smckusick inodirty(); 7904236Smckusick inosumbad++; 791*9255Smckusick statemap[inum] = DSTATE; 7924236Smckusick /* fall into ... */ 7934236Smckusick 7944236Smckusick case DSTATE: 7954236Smckusick descend(); 7964236Smckusick break; 7974236Smckusick 7984236Smckusick case CLEAR: 7994236Smckusick pfatal("DUPS/BAD IN ROOT INODE"); 8004236Smckusick printf("\n"); 8014236Smckusick if (reply("CONTINUE") == 0) 8024236Smckusick errexit(""); 803*9255Smckusick statemap[inum] = DSTATE; 8044236Smckusick descend(); 8054236Smckusick } 806*9255Smckusick } 807*9255Smckusick 808*9255Smckusick pass2check(dirp) 809*9255Smckusick register DIRECT *dirp; 810*9255Smckusick { 811*9255Smckusick register char *p; 812*9255Smckusick register n; 813*9255Smckusick DINODE *dp; 814*9255Smckusick 815*9255Smckusick if ((inum = dirp->d_ino) == 0) 816*9255Smckusick return (KEEPON); 817*9255Smckusick thisname = pathp; 818*9255Smckusick for (p = dirp->d_name; p < &dirp->d_name[MAXNAMLEN]; ) 819*9255Smckusick if ((*pathp++ = *p++) == 0) { 820*9255Smckusick --pathp; 821*9255Smckusick break; 822*9255Smckusick } 823*9255Smckusick *pathp = 0; 824*9255Smckusick n = 0; 825*9255Smckusick if (inum > imax || inum <= 0) 826*9255Smckusick n = direrr("I OUT OF RANGE"); 827*9255Smckusick else { 828*9255Smckusick again: 829*9255Smckusick switch (statemap[inum]) { 830*9255Smckusick case USTATE: 831*9255Smckusick n = direrr("UNALLOCATED"); 832*9255Smckusick break; 833*9255Smckusick 834*9255Smckusick case CLEAR: 835*9255Smckusick if ((n = direrr("DUP/BAD")) == 1) 836*9255Smckusick break; 837*9255Smckusick if ((dp = ginode()) == NULL) 838*9255Smckusick break; 839*9255Smckusick statemap[inum] = DIRCT ? DSTATE : FSTATE; 840*9255Smckusick goto again; 841*9255Smckusick 842*9255Smckusick case FSTATE: 843*9255Smckusick lncntp[inum]--; 844*9255Smckusick break; 845*9255Smckusick 846*9255Smckusick case DSTATE: 847*9255Smckusick lncntp[inum]--; 848*9255Smckusick descend(); 849*9255Smckusick break; 850*9255Smckusick } 851*9255Smckusick } 852*9255Smckusick pathp = thisname; 853*9255Smckusick if (n == 0) 854*9255Smckusick return (KEEPON); 855*9255Smckusick dirp->d_ino = 0; 856*9255Smckusick return (KEEPON|ALTERD); 857*9255Smckusick } 858*9255Smckusick 859*9255Smckusick pass3() 860*9255Smckusick { 861*9255Smckusick ino_t savino; 862*9255Smckusick register DINODE *dp; 863*9255Smckusick 8644236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 865*9255Smckusick if (statemap[inum] == DSTATE) { 8664236Smckusick pfunc = findino; 8674236Smckusick srchname = ".."; 8684236Smckusick savino = inum; 8694236Smckusick do { 8704236Smckusick orphan = inum; 8714236Smckusick if ((dp = ginode()) == NULL) 8724236Smckusick break; 8734236Smckusick filsize = dp->di_size; 8744236Smckusick parentdir = 0; 8754236Smckusick ckinode(dp, DATA); 8764236Smckusick if ((inum = parentdir) == 0) 8774236Smckusick break; 878*9255Smckusick } while (statemap[inum] == DSTATE); 8794236Smckusick inum = orphan; 8804236Smckusick if (linkup() == 1) { 8814236Smckusick thisname = pathp = pathname; 8824236Smckusick *pathp++ = '?'; 883*9255Smckusick pfunc = pass2check; 8844236Smckusick descend(); 8854236Smckusick } 8864236Smckusick inum = savino; 8874236Smckusick } 8884236Smckusick } 889*9255Smckusick } 890*9255Smckusick 891*9255Smckusick pass4() 892*9255Smckusick { 893*9255Smckusick register int n; 894*9255Smckusick register ino_t *blp; 895*9255Smckusick 896*9255Smckusick pfunc = pass4check; 8974236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 898*9255Smckusick switch (statemap[inum]) { 8994236Smckusick 9004236Smckusick case FSTATE: 901*9255Smckusick n = lncntp[inum]; 902*9255Smckusick if (n) 9034236Smckusick adjust((short)n); 9044236Smckusick else { 9054236Smckusick for (blp = badlncnt;blp < badlnp; blp++) 9064236Smckusick if (*blp == inum) { 9074236Smckusick clri("UNREF", 1); 9084236Smckusick break; 9094236Smckusick } 9104236Smckusick } 9114236Smckusick break; 9124236Smckusick 9134236Smckusick case DSTATE: 9144236Smckusick clri("UNREF", 1); 9154236Smckusick break; 9164236Smckusick 9174236Smckusick case CLEAR: 9184236Smckusick clri("BAD/DUP", 1); 9194236Smckusick break; 9204236Smckusick } 9214236Smckusick } 9225337Smckusic if (imax - ROOTINO - n_files != sblock.fs_cstotal.cs_nifree) { 9234236Smckusick pwarn("FREE INODE COUNT WRONG IN SUPERBLK"); 9244236Smckusick if (preen) 9254236Smckusick printf(" (FIXED)\n"); 9264236Smckusick if (preen || reply("FIX") == 1) { 9275944Smckusic sblock.fs_cstotal.cs_nifree = imax - ROOTINO - n_files; 9284236Smckusick sbdirty(); 9294236Smckusick } 9304236Smckusick } 9314236Smckusick flush(&dfile, &fileblk); 932*9255Smckusick } 9334236Smckusick 934*9255Smckusick pass4check(blk, size) 935*9255Smckusick daddr_t blk; 936*9255Smckusick { 937*9255Smckusick register daddr_t *dlp; 938*9255Smckusick int res = KEEPON; 939*9255Smckusick 940*9255Smckusick for (; size > 0; blk++, size--) { 941*9255Smckusick if (outrange(blk, 1)) 942*9255Smckusick res = SKIP; 943*9255Smckusick else if (getbmap(blk)) { 944*9255Smckusick for (dlp = duplist; dlp < enddup; dlp++) 945*9255Smckusick if (*dlp == blk) { 946*9255Smckusick *dlp = *--enddup; 947*9255Smckusick return (KEEPON); 948*9255Smckusick } 949*9255Smckusick clrbmap(blk); 950*9255Smckusick n_blks--; 951*9255Smckusick } 952*9255Smckusick } 953*9255Smckusick return (res); 954*9255Smckusick } 955*9255Smckusick 956*9255Smckusick pass5() 957*9255Smckusick { 958*9255Smckusick register int c, n, i, b, d; 959*9255Smckusick short bo[MAXCPG][NRPOS]; 960*9255Smckusick long botot[MAXCPG]; 961*9255Smckusick long frsum[MAXFRAG]; 962*9255Smckusick int blk; 963*9255Smckusick daddr_t cbase; 964*9255Smckusick int blockbits = (1<<sblock.fs_frag)-1; 965*9255Smckusick 966*9255Smckusick blkcpy((unsigned)bmapsz, blockmap, freemap); 9674236Smckusick dupblk = 0; 9685381Smckusic n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0)); 9694236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 970*9255Smckusick cbase = cgbase(&sblock, c); 971*9255Smckusick bzero(botot, sizeof (botot)); 972*9255Smckusick bzero(bo, sizeof (bo)); 973*9255Smckusick bzero(frsum, sizeof (frsum)); 9744465Smckusic /* 9756533Smckusick * need to account for the super blocks 9764465Smckusic * which appear (inaccurately) bad 9774465Smckusic */ 9786533Smckusick n_bad += cgtod(&sblock, c) - cgsblock(&sblock, c); 9795381Smckusic if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0) 9804236Smckusick continue; 981*9255Smckusick if (cgrp.cg_magic != CG_MAGIC) { 982*9255Smckusick pfatal("cg %d: bad magic number\n", c); 983*9255Smckusick bzero((caddr_t)&cgrp, sblock.fs_cgsize); 984*9255Smckusick } 9855325Smckusic for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 986*9255Smckusick blk = blkmap(&sblock, cgrp.cg_free, b); 987*9255Smckusick if (blk == 0) 988*9255Smckusick continue; 989*9255Smckusick if (blk == blockbits) { 990*9255Smckusick if (pass5check(cbase+b, sblock.fs_frag) == STOP) 9914236Smckusick goto out5; 9924236Smckusick /* this is clumsy ... */ 9935325Smckusic n_ffree -= sblock.fs_frag; 9944236Smckusick n_bfree++; 9955371Smckusic botot[cbtocylno(&sblock, b)]++; 9965363Smckusic bo[cbtocylno(&sblock, b)] 9975363Smckusic [cbtorpos(&sblock, b)]++; 998*9255Smckusick continue; 9994465Smckusic } 1000*9255Smckusick for (d = 0; d < sblock.fs_frag; d++) 1001*9255Smckusick if ((blk & (1<<d)) && 1002*9255Smckusick pass5check(cbase+b+d,1) == STOP) 1003*9255Smckusick goto out5; 1004*9255Smckusick fragacct(&sblock, blk, frsum, 1); 10054236Smckusick } 1006*9255Smckusick if (bcmp(cgrp.cg_frsum, frsum, sizeof (frsum))) { 1007*9255Smckusick if (debug) 1008*9255Smckusick for (i = 0; i < sblock.fs_frag; i++) 1009*9255Smckusick if (cgrp.cg_frsum[i] != frsum[i]) 1010*9255Smckusick printf("cg[%d].cg_frsum[%d] have %d calc %d\n", 1011*9255Smckusick c, i, cgrp.cg_frsum[i], frsum[i]); 1012*9255Smckusick frsumbad++; 10134465Smckusic } 1014*9255Smckusick if (bcmp(cgrp.cg_btot, botot, sizeof (botot))) { 1015*9255Smckusick if (debug) 1016*9255Smckusick for (n = 0; n < sblock.fs_cpg; n++) 1017*9255Smckusick if (botot[n] != cgrp.cg_btot[n]) 1018*9255Smckusick printf("cg[%d].cg_btot[%d] have %d calc %d\n", 1019*9255Smckusick c, n, cgrp.cg_btot[n], botot[n]); 1020*9255Smckusick offsumbad++; 1021*9255Smckusick } 1022*9255Smckusick if (bcmp(cgrp.cg_b, bo, sizeof (bo))) { 1023*9255Smckusick if (debug) 10244236Smckusick for (i = 0; i < NRPOS; i++) 1025*9255Smckusick if (bo[n][i] != cgrp.cg_b[n][i]) 1026*9255Smckusick printf("cg[%d].cg_b[%d][%d] have %d calc %d\n", 1027*9255Smckusick c, n, i, cgrp.cg_b[n][i], bo[n][i]); 1028*9255Smckusick offsumbad++; 10295371Smckusic } 10304236Smckusick } 10314236Smckusick out5: 10324236Smckusick if (dupblk) 10334236Smckusick pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk); 10344236Smckusick if (fixcg == 0) { 10355325Smckusic if ((b = n_blks+n_ffree+sblock.fs_frag*n_bfree+n_index+n_bad) != fmax) { 10364236Smckusick pwarn("%ld BLK(S) MISSING\n", fmax - b); 10374236Smckusick fixcg = 1; 10386491Smckusick } else if (inosumbad + offsumbad + frsumbad + sbsumbad) { 10396491Smckusick pwarn("SUMMARY INFORMATION %s%s%s%sBAD\n", 10404236Smckusick inosumbad ? "(INODE FREE) " : "", 10414465Smckusic offsumbad ? "(BLOCK OFFSETS) " : "", 10426491Smckusick frsumbad ? "(FRAG SUMMARIES) " : "", 10436491Smckusick sbsumbad ? "(SUPER BLOCK SUMMARIES) " : ""); 10444236Smckusick fixcg = 1; 10454789Smckusic } else if (n_ffree != sblock.fs_cstotal.cs_nffree || 10464789Smckusic n_bfree != sblock.fs_cstotal.cs_nbfree) { 10474236Smckusick pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK"); 10484236Smckusick if (preen) 10494236Smckusick printf(" (FIXED)\n"); 10504236Smckusick if (preen || reply("FIX") == 1) { 10514789Smckusic sblock.fs_cstotal.cs_nffree = n_ffree; 10524789Smckusic sblock.fs_cstotal.cs_nbfree = n_bfree; 10534236Smckusick sbdirty(); 10544236Smckusick } 10554236Smckusick } 10564236Smckusick } 10574236Smckusick if (fixcg) { 10584236Smckusick pwarn("BAD CYLINDER GROUPS"); 10594236Smckusick if (preen) 10604236Smckusick printf(" (SALVAGED)\n"); 10614236Smckusick else if (reply("SALVAGE") == 0) 10624236Smckusick fixcg = 0; 10634236Smckusick } 10647608Sroot } 10654236Smckusick 1066*9255Smckusick pass5check(blk, size) 1067*9255Smckusick daddr_t blk; 1068*9255Smckusick int size; 10697608Sroot { 10704236Smckusick 1071*9255Smckusick if (outrange(blk, size)) { 1072*9255Smckusick fixcg = 1; 1073*9255Smckusick if (preen) 1074*9255Smckusick pfatal("BAD BLOCKS IN BIT MAPS."); 1075*9255Smckusick if (++badblk >= MAXBAD) { 1076*9255Smckusick printf("EXCESSIVE BAD BLKS IN BIT MAPS."); 1077*9255Smckusick if (reply("CONTINUE") == 0) 1078*9255Smckusick errexit(""); 1079*9255Smckusick return (STOP); 1080*9255Smckusick } 10818534Sroot } 1082*9255Smckusick for (; size > 0; blk++, size--) 1083*9255Smckusick if (getfmap(blk)) { 1084*9255Smckusick fixcg = 1; 1085*9255Smckusick ++dupblk; 1086*9255Smckusick } else { 1087*9255Smckusick n_ffree++; 1088*9255Smckusick setfmap(blk); 1089*9255Smckusick } 1090*9255Smckusick return (KEEPON); 10914236Smckusick } 10924236Smckusick 10934236Smckusick ckinode(dp, flg) 10944236Smckusick DINODE *dp; 10954236Smckusick register flg; 10964236Smckusick { 10974236Smckusick register daddr_t *ap; 10984236Smckusick register ret; 10995956Smckusic int (*func)(), n, ndb, size, offset; 11006634Smckusick ino_t number = inum; 11016634Smckusick DINODE dino; 11024236Smckusick 11034236Smckusick if (SPECIAL) 11044236Smckusick return (KEEPON); 11056634Smckusick dino = *dp; 11064236Smckusick func = (flg == ADDR) ? pfunc : dirscan; 11076634Smckusick ndb = howmany(dino.di_size, sblock.fs_bsize); 11086634Smckusick for (ap = &dino.di_db[0]; ap < &dino.di_db[NDADDR]; ap++) { 11096634Smckusick if (--ndb == 0 && (offset = blkoff(&sblock, dino.di_size)) != 0) 11105956Smckusic size = numfrags(&sblock, fragroundup(&sblock, offset)); 11114236Smckusick else 11125325Smckusic size = sblock.fs_frag; 11136634Smckusick dnum = number; 11144236Smckusick if (*ap && (ret = (*func)(*ap, size)) & STOP) 11154236Smckusick return (ret); 11164236Smckusick } 11176634Smckusick for (ap = &dino.di_ib[0], n = 1; n <= 2; ap++, n++) { 11186634Smckusick dnum = number; 1119*9255Smckusick if (*ap) { 1120*9255Smckusick ret = iblock(*ap, n, flg, 1121*9255Smckusick dino.di_size - sblock.fs_bsize * NDADDR); 1122*9255Smckusick if (ret & STOP) 1123*9255Smckusick return (ret); 1124*9255Smckusick } 11254236Smckusick } 11264236Smckusick return (KEEPON); 11274236Smckusick } 11284236Smckusick 11294236Smckusick iblock(blk, ilevel, flg, isize) 11304236Smckusick daddr_t blk; 11314236Smckusick register ilevel; 11324236Smckusick int isize; 11334236Smckusick { 11344236Smckusick register daddr_t *ap; 11354236Smckusick register daddr_t *aplim; 11364428Smckusic register int i, n; 11374236Smckusick int (*func)(), nif; 11384236Smckusick BUFAREA ib; 11394236Smckusick 11404236Smckusick if (flg == ADDR) { 11414236Smckusick func = pfunc; 11425325Smckusic if (((n = (*func)(blk, sblock.fs_frag)) & KEEPON) == 0) 11434236Smckusick return (n); 11444236Smckusick } else 11454236Smckusick func = dirscan; 1146*9255Smckusick if (outrange(blk, sblock.fs_frag)) /* protect thyself */ 11474236Smckusick return (SKIP); 11484236Smckusick initbarea(&ib); 11495325Smckusic if (getblk(&ib, blk, sblock.fs_bsize) == NULL) 11504236Smckusick return (SKIP); 11514236Smckusick ilevel--; 11524428Smckusic if (ilevel == 0) { 11535956Smckusic nif = lblkno(&sblock, isize) + 1; 11544428Smckusic } else /* ilevel == 1 */ { 11555325Smckusic nif = isize / (sblock.fs_bsize * NINDIR(&sblock)) + 1; 11564428Smckusic } 11575325Smckusic if (nif > NINDIR(&sblock)) 11585325Smckusic nif = NINDIR(&sblock); 1159*9255Smckusick aplim = &ib.b_un.b_indir[nif]; 11604428Smckusic for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++) 11614236Smckusick if (*ap) { 11624236Smckusick if (ilevel > 0) 1163*9255Smckusick n = iblock(*ap, ilevel, flg, 1164*9255Smckusick isize - i*NINDIR(&sblock)*sblock.fs_bsize); 11654236Smckusick else 11665325Smckusic n = (*func)(*ap, sblock.fs_frag); 11674236Smckusick if (n & STOP) 11684236Smckusick return (n); 11694236Smckusick } 11704236Smckusick return (KEEPON); 11714236Smckusick } 11724236Smckusick 1173*9255Smckusick outrange(blk, cnt) 11744236Smckusick daddr_t blk; 1175*9255Smckusick int cnt; 11764236Smckusick { 1177*9255Smckusick register int c; 11784236Smckusick 1179*9255Smckusick if ((unsigned)(blk+cnt) > fmax) 1180*9255Smckusick return (1); 1181*9255Smckusick c = dtog(&sblock, blk); 1182*9255Smckusick if (blk < cgdmin(&sblock, c)) { 1183*9255Smckusick if ((blk+cnt) > cgsblock(&sblock, c)) { 1184*9255Smckusick if (debug) { 1185*9255Smckusick printf("blk %d < cgdmin %d;", 1186*9255Smckusick blk, cgdmin(&sblock, c)); 1187*9255Smckusick printf(" blk+cnt %d > cgsbase %d\n", 1188*9255Smckusick blk+cnt, cgsblock(&sblock, c)); 11898534Sroot } 1190*9255Smckusick return (1); 11918534Sroot } 1192*9255Smckusick } else { 1193*9255Smckusick if ((blk+cnt) > cgbase(&sblock, c+1)) { 1194*9255Smckusick if (debug) { 1195*9255Smckusick printf("blk %d >= cgdmin %d;", 1196*9255Smckusick blk, cgdmin(&sblock, c)); 1197*9255Smckusick printf(" blk+cnt %d > sblock.fs_fpg %d\n", 1198*9255Smckusick blk+cnt, sblock.fs_fpg); 11998534Sroot } 1200*9255Smckusick return (1); 12018534Sroot } 12024428Smckusic } 12034236Smckusick return (0); 12044236Smckusick } 12054236Smckusick 12064236Smckusick blkerr(s, blk) 12074236Smckusick daddr_t blk; 12084236Smckusick char *s; 12094236Smckusick { 1210*9255Smckusick 12114236Smckusick pfatal("%ld %s I=%u", blk, s, inum); 12124236Smckusick printf("\n"); 1213*9255Smckusick statemap[inum] = CLEAR; 12144236Smckusick } 12154236Smckusick 12164236Smckusick descend() 12174236Smckusick { 12184236Smckusick register DINODE *dp; 12194236Smckusick register char *savname; 12204236Smckusick off_t savsize; 12214236Smckusick 1222*9255Smckusick statemap[inum] = FSTATE; 12234236Smckusick if ((dp = ginode()) == NULL) 12244236Smckusick return; 12254236Smckusick savname = thisname; 12264236Smckusick *pathp++ = '/'; 12274236Smckusick savsize = filsize; 12284236Smckusick filsize = dp->di_size; 12294236Smckusick ckinode(dp, DATA); 12304236Smckusick thisname = savname; 12314236Smckusick *--pathp = 0; 12324236Smckusick filsize = savsize; 12334236Smckusick } 12344236Smckusick 12355877Smckusic struct dirstuff { 12365877Smckusic int loc; 12375877Smckusic int blkno; 12385877Smckusic int blksiz; 12396634Smckusick ino_t number; 12406838Smckusick enum {DONTKNOW, NOFIX, FIX} fix; 12415877Smckusic }; 12425877Smckusic 12434236Smckusick dirscan(blk, nf) 12444715Smckusic daddr_t blk; 12454715Smckusic int nf; 12464236Smckusick { 12475877Smckusic register DIRECT *dp; 12485877Smckusic struct dirstuff dirp; 12496251Smckusick int blksiz, dsize, n; 12506251Smckusick char dbuf[DIRBLKSIZ]; 12514236Smckusick 1252*9255Smckusick if (outrange(blk, 1)) { 12535325Smckusic filsize -= sblock.fs_bsize; 12544236Smckusick return (SKIP); 12554236Smckusick } 12565877Smckusic blksiz = nf * sblock.fs_fsize; 12575877Smckusic dirp.loc = 0; 12585877Smckusic dirp.blkno = blk; 12595877Smckusic dirp.blksiz = blksiz; 12606837Smckusick if (dirp.number != dnum) { 12616837Smckusick dirp.number = dnum; 12626838Smckusick dirp.fix = DONTKNOW; 12636837Smckusick } 12645877Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 12656251Smckusick dsize = dp->d_reclen; 1266*9255Smckusick bcopy(dp, dbuf, dsize); 12676251Smckusick if ((n = (*pfunc)(dbuf)) & ALTERD) { 12685877Smckusic if (getblk(&fileblk, blk, blksiz) != NULL) { 1269*9255Smckusick bcopy(dbuf, dp, dsize); 12704715Smckusic dirty(&fileblk); 12714236Smckusick sbdirty(); 12724236Smckusick } else 12734236Smckusick n &= ~ALTERD; 12744236Smckusick } 12755877Smckusic if (n & STOP) 12764236Smckusick return (n); 12774236Smckusick } 12784236Smckusick return (filsize > 0 ? KEEPON : STOP); 12794236Smckusick } 12804236Smckusick 12815877Smckusic /* 12825877Smckusic * get next entry in a directory. 12835877Smckusic */ 12845877Smckusic DIRECT * 12855877Smckusic readdir(dirp) 12865877Smckusic register struct dirstuff *dirp; 12875877Smckusic { 12886251Smckusick register DIRECT *dp, *ndp; 12896837Smckusick long size; 12905877Smckusic 12915877Smckusic if (getblk(&fileblk, dirp->blkno, dirp->blksiz) == NULL) { 12925877Smckusic filsize -= dirp->blksiz - dirp->loc; 12935877Smckusic return NULL; 12945877Smckusic } 12956837Smckusick while (dirp->loc % DIRBLKSIZ == 0 && filsize > 0 && 12966837Smckusick dirp->loc < dirp->blksiz) { 12975935Smckusic dp = (DIRECT *)(dirblk.b_buf + dirp->loc); 12986837Smckusick if (dp->d_ino < imax && 12996837Smckusick dp->d_namlen <= MAXNAMLEN && dp->d_namlen >= 0 && 13006837Smckusick dp->d_reclen > 0 && dp->d_reclen <= DIRBLKSIZ) 13016837Smckusick break; 13026837Smckusick dirp->loc += DIRBLKSIZ; 13036837Smckusick filsize -= DIRBLKSIZ; 13046838Smckusick if (dirp->fix == DONTKNOW) { 13056634Smckusick pwarn("DIRECTORY %D CORRUPTED", dirp->number); 13066838Smckusick dirp->fix = NOFIX; 13076837Smckusick if (preen) { 13086251Smckusick printf(" (SALVAGED)\n"); 13096838Smckusick dirp->fix = FIX; 13106837Smckusick } else if (reply("SALVAGE") != 0) 13116838Smckusick dirp->fix = FIX; 13126837Smckusick } 13136838Smckusick if (dirp->fix != FIX) 13145877Smckusic continue; 13156837Smckusick dp->d_reclen = DIRBLKSIZ; 13166837Smckusick dp->d_ino = 0; 13176837Smckusick dp->d_namlen = 0; 13186837Smckusick dirty(&fileblk); 13196837Smckusick } 13206837Smckusick if (filsize <= 0 || dirp->loc >= dirp->blksiz) 13216837Smckusick return NULL; 13226837Smckusick dp = (DIRECT *)(dirblk.b_buf + dirp->loc); 13236837Smckusick dirp->loc += dp->d_reclen; 13246837Smckusick filsize -= dp->d_reclen; 13256837Smckusick ndp = (DIRECT *)(dirblk.b_buf + dirp->loc); 13267529Smckusick if ((filsize <= 0 && dirp->loc % DIRBLKSIZ != 0) || 13277529Smckusick (dirp->loc < dirp->blksiz && filsize > 0 && 13286837Smckusick (ndp->d_ino >= imax || 13296837Smckusick ndp->d_namlen > MAXNAMLEN || ndp->d_namlen < 0 || 13306837Smckusick ndp->d_reclen <= 0 || 13317529Smckusick ndp->d_reclen > DIRBLKSIZ - (dirp->loc % DIRBLKSIZ)))) { 13326837Smckusick size = DIRBLKSIZ - (dirp->loc % DIRBLKSIZ); 13336837Smckusick dirp->loc += size; 13346837Smckusick filsize -= size; 13356838Smckusick if (dirp->fix == DONTKNOW) { 13366837Smckusick pwarn("DIRECTORY %D CORRUPTED", dirp->number); 13376838Smckusick dirp->fix = NOFIX; 13386837Smckusick if (preen) { 13396837Smckusick printf(" (SALVAGED)\n"); 13406838Smckusick dirp->fix = FIX; 13416837Smckusick } else if (reply("SALVAGE") != 0) 13426838Smckusick dirp->fix = FIX; 13436251Smckusick } 13446838Smckusick if (dirp->fix == FIX) { 13456837Smckusick dp->d_reclen += size; 13466837Smckusick dirty(&fileblk); 13476837Smckusick } 13485877Smckusic } 13496837Smckusick return (dp); 13505877Smckusic } 13515877Smckusic 13524236Smckusick direrr(s) 13534715Smckusic char *s; 13544236Smckusick { 13554236Smckusick register DINODE *dp; 13564236Smckusick 13574236Smckusick pwarn("%s ", s); 13584236Smckusick pinode(); 13594236Smckusick printf("\n"); 13604236Smckusick if ((dp = ginode()) != NULL && ftypeok(dp)) 13615877Smckusic pfatal("%s=%s", DIRCT?"DIR":"FILE", pathname); 13624236Smckusick else 13634236Smckusick pfatal("NAME=%s", pathname); 13644236Smckusick return (reply("REMOVE")); 13654236Smckusick } 13664236Smckusick 13674236Smckusick adjust(lcnt) 13684465Smckusic register short lcnt; 13694236Smckusick { 13704236Smckusick register DINODE *dp; 13714236Smckusick 13724236Smckusick if ((dp = ginode()) == NULL) 13734236Smckusick return; 13744236Smckusick if (dp->di_nlink == lcnt) { 13754236Smckusick if (linkup() == 0) 13764236Smckusick clri("UNREF", 0); 13774236Smckusick } 13784236Smckusick else { 13794236Smckusick pwarn("LINK COUNT %s", 13805877Smckusic (lfdir==inum)?lfname:(DIRCT?"DIR":"FILE")); 13814236Smckusick pinode(); 13824236Smckusick printf(" COUNT %d SHOULD BE %d", 13834236Smckusick dp->di_nlink, dp->di_nlink-lcnt); 13844236Smckusick if (preen) { 13854236Smckusick if (lcnt < 0) { 13864236Smckusick printf("\n"); 13874236Smckusick preendie(); 13884236Smckusick } 13894236Smckusick printf(" (ADJUSTED)\n"); 13904236Smckusick } 13914236Smckusick if (preen || reply("ADJUST") == 1) { 13924236Smckusick dp->di_nlink -= lcnt; 13934236Smckusick inodirty(); 13944236Smckusick } 13954236Smckusick } 13964236Smckusick } 13974236Smckusick 13984236Smckusick clri(s, flg) 13994715Smckusic char *s; 14004236Smckusick { 14014236Smckusick register DINODE *dp; 14024236Smckusick 14034236Smckusick if ((dp = ginode()) == NULL) 14044236Smckusick return; 14054236Smckusick if (flg == 1) { 14065877Smckusic pwarn("%s %s", s, DIRCT?"DIR":"FILE"); 14074236Smckusick pinode(); 14084236Smckusick } 14094236Smckusick if (preen || reply("CLEAR") == 1) { 14104236Smckusick if (preen) 14114236Smckusick printf(" (CLEARED)\n"); 14124236Smckusick n_files--; 1413*9255Smckusick pfunc = pass4check; 14144236Smckusick ckinode(dp, ADDR); 14154236Smckusick zapino(dp); 1416*9255Smckusick statemap[inum] = USTATE; 14174236Smckusick inodirty(); 14184236Smckusick inosumbad++; 14194236Smckusick } 14204236Smckusick } 14214236Smckusick 14224236Smckusick badsb(s) 14234236Smckusick char *s; 14244236Smckusick { 14254236Smckusick 14264236Smckusick if (preen) 14274236Smckusick printf("%s: ", devname); 14284236Smckusick printf("BAD SUPER BLOCK: %s\n", s); 14294236Smckusick pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n"); 14304236Smckusick pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n"); 14314236Smckusick } 14324236Smckusick 14334236Smckusick DINODE * 14344236Smckusick ginode() 14354236Smckusick { 14364236Smckusick daddr_t iblk; 14374236Smckusick 14386547Smckusick if (inum < ROOTINO || inum > imax) { 14396547Smckusick if (debug && (inum < 0 || inum > imax)) 14406547Smckusick printf("inum out of range (%d)\n", inum); 14414236Smckusick return (NULL); 14426547Smckusick } 14435325Smckusic if (inum < startinum || inum >= startinum + INOPB(&sblock)) { 14445381Smckusic iblk = itod(&sblock, inum); 14455325Smckusic if (getblk(&inoblk, iblk, sblock.fs_bsize) == NULL) { 14464236Smckusick return (NULL); 14474236Smckusick } 14485325Smckusic startinum = (inum / INOPB(&sblock)) * INOPB(&sblock); 14494236Smckusick } 14505325Smckusic return (&inoblk.b_un.b_dinode[inum % INOPB(&sblock)]); 14514236Smckusick } 14524236Smckusick 14534236Smckusick ftypeok(dp) 14544236Smckusick DINODE *dp; 14554236Smckusick { 14564236Smckusick switch (dp->di_mode & IFMT) { 14574236Smckusick 14584236Smckusick case IFDIR: 14594236Smckusick case IFREG: 14604236Smckusick case IFBLK: 14614236Smckusick case IFCHR: 14626285Smckusick case IFLNK: 14634236Smckusick return (1); 14644236Smckusick 14654236Smckusick default: 14669235Smckusick if (debug) 14679235Smckusick printf("bad file type 0%o\n", dp->di_mode); 14684236Smckusick return (0); 14694236Smckusick } 14704236Smckusick } 14714236Smckusick 14724236Smckusick reply(s) 14734236Smckusick char *s; 14744236Smckusick { 14754236Smckusick char line[80]; 14764236Smckusick 14774236Smckusick if (preen) 14784236Smckusick pfatal("INTERNAL ERROR: GOT TO reply()"); 14794236Smckusick rplyflag = 1; 14804236Smckusick printf("\n%s? ", s); 14814236Smckusick if (nflag || dfile.wfdes < 0) { 14824236Smckusick printf(" no\n\n"); 14834236Smckusick return (0); 14844236Smckusick } 14854236Smckusick if (yflag) { 14864236Smckusick printf(" yes\n\n"); 14874236Smckusick return (1); 14884236Smckusick } 14894236Smckusick if (getline(stdin, line, sizeof(line)) == EOF) 14904236Smckusick errexit("\n"); 14914236Smckusick printf("\n"); 14924236Smckusick if (line[0] == 'y' || line[0] == 'Y') 14934236Smckusick return (1); 14944236Smckusick else 14954236Smckusick return (0); 14964236Smckusick } 14974236Smckusick 14984236Smckusick getline(fp, loc, maxlen) 14994236Smckusick FILE *fp; 15004236Smckusick char *loc; 15014236Smckusick { 15024236Smckusick register n; 15034236Smckusick register char *p, *lastloc; 15044236Smckusick 15054236Smckusick p = loc; 15064236Smckusick lastloc = &p[maxlen-1]; 15074236Smckusick while ((n = getc(fp)) != '\n') { 15084236Smckusick if (n == EOF) 15094236Smckusick return (EOF); 15104236Smckusick if (!isspace(n) && p < lastloc) 15114236Smckusick *p++ = n; 15124236Smckusick } 15134236Smckusick *p = 0; 15144236Smckusick return (p - loc); 15154236Smckusick } 15164236Smckusick 15174236Smckusick BUFAREA * 15184236Smckusick getblk(bp, blk, size) 15194236Smckusick daddr_t blk; 15204236Smckusick register BUFAREA *bp; 15214236Smckusick int size; 15224236Smckusick { 15234236Smckusick register struct filecntl *fcp; 15245325Smckusic daddr_t dblk; 15254236Smckusick 15264236Smckusick fcp = &dfile; 15275325Smckusic dblk = fsbtodb(&sblock, blk); 15285325Smckusic if (bp->b_bno == dblk) 15294236Smckusick return (bp); 15304236Smckusick flush(fcp, bp); 15315325Smckusic if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) { 15325325Smckusic bp->b_bno = dblk; 15334236Smckusick bp->b_size = size; 15344236Smckusick return (bp); 15354236Smckusick } 15364236Smckusick bp->b_bno = (daddr_t)-1; 15374236Smckusick return (NULL); 15384236Smckusick } 15394236Smckusick 15404236Smckusick flush(fcp, bp) 15414236Smckusick struct filecntl *fcp; 15424236Smckusick register BUFAREA *bp; 15434236Smckusick { 15444236Smckusick 15454236Smckusick if (bp->b_dirty) 15464236Smckusick bwrite(fcp, bp->b_un.b_buf, bp->b_bno, bp->b_size); 15474236Smckusick bp->b_dirty = 0; 15484236Smckusick } 15494236Smckusick 15504236Smckusick rwerr(s, blk) 15514236Smckusick char *s; 15524236Smckusick daddr_t blk; 15534236Smckusick { 15544236Smckusick 15554236Smckusick if (preen == 0) 15564236Smckusick printf("\n"); 15574236Smckusick pfatal("CANNOT %s: BLK %ld", s, blk); 15584236Smckusick if (reply("CONTINUE") == 0) 15594236Smckusick errexit("Program terminated\n"); 15604236Smckusick } 15614236Smckusick 15624236Smckusick ckfini() 15634236Smckusick { 15644236Smckusick 15654236Smckusick flush(&dfile, &fileblk); 15664236Smckusick flush(&dfile, &sblk); 15674465Smckusic if (sblk.b_bno != SBLOCK) { 15684465Smckusic sblk.b_bno = SBLOCK; 15694465Smckusic sbdirty(); 15704465Smckusic flush(&dfile, &sblk); 15714465Smckusic } 15724236Smckusick flush(&dfile, &inoblk); 15734236Smckusick close(dfile.rfdes); 15744236Smckusick close(dfile.wfdes); 15754236Smckusick } 15764236Smckusick 15774236Smckusick pinode() 15784236Smckusick { 15794236Smckusick register DINODE *dp; 15804236Smckusick register char *p; 15815877Smckusic char uidbuf[BUFSIZ]; 15824236Smckusick char *ctime(); 15834236Smckusick 15844236Smckusick printf(" I=%u ", inum); 15854236Smckusick if ((dp = ginode()) == NULL) 15864236Smckusick return; 15874236Smckusick printf(" OWNER="); 15884236Smckusick if (getpw((int)dp->di_uid, uidbuf) == 0) { 15894236Smckusick for (p = uidbuf; *p != ':'; p++); 15904236Smckusick *p = 0; 15914236Smckusick printf("%s ", uidbuf); 15924236Smckusick } 15934236Smckusick else { 15944236Smckusick printf("%d ", dp->di_uid); 15954236Smckusick } 15964236Smckusick printf("MODE=%o\n", dp->di_mode); 15974236Smckusick if (preen) 15984236Smckusick printf("%s: ", devname); 15994236Smckusick printf("SIZE=%ld ", dp->di_size); 16004236Smckusick p = ctime(&dp->di_mtime); 16014236Smckusick printf("MTIME=%12.12s %4.4s ", p+4, p+20); 16024236Smckusick } 16034236Smckusick 16044236Smckusick makecg() 16054236Smckusick { 16064465Smckusic int c, blk; 16076533Smckusick daddr_t dbase, d, dlower, dupper, dmax; 16084236Smckusick long i, j, s; 16094236Smckusick register struct csum *cs; 16104465Smckusic register DINODE *dp; 16114236Smckusick 16124789Smckusic sblock.fs_cstotal.cs_nbfree = 0; 16134789Smckusic sblock.fs_cstotal.cs_nffree = 0; 16144789Smckusic sblock.fs_cstotal.cs_nifree = 0; 16154789Smckusic sblock.fs_cstotal.cs_ndir = 0; 16164236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 16175381Smckusic dbase = cgbase(&sblock, c); 16184236Smckusick dmax = dbase + sblock.fs_fpg; 16195409Smckusic if (dmax > sblock.fs_size) { 16205944Smckusic for ( ; dmax >= sblock.fs_size; dmax--) 16215401Smckusic clrbit(cgrp.cg_free, dmax - dbase); 16225409Smckusic dmax++; 16235409Smckusic } 16246533Smckusick dlower = cgsblock(&sblock, c) - dbase; 16256533Smckusick dupper = cgdmin(&sblock, c) - dbase; 16265325Smckusic cs = &sblock.fs_cs(&sblock, c); 16274236Smckusick cgrp.cg_time = time(0); 16284236Smckusick cgrp.cg_magic = CG_MAGIC; 16294236Smckusick cgrp.cg_cgx = c; 16309235Smckusick if (c == sblock.fs_ncg - 1) 16319235Smckusick cgrp.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 16329235Smckusick else 16339235Smckusick cgrp.cg_ncyl = sblock.fs_cpg; 16344236Smckusick cgrp.cg_niblk = sblock.fs_ipg; 16354236Smckusick cgrp.cg_ndblk = dmax - dbase; 16364789Smckusic cgrp.cg_cs.cs_ndir = 0; 16374789Smckusic cgrp.cg_cs.cs_nffree = 0; 16384789Smckusic cgrp.cg_cs.cs_nbfree = 0; 16394789Smckusic cgrp.cg_cs.cs_nifree = 0; 16406533Smckusick cgrp.cg_rotor = 0; 16416533Smckusick cgrp.cg_frotor = 0; 16424258Smckusic cgrp.cg_irotor = 0; 16435325Smckusic for (i = 0; i < sblock.fs_frag; i++) 16444465Smckusic cgrp.cg_frsum[i] = 0; 16454236Smckusick inum = sblock.fs_ipg * c; 16464465Smckusic for (i = 0; i < sblock.fs_ipg; inum++, i++) { 16475944Smckusic cgrp.cg_cs.cs_nifree++; 16485944Smckusic clrbit(cgrp.cg_iused, i); 16494465Smckusic dp = ginode(); 16504465Smckusic if (dp == NULL) 16514465Smckusic continue; 16524465Smckusic if (ALLOC) { 16535877Smckusic if (DIRCT) 16544789Smckusic cgrp.cg_cs.cs_ndir++; 16555944Smckusic cgrp.cg_cs.cs_nifree--; 16564465Smckusic setbit(cgrp.cg_iused, i); 16574465Smckusic continue; 16584465Smckusic } 16594236Smckusick } 16604236Smckusick while (i < MAXIPG) { 16614236Smckusick clrbit(cgrp.cg_iused, i); 16624236Smckusick i++; 16634236Smckusick } 16645944Smckusic if (c == 0) 16655944Smckusic for (i = 0; i < ROOTINO; i++) { 16665944Smckusic setbit(cgrp.cg_iused, i); 16675944Smckusic cgrp.cg_cs.cs_nifree--; 16685944Smckusic } 16695371Smckusic for (s = 0; s < MAXCPG; s++) { 16705371Smckusic cgrp.cg_btot[s] = 0; 16714236Smckusick for (i = 0; i < NRPOS; i++) 16724236Smckusick cgrp.cg_b[s][i] = 0; 16735371Smckusic } 16744236Smckusick if (c == 0) { 16756533Smckusick dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 16764236Smckusick } 16776533Smckusick for (d = dlower; d < dupper; d++) 16784236Smckusick clrbit(cgrp.cg_free, d); 16796533Smckusick for (d = 0; (d + sblock.fs_frag) <= dmax - dbase; 16806533Smckusick d += sblock.fs_frag) { 16814236Smckusick j = 0; 16825325Smckusic for (i = 0; i < sblock.fs_frag; i++) { 16836533Smckusick if (!getbmap(dbase + d + i)) { 16846533Smckusick setbit(cgrp.cg_free, d + i); 16854236Smckusick j++; 16864236Smckusick } else 16874236Smckusick clrbit(cgrp.cg_free, d+i); 16884236Smckusick } 16895325Smckusic if (j == sblock.fs_frag) { 16904789Smckusic cgrp.cg_cs.cs_nbfree++; 16915371Smckusic cgrp.cg_btot[cbtocylno(&sblock, d)]++; 16925363Smckusic cgrp.cg_b[cbtocylno(&sblock, d)] 16935363Smckusic [cbtorpos(&sblock, d)]++; 16944465Smckusic } else if (j > 0) { 16954789Smckusic cgrp.cg_cs.cs_nffree += j; 16966533Smckusick blk = blkmap(&sblock, cgrp.cg_free, d); 16975325Smckusic fragacct(&sblock, blk, cgrp.cg_frsum, 1); 16984465Smckusic } 16994236Smckusick } 17004465Smckusic for (j = d; d < dmax - dbase; d++) { 17016533Smckusick if (!getbmap(dbase + d)) { 17024236Smckusick setbit(cgrp.cg_free, d); 17034789Smckusic cgrp.cg_cs.cs_nffree++; 17044236Smckusick } else 17054236Smckusick clrbit(cgrp.cg_free, d); 17064236Smckusick } 17079235Smckusick for (; d % sblock.fs_frag != 0; d++) 17089235Smckusick clrbit(cgrp.cg_free, d); 17094465Smckusic if (j != d) { 17106533Smckusick blk = blkmap(&sblock, cgrp.cg_free, j); 17115325Smckusic fragacct(&sblock, blk, cgrp.cg_frsum, 1); 17124465Smckusic } 17139235Smckusick for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++) 17149235Smckusick clrblock(&sblock, cgrp.cg_free, d); 17154789Smckusic sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree; 17164789Smckusic sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree; 17174789Smckusic sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree; 17184789Smckusic sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir; 17194789Smckusic *cs = cgrp.cg_cs; 17205381Smckusic bwrite(&dfile, &cgrp, fsbtodb(&sblock, cgtod(&sblock, c)), 17215956Smckusic sblock.fs_cgsize); 17224236Smckusick } 17236533Smckusick for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 17246533Smckusick bwrite(&dfile, (char *)sblock.fs_csp[j], 17256533Smckusick fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 17266533Smckusick sblock.fs_cssize - i < sblock.fs_bsize ? 17276533Smckusick sblock.fs_cssize - i : sblock.fs_bsize); 17285097Smckusic } 17294236Smckusick sblock.fs_ronly = 0; 17304236Smckusick sblock.fs_fmod = 0; 17314236Smckusick sbdirty(); 17324236Smckusick } 17334236Smckusick 17344236Smckusick findino(dirp) 17354236Smckusick register DIRECT *dirp; 17364236Smckusick { 17374236Smckusick if (dirp->d_ino == 0) 17384236Smckusick return (KEEPON); 17395877Smckusic if (!strcmp(dirp->d_name, srchname)) { 17405877Smckusic if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) 17415877Smckusic parentdir = dirp->d_ino; 17425877Smckusic return (STOP); 17434236Smckusick } 17444236Smckusick return (KEEPON); 17454236Smckusick } 17464236Smckusick 17474236Smckusick mkentry(dirp) 17484236Smckusick register DIRECT *dirp; 17494236Smckusick { 17504236Smckusick register ino_t in; 17514236Smckusick register char *p; 17526251Smckusick DIRECT newent; 17536251Smckusick int newlen, oldlen; 17544236Smckusick 17556251Smckusick newent.d_namlen = 11; 17566251Smckusick newlen = DIRSIZ(&newent); 17576251Smckusick if (dirp->d_ino != 0) 17586251Smckusick oldlen = DIRSIZ(dirp); 17596251Smckusick else 17606251Smckusick oldlen = 0; 17616251Smckusick if (dirp->d_reclen - oldlen < newlen) 17624236Smckusick return (KEEPON); 17636251Smckusick newent.d_reclen = dirp->d_reclen - oldlen; 17646251Smckusick dirp->d_reclen = oldlen; 17656251Smckusick dirp = (struct direct *)(((char *)dirp) + oldlen); 17664236Smckusick dirp->d_ino = orphan; 17676251Smckusick dirp->d_reclen = newent.d_reclen; 17686251Smckusick p = &dirp->d_name[2]; 17696251Smckusick for (in = imax; in > 0; in /= 10) 17706251Smckusick p++; 17716251Smckusick *--p = 0; 17726251Smckusick dirp->d_namlen = p - dirp->d_name; 17734236Smckusick in = orphan; 17744236Smckusick while (p > dirp->d_name) { 17754236Smckusick *--p = (in % 10) + '0'; 17764236Smckusick in /= 10; 17774236Smckusick } 17784236Smckusick *p = '#'; 17794236Smckusick return (ALTERD|STOP); 17804236Smckusick } 17814236Smckusick 17824236Smckusick chgdd(dirp) 17834236Smckusick register DIRECT *dirp; 17844236Smckusick { 17854236Smckusick if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' && 17864236Smckusick dirp->d_name[2] == 0) { 17874236Smckusick dirp->d_ino = lfdir; 17884236Smckusick return (ALTERD|STOP); 17894236Smckusick } 17904236Smckusick return (KEEPON); 17914236Smckusick } 17924236Smckusick 17934236Smckusick linkup() 17944236Smckusick { 17954236Smckusick register DINODE *dp; 17964236Smckusick register lostdir; 17974236Smckusick register ino_t pdir; 17984236Smckusick 17994236Smckusick if ((dp = ginode()) == NULL) 18004236Smckusick return (0); 18015877Smckusic lostdir = DIRCT; 18024236Smckusick pdir = parentdir; 18034236Smckusick pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); 18044236Smckusick pinode(); 18054236Smckusick if (preen && dp->di_size == 0) 18064236Smckusick return (0); 18074236Smckusick if (preen) 18084236Smckusick printf(" (RECONNECTED)\n"); 18094236Smckusick else 18104236Smckusick if (reply("RECONNECT") == 0) 18114236Smckusick return (0); 18124236Smckusick orphan = inum; 18134236Smckusick if (lfdir == 0) { 18144236Smckusick inum = ROOTINO; 18154236Smckusick if ((dp = ginode()) == NULL) { 18164236Smckusick inum = orphan; 18174236Smckusick return (0); 18184236Smckusick } 18194236Smckusick pfunc = findino; 18204236Smckusick srchname = lfname; 18214236Smckusick filsize = dp->di_size; 18224236Smckusick parentdir = 0; 18234236Smckusick ckinode(dp, DATA); 18244236Smckusick inum = orphan; 18254236Smckusick if ((lfdir = parentdir) == 0) { 18264236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 18274236Smckusick printf("\n\n"); 18284236Smckusick return (0); 18294236Smckusick } 18304236Smckusick } 18314236Smckusick inum = lfdir; 1832*9255Smckusick if ((dp = ginode()) == NULL || !DIRCT || statemap[inum] != FSTATE) { 18334236Smckusick inum = orphan; 18344236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 18354236Smckusick printf("\n\n"); 18364236Smckusick return (0); 18374236Smckusick } 18385956Smckusic if (fragoff(&sblock, dp->di_size)) { 18395956Smckusic dp->di_size = fragroundup(&sblock, dp->di_size); 18404236Smckusick inodirty(); 18414236Smckusick } 18424236Smckusick filsize = dp->di_size; 18434236Smckusick inum = orphan; 18444236Smckusick pfunc = mkentry; 18454236Smckusick if ((ckinode(dp, DATA) & ALTERD) == 0) { 18464236Smckusick pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); 18474236Smckusick printf("\n\n"); 18484236Smckusick return (0); 18494236Smckusick } 1850*9255Smckusick lncntp[inum]--; 18514236Smckusick if (lostdir) { 18524236Smckusick pfunc = chgdd; 18534236Smckusick dp = ginode(); 18544236Smckusick filsize = dp->di_size; 18554236Smckusick ckinode(dp, DATA); 18564236Smckusick inum = lfdir; 18574236Smckusick if ((dp = ginode()) != NULL) { 18584236Smckusick dp->di_nlink++; 18594236Smckusick inodirty(); 1860*9255Smckusick lncntp[inum]++; 18614236Smckusick } 18624236Smckusick inum = orphan; 18634236Smckusick pwarn("DIR I=%u CONNECTED. ", orphan); 18644236Smckusick printf("PARENT WAS I=%u\n", pdir); 18654236Smckusick if (preen == 0) 18664236Smckusick printf("\n"); 18674236Smckusick } 18684236Smckusick return (1); 18694236Smckusick } 18704236Smckusick 18714236Smckusick bread(fcp, buf, blk, size) 18724236Smckusick daddr_t blk; 18734236Smckusick register struct filecntl *fcp; 18744236Smckusick register size; 18754236Smckusick char *buf; 18764236Smckusick { 18775325Smckusic if (lseek(fcp->rfdes, blk * DEV_BSIZE, 0) < 0) 18784236Smckusick rwerr("SEEK", blk); 18794236Smckusick else if (read(fcp->rfdes, buf, size) == size) 18804236Smckusick return (1); 18814236Smckusick rwerr("READ", blk); 18824236Smckusick return (0); 18834236Smckusick } 18844236Smckusick 18854236Smckusick bwrite(fcp, buf, blk, size) 18864236Smckusick daddr_t blk; 18874236Smckusick register struct filecntl *fcp; 18884236Smckusick register size; 18894236Smckusick char *buf; 18904236Smckusick { 18914236Smckusick 18924236Smckusick if (fcp->wfdes < 0) 18934236Smckusick return (0); 18945325Smckusic if (lseek(fcp->wfdes, blk * DEV_BSIZE, 0) < 0) 18954236Smckusick rwerr("SEEK", blk); 18964236Smckusick else if (write(fcp->wfdes, buf, size) == size) { 18974236Smckusick fcp->mod = 1; 18984236Smckusick return (1); 18994236Smckusick } 19004236Smckusick rwerr("WRITE", blk); 19014236Smckusick return (0); 19024236Smckusick } 19034236Smckusick 19044236Smckusick catch() 19054236Smckusick { 19064236Smckusick 19074236Smckusick ckfini(); 19084236Smckusick exit(12); 19094236Smckusick } 19105325Smckusic 1911*9255Smckusick char * 1912*9255Smckusick unrawname(cp) 1913*9255Smckusick char *cp; 1914*9255Smckusick { 1915*9255Smckusick char *dp = rindex(cp, '/'); 1916*9255Smckusick struct stat stb; 19176489Smckusick 1918*9255Smckusick if (dp == 0) 1919*9255Smckusick return (cp); 1920*9255Smckusick if (stat(cp, &stb) < 0) 1921*9255Smckusick return (cp); 1922*9255Smckusick if ((stb.st_mode&S_IFMT) != S_IFCHR) 1923*9255Smckusick return (cp); 1924*9255Smckusick if (*(dp+1) != 'r') 1925*9255Smckusick return (cp); 1926*9255Smckusick strcpy(dp+1, dp+2); 1927*9255Smckusick return (cp); 1928*9255Smckusick } 1929*9255Smckusick 1930*9255Smckusick char * 1931*9255Smckusick rawname(cp) 1932*9255Smckusick char *cp; 19337608Sroot { 1934*9255Smckusick static char rawbuf[32]; 1935*9255Smckusick char *dp = rindex(cp, '/'); 19366489Smckusick 1937*9255Smckusick if (dp == 0) 19387608Sroot return (0); 1939*9255Smckusick *dp = 0; 1940*9255Smckusick strcpy(rawbuf, cp); 1941*9255Smckusick *dp = '/'; 1942*9255Smckusick strcat(rawbuf, "/r"); 1943*9255Smckusick strcat(rawbuf, dp+1); 1944*9255Smckusick return (rawbuf); 19457608Sroot } 19466489Smckusick 1947*9255Smckusick /* VARARGS1 */ 1948*9255Smckusick error(s1, s2, s3, s4) 1949*9255Smckusick char *s1; 1950*9255Smckusick { 1951*9255Smckusick 1952*9255Smckusick printf(s1, s2, s3, s4); 1953*9255Smckusick } 1954*9255Smckusick 1955*9255Smckusick /* VARARGS1 */ 1956*9255Smckusick errexit(s1, s2, s3, s4) 1957*9255Smckusick char *s1; 1958*9255Smckusick { 1959*9255Smckusick error(s1, s2, s3, s4); 1960*9255Smckusick exit(8); 1961*9255Smckusick } 1962*9255Smckusick 19639235Smckusick /* 1964*9255Smckusick * An inconsistency occured which shouldn't during normal operations. 1965*9255Smckusick * Die if preening, otw just printf. 19669235Smckusick */ 1967*9255Smckusick /* VARARGS1 */ 1968*9255Smckusick pfatal(s, a1, a2, a3) 1969*9255Smckusick char *s; 19709235Smckusick { 1971*9255Smckusick 1972*9255Smckusick if (preen) { 1973*9255Smckusick printf("%s: ", devname); 1974*9255Smckusick printf(s, a1, a2, a3); 1975*9255Smckusick printf("\n"); 1976*9255Smckusick preendie(); 19779235Smckusick } 1978*9255Smckusick printf(s, a1, a2, a3); 19799235Smckusick } 19809235Smckusick 1981*9255Smckusick preendie() 1982*9255Smckusick { 19837608Sroot 1984*9255Smckusick printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); 1985*9255Smckusick exit(8); 1986*9255Smckusick } 19877608Sroot 19886489Smckusick /* 1989*9255Smckusick * Pwarn is like printf when not preening, 1990*9255Smckusick * or a warning (preceded by filename) when preening. 19916489Smckusick */ 1992*9255Smckusick /* VARARGS1 */ 1993*9255Smckusick pwarn(s, a1, a2, a3, a4, a5, a6) 1994*9255Smckusick char *s; 1995*9255Smckusick { 19966489Smckusick 1997*9255Smckusick if (preen) 1998*9255Smckusick printf("%s: ", devname); 1999*9255Smckusick printf(s, a1, a2, a3, a4, a5, a6); 2000*9255Smckusick } 20016489Smckusick 2002*9255Smckusick panic(s) 2003*9255Smckusick char *s; 2004*9255Smckusick { 20056489Smckusick 2006*9255Smckusick pfatal("internal inconsistency: %s\n"); 2007*9255Smckusick exit(12); 2008*9255Smckusick } 2009