1*6251Smckusick static char *sccsid = "@(#)main.c 1.26 (Berkeley) 03/17/82"; 24428Smckusic 34236Smckusick #include <stdio.h> 44236Smckusick #include <ctype.h> 54236Smckusick #include "../h/param.h" 64236Smckusick #include "../h/fs.h" 74236Smckusick #include "../h/inode.h" 84236Smckusick #include "../h/stat.h" 94878Smckusic #include "../h/ostat.h" 105956Smckusic #include <ndir.h> 114236Smckusick #include <fstab.h> 124236Smckusick 134236Smckusick typedef int (*SIG_TYP)(); 144236Smckusick 155347Smckusic #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 165347Smckusic #define MAXINOPB (MAXBSIZE / sizeof (struct dinode)) 175325Smckusic #define SPERB (MAXBSIZE / sizeof(short)) 184236Smckusick 194236Smckusick #define MAXDUP 10 /* limit on dup blks (per inode) */ 204236Smckusick #define MAXBAD 10 /* limit on bad blks (per inode) */ 214236Smckusick 224236Smckusick #define USTATE 0 /* inode not allocated */ 234236Smckusick #define FSTATE 01 /* inode is file */ 244236Smckusick #define DSTATE 02 /* inode is directory */ 254236Smckusick #define CLEAR 03 /* inode is to be cleared */ 264236Smckusick 274236Smckusick typedef struct dinode DINODE; 284236Smckusick typedef struct direct DIRECT; 294236Smckusick 304236Smckusick #define ALLOC ((dp->di_mode & IFMT) != 0) 315877Smckusic #define DIRCT ((dp->di_mode & IFMT) == IFDIR) 324236Smckusick #define REG ((dp->di_mode & IFMT) == IFREG) 334236Smckusick #define BLK ((dp->di_mode & IFMT) == IFBLK) 344236Smckusick #define CHR ((dp->di_mode & IFMT) == IFCHR) 354236Smckusick #define MPC ((dp->di_mode & IFMT) == IFMPC) 364236Smckusick #define MPB ((dp->di_mode & IFMT) == IFMPB) 374236Smckusick #define SPECIAL (BLK || CHR || MPC || MPB) 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 844236Smckusick #define MAXLNCNT 20 /* 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 984236Smckusick char *blkmap; /* 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 */ 1114236Smckusick ino_t imax; /* number of inodes */ 1124236Smckusick ino_t parentdir; /* i number of parent directory */ 1134236Smckusick ino_t lastino; /* hiwater mark of inodes */ 1144236Smckusick ino_t lfdir; /* lost & found directory */ 1154236Smckusick ino_t orphan; /* orphaned inode */ 1164236Smckusick 1174236Smckusick off_t filsize; /* num blks seen in file */ 1184236Smckusick off_t maxblk; /* largest logical blk in file */ 1194236Smckusick off_t bmapsz; /* num chars in blkmap */ 1204236Smckusick 1214236Smckusick daddr_t n_ffree; /* number of small free blocks */ 1224236Smckusick daddr_t n_bfree; /* number of large free blocks */ 1234236Smckusick daddr_t n_blks; /* number of blocks used */ 1244236Smckusick daddr_t n_files; /* number of files seen */ 1254236Smckusick daddr_t n_index; 1264236Smckusick daddr_t n_bad; 1274236Smckusick daddr_t fmax; /* number of blocks in the volume */ 1284236Smckusick 1294236Smckusick daddr_t badblk; 1304236Smckusick daddr_t dupblk; 1314236Smckusick 1324236Smckusick int inosumbad; 1334236Smckusick int offsumbad; 1344465Smckusic int frsumbad; 1354236Smckusick 1364236Smckusick #define zapino(x) (*(x) = zino) 1374236Smckusick struct dinode zino; 1384236Smckusick 1394236Smckusick #define setlncnt(x) (lncntp[inum] = x) 1404236Smckusick #define getlncnt() (lncntp[inum]) 1414236Smckusick #define declncnt() (--lncntp[inum]) 1424236Smckusick 1434236Smckusick #define setbmap(x) setbit(blkmap, x) 1444236Smckusick #define getbmap(x) isset(blkmap, x) 1454236Smckusick #define clrbmap(x) clrbit(blkmap, x) 1464236Smckusick 1474236Smckusick #define setfmap(x) setbit(freemap, x) 1484236Smckusick #define getfmap(x) isset(freemap, x) 1494236Smckusick #define clrfmap(x) clrbit(freemap, x) 1504236Smckusick 1514236Smckusick #define setstate(x) (statemap[inum] = x) 1524236Smckusick #define getstate() statemap[inum] 1534236Smckusick 1544236Smckusick #define DATA 1 1554236Smckusick #define ADDR 0 1564236Smckusick 1574236Smckusick #define ALTERD 010 1584236Smckusick #define KEEPON 04 1594236Smckusick #define SKIP 02 1604236Smckusick #define STOP 01 1614236Smckusick 1624236Smckusick int (*signal())(); 1634236Smckusick long lseek(); 1644236Smckusick time_t time(); 1654236Smckusick DINODE *ginode(); 1664236Smckusick BUFAREA *getblk(); 1674236Smckusick int dirscan(); 1684236Smckusick int findino(); 1694236Smckusick int catch(); 1704236Smckusick int mkentry(); 1714236Smckusick int chgdd(); 1724236Smckusick int pass1(), pass1b(), pass2(), pass4(), pass5(); 1734236Smckusick int (*pfunc)(); 1744236Smckusick char *rawname(), *rindex(), *unrawname(); 1754606Smckusic extern int inside[], around[]; 1765325Smckusic extern unsigned char *fragtbl[]; 1774236Smckusick 1784236Smckusick char *devname; 1794236Smckusick 1804236Smckusick main(argc, argv) 1814715Smckusic int argc; 1824715Smckusic char *argv[]; 1834236Smckusick { 1844236Smckusick struct fstab *fsp; 1854236Smckusick int pid, passno, anygtr, sumstatus; 1864236Smckusick 1874236Smckusick sync(); 1884236Smckusick while (--argc > 0 && **++argv == '-') { 1894236Smckusick switch (*++*argv) { 1904236Smckusick 1914236Smckusick case 'p': 1924236Smckusick preen++; 1934236Smckusick break; 1944236Smckusick 1954236Smckusick case 'b': 1964236Smckusick bflag = atoi(argv[0]+1); 1974236Smckusick printf("Alternate super block location: %d\n", bflag); 1984236Smckusick break; 1994236Smckusick 2005381Smckusic case 'd': 2015381Smckusic debug++; 2025381Smckusic break; 2035381Smckusic 2044236Smckusick case 'n': /* default no answer flag */ 2054236Smckusick case 'N': 2064236Smckusick nflag++; 2074236Smckusick yflag = 0; 2084236Smckusick break; 2094236Smckusick 2104236Smckusick case 'y': /* default yes answer flag */ 2114236Smckusick case 'Y': 2124236Smckusick yflag++; 2134236Smckusick nflag = 0; 2144236Smckusick break; 2154236Smckusick 2164236Smckusick default: 2174236Smckusick errexit("%c option?\n", **argv); 2184236Smckusick } 2194236Smckusick } 2204236Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2214236Smckusick signal(SIGINT, catch); 2224236Smckusick if (argc) { 2234236Smckusick while (argc-- > 0) { 2244236Smckusick hotroot = 0; 2254236Smckusick check(*argv++); 2264236Smckusick } 2274236Smckusick exit(0); 2284236Smckusick } 2294236Smckusick sumstatus = 0; 2304236Smckusick passno = 1; 2314236Smckusick do { 2324236Smckusick anygtr = 0; 2334236Smckusick if (setfsent() == 0) 2344236Smckusick errexit("Can't open checklist file: %s\n", FSTAB); 2354236Smckusick while ((fsp = getfsent()) != 0) { 2364236Smckusick if (strcmp(fsp->fs_type, FSTAB_RW) && 2374236Smckusick strcmp(fsp->fs_type, FSTAB_RO)) 2384236Smckusick continue; 2394236Smckusick if (preen == 0 || 2404236Smckusick passno == 1 && fsp->fs_passno == passno) { 2414236Smckusick if (blockcheck(fsp->fs_spec) == 0 && preen) 2424236Smckusick exit(8); 2434236Smckusick } else if (fsp->fs_passno > passno) 2444236Smckusick anygtr = 1; 2454236Smckusick else if (fsp->fs_passno == passno) { 2464236Smckusick pid = fork(); 2474236Smckusick if (pid < 0) { 2484236Smckusick perror("fork"); 2494236Smckusick exit(8); 2504236Smckusick } 2514236Smckusick if (pid == 0) 2524236Smckusick if (blockcheck(fsp->fs_spec)==0) 2534236Smckusick exit(8); 2544236Smckusick else 2554236Smckusick exit(0); 2564236Smckusick } 2574236Smckusick } 2584236Smckusick if (preen) { 2594236Smckusick int status; 2604236Smckusick while (wait(&status) != -1) 2614236Smckusick sumstatus |= status; 2624236Smckusick } 2634236Smckusick passno++; 2644236Smckusick } while (anygtr); 2654236Smckusick if (sumstatus) 2664236Smckusick exit(8); 2674236Smckusick endfsent(); 2684236Smckusick exit(0); 2694236Smckusick } 2704236Smckusick 2714236Smckusick blockcheck(name) 2724236Smckusick char *name; 2734236Smckusick { 2744878Smckusic struct ostat stslash, stblock, stchar; 2754236Smckusick char *raw; 2764236Smckusick int looped = 0; 2774236Smckusick 2784236Smckusick hotroot = 0; 2794236Smckusick if (stat("/", &stslash) < 0){ 2804236Smckusick error("Can't stat root\n"); 2814236Smckusick return (0); 2824236Smckusick } 2834236Smckusick retry: 2844236Smckusick if (stat(name, &stblock) < 0){ 2854236Smckusick error("Can't stat %s\n", name); 2864236Smckusick return (0); 2874236Smckusick } 2884236Smckusick if (stblock.st_mode & S_IFBLK) { 2894236Smckusick raw = rawname(name); 2904236Smckusick if (stat(raw, &stchar) < 0){ 2914236Smckusick error("Can't stat %s\n", raw); 2924236Smckusick return (0); 2934236Smckusick } 2944236Smckusick if (stchar.st_mode & S_IFCHR) { 2954236Smckusick if (stslash.st_dev == stblock.st_rdev) { 2964236Smckusick hotroot++; 2974236Smckusick raw = unrawname(name); 2984236Smckusick } 2994236Smckusick check(raw); 3004236Smckusick return (1); 3014236Smckusick } else { 3024236Smckusick error("%s is not a character device\n", raw); 3034236Smckusick return (0); 3044236Smckusick } 3054236Smckusick } else if (stblock.st_mode & S_IFCHR) { 3064236Smckusick if (looped) { 3074236Smckusick error("Can't make sense out of name %s\n", name); 3084236Smckusick return (0); 3094236Smckusick } 3104236Smckusick name = unrawname(name); 3114236Smckusick looped++; 3124236Smckusick goto retry; 3134236Smckusick } 3144236Smckusick error("Can't make sense out of name %s\n", name); 3154236Smckusick return (0); 3164236Smckusick } 3174236Smckusick 3184236Smckusick char * 3194236Smckusick unrawname(cp) 3204236Smckusick char *cp; 3214236Smckusick { 3224236Smckusick char *dp = rindex(cp, '/'); 3234878Smckusic struct ostat stb; 3244236Smckusick 3254236Smckusick if (dp == 0) 3264236Smckusick return (cp); 3274236Smckusick if (stat(cp, &stb) < 0) 3284236Smckusick return (cp); 3294236Smckusick if ((stb.st_mode&S_IFMT) != S_IFCHR) 3304236Smckusick return (cp); 3314236Smckusick if (*(dp+1) != 'r') 3324236Smckusick return (cp); 3334236Smckusick strcpy(dp+1, dp+2); 3344236Smckusick return (cp); 3354236Smckusick } 3364236Smckusick 3374236Smckusick char * 3384236Smckusick rawname(cp) 3394236Smckusick char *cp; 3404236Smckusick { 3414236Smckusick static char rawbuf[32]; 3424236Smckusick char *dp = rindex(cp, '/'); 3434236Smckusick 3444236Smckusick if (dp == 0) 3454236Smckusick return (0); 3464236Smckusick *dp = 0; 3474236Smckusick strcpy(rawbuf, cp); 3484236Smckusick *dp = '/'; 3494236Smckusick strcat(rawbuf, "/r"); 3504236Smckusick strcat(rawbuf, dp+1); 3514236Smckusick return (rawbuf); 3524236Smckusick } 3534236Smckusick 3544236Smckusick check(dev) 3554236Smckusick char *dev; 3564236Smckusick { 3574236Smckusick register DINODE *dp; 3584236Smckusick register ino_t *blp; 3594236Smckusick register int i, n; 3604236Smckusick ino_t savino; 3614236Smckusick int b, c; 3624236Smckusick daddr_t d, s; 3634236Smckusick 3644236Smckusick devname = dev; 3654236Smckusick if (setup(dev) == 0) { 3664236Smckusick if (preen) 3674236Smckusick pfatal("CAN'T CHECK DEVICE."); 3684236Smckusick return; 3694236Smckusick } 3704236Smckusick /* 1 */ 3714236Smckusick if (preen==0) { 3724236Smckusick if (hotroot) 3734236Smckusick printf("** Root file system\n"); 3744236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 3754236Smckusick } 3764236Smckusick pfunc = pass1; 3774236Smckusick inum = 0; 3785325Smckusic n_blks += howmany(sblock.fs_cssize, sblock.fs_bsize) * sblock.fs_frag; 3794236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 3805381Smckusic if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0) 3814236Smckusick continue; 3824236Smckusick n = 0; 3834465Smckusic for (i = 0; i < sblock.fs_ipg; i++, inum++) { 3844465Smckusic dp = ginode(); 3854465Smckusic if (dp == NULL) 3864465Smckusic continue; 3875944Smckusic n++; 3884236Smckusick if (ALLOC) { 3894236Smckusick if (!isset(cgrp.cg_iused, i)) { 3905381Smckusic if (debug) 3915381Smckusic printf("%d bad, not used\n", 3925381Smckusic inum); 3934236Smckusick inosumbad++; 3944236Smckusick } 3955944Smckusic n--; 3964236Smckusick lastino = inum; 3974236Smckusick if (ftypeok(dp) == 0) { 3984236Smckusick pfatal("UNKNOWN FILE TYPE I=%u", inum); 3994236Smckusick if (reply("CLEAR") == 1) { 4004236Smckusick zapino(dp); 4014236Smckusick inodirty(); 4024236Smckusick inosumbad++; 4034236Smckusick } 4044236Smckusick continue; 4054236Smckusick } 4064236Smckusick n_files++; 4074236Smckusick if (setlncnt(dp->di_nlink) <= 0) { 4084236Smckusick if (badlnp < &badlncnt[MAXLNCNT]) 4094236Smckusick *badlnp++ = inum; 4104236Smckusick else { 4114236Smckusick pfatal("LINK COUNT TABLE OVERFLOW"); 4124236Smckusick if (reply("CONTINUE") == 0) 4134236Smckusick errexit(""); 4144236Smckusick } 4154236Smckusick } 4165877Smckusic setstate(DIRCT ? DSTATE : FSTATE); 4174236Smckusick badblk = dupblk = 0; filsize = 0; maxblk = 0; 4184236Smckusick ckinode(dp, ADDR); 4194236Smckusick } else { 4204236Smckusick if (isset(cgrp.cg_iused, i)) { 4215381Smckusic if (debug) 4225381Smckusic printf("%d bad, marked used\n", 4235381Smckusic inum); 4244236Smckusick inosumbad++; 4254465Smckusic n--; 4264236Smckusick } 4274236Smckusick if (dp->di_mode != 0) { 4284236Smckusick pfatal("PARTIALLY ALLOCATED INODE I=%u", inum); 4294236Smckusick if (reply("CLEAR") == 1) { 4304236Smckusick zapino(dp); 4314236Smckusick inodirty(); 4324236Smckusick inosumbad++; 4334236Smckusick } 4344236Smckusick } 4354236Smckusick } 4364236Smckusick } 4374789Smckusic if (n != cgrp.cg_cs.cs_nifree) { 4385381Smckusic if (debug) 4395944Smckusic printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n", 4405381Smckusic c, cgrp.cg_cs.cs_nifree, n); 4414236Smckusick inosumbad++; 4424236Smckusick } 4434236Smckusick } 4444236Smckusick /* 1b */ 4454236Smckusick if (enddup != &duplist[0]) { 4464236Smckusick if (preen) 4474236Smckusick pfatal("INTERNAL ERROR: dups with -p"); 4484236Smckusick printf("** Phase 1b - Rescan For More DUPS\n"); 4494236Smckusick pfunc = pass1b; 4504236Smckusick inum = 0; 4514236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 4524465Smckusic for (i = 0; i < sblock.fs_ipg; i++, inum++) { 4534465Smckusic dp = ginode(); 4544465Smckusic if (dp == NULL) 4554465Smckusic continue; 4564236Smckusick if (getstate() != USTATE && 4574236Smckusick (ckinode(dp, ADDR) & STOP)) 4584236Smckusick goto out1b; 4594465Smckusic } 4604236Smckusick } 4614236Smckusick } 4624236Smckusick out1b: 4634465Smckusic flush(&dfile, &inoblk); 4644236Smckusick /* 2 */ 4654236Smckusick if (preen == 0) 4664236Smckusick printf("** Phase 2 - Check Pathnames\n"); 4674236Smckusick inum = ROOTINO; 4684236Smckusick thisname = pathp = pathname; 4694236Smckusick pfunc = pass2; 4704236Smckusick switch (getstate()) { 4714236Smckusick 4724236Smckusick case USTATE: 4734236Smckusick errexit("ROOT INODE UNALLOCATED. TERMINATING.\n"); 4744236Smckusick 4754236Smckusick case FSTATE: 4764236Smckusick pfatal("ROOT INODE NOT DIRECTORY"); 4774236Smckusick if (reply("FIX") == 0 || (dp = ginode()) == NULL) 4784236Smckusick errexit(""); 4794236Smckusick dp->di_mode &= ~IFMT; 4804236Smckusick dp->di_mode |= IFDIR; 4814236Smckusick inodirty(); 4824236Smckusick inosumbad++; 4834236Smckusick setstate(DSTATE); 4844236Smckusick /* fall into ... */ 4854236Smckusick 4864236Smckusick case DSTATE: 4874236Smckusick descend(); 4884236Smckusick break; 4894236Smckusick 4904236Smckusick case CLEAR: 4914236Smckusick pfatal("DUPS/BAD IN ROOT INODE"); 4924236Smckusick printf("\n"); 4934236Smckusick if (reply("CONTINUE") == 0) 4944236Smckusick errexit(""); 4954236Smckusick setstate(DSTATE); 4964236Smckusick descend(); 4974236Smckusick } 4984236Smckusick /* 3 */ 4994236Smckusick if (preen == 0) 5004236Smckusick printf("** Phase 3 - Check Connectivity\n"); 5014236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 5024236Smckusick if (getstate() == DSTATE) { 5034236Smckusick pfunc = findino; 5044236Smckusick srchname = ".."; 5054236Smckusick savino = inum; 5064236Smckusick do { 5074236Smckusick orphan = inum; 5084236Smckusick if ((dp = ginode()) == NULL) 5094236Smckusick break; 5104236Smckusick filsize = dp->di_size; 5114236Smckusick parentdir = 0; 5124236Smckusick ckinode(dp, DATA); 5134236Smckusick if ((inum = parentdir) == 0) 5144236Smckusick break; 5154236Smckusick } while (getstate() == DSTATE); 5164236Smckusick inum = orphan; 5174236Smckusick if (linkup() == 1) { 5184236Smckusick thisname = pathp = pathname; 5194236Smckusick *pathp++ = '?'; 5204236Smckusick pfunc = pass2; 5214236Smckusick descend(); 5224236Smckusick } 5234236Smckusick inum = savino; 5244236Smckusick } 5254236Smckusick } 5264236Smckusick /* 4 */ 5274236Smckusick if (preen == 0) 5284236Smckusick printf("** Phase 4 - Check Reference Counts\n"); 5294236Smckusick pfunc = pass4; 5304236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 5314236Smckusick switch (getstate()) { 5324236Smckusick 5334236Smckusick case FSTATE: 5344236Smckusick if (n = getlncnt()) 5354236Smckusick adjust((short)n); 5364236Smckusick else { 5374236Smckusick for (blp = badlncnt;blp < badlnp; blp++) 5384236Smckusick if (*blp == inum) { 5394236Smckusick clri("UNREF", 1); 5404236Smckusick break; 5414236Smckusick } 5424236Smckusick } 5434236Smckusick break; 5444236Smckusick 5454236Smckusick case DSTATE: 5464236Smckusick clri("UNREF", 1); 5474236Smckusick break; 5484236Smckusick 5494236Smckusick case CLEAR: 5504236Smckusick clri("BAD/DUP", 1); 5514236Smckusick break; 5524236Smckusick } 5534236Smckusick } 5545337Smckusic if (imax - ROOTINO - n_files != sblock.fs_cstotal.cs_nifree) { 5554236Smckusick pwarn("FREE INODE COUNT WRONG IN SUPERBLK"); 5564236Smckusick if (preen) 5574236Smckusick printf(" (FIXED)\n"); 5584236Smckusick if (preen || reply("FIX") == 1) { 5595944Smckusic sblock.fs_cstotal.cs_nifree = imax - ROOTINO - n_files; 5604236Smckusick sbdirty(); 5614236Smckusick } 5624236Smckusick } 5634236Smckusick flush(&dfile, &fileblk); 5644236Smckusick 5654236Smckusick /* 5 */ 5664236Smckusick if (preen == 0) 5674236Smckusick printf("** Phase 5 - Check Cyl groups\n"); 5684236Smckusick copy(blkmap, freemap, (unsigned)bmapsz); 5694236Smckusick dupblk = 0; 5705381Smckusic n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0)); 5714236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 5725381Smckusic daddr_t cbase = cgbase(&sblock, c); 5734236Smckusick short bo[MAXCPG][NRPOS]; 5745371Smckusic long botot[MAXCPG]; 5755325Smckusic long frsum[MAXFRAG]; 5764465Smckusic int blk; 5774465Smckusic 5785371Smckusic for (n = 0; n < sblock.fs_cpg; n++) { 5795371Smckusic botot[n] = 0; 5804236Smckusick for (i = 0; i < NRPOS; i++) 5814236Smckusick bo[n][i] = 0; 5825371Smckusic } 5835325Smckusic for (i = 0; i < sblock.fs_frag; i++) { 5844465Smckusic frsum[i] = 0; 5854465Smckusic } 5864465Smckusic /* 5874465Smckusic * need to account for the spare boot and super blocks 5884465Smckusic * which appear (inaccurately) bad 5894465Smckusic */ 5905381Smckusic n_bad += cgtod(&sblock, c) - cbase; 5915381Smckusic if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0) 5924236Smckusick continue; 5935325Smckusic for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 5945325Smckusic if (isblock(&sblock, cgrp.cg_free, b/sblock.fs_frag)) { 5955325Smckusic if (pass5(cbase+b, sblock.fs_frag) == STOP) 5964236Smckusick goto out5; 5974236Smckusick /* this is clumsy ... */ 5985325Smckusic n_ffree -= sblock.fs_frag; 5994236Smckusick n_bfree++; 6005371Smckusic botot[cbtocylno(&sblock, b)]++; 6015363Smckusic bo[cbtocylno(&sblock, b)] 6025363Smckusic [cbtorpos(&sblock, b)]++; 6034465Smckusic } else { 6045325Smckusic for (d = 0; d < sblock.fs_frag; d++) 6054236Smckusick if (isset(cgrp.cg_free, b+d)) 6064236Smckusick if (pass5(cbase+b+d,1) == STOP) 6074236Smckusick goto out5; 6084465Smckusic blk = ((cgrp.cg_free[b / NBBY] >> (b % NBBY)) & 6095325Smckusic (0xff >> (NBBY - sblock.fs_frag))); 6104465Smckusic if (blk != 0) 6115325Smckusic fragacct(&sblock, blk, frsum, 1); 6124465Smckusic } 6134236Smckusick } 6145325Smckusic for (i = 0; i < sblock.fs_frag; i++) { 6154465Smckusic if (cgrp.cg_frsum[i] != frsum[i]) { 6165381Smckusic if (debug) 6175381Smckusic printf("cg[%d].cg_frsum[%d] have %d calc %d\n", 6185381Smckusic c, i, cgrp.cg_frsum[i], frsum[i]); 6194465Smckusic frsumbad++; 6204465Smckusic } 6214465Smckusic } 6225371Smckusic for (n = 0; n < sblock.fs_cpg; n++) { 6235371Smckusic if (botot[n] != cgrp.cg_btot[n]) { 6245381Smckusic if (debug) 6255381Smckusic printf("cg[%d].cg_btot[%d] have %d calc %d\n", 6265381Smckusic c, n, cgrp.cg_btot[n], botot[n]); 6275371Smckusic offsumbad++; 6285371Smckusic } 6294236Smckusick for (i = 0; i < NRPOS; i++) 6304236Smckusick if (bo[n][i] != cgrp.cg_b[n][i]) { 6315381Smckusic if (debug) 6325381Smckusic printf("cg[%d].cg_b[%d][%d] have %d calc %d\n", 6335381Smckusic c, n, i, cgrp.cg_b[n][i], 6345381Smckusic bo[n][i]); 6354236Smckusick offsumbad++; 6364236Smckusick } 6375371Smckusic } 6384236Smckusick } 6394236Smckusick out5: 6404236Smckusick if (dupblk) 6414236Smckusick pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk); 6424236Smckusick if (fixcg == 0) { 6435325Smckusic if ((b = n_blks+n_ffree+sblock.fs_frag*n_bfree+n_index+n_bad) != fmax) { 6444236Smckusick pwarn("%ld BLK(S) MISSING\n", fmax - b); 6454236Smckusick fixcg = 1; 6464465Smckusic } else if (inosumbad + offsumbad + frsumbad) { 6474465Smckusic pwarn("SUMMARY INFORMATION %s%s%sBAD\n", 6484236Smckusick inosumbad ? "(INODE FREE) " : "", 6494465Smckusic offsumbad ? "(BLOCK OFFSETS) " : "", 6504465Smckusic frsumbad ? "(FRAG SUMMARIES) " : ""); 6514236Smckusick fixcg = 1; 6524789Smckusic } else if (n_ffree != sblock.fs_cstotal.cs_nffree || 6534789Smckusic n_bfree != sblock.fs_cstotal.cs_nbfree) { 6544236Smckusick pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK"); 6554236Smckusick if (preen) 6564236Smckusick printf(" (FIXED)\n"); 6574236Smckusick if (preen || reply("FIX") == 1) { 6584789Smckusic sblock.fs_cstotal.cs_nffree = n_ffree; 6594789Smckusic sblock.fs_cstotal.cs_nbfree = n_bfree; 6604236Smckusick sbdirty(); 6614236Smckusick } 6624236Smckusick } 6634236Smckusick } 6644236Smckusick if (fixcg) { 6654236Smckusick pwarn("BAD CYLINDER GROUPS"); 6664236Smckusick if (preen) 6674236Smckusick printf(" (SALVAGED)\n"); 6684236Smckusick else if (reply("SALVAGE") == 0) 6694236Smckusick fixcg = 0; 6704236Smckusick } 6714236Smckusick 6724236Smckusick if (fixcg) { 6734236Smckusick if (preen == 0) 6744236Smckusick printf("** Phase 6 - Salvage Cylinder Groups\n"); 6754236Smckusick makecg(); 6764789Smckusic n_ffree = sblock.fs_cstotal.cs_nffree; 6774789Smckusic n_bfree = sblock.fs_cstotal.cs_nbfree; 6784236Smckusick } 6794236Smckusick 6804236Smckusick pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n", 6815325Smckusic n_files, n_blks - howmany(sblock.fs_cssize, sblock.fs_bsize) * sblock.fs_frag, 6825325Smckusic n_ffree + sblock.fs_frag * n_bfree, n_ffree, n_bfree); 6834236Smckusick if (dfile.mod) { 6844236Smckusick time(&sblock.fs_time); 6854236Smckusick sbdirty(); 6864236Smckusick } 6874236Smckusick ckfini(); 6884236Smckusick sync(); 6894236Smckusick if (dfile.mod && hotroot) { 6904236Smckusick printf("\n***** BOOT UNIX (NO SYNC!) *****\n"); 6914236Smckusick exit(4); 6924236Smckusick } 6934236Smckusick if (dfile.mod && preen == 0) 6944236Smckusick printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 6954236Smckusick free(blkmap); 6964236Smckusick free(freemap); 6974236Smckusick free(statemap); 6984236Smckusick free(lncntp); 6994236Smckusick } 7004236Smckusick 7014236Smckusick /* VARARGS1 */ 7024236Smckusick error(s1, s2, s3, s4) 7034715Smckusic char *s1; 7044236Smckusick { 7054236Smckusick 7064236Smckusick printf(s1, s2, s3, s4); 7074236Smckusick } 7084236Smckusick 7094236Smckusick /* VARARGS1 */ 7104236Smckusick errexit(s1, s2, s3, s4) 7114715Smckusic char *s1; 7124236Smckusick { 7134236Smckusick error(s1, s2, s3, s4); 7144236Smckusick exit(8); 7154236Smckusick } 7164236Smckusick 7174236Smckusick /* 7184236Smckusick * An inconsistency occured which shouldn't during normal operations. 7194236Smckusick * Die if preening, otw just printf. 7204236Smckusick */ 7214236Smckusick /* VARARGS1 */ 7224236Smckusick pfatal(s, a1, a2, a3) 7234236Smckusick char *s; 7244236Smckusick { 7254236Smckusick 7264236Smckusick if (preen) { 7274236Smckusick printf("%s: ", devname); 7284236Smckusick printf(s, a1, a2, a3); 7294236Smckusick printf("\n"); 7304236Smckusick preendie(); 7314236Smckusick } 7324236Smckusick printf(s, a1, a2, a3); 7334236Smckusick } 7344236Smckusick 7354236Smckusick preendie() 7364236Smckusick { 7374236Smckusick 7384236Smckusick printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); 7394236Smckusick exit(8); 7404236Smckusick } 7414236Smckusick 7424236Smckusick /* 7434236Smckusick * Pwarn is like printf when not preening, 7444236Smckusick * or a warning (preceded by filename) when preening. 7454236Smckusick */ 7464236Smckusick /* VARARGS1 */ 7474236Smckusick pwarn(s, a1, a2, a3, a4, a5) 7484236Smckusick char *s; 7494236Smckusick { 7504236Smckusick 7514236Smckusick if (preen) 7524236Smckusick printf("%s: ", devname); 7534236Smckusick printf(s, a1, a2, a3, a4, a5); 7544236Smckusick } 7554236Smckusick 7564236Smckusick ckinode(dp, flg) 7574236Smckusick DINODE *dp; 7584236Smckusick register flg; 7594236Smckusick { 7604236Smckusick register daddr_t *ap; 7614236Smckusick register ret; 7625956Smckusic int (*func)(), n, ndb, size, offset; 7634236Smckusick 7644236Smckusick if (SPECIAL) 7654236Smckusick return (KEEPON); 7664236Smckusick func = (flg == ADDR) ? pfunc : dirscan; 7675325Smckusic ndb = howmany(dp->di_size, sblock.fs_bsize); 7684428Smckusic for (ap = &dp->di_db[0]; ap < &dp->di_db[NDADDR]; ap++) { 7695956Smckusic if (--ndb == 0 && (offset = blkoff(&sblock, dp->di_size)) != 0) 7705956Smckusic size = numfrags(&sblock, fragroundup(&sblock, offset)); 7714236Smckusick else 7725325Smckusic size = sblock.fs_frag; 7734236Smckusick if (*ap && (ret = (*func)(*ap, size)) & STOP) 7744236Smckusick return (ret); 7754236Smckusick } 7764428Smckusic for (ap = &dp->di_ib[0], n = 1; n <= 2; ap++, n++) { 7775325Smckusic if (*ap && (ret = iblock(*ap, n, flg, dp->di_size - sblock.fs_bsize * NDADDR)) & STOP) 7784236Smckusick return (ret); 7794236Smckusick } 7804236Smckusick return (KEEPON); 7814236Smckusick } 7824236Smckusick 7834236Smckusick iblock(blk, ilevel, flg, isize) 7844236Smckusick daddr_t blk; 7854236Smckusick register ilevel; 7864236Smckusick int isize; 7874236Smckusick { 7884236Smckusick register daddr_t *ap; 7894236Smckusick register daddr_t *aplim; 7904428Smckusic register int i, n; 7914236Smckusick int (*func)(), nif; 7924236Smckusick BUFAREA ib; 7934236Smckusick 7944236Smckusick if (flg == ADDR) { 7954236Smckusick func = pfunc; 7965325Smckusic if (((n = (*func)(blk, sblock.fs_frag)) & KEEPON) == 0) 7974236Smckusick return (n); 7984236Smckusick } else 7994236Smckusick func = dirscan; 8004236Smckusick if (outrange(blk)) /* protect thyself */ 8014236Smckusick return (SKIP); 8024236Smckusick initbarea(&ib); 8035325Smckusic if (getblk(&ib, blk, sblock.fs_bsize) == NULL) 8044236Smckusick return (SKIP); 8054236Smckusick ilevel--; 8064428Smckusic if (ilevel == 0) { 8075956Smckusic nif = lblkno(&sblock, isize) + 1; 8084428Smckusic } else /* ilevel == 1 */ { 8095325Smckusic nif = isize / (sblock.fs_bsize * NINDIR(&sblock)) + 1; 8104428Smckusic } 8115325Smckusic if (nif > NINDIR(&sblock)) 8125325Smckusic nif = NINDIR(&sblock); 8134428Smckusic aplim = & ib.b_un.b_indir[nif]; 8144428Smckusic for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++) 8154236Smckusick if (*ap) { 8164236Smckusick if (ilevel > 0) 8175325Smckusic n = iblock(*ap, ilevel, flg, isize - i * NINDIR(&sblock) * sblock.fs_bsize); 8184236Smckusick else 8195325Smckusic n = (*func)(*ap, sblock.fs_frag); 8204236Smckusick if (n & STOP) 8214236Smckusick return (n); 8224236Smckusick } 8234236Smckusick return (KEEPON); 8244236Smckusick } 8254236Smckusick 8264236Smckusick pass1(blk, size) 8274236Smckusick daddr_t blk; 8284236Smckusick int size; 8294236Smckusick { 8304236Smckusick register daddr_t *dlp; 8314236Smckusick int res = KEEPON; 8324236Smckusick 8334236Smckusick for (; size > 0; blk++, size--) { 8344236Smckusick if (outrange(blk)) { 8354236Smckusick blkerr("BAD", blk); 8364236Smckusick if (++badblk >= MAXBAD) { 8374236Smckusick printf("EXCESSIVE BAD BLKS I=%u", inum); 8384236Smckusick if (reply("CONTINUE") == 0) 8394236Smckusick errexit(""); 8404236Smckusick return (STOP); 8414236Smckusick } 8424236Smckusick res = SKIP; 8434236Smckusick } else if (getbmap(blk)) { 8444236Smckusick blkerr("DUP", blk); 8454236Smckusick if (++dupblk >= MAXDUP) { 8464236Smckusick printf("EXCESSIVE DUP BLKS I=%u", inum); 8474236Smckusick if (reply("CONTINUE") == 0) 8484236Smckusick errexit(""); 8494236Smckusick return (STOP); 8504236Smckusick } 8514236Smckusick if (enddup >= &duplist[DUPTBLSIZE]) { 8524236Smckusick printf("DUP TABLE OVERFLOW."); 8534236Smckusick if (reply("CONTINUE") == 0) 8544236Smckusick errexit(""); 8554236Smckusick return (STOP); 8564236Smckusick } 8574236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8584236Smckusick if (*dlp == blk) { 8594236Smckusick *enddup++ = blk; 8604236Smckusick break; 8614236Smckusick } 8624236Smckusick if (dlp >= muldup) { 8634236Smckusick *enddup++ = *muldup; 8644236Smckusick *muldup++ = blk; 8654236Smckusick } 8664236Smckusick } else { 8674236Smckusick n_blks++; 8684236Smckusick setbmap(blk); 8694236Smckusick } 8704236Smckusick filsize++; 8714236Smckusick } 8724236Smckusick return (res); 8734236Smckusick } 8744236Smckusick 8754236Smckusick pass1b(blk, size) 8764236Smckusick daddr_t blk; 8774236Smckusick int size; 8784236Smckusick { 8794236Smckusick register daddr_t *dlp; 8804236Smckusick int res = KEEPON; 8814236Smckusick 8824236Smckusick for (; size > 0; blk++, size--) { 8834236Smckusick if (outrange(blk)) 8844236Smckusick res = SKIP; 8854236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8864236Smckusick if (*dlp == blk) { 8874236Smckusick blkerr("DUP", blk); 8884236Smckusick *dlp = *--muldup; 8894236Smckusick *muldup = blk; 8904236Smckusick if (muldup == duplist) 8914236Smckusick return (STOP); 8924236Smckusick } 8934236Smckusick } 8944236Smckusick return (res); 8954236Smckusick } 8964236Smckusick 8974236Smckusick pass2(dirp) 8984236Smckusick register DIRECT *dirp; 8994236Smckusick { 9004236Smckusick register char *p; 9014236Smckusick register n; 9024236Smckusick DINODE *dp; 9034236Smckusick 9044236Smckusick if ((inum = dirp->d_ino) == 0) 9054236Smckusick return (KEEPON); 9064236Smckusick thisname = pathp; 9075877Smckusic for (p = dirp->d_name; p < &dirp->d_name[MAXNAMLEN]; ) 9084236Smckusick if ((*pathp++ = *p++) == 0) { 9094236Smckusick --pathp; 9104236Smckusick break; 9114236Smckusick } 9124236Smckusick *pathp = 0; 9134236Smckusick n = 0; 9144715Smckusic if (inum > imax || inum <= 0) 9154236Smckusick n = direrr("I OUT OF RANGE"); 9164236Smckusick else { 9174236Smckusick again: 9184236Smckusick switch (getstate()) { 9194236Smckusick case USTATE: 9204236Smckusick n = direrr("UNALLOCATED"); 9214236Smckusick break; 9224236Smckusick 9234236Smckusick case CLEAR: 9244236Smckusick if ((n = direrr("DUP/BAD")) == 1) 9254236Smckusick break; 9264236Smckusick if ((dp = ginode()) == NULL) 9274236Smckusick break; 9285877Smckusic setstate(DIRCT ? DSTATE : FSTATE); 9294236Smckusick goto again; 9304236Smckusick 9314236Smckusick case FSTATE: 9324236Smckusick declncnt(); 9334236Smckusick break; 9344236Smckusick 9354236Smckusick case DSTATE: 9364236Smckusick declncnt(); 9374236Smckusick descend(); 9384236Smckusick break; 9394236Smckusick } 9404236Smckusick } 9414236Smckusick pathp = thisname; 9424236Smckusick if (n == 0) 9434236Smckusick return (KEEPON); 9444236Smckusick dirp->d_ino = 0; 9454236Smckusick return (KEEPON|ALTERD); 9464236Smckusick } 9474236Smckusick 9484236Smckusick pass4(blk, size) 9494715Smckusic daddr_t blk; 9504236Smckusick { 9514236Smckusick register daddr_t *dlp; 9524236Smckusick int res = KEEPON; 9534236Smckusick 9544236Smckusick for (; size > 0; blk++, size--) { 9554236Smckusick if (outrange(blk)) 9564236Smckusick res = SKIP; 9574236Smckusick else if (getbmap(blk)) { 9584236Smckusick for (dlp = duplist; dlp < enddup; dlp++) 9594236Smckusick if (*dlp == blk) { 9604236Smckusick *dlp = *--enddup; 9614236Smckusick return (KEEPON); 9624236Smckusick } 9634236Smckusick clrbmap(blk); 9644236Smckusick n_blks--; 9654236Smckusick } 9664236Smckusick } 9674236Smckusick return (res); 9684236Smckusick } 9694236Smckusick 9704236Smckusick pass5(blk, size) 9714236Smckusick daddr_t blk; 9724236Smckusick int size; 9734236Smckusick { 9744236Smckusick int res = KEEPON; 9754236Smckusick 9764236Smckusick for (; size > 0; blk++, size--) { 9774236Smckusick if (outrange(blk)) { 9784236Smckusick fixcg = 1; 9794236Smckusick if (preen) 9804236Smckusick pfatal("BAD BLOCKS IN BIT MAPS."); 9814236Smckusick if (++badblk >= MAXBAD) { 9824236Smckusick printf("EXCESSIVE BAD BLKS IN BIT MAPS."); 9834236Smckusick if (reply("CONTINUE") == 0) 9844236Smckusick errexit(""); 9854236Smckusick return (STOP); 9864236Smckusick } 9874236Smckusick } else if (getfmap(blk)) { 9884236Smckusick fixcg = 1; 9894236Smckusick if (++dupblk >= DUPTBLSIZE) { 9904236Smckusick printf("EXCESSIVE DUP BLKS IN BIT MAPS."); 9914236Smckusick if (reply("CONTINUE") == 0) 9924236Smckusick errexit(""); 9934236Smckusick return (STOP); 9944236Smckusick } 9954236Smckusick } else { 9964236Smckusick n_ffree++; 9974236Smckusick setfmap(blk); 9984236Smckusick } 9994236Smckusick } 10004236Smckusick return (res); 10014236Smckusick } 10024236Smckusick 10034236Smckusick outrange(blk) 10044236Smckusick daddr_t blk; 10054236Smckusick { 10064236Smckusick register int c; 10074236Smckusick 10085381Smckusic c = dtog(&sblock, blk); 10095381Smckusic if (blk >= fmax || blk < cgdmin(&sblock, c)) { 10104236Smckusick return (1); 10114428Smckusic } 10124236Smckusick return (0); 10134236Smckusick } 10144236Smckusick 10154236Smckusick blkerr(s, blk) 10164236Smckusick daddr_t blk; 10174236Smckusick char *s; 10184236Smckusick { 10194236Smckusick pfatal("%ld %s I=%u", blk, s, inum); 10204236Smckusick printf("\n"); 10214236Smckusick setstate(CLEAR); /* mark for possible clearing */ 10224236Smckusick } 10234236Smckusick 10244236Smckusick descend() 10254236Smckusick { 10264236Smckusick register DINODE *dp; 10274236Smckusick register char *savname; 10284236Smckusick off_t savsize; 10294236Smckusick 10304236Smckusick setstate(FSTATE); 10314236Smckusick if ((dp = ginode()) == NULL) 10324236Smckusick return; 10334236Smckusick savname = thisname; 10344236Smckusick *pathp++ = '/'; 10354236Smckusick savsize = filsize; 10364236Smckusick filsize = dp->di_size; 10374236Smckusick ckinode(dp, DATA); 10384236Smckusick thisname = savname; 10394236Smckusick *--pathp = 0; 10404236Smckusick filsize = savsize; 10414236Smckusick } 10424236Smckusick 10435877Smckusic struct dirstuff { 10445877Smckusic int loc; 10455877Smckusic int blkno; 10465877Smckusic int blksiz; 10475877Smckusic }; 10485877Smckusic 10494236Smckusick dirscan(blk, nf) 10504715Smckusic daddr_t blk; 10514715Smckusic int nf; 10524236Smckusick { 10535877Smckusic register DIRECT *dp; 10545877Smckusic struct dirstuff dirp; 1055*6251Smckusick int blksiz, dsize, n; 1056*6251Smckusick char dbuf[DIRBLKSIZ]; 10574236Smckusick 10584236Smckusick if (outrange(blk)) { 10595325Smckusic filsize -= sblock.fs_bsize; 10604236Smckusick return (SKIP); 10614236Smckusick } 10625877Smckusic blksiz = nf * sblock.fs_fsize; 10635877Smckusic dirp.loc = 0; 10645877Smckusic dirp.blkno = blk; 10655877Smckusic dirp.blksiz = blksiz; 10665877Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 1067*6251Smckusick dsize = dp->d_reclen; 1068*6251Smckusick copy(dp, dbuf, dsize); 1069*6251Smckusick if ((n = (*pfunc)(dbuf)) & ALTERD) { 10705877Smckusic if (getblk(&fileblk, blk, blksiz) != NULL) { 1071*6251Smckusick copy(dbuf, dp, dsize); 10724715Smckusic dirty(&fileblk); 10734236Smckusick sbdirty(); 10744236Smckusick } else 10754236Smckusick n &= ~ALTERD; 10764236Smckusick } 10775877Smckusic if (n & STOP) 10784236Smckusick return (n); 10794236Smckusick } 10804236Smckusick return (filsize > 0 ? KEEPON : STOP); 10814236Smckusick } 10824236Smckusick 10835877Smckusic /* 10845877Smckusic * get next entry in a directory. 10855877Smckusic */ 10865877Smckusic DIRECT * 10875877Smckusic readdir(dirp) 10885877Smckusic register struct dirstuff *dirp; 10895877Smckusic { 1090*6251Smckusick register DIRECT *dp, *ndp; 10915877Smckusic 10925877Smckusic if (getblk(&fileblk, dirp->blkno, dirp->blksiz) == NULL) { 10935877Smckusic filsize -= dirp->blksiz - dirp->loc; 10945877Smckusic return NULL; 10955877Smckusic } 10965877Smckusic for (;;) { 10975877Smckusic if (filsize <= 0 || dirp->loc >= dirp->blksiz) 10985877Smckusic return NULL; 10995935Smckusic dp = (DIRECT *)(dirblk.b_buf + dirp->loc); 11005935Smckusic dirp->loc += dp->d_reclen; 11015935Smckusic filsize -= dp->d_reclen; 1102*6251Smckusick ndp = (DIRECT *)(dirblk.b_buf + dirp->loc); 1103*6251Smckusick if (dirp->loc < dirp->blksiz && 1104*6251Smckusick (ndp->d_ino > imax || ndp->d_namlen > MAXNAMLEN || 1105*6251Smckusick ndp->d_reclen <= 0 || 1106*6251Smckusick ndp->d_reclen > DIRBLKSIZ - (dirp->loc % DIRBLKSIZ))) { 1107*6251Smckusick pwarn("DIRECTORY CORRUPTED"); 1108*6251Smckusick if (preen) 1109*6251Smckusick printf(" (SALVAGED)\n"); 1110*6251Smckusick else if (reply("SALVAGE") == 0) { 1111*6251Smckusick dirp->loc += 1112*6251Smckusick DIRBLKSIZ - (dirp->loc % DIRBLKSIZ); 1113*6251Smckusick filsize -= DIRBLKSIZ - (dirp->loc % DIRBLKSIZ); 1114*6251Smckusick return(dp); 1115*6251Smckusick } 1116*6251Smckusick dirp->loc -= dp->d_reclen; 1117*6251Smckusick filsize += dp->d_reclen; 1118*6251Smckusick dp->d_reclen = DIRBLKSIZ - (dirp->loc % DIRBLKSIZ); 1119*6251Smckusick dirty(&fileblk); 11205877Smckusic continue; 1121*6251Smckusick } 11225935Smckusic return (dp); 11235877Smckusic } 11245877Smckusic } 11255877Smckusic 11264236Smckusick direrr(s) 11274715Smckusic char *s; 11284236Smckusick { 11294236Smckusick register DINODE *dp; 11304236Smckusick 11314236Smckusick pwarn("%s ", s); 11324236Smckusick pinode(); 11334236Smckusick printf("\n"); 11344236Smckusick if ((dp = ginode()) != NULL && ftypeok(dp)) 11355877Smckusic pfatal("%s=%s", DIRCT?"DIR":"FILE", pathname); 11364236Smckusick else 11374236Smckusick pfatal("NAME=%s", pathname); 11384236Smckusick return (reply("REMOVE")); 11394236Smckusick } 11404236Smckusick 11414236Smckusick adjust(lcnt) 11424465Smckusic register short lcnt; 11434236Smckusick { 11444236Smckusick register DINODE *dp; 11454236Smckusick 11464236Smckusick if ((dp = ginode()) == NULL) 11474236Smckusick return; 11484236Smckusick if (dp->di_nlink == lcnt) { 11494236Smckusick if (linkup() == 0) 11504236Smckusick clri("UNREF", 0); 11514236Smckusick } 11524236Smckusick else { 11534236Smckusick pwarn("LINK COUNT %s", 11545877Smckusic (lfdir==inum)?lfname:(DIRCT?"DIR":"FILE")); 11554236Smckusick pinode(); 11564236Smckusick printf(" COUNT %d SHOULD BE %d", 11574236Smckusick dp->di_nlink, dp->di_nlink-lcnt); 11584236Smckusick if (preen) { 11594236Smckusick if (lcnt < 0) { 11604236Smckusick printf("\n"); 11614236Smckusick preendie(); 11624236Smckusick } 11634236Smckusick printf(" (ADJUSTED)\n"); 11644236Smckusick } 11654236Smckusick if (preen || reply("ADJUST") == 1) { 11664236Smckusick dp->di_nlink -= lcnt; 11674236Smckusick inodirty(); 11684236Smckusick } 11694236Smckusick } 11704236Smckusick } 11714236Smckusick 11724236Smckusick clri(s, flg) 11734715Smckusic char *s; 11744236Smckusick { 11754236Smckusick register DINODE *dp; 11764236Smckusick 11774236Smckusick if ((dp = ginode()) == NULL) 11784236Smckusick return; 11794236Smckusick if (flg == 1) { 11805877Smckusic pwarn("%s %s", s, DIRCT?"DIR":"FILE"); 11814236Smckusick pinode(); 11824236Smckusick } 11834236Smckusick if (preen || reply("CLEAR") == 1) { 11844236Smckusick if (preen) 11854236Smckusick printf(" (CLEARED)\n"); 11864236Smckusick n_files--; 11874236Smckusick pfunc = pass4; 11884236Smckusick ckinode(dp, ADDR); 11894236Smckusick zapino(dp); 11904465Smckusic setstate(USTATE); 11914236Smckusick inodirty(); 11924236Smckusick inosumbad++; 11934236Smckusick } 11944236Smckusick } 11954236Smckusick 11964236Smckusick setup(dev) 11974715Smckusic char *dev; 11984236Smckusick { 11994236Smckusick dev_t rootdev; 12004878Smckusic struct ostat statb; 12014236Smckusick int super = bflag ? bflag : SBLOCK; 12024236Smckusick 12034236Smckusick bflag = 0; 12044236Smckusick if (stat("/", &statb) < 0) 12054236Smckusick errexit("Can't stat root\n"); 12064236Smckusick rootdev = statb.st_dev; 12074236Smckusick if (stat(dev, &statb) < 0) { 12084236Smckusick error("Can't stat %s\n", dev); 12094236Smckusick return (0); 12104236Smckusick } 12114236Smckusick rawflg = 0; 12124236Smckusick if ((statb.st_mode & S_IFMT) == S_IFBLK) 12134236Smckusick ; 12144236Smckusick else if ((statb.st_mode & S_IFMT) == S_IFCHR) 12154236Smckusick rawflg++; 12164236Smckusick else { 12174236Smckusick if (reply("file is not a block or character device; OK") == 0) 12184236Smckusick return (0); 12194236Smckusick } 12204236Smckusick if (rootdev == statb.st_rdev) 12214236Smckusick hotroot++; 12224236Smckusick if ((dfile.rfdes = open(dev, 0)) < 0) { 12234236Smckusick error("Can't open %s\n", dev); 12244236Smckusick return (0); 12254236Smckusick } 12264236Smckusick if (preen == 0) 12274236Smckusick printf("** %s", dev); 12284236Smckusick if (nflag || (dfile.wfdes = open(dev, 1)) < 0) { 12294236Smckusick dfile.wfdes = -1; 12304236Smckusick if (preen) 12314236Smckusick pfatal("NO WRITE ACCESS"); 12324236Smckusick printf(" (NO WRITE)"); 12334236Smckusick } 12344236Smckusick if (preen == 0) 12354236Smckusick printf("\n"); 12364465Smckusic fixcg = 0; inosumbad = 0; offsumbad = 0; frsumbad = 0; 12374236Smckusick dfile.mod = 0; 12384236Smckusick n_files = n_blks = n_ffree = n_bfree = 0; 12394236Smckusick muldup = enddup = &duplist[0]; 12404236Smckusick badlnp = &badlncnt[0]; 12414236Smckusick lfdir = 0; 12424236Smckusick rplyflag = 0; 12434236Smckusick initbarea(&sblk); 12444236Smckusick initbarea(&fileblk); 12454236Smckusick initbarea(&inoblk); 12464236Smckusick initbarea(&cgblk); 12475347Smckusic if (bread(&dfile, &sblock, super, SBSIZE) == 0) 12484236Smckusick return (0); 12494465Smckusic sblk.b_bno = super; 12505347Smckusic sblk.b_size = SBSIZE; 12515363Smckusic /* 12525363Smckusic * run a few consistency checks of the super block 12535363Smckusic */ 12544236Smckusick if (sblock.fs_magic != FS_MAGIC) 12554236Smckusick { badsb("MAGIC NUMBER WRONG"); return (0); } 12564236Smckusick if (sblock.fs_ncg < 1) 12574236Smckusick { badsb("NCG OUT OF RANGE"); return (0); } 12584236Smckusick if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG) 12594236Smckusick { badsb("CPG OUT OF RANGE"); return (0); } 12604236Smckusick if (sblock.fs_nsect < 1) 12614236Smckusick { badsb("NSECT < 1"); return (0); } 12624236Smckusick if (sblock.fs_ntrak < 1) 12634236Smckusick { badsb("NTRAK < 1"); return (0); } 12645363Smckusic if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak) 12655363Smckusic { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); } 12665363Smckusic if (sblock.fs_ipg % INOPB(&sblock)) 12675363Smckusic { badsb("INODES NOT MULTIPLE OF A BLOCK"); return (0); } 12685381Smckusic if (cgdmin(&sblock, 0) >= sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock)) 12694236Smckusick { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); } 12705363Smckusic if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl || 12715363Smckusic (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) 12724236Smckusick { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); } 12735325Smckusic if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock)) 12744236Smckusick { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); } 12755363Smckusic if (sblock.fs_size * NSPF(&sblock) <= 12765363Smckusic (sblock.fs_ncyl - 1) * sblock.fs_spc) 12774236Smckusick { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); } 12785363Smckusic if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) 12794236Smckusick { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); } 12804236Smckusick /* rest we COULD repair... */ 12814236Smckusick if (sblock.fs_sblkno != SBLOCK) 12825363Smckusic { badsb("SBLKNO CORRUPTED"); return (0); } 12835363Smckusic if (sblock.fs_cblkno != 12845363Smckusic roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag)) 12855363Smckusic { badsb("CBLKNO CORRUPTED"); return (0); } 12865363Smckusic if (sblock.fs_iblkno != sblock.fs_cblkno + sblock.fs_frag) 12875363Smckusic { badsb("IBLKNO CORRUPTED"); return (0); } 12885363Smckusic if (sblock.fs_dblkno != 12895363Smckusic sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock)) 12905363Smckusic { badsb("DBLKNO CORRUPTED"); return (0); } 12915956Smckusic if (sblock.fs_cgsize != fragroundup(&sblock, 12925956Smckusic sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY))) 12934236Smckusick { badsb("CGSIZE INCORRECT"); return (0); } 12945325Smckusic if (sblock.fs_cssize != sblock.fs_ncg * sizeof(struct csum)) 12954236Smckusick { badsb("CSSIZE INCORRECT"); return (0); } 12964236Smckusick fmax = sblock.fs_size; 12974236Smckusick imax = sblock.fs_ncg * sblock.fs_ipg; 12985363Smckusic /* 12995363Smckusic * allocate the necessary maps 13005363Smckusic */ 13014236Smckusick bmapsz = roundup(howmany(fmax, NBBY), sizeof(short)); 13024236Smckusick blkmap = (char *)calloc(bmapsz, sizeof (char)); 13034236Smckusick freemap = (char *)calloc(bmapsz, sizeof (char)); 13044236Smckusick statemap = (char *)calloc(imax+1, sizeof(char)); 13054236Smckusick lncntp = (short *)calloc(imax+1, sizeof(short)); 13064236Smckusick 13074465Smckusic startinum = imax + 1; 13084236Smckusick return (1); 13094236Smckusick 13104236Smckusick badsb: 13114236Smckusick ckfini(); 13124236Smckusick return (0); 13134236Smckusick } 13144236Smckusick 13154236Smckusick badsb(s) 13164236Smckusick char *s; 13174236Smckusick { 13184236Smckusick 13194236Smckusick if (preen) 13204236Smckusick printf("%s: ", devname); 13214236Smckusick printf("BAD SUPER BLOCK: %s\n", s); 13224236Smckusick pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n"); 13234236Smckusick pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n"); 13244236Smckusick } 13254236Smckusick 13264236Smckusick DINODE * 13274236Smckusick ginode() 13284236Smckusick { 13294236Smckusick daddr_t iblk; 13304236Smckusick 13315337Smckusic if (inum < ROOTINO || inum > imax) 13324236Smckusick return (NULL); 13335325Smckusic if (inum < startinum || inum >= startinum + INOPB(&sblock)) { 13345381Smckusic iblk = itod(&sblock, inum); 13355325Smckusic if (getblk(&inoblk, iblk, sblock.fs_bsize) == NULL) { 13364236Smckusick return (NULL); 13374236Smckusick } 13385325Smckusic startinum = (inum / INOPB(&sblock)) * INOPB(&sblock); 13394236Smckusick } 13405325Smckusic return (&inoblk.b_un.b_dinode[inum % INOPB(&sblock)]); 13414236Smckusick } 13424236Smckusick 13434236Smckusick ftypeok(dp) 13444236Smckusick DINODE *dp; 13454236Smckusick { 13464236Smckusick switch (dp->di_mode & IFMT) { 13474236Smckusick 13484236Smckusick case IFDIR: 13494236Smckusick case IFREG: 13504236Smckusick case IFBLK: 13514236Smckusick case IFCHR: 13524236Smckusick case IFMPC: 13534236Smckusick case IFMPB: 13544236Smckusick return (1); 13554236Smckusick 13564236Smckusick default: 13574236Smckusick return (0); 13584236Smckusick } 13594236Smckusick } 13604236Smckusick 13614236Smckusick reply(s) 13624236Smckusick char *s; 13634236Smckusick { 13644236Smckusick char line[80]; 13654236Smckusick 13664236Smckusick if (preen) 13674236Smckusick pfatal("INTERNAL ERROR: GOT TO reply()"); 13684236Smckusick rplyflag = 1; 13694236Smckusick printf("\n%s? ", s); 13704236Smckusick if (nflag || dfile.wfdes < 0) { 13714236Smckusick printf(" no\n\n"); 13724236Smckusick return (0); 13734236Smckusick } 13744236Smckusick if (yflag) { 13754236Smckusick printf(" yes\n\n"); 13764236Smckusick return (1); 13774236Smckusick } 13784236Smckusick if (getline(stdin, line, sizeof(line)) == EOF) 13794236Smckusick errexit("\n"); 13804236Smckusick printf("\n"); 13814236Smckusick if (line[0] == 'y' || line[0] == 'Y') 13824236Smckusick return (1); 13834236Smckusick else 13844236Smckusick return (0); 13854236Smckusick } 13864236Smckusick 13874236Smckusick getline(fp, loc, maxlen) 13884236Smckusick FILE *fp; 13894236Smckusick char *loc; 13904236Smckusick { 13914236Smckusick register n; 13924236Smckusick register char *p, *lastloc; 13934236Smckusick 13944236Smckusick p = loc; 13954236Smckusick lastloc = &p[maxlen-1]; 13964236Smckusick while ((n = getc(fp)) != '\n') { 13974236Smckusick if (n == EOF) 13984236Smckusick return (EOF); 13994236Smckusick if (!isspace(n) && p < lastloc) 14004236Smckusick *p++ = n; 14014236Smckusick } 14024236Smckusick *p = 0; 14034236Smckusick return (p - loc); 14044236Smckusick } 14054236Smckusick 14064236Smckusick BUFAREA * 14074236Smckusick getblk(bp, blk, size) 14084236Smckusick daddr_t blk; 14094236Smckusick register BUFAREA *bp; 14104236Smckusick int size; 14114236Smckusick { 14124236Smckusick register struct filecntl *fcp; 14135325Smckusic daddr_t dblk; 14144236Smckusick 14154236Smckusick fcp = &dfile; 14165325Smckusic dblk = fsbtodb(&sblock, blk); 14175325Smckusic if (bp->b_bno == dblk) 14184236Smckusick return (bp); 14194236Smckusick flush(fcp, bp); 14205325Smckusic if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) { 14215325Smckusic bp->b_bno = dblk; 14224236Smckusick bp->b_size = size; 14234236Smckusick return (bp); 14244236Smckusick } 14254236Smckusick bp->b_bno = (daddr_t)-1; 14264236Smckusick return (NULL); 14274236Smckusick } 14284236Smckusick 14294236Smckusick flush(fcp, bp) 14304236Smckusick struct filecntl *fcp; 14314236Smckusick register BUFAREA *bp; 14324236Smckusick { 14334236Smckusick 14344236Smckusick if (bp->b_dirty) 14354236Smckusick bwrite(fcp, bp->b_un.b_buf, bp->b_bno, bp->b_size); 14364236Smckusick bp->b_dirty = 0; 14374236Smckusick } 14384236Smckusick 14394236Smckusick rwerr(s, blk) 14404236Smckusick char *s; 14414236Smckusick daddr_t blk; 14424236Smckusick { 14434236Smckusick 14444236Smckusick if (preen == 0) 14454236Smckusick printf("\n"); 14464236Smckusick pfatal("CANNOT %s: BLK %ld", s, blk); 14474236Smckusick if (reply("CONTINUE") == 0) 14484236Smckusick errexit("Program terminated\n"); 14494236Smckusick } 14504236Smckusick 14514236Smckusick ckfini() 14524236Smckusick { 14534236Smckusick 14544236Smckusick flush(&dfile, &fileblk); 14554236Smckusick flush(&dfile, &sblk); 14564465Smckusic if (sblk.b_bno != SBLOCK) { 14574465Smckusic sblk.b_bno = SBLOCK; 14584465Smckusic sbdirty(); 14594465Smckusic flush(&dfile, &sblk); 14604465Smckusic } 14614236Smckusick flush(&dfile, &inoblk); 14624236Smckusick close(dfile.rfdes); 14634236Smckusick close(dfile.wfdes); 14644236Smckusick } 14654236Smckusick 14664236Smckusick pinode() 14674236Smckusick { 14684236Smckusick register DINODE *dp; 14694236Smckusick register char *p; 14705877Smckusic char uidbuf[BUFSIZ]; 14714236Smckusick char *ctime(); 14724236Smckusick 14734236Smckusick printf(" I=%u ", inum); 14744236Smckusick if ((dp = ginode()) == NULL) 14754236Smckusick return; 14764236Smckusick printf(" OWNER="); 14774236Smckusick if (getpw((int)dp->di_uid, uidbuf) == 0) { 14784236Smckusick for (p = uidbuf; *p != ':'; p++); 14794236Smckusick *p = 0; 14804236Smckusick printf("%s ", uidbuf); 14814236Smckusick } 14824236Smckusick else { 14834236Smckusick printf("%d ", dp->di_uid); 14844236Smckusick } 14854236Smckusick printf("MODE=%o\n", dp->di_mode); 14864236Smckusick if (preen) 14874236Smckusick printf("%s: ", devname); 14884236Smckusick printf("SIZE=%ld ", dp->di_size); 14894236Smckusick p = ctime(&dp->di_mtime); 14904236Smckusick printf("MTIME=%12.12s %4.4s ", p+4, p+20); 14914236Smckusick } 14924236Smckusick 14934236Smckusick copy(fp, tp, size) 14944236Smckusick register char *tp, *fp; 14954236Smckusick unsigned size; 14964236Smckusick { 14974236Smckusick 14984236Smckusick while (size--) 14994236Smckusick *tp++ = *fp++; 15004236Smckusick } 15014236Smckusick 15024236Smckusick makecg() 15034236Smckusick { 15044465Smckusic int c, blk; 15054236Smckusick daddr_t dbase, d, dmin, dmax; 15064236Smckusick long i, j, s; 15074236Smckusick register struct csum *cs; 15084465Smckusic register DINODE *dp; 15094236Smckusick 15104789Smckusic sblock.fs_cstotal.cs_nbfree = 0; 15114789Smckusic sblock.fs_cstotal.cs_nffree = 0; 15124789Smckusic sblock.fs_cstotal.cs_nifree = 0; 15134789Smckusic sblock.fs_cstotal.cs_ndir = 0; 15145325Smckusic for (i = 0; i < howmany(sblock.fs_cssize, sblock.fs_bsize); i++) { 15155325Smckusic sblock.fs_csp[i] = (struct csum *)calloc(1, sblock.fs_bsize); 15165097Smckusic getblk((char *)sblock.fs_csp[i], 15175325Smckusic sblock.fs_csaddr + (i * sblock.fs_frag), sblock.fs_bsize); 15185097Smckusic } 15194236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 15205381Smckusic dbase = cgbase(&sblock, c); 15214236Smckusick dmax = dbase + sblock.fs_fpg; 15225409Smckusic if (dmax > sblock.fs_size) { 15235944Smckusic for ( ; dmax >= sblock.fs_size; dmax--) 15245401Smckusic clrbit(cgrp.cg_free, dmax - dbase); 15255409Smckusic dmax++; 15265409Smckusic } 15275401Smckusic dmin = sblock.fs_dblkno; 15285325Smckusic cs = &sblock.fs_cs(&sblock, c); 15294236Smckusick cgrp.cg_time = time(0); 15304236Smckusick cgrp.cg_magic = CG_MAGIC; 15314236Smckusick cgrp.cg_cgx = c; 15324236Smckusick cgrp.cg_ncyl = sblock.fs_cpg; 15334236Smckusick cgrp.cg_niblk = sblock.fs_ipg; 15344236Smckusick cgrp.cg_ndblk = dmax - dbase; 15354789Smckusic cgrp.cg_cs.cs_ndir = 0; 15364789Smckusic cgrp.cg_cs.cs_nffree = 0; 15374789Smckusic cgrp.cg_cs.cs_nbfree = 0; 15384789Smckusic cgrp.cg_cs.cs_nifree = 0; 15394465Smckusic cgrp.cg_rotor = dmin; 15404465Smckusic cgrp.cg_frotor = dmin; 15414258Smckusic cgrp.cg_irotor = 0; 15425325Smckusic for (i = 0; i < sblock.fs_frag; i++) 15434465Smckusic cgrp.cg_frsum[i] = 0; 15444236Smckusick inum = sblock.fs_ipg * c; 15454465Smckusic for (i = 0; i < sblock.fs_ipg; inum++, i++) { 15465944Smckusic cgrp.cg_cs.cs_nifree++; 15475944Smckusic clrbit(cgrp.cg_iused, i); 15484465Smckusic dp = ginode(); 15494465Smckusic if (dp == NULL) 15504465Smckusic continue; 15514465Smckusic if (ALLOC) { 15525877Smckusic if (DIRCT) 15534789Smckusic cgrp.cg_cs.cs_ndir++; 15545944Smckusic cgrp.cg_cs.cs_nifree--; 15554465Smckusic setbit(cgrp.cg_iused, i); 15564465Smckusic continue; 15574465Smckusic } 15584236Smckusick } 15594236Smckusick while (i < MAXIPG) { 15604236Smckusick clrbit(cgrp.cg_iused, i); 15614236Smckusick i++; 15624236Smckusick } 15635944Smckusic if (c == 0) 15645944Smckusic for (i = 0; i < ROOTINO; i++) { 15655944Smckusic setbit(cgrp.cg_iused, i); 15665944Smckusic cgrp.cg_cs.cs_nifree--; 15675944Smckusic } 15685371Smckusic for (s = 0; s < MAXCPG; s++) { 15695371Smckusic cgrp.cg_btot[s] = 0; 15704236Smckusick for (i = 0; i < NRPOS; i++) 15714236Smckusick cgrp.cg_b[s][i] = 0; 15725371Smckusic } 15734236Smckusick if (c == 0) { 15745944Smckusic dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) * 15755944Smckusic sblock.fs_frag; 15764236Smckusick } 15774236Smckusick for (d = 0; d < dmin; d++) 15784236Smckusick clrbit(cgrp.cg_free, d); 15795325Smckusic for (; (d + sblock.fs_frag) <= dmax - dbase; d += sblock.fs_frag) { 15804236Smckusick j = 0; 15815325Smckusic for (i = 0; i < sblock.fs_frag; i++) { 15824236Smckusick if (!getbmap(dbase+d+i)) { 15834236Smckusick setbit(cgrp.cg_free, d+i); 15844236Smckusick j++; 15854236Smckusick } else 15864236Smckusick clrbit(cgrp.cg_free, d+i); 15874236Smckusick } 15885325Smckusic if (j == sblock.fs_frag) { 15894789Smckusic cgrp.cg_cs.cs_nbfree++; 15905371Smckusic cgrp.cg_btot[cbtocylno(&sblock, d)]++; 15915363Smckusic cgrp.cg_b[cbtocylno(&sblock, d)] 15925363Smckusic [cbtorpos(&sblock, d)]++; 15934465Smckusic } else if (j > 0) { 15944789Smckusic cgrp.cg_cs.cs_nffree += j; 15954465Smckusic blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) & 15965325Smckusic (0xff >> (NBBY - sblock.fs_frag))); 15975325Smckusic fragacct(&sblock, blk, cgrp.cg_frsum, 1); 15984465Smckusic } 15994236Smckusick } 16004465Smckusic for (j = d; d < dmax - dbase; d++) { 16014236Smckusick if (!getbmap(dbase+d)) { 16024236Smckusick setbit(cgrp.cg_free, d); 16034789Smckusic cgrp.cg_cs.cs_nffree++; 16044236Smckusick } else 16054236Smckusick clrbit(cgrp.cg_free, d); 16064236Smckusick } 16074465Smckusic if (j != d) { 16084465Smckusic blk = ((cgrp.cg_free[j / NBBY] >> (j % NBBY)) & 16095325Smckusic (0xff >> (NBBY - sblock.fs_frag))); 16105325Smckusic fragacct(&sblock, blk, cgrp.cg_frsum, 1); 16114465Smckusic } 16125325Smckusic for (; d < MAXBPG(&sblock); d++) 16134236Smckusick clrbit(cgrp.cg_free, d); 16144789Smckusic sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree; 16154789Smckusic sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree; 16164789Smckusic sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree; 16174789Smckusic sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir; 16184789Smckusic *cs = cgrp.cg_cs; 16195381Smckusic bwrite(&dfile, &cgrp, fsbtodb(&sblock, cgtod(&sblock, c)), 16205956Smckusic sblock.fs_cgsize); 16214236Smckusick } 16225325Smckusic for (i = 0; i < howmany(sblock.fs_cssize, sblock.fs_bsize); i++) { 16235097Smckusic bwrite(&dfile, (char *)sblock.fs_csp[i], 16245325Smckusic fsbtodb(&sblock, sblock.fs_csaddr + (i * sblock.fs_frag)), 16255325Smckusic sblock.fs_bsize); 16265097Smckusic } 16274236Smckusick sblock.fs_ronly = 0; 16284236Smckusick sblock.fs_fmod = 0; 16294236Smckusick sbdirty(); 16304236Smckusick } 16314236Smckusick 16324465Smckusic /* 16334465Smckusic * update the frsum fields to reflect addition or deletion 16344465Smckusic * of some frags 16354465Smckusic */ 16365325Smckusic fragacct(fs, fragmap, fraglist, cnt) 16375325Smckusic struct fs *fs; 16384470Smckusic int fragmap; 16394789Smckusic long fraglist[]; 16404465Smckusic int cnt; 16414465Smckusic { 16424465Smckusic int inblk; 16434465Smckusic register int field, subfield; 16444465Smckusic register int siz, pos; 16454465Smckusic 16465325Smckusic inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1); 16474465Smckusic fragmap <<= 1; 16485325Smckusic for (siz = 1; siz < fs->fs_frag; siz++) { 16494465Smckusic if (((1 << siz) & inblk) == 0) 16504465Smckusic continue; 16514465Smckusic field = around[siz]; 16524465Smckusic subfield = inside[siz]; 16535325Smckusic for (pos = siz; pos <= fs->fs_frag; pos++) { 16544465Smckusic if ((fragmap & field) == subfield) { 16554465Smckusic fraglist[siz] += cnt; 16564465Smckusic pos += siz; 16574465Smckusic field <<= siz; 16584465Smckusic subfield <<= siz; 16594465Smckusic } 16604465Smckusic field <<= 1; 16614465Smckusic subfield <<= 1; 16624465Smckusic } 16634465Smckusic } 16644465Smckusic } 16654465Smckusic 16664236Smckusick findino(dirp) 16674236Smckusick register DIRECT *dirp; 16684236Smckusick { 16694236Smckusick if (dirp->d_ino == 0) 16704236Smckusick return (KEEPON); 16715877Smckusic if (!strcmp(dirp->d_name, srchname)) { 16725877Smckusic if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) 16735877Smckusic parentdir = dirp->d_ino; 16745877Smckusic return (STOP); 16754236Smckusick } 16764236Smckusick return (KEEPON); 16774236Smckusick } 16784236Smckusick 16794236Smckusick mkentry(dirp) 16804236Smckusick register DIRECT *dirp; 16814236Smckusick { 16824236Smckusick register ino_t in; 16834236Smckusick register char *p; 1684*6251Smckusick DIRECT newent; 1685*6251Smckusick int newlen, oldlen; 16864236Smckusick 1687*6251Smckusick newent.d_namlen = 11; 1688*6251Smckusick newlen = DIRSIZ(&newent); 1689*6251Smckusick if (dirp->d_ino != 0) 1690*6251Smckusick oldlen = DIRSIZ(dirp); 1691*6251Smckusick else 1692*6251Smckusick oldlen = 0; 1693*6251Smckusick if (dirp->d_reclen - oldlen < newlen) 16944236Smckusick return (KEEPON); 1695*6251Smckusick newent.d_reclen = dirp->d_reclen - oldlen; 1696*6251Smckusick dirp->d_reclen = oldlen; 1697*6251Smckusick dirp = (struct direct *)(((char *)dirp) + oldlen); 16984236Smckusick dirp->d_ino = orphan; 1699*6251Smckusick dirp->d_reclen = newent.d_reclen; 1700*6251Smckusick p = &dirp->d_name[2]; 1701*6251Smckusick for (in = imax; in > 0; in /= 10) 1702*6251Smckusick p++; 1703*6251Smckusick *--p = 0; 1704*6251Smckusick dirp->d_namlen = p - dirp->d_name; 17054236Smckusick in = orphan; 17064236Smckusick while (p > dirp->d_name) { 17074236Smckusick *--p = (in % 10) + '0'; 17084236Smckusick in /= 10; 17094236Smckusick } 17104236Smckusick *p = '#'; 17114236Smckusick return (ALTERD|STOP); 17124236Smckusick } 17134236Smckusick 17144236Smckusick chgdd(dirp) 17154236Smckusick register DIRECT *dirp; 17164236Smckusick { 17174236Smckusick if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' && 17184236Smckusick dirp->d_name[2] == 0) { 17194236Smckusick dirp->d_ino = lfdir; 17204236Smckusick return (ALTERD|STOP); 17214236Smckusick } 17224236Smckusick return (KEEPON); 17234236Smckusick } 17244236Smckusick 17254236Smckusick linkup() 17264236Smckusick { 17274236Smckusick register DINODE *dp; 17284236Smckusick register lostdir; 17294236Smckusick register ino_t pdir; 17304236Smckusick 17314236Smckusick if ((dp = ginode()) == NULL) 17324236Smckusick return (0); 17335877Smckusic lostdir = DIRCT; 17344236Smckusick pdir = parentdir; 17354236Smckusick pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); 17364236Smckusick pinode(); 17374236Smckusick if (preen && dp->di_size == 0) 17384236Smckusick return (0); 17394236Smckusick if (preen) 17404236Smckusick printf(" (RECONNECTED)\n"); 17414236Smckusick else 17424236Smckusick if (reply("RECONNECT") == 0) 17434236Smckusick return (0); 17444236Smckusick orphan = inum; 17454236Smckusick if (lfdir == 0) { 17464236Smckusick inum = ROOTINO; 17474236Smckusick if ((dp = ginode()) == NULL) { 17484236Smckusick inum = orphan; 17494236Smckusick return (0); 17504236Smckusick } 17514236Smckusick pfunc = findino; 17524236Smckusick srchname = lfname; 17534236Smckusick filsize = dp->di_size; 17544236Smckusick parentdir = 0; 17554236Smckusick ckinode(dp, DATA); 17564236Smckusick inum = orphan; 17574236Smckusick if ((lfdir = parentdir) == 0) { 17584236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 17594236Smckusick printf("\n\n"); 17604236Smckusick return (0); 17614236Smckusick } 17624236Smckusick } 17634236Smckusick inum = lfdir; 17645877Smckusic if ((dp = ginode()) == NULL || !DIRCT || getstate() != FSTATE) { 17654236Smckusick inum = orphan; 17664236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 17674236Smckusick printf("\n\n"); 17684236Smckusick return (0); 17694236Smckusick } 17705956Smckusic if (fragoff(&sblock, dp->di_size)) { 17715956Smckusic dp->di_size = fragroundup(&sblock, dp->di_size); 17724236Smckusick inodirty(); 17734236Smckusick } 17744236Smckusick filsize = dp->di_size; 17754236Smckusick inum = orphan; 17764236Smckusick pfunc = mkentry; 17774236Smckusick if ((ckinode(dp, DATA) & ALTERD) == 0) { 17784236Smckusick pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); 17794236Smckusick printf("\n\n"); 17804236Smckusick return (0); 17814236Smckusick } 17824236Smckusick declncnt(); 17834236Smckusick if (lostdir) { 17844236Smckusick pfunc = chgdd; 17854236Smckusick dp = ginode(); 17864236Smckusick filsize = dp->di_size; 17874236Smckusick ckinode(dp, DATA); 17884236Smckusick inum = lfdir; 17894236Smckusick if ((dp = ginode()) != NULL) { 17904236Smckusick dp->di_nlink++; 17914236Smckusick inodirty(); 17924236Smckusick setlncnt(getlncnt()+1); 17934236Smckusick } 17944236Smckusick inum = orphan; 17954236Smckusick pwarn("DIR I=%u CONNECTED. ", orphan); 17964236Smckusick printf("PARENT WAS I=%u\n", pdir); 17974236Smckusick if (preen == 0) 17984236Smckusick printf("\n"); 17994236Smckusick } 18004236Smckusick return (1); 18014236Smckusick } 18024236Smckusick 18034236Smckusick bread(fcp, buf, blk, size) 18044236Smckusick daddr_t blk; 18054236Smckusick register struct filecntl *fcp; 18064236Smckusick register size; 18074236Smckusick char *buf; 18084236Smckusick { 18095325Smckusic if (lseek(fcp->rfdes, blk * DEV_BSIZE, 0) < 0) 18104236Smckusick rwerr("SEEK", blk); 18114236Smckusick else if (read(fcp->rfdes, buf, size) == size) 18124236Smckusick return (1); 18134236Smckusick rwerr("READ", blk); 18144236Smckusick return (0); 18154236Smckusick } 18164236Smckusick 18174236Smckusick bwrite(fcp, buf, blk, size) 18184236Smckusick daddr_t blk; 18194236Smckusick register struct filecntl *fcp; 18204236Smckusick register size; 18214236Smckusick char *buf; 18224236Smckusick { 18234236Smckusick 18244236Smckusick if (fcp->wfdes < 0) 18254236Smckusick return (0); 18265325Smckusic if (lseek(fcp->wfdes, blk * DEV_BSIZE, 0) < 0) 18274236Smckusick rwerr("SEEK", blk); 18284236Smckusick else if (write(fcp->wfdes, buf, size) == size) { 18294236Smckusick fcp->mod = 1; 18304236Smckusick return (1); 18314236Smckusick } 18324236Smckusick rwerr("WRITE", blk); 18334236Smckusick return (0); 18344236Smckusick } 18354236Smckusick 18364236Smckusick catch() 18374236Smckusick { 18384236Smckusick 18394236Smckusick ckfini(); 18404236Smckusick exit(12); 18414236Smckusick } 18425325Smckusic 18435325Smckusic /* 18445325Smckusic * block operations 18455325Smckusic */ 18465325Smckusic 18475325Smckusic isblock(fs, cp, h) 18485325Smckusic struct fs *fs; 18495325Smckusic unsigned char *cp; 18505325Smckusic int h; 18515325Smckusic { 18525325Smckusic unsigned char mask; 18535325Smckusic 18545325Smckusic switch (fs->fs_frag) { 18555325Smckusic case 8: 18565325Smckusic return (cp[h] == 0xff); 18575325Smckusic case 4: 18585325Smckusic mask = 0x0f << ((h & 0x1) << 2); 18595325Smckusic return ((cp[h >> 1] & mask) == mask); 18605325Smckusic case 2: 18615325Smckusic mask = 0x03 << ((h & 0x3) << 1); 18625325Smckusic return ((cp[h >> 2] & mask) == mask); 18635325Smckusic case 1: 18645325Smckusic mask = 0x01 << (h & 0x7); 18655325Smckusic return ((cp[h >> 3] & mask) == mask); 18665325Smckusic default: 18675381Smckusic error("isblock bad fs_frag %d\n", fs->fs_frag); 18685381Smckusic return (0); 18695325Smckusic } 18705325Smckusic } 1871