1*5401Smckusic static char *sccsid = "@(#)main.c 1.20 (Berkeley) 01/13/82"; 24428Smckusic 34236Smckusick #include <stdio.h> 44236Smckusick #include <ctype.h> 54236Smckusick #include "../h/param.h" 64236Smckusick #include "../h/fs.h" 74236Smckusick #include "../h/dir.h" 84236Smckusick #include "../h/inode.h" 94236Smckusick #include "../h/stat.h" 104878Smckusic #include "../h/ostat.h" 114236Smckusick #include <fstab.h> 124236Smckusick 134236Smckusick typedef int (*SIG_TYP)(); 144236Smckusick 155325Smckusic #define NDIRECT(fs) ((fs)->fs_bsize / sizeof(struct direct)) 165325Smckusic #define MAXNDIRECT (MAXBSIZE / sizeof(struct direct)) 175347Smckusic #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) 185347Smckusic #define MAXINOPB (MAXBSIZE / sizeof (struct dinode)) 195325Smckusic #define SPERB (MAXBSIZE / sizeof(short)) 204236Smckusick 214236Smckusick #define MAXDUP 10 /* limit on dup blks (per inode) */ 224236Smckusick #define MAXBAD 10 /* limit on bad blks (per inode) */ 234236Smckusick 244236Smckusick #define USTATE 0 /* inode not allocated */ 254236Smckusick #define FSTATE 01 /* inode is file */ 264236Smckusick #define DSTATE 02 /* inode is directory */ 274236Smckusick #define CLEAR 03 /* inode is to be cleared */ 284236Smckusick 294236Smckusick typedef struct dinode DINODE; 304236Smckusick typedef struct direct DIRECT; 314236Smckusick 324236Smckusick #define ALLOC ((dp->di_mode & IFMT) != 0) 334236Smckusick #define DIR ((dp->di_mode & IFMT) == IFDIR) 344236Smckusick #define REG ((dp->di_mode & IFMT) == IFREG) 354236Smckusick #define BLK ((dp->di_mode & IFMT) == IFBLK) 364236Smckusick #define CHR ((dp->di_mode & IFMT) == IFCHR) 374236Smckusick #define MPC ((dp->di_mode & IFMT) == IFMPC) 384236Smckusick #define MPB ((dp->di_mode & IFMT) == IFMPB) 394236Smckusick #define SPECIAL (BLK || CHR || MPC || MPB) 404236Smckusick 414465Smckusic ino_t startinum; /* blk num of first in raw area */ 424236Smckusick 434236Smckusick struct bufarea { 444236Smckusick struct bufarea *b_next; /* must be first */ 454236Smckusick daddr_t b_bno; 464236Smckusick int b_size; 474236Smckusick union { 485325Smckusic char b_buf[MAXBSIZE]; /* buffer space */ 494236Smckusick short b_lnks[SPERB]; /* link counts */ 505325Smckusic daddr_t b_indir[MAXNINDIR]; /* indirect block */ 514236Smckusick struct fs b_fs; /* super block */ 524236Smckusick struct cg b_cg; /* cylinder group */ 535325Smckusic struct dinode b_dinode[MAXINOPB]; /* inode block */ 545325Smckusic DIRECT b_dir[MAXNDIRECT]; /* directory */ 554236Smckusick } b_un; 564236Smckusick char b_dirty; 574236Smckusick }; 584236Smckusick 594236Smckusick typedef struct bufarea BUFAREA; 604236Smckusick 614236Smckusick BUFAREA inoblk; /* inode blocks */ 624236Smckusick BUFAREA fileblk; /* other blks in filesys */ 634236Smckusick BUFAREA sblk; /* file system superblock */ 644236Smckusick BUFAREA cgblk; 654236Smckusick 664236Smckusick #define initbarea(x) (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1 674236Smckusick #define dirty(x) (x)->b_dirty = 1 684236Smckusick #define inodirty() inoblk.b_dirty = 1 694236Smckusick #define sbdirty() sblk.b_dirty = 1 704236Smckusick #define cgdirty() cgblk.b_dirty = 1 714236Smckusick 724236Smckusick #define dirblk fileblk.b_un 734236Smckusick #define sblock sblk.b_un.b_fs 744236Smckusick #define cgrp cgblk.b_un.b_cg 754236Smckusick 764236Smckusick struct filecntl { 774236Smckusick int rfdes; 784236Smckusick int wfdes; 794236Smckusick int mod; 804236Smckusick } dfile; /* file descriptors for filesys */ 814236Smckusick 824236Smckusick #define DUPTBLSIZE 100 /* num of dup blocks to remember */ 834236Smckusick daddr_t duplist[DUPTBLSIZE]; /* dup block table */ 844236Smckusick daddr_t *enddup; /* next entry in dup table */ 854236Smckusick daddr_t *muldup; /* multiple dups part of table */ 864236Smckusick 874236Smckusick #define MAXLNCNT 20 /* num zero link cnts to remember */ 884236Smckusick ino_t badlncnt[MAXLNCNT]; /* table of inos with zero link cnts */ 894236Smckusick ino_t *badlnp; /* next entry in table */ 904236Smckusick 914236Smckusick char rawflg; 924236Smckusick char nflag; /* assume a no response */ 934236Smckusick char yflag; /* assume a yes response */ 944236Smckusick int bflag; /* location of alternate super block */ 955381Smckusic int debug; /* output debugging info */ 964236Smckusick char preen; /* just fix normal inconsistencies */ 974236Smckusick char rplyflag; /* any questions asked? */ 984236Smckusick char hotroot; /* checking root device */ 994236Smckusick char fixcg; /* corrupted free list bit maps */ 1004236Smckusick 1014236Smckusick char *blkmap; /* ptr to primary blk allocation map */ 1024236Smckusick char *freemap; /* ptr to secondary blk allocation map */ 1034236Smckusick char *statemap; /* ptr to inode state table */ 1044236Smckusick short *lncntp; /* ptr to link count table */ 1054236Smckusick 1064236Smckusick char *pathp; /* pointer to pathname position */ 1074236Smckusick char *thisname; /* ptr to current pathname component */ 1084236Smckusick char *srchname; /* name being searched for in dir */ 1094236Smckusick char pathname[200]; 1104236Smckusick 1114236Smckusick char *lfname = "lost+found"; 1124236Smckusick 1134236Smckusick ino_t inum; /* inode we are currently working on */ 1144236Smckusick ino_t imax; /* number of inodes */ 1154236Smckusick ino_t parentdir; /* i number of parent directory */ 1164236Smckusick ino_t lastino; /* hiwater mark of inodes */ 1174236Smckusick ino_t lfdir; /* lost & found directory */ 1184236Smckusick ino_t orphan; /* orphaned inode */ 1194236Smckusick 1204236Smckusick off_t filsize; /* num blks seen in file */ 1214236Smckusick off_t maxblk; /* largest logical blk in file */ 1224236Smckusick off_t bmapsz; /* num chars in blkmap */ 1234236Smckusick 1244236Smckusick daddr_t n_ffree; /* number of small free blocks */ 1254236Smckusick daddr_t n_bfree; /* number of large free blocks */ 1264236Smckusick daddr_t n_blks; /* number of blocks used */ 1274236Smckusick daddr_t n_files; /* number of files seen */ 1284236Smckusick daddr_t n_index; 1294236Smckusick daddr_t n_bad; 1304236Smckusick daddr_t fmax; /* number of blocks in the volume */ 1314236Smckusick 1324236Smckusick daddr_t badblk; 1334236Smckusick daddr_t dupblk; 1344236Smckusick 1354236Smckusick int inosumbad; 1364236Smckusick int offsumbad; 1374465Smckusic int frsumbad; 1384236Smckusick 1394236Smckusick #define zapino(x) (*(x) = zino) 1404236Smckusick struct dinode zino; 1414236Smckusick 1424236Smckusick #define setlncnt(x) (lncntp[inum] = x) 1434236Smckusick #define getlncnt() (lncntp[inum]) 1444236Smckusick #define declncnt() (--lncntp[inum]) 1454236Smckusick 1464236Smckusick #define setbmap(x) setbit(blkmap, x) 1474236Smckusick #define getbmap(x) isset(blkmap, x) 1484236Smckusick #define clrbmap(x) clrbit(blkmap, x) 1494236Smckusick 1504236Smckusick #define setfmap(x) setbit(freemap, x) 1514236Smckusick #define getfmap(x) isset(freemap, x) 1524236Smckusick #define clrfmap(x) clrbit(freemap, x) 1534236Smckusick 1544236Smckusick #define setstate(x) (statemap[inum] = x) 1554236Smckusick #define getstate() statemap[inum] 1564236Smckusick 1574236Smckusick #define DATA 1 1584236Smckusick #define ADDR 0 1594236Smckusick 1604236Smckusick #define ALTERD 010 1614236Smckusick #define KEEPON 04 1624236Smckusick #define SKIP 02 1634236Smckusick #define STOP 01 1644236Smckusick 1654236Smckusick int (*signal())(); 1664236Smckusick long lseek(); 1674236Smckusick time_t time(); 1684236Smckusick DINODE *ginode(); 1694236Smckusick BUFAREA *getblk(); 1704236Smckusick int dirscan(); 1714236Smckusick int findino(); 1724236Smckusick int catch(); 1734236Smckusick int mkentry(); 1744236Smckusick int chgdd(); 1754236Smckusick int pass1(), pass1b(), pass2(), pass4(), pass5(); 1764236Smckusick int (*pfunc)(); 1774236Smckusick char *rawname(), *rindex(), *unrawname(); 1784606Smckusic extern int inside[], around[]; 1795325Smckusic extern unsigned char *fragtbl[]; 1804236Smckusick 1814236Smckusick char *devname; 1824236Smckusick 1834236Smckusick main(argc, argv) 1844715Smckusic int argc; 1854715Smckusic char *argv[]; 1864236Smckusick { 1874236Smckusick struct fstab *fsp; 1884236Smckusick int pid, passno, anygtr, sumstatus; 1894236Smckusick 1904236Smckusick sync(); 1914236Smckusick while (--argc > 0 && **++argv == '-') { 1924236Smckusick switch (*++*argv) { 1934236Smckusick 1944236Smckusick case 'p': 1954236Smckusick preen++; 1964236Smckusick break; 1974236Smckusick 1984236Smckusick case 'b': 1994236Smckusick bflag = atoi(argv[0]+1); 2004236Smckusick printf("Alternate super block location: %d\n", bflag); 2014236Smckusick break; 2024236Smckusick 2035381Smckusic case 'd': 2045381Smckusic debug++; 2055381Smckusic break; 2065381Smckusic 2074236Smckusick case 'n': /* default no answer flag */ 2084236Smckusick case 'N': 2094236Smckusick nflag++; 2104236Smckusick yflag = 0; 2114236Smckusick break; 2124236Smckusick 2134236Smckusick case 'y': /* default yes answer flag */ 2144236Smckusick case 'Y': 2154236Smckusick yflag++; 2164236Smckusick nflag = 0; 2174236Smckusick break; 2184236Smckusick 2194236Smckusick default: 2204236Smckusick errexit("%c option?\n", **argv); 2214236Smckusick } 2224236Smckusick } 2234236Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2244236Smckusick signal(SIGINT, catch); 2254236Smckusick if (argc) { 2264236Smckusick while (argc-- > 0) { 2274236Smckusick hotroot = 0; 2284236Smckusick check(*argv++); 2294236Smckusick } 2304236Smckusick exit(0); 2314236Smckusick } 2324236Smckusick sumstatus = 0; 2334236Smckusick passno = 1; 2344236Smckusick do { 2354236Smckusick anygtr = 0; 2364236Smckusick if (setfsent() == 0) 2374236Smckusick errexit("Can't open checklist file: %s\n", FSTAB); 2384236Smckusick while ((fsp = getfsent()) != 0) { 2394236Smckusick if (strcmp(fsp->fs_type, FSTAB_RW) && 2404236Smckusick strcmp(fsp->fs_type, FSTAB_RO)) 2414236Smckusick continue; 2424236Smckusick if (preen == 0 || 2434236Smckusick passno == 1 && fsp->fs_passno == passno) { 2444236Smckusick if (blockcheck(fsp->fs_spec) == 0 && preen) 2454236Smckusick exit(8); 2464236Smckusick } else if (fsp->fs_passno > passno) 2474236Smckusick anygtr = 1; 2484236Smckusick else if (fsp->fs_passno == passno) { 2494236Smckusick pid = fork(); 2504236Smckusick if (pid < 0) { 2514236Smckusick perror("fork"); 2524236Smckusick exit(8); 2534236Smckusick } 2544236Smckusick if (pid == 0) 2554236Smckusick if (blockcheck(fsp->fs_spec)==0) 2564236Smckusick exit(8); 2574236Smckusick else 2584236Smckusick exit(0); 2594236Smckusick } 2604236Smckusick } 2614236Smckusick if (preen) { 2624236Smckusick int status; 2634236Smckusick while (wait(&status) != -1) 2644236Smckusick sumstatus |= status; 2654236Smckusick } 2664236Smckusick passno++; 2674236Smckusick } while (anygtr); 2684236Smckusick if (sumstatus) 2694236Smckusick exit(8); 2704236Smckusick endfsent(); 2714236Smckusick exit(0); 2724236Smckusick } 2734236Smckusick 2744236Smckusick blockcheck(name) 2754236Smckusick char *name; 2764236Smckusick { 2774878Smckusic struct ostat stslash, stblock, stchar; 2784236Smckusick char *raw; 2794236Smckusick int looped = 0; 2804236Smckusick 2814236Smckusick hotroot = 0; 2824236Smckusick if (stat("/", &stslash) < 0){ 2834236Smckusick error("Can't stat root\n"); 2844236Smckusick return (0); 2854236Smckusick } 2864236Smckusick retry: 2874236Smckusick if (stat(name, &stblock) < 0){ 2884236Smckusick error("Can't stat %s\n", name); 2894236Smckusick return (0); 2904236Smckusick } 2914236Smckusick if (stblock.st_mode & S_IFBLK) { 2924236Smckusick raw = rawname(name); 2934236Smckusick if (stat(raw, &stchar) < 0){ 2944236Smckusick error("Can't stat %s\n", raw); 2954236Smckusick return (0); 2964236Smckusick } 2974236Smckusick if (stchar.st_mode & S_IFCHR) { 2984236Smckusick if (stslash.st_dev == stblock.st_rdev) { 2994236Smckusick hotroot++; 3004236Smckusick raw = unrawname(name); 3014236Smckusick } 3024236Smckusick check(raw); 3034236Smckusick return (1); 3044236Smckusick } else { 3054236Smckusick error("%s is not a character device\n", raw); 3064236Smckusick return (0); 3074236Smckusick } 3084236Smckusick } else if (stblock.st_mode & S_IFCHR) { 3094236Smckusick if (looped) { 3104236Smckusick error("Can't make sense out of name %s\n", name); 3114236Smckusick return (0); 3124236Smckusick } 3134236Smckusick name = unrawname(name); 3144236Smckusick looped++; 3154236Smckusick goto retry; 3164236Smckusick } 3174236Smckusick error("Can't make sense out of name %s\n", name); 3184236Smckusick return (0); 3194236Smckusick } 3204236Smckusick 3214236Smckusick char * 3224236Smckusick unrawname(cp) 3234236Smckusick char *cp; 3244236Smckusick { 3254236Smckusick char *dp = rindex(cp, '/'); 3264878Smckusic struct ostat stb; 3274236Smckusick 3284236Smckusick if (dp == 0) 3294236Smckusick return (cp); 3304236Smckusick if (stat(cp, &stb) < 0) 3314236Smckusick return (cp); 3324236Smckusick if ((stb.st_mode&S_IFMT) != S_IFCHR) 3334236Smckusick return (cp); 3344236Smckusick if (*(dp+1) != 'r') 3354236Smckusick return (cp); 3364236Smckusick strcpy(dp+1, dp+2); 3374236Smckusick return (cp); 3384236Smckusick } 3394236Smckusick 3404236Smckusick char * 3414236Smckusick rawname(cp) 3424236Smckusick char *cp; 3434236Smckusick { 3444236Smckusick static char rawbuf[32]; 3454236Smckusick char *dp = rindex(cp, '/'); 3464236Smckusick 3474236Smckusick if (dp == 0) 3484236Smckusick return (0); 3494236Smckusick *dp = 0; 3504236Smckusick strcpy(rawbuf, cp); 3514236Smckusick *dp = '/'; 3524236Smckusick strcat(rawbuf, "/r"); 3534236Smckusick strcat(rawbuf, dp+1); 3544236Smckusick return (rawbuf); 3554236Smckusick } 3564236Smckusick 3574236Smckusick check(dev) 3584236Smckusick char *dev; 3594236Smckusick { 3604236Smckusick register DINODE *dp; 3614236Smckusick register ino_t *blp; 3624236Smckusick register int i, n; 3634236Smckusick ino_t savino; 3644236Smckusick int b, c; 3654236Smckusick daddr_t d, s; 3664236Smckusick 3674236Smckusick devname = dev; 3684236Smckusick if (setup(dev) == 0) { 3694236Smckusick if (preen) 3704236Smckusick pfatal("CAN'T CHECK DEVICE."); 3714236Smckusick return; 3724236Smckusick } 3734236Smckusick /* 1 */ 3744236Smckusick if (preen==0) { 3754236Smckusick if (hotroot) 3764236Smckusick printf("** Root file system\n"); 3774236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 3784236Smckusick } 3794236Smckusick pfunc = pass1; 3804236Smckusick inum = 0; 3815325Smckusic n_blks += howmany(sblock.fs_cssize, sblock.fs_bsize) * sblock.fs_frag; 3824236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 3835381Smckusic if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0) 3844236Smckusick continue; 3854236Smckusick n = 0; 3864465Smckusic for (i = 0; i < sblock.fs_ipg; i++, inum++) { 3874465Smckusic dp = ginode(); 3884465Smckusic if (dp == NULL) 3894465Smckusic continue; 3904236Smckusick if (ALLOC) { 3914236Smckusick if (!isset(cgrp.cg_iused, i)) { 3925381Smckusic if (debug) 3935381Smckusic printf("%d bad, not used\n", 3945381Smckusic inum); 3954236Smckusick inosumbad++; 3964465Smckusic n++; 3974236Smckusick } 3984236Smckusick lastino = inum; 3994236Smckusick if (ftypeok(dp) == 0) { 4004236Smckusick pfatal("UNKNOWN FILE TYPE I=%u", inum); 4014236Smckusick if (reply("CLEAR") == 1) { 4024236Smckusick zapino(dp); 4034236Smckusick inodirty(); 4044236Smckusick inosumbad++; 4054236Smckusick } 4064236Smckusick continue; 4074236Smckusick } 4084236Smckusick n_files++; 4094236Smckusick if (setlncnt(dp->di_nlink) <= 0) { 4104236Smckusick if (badlnp < &badlncnt[MAXLNCNT]) 4114236Smckusick *badlnp++ = inum; 4124236Smckusick else { 4134236Smckusick pfatal("LINK COUNT TABLE OVERFLOW"); 4144236Smckusick if (reply("CONTINUE") == 0) 4154236Smckusick errexit(""); 4164236Smckusick } 4174236Smckusick } 4184236Smckusick setstate(DIR ? DSTATE : FSTATE); 4194236Smckusick badblk = dupblk = 0; filsize = 0; maxblk = 0; 4204236Smckusick ckinode(dp, ADDR); 4214236Smckusick if (DIR && dp->di_size % sizeof(DIRECT)) { 4224236Smckusick pwarn("DIRECTORY MISALIGNED I=%u\n", 4234236Smckusick inum); 4244236Smckusick if (preen == 0) 4254236Smckusick printf("\n"); 4264236Smckusick } 4274236Smckusick } else { 4284236Smckusick n++; 4294236Smckusick if (isset(cgrp.cg_iused, i)) { 4305381Smckusic if (debug) 4315381Smckusic printf("%d bad, marked used\n", 4325381Smckusic inum); 4334236Smckusick inosumbad++; 4344465Smckusic n--; 4354236Smckusick } 4364236Smckusick if (dp->di_mode != 0) { 4374236Smckusick pfatal("PARTIALLY ALLOCATED INODE I=%u", inum); 4384236Smckusick if (reply("CLEAR") == 1) { 4394236Smckusick zapino(dp); 4404236Smckusick inodirty(); 4414236Smckusick inosumbad++; 4424236Smckusick } 4434236Smckusick } 4444236Smckusick } 4454236Smckusick } 4464789Smckusic if (n != cgrp.cg_cs.cs_nifree) { 4475381Smckusic if (debug) 4485381Smckusic printf("cg[%d].cg_cs.cs_nifree is %d not %d\n", 4495381Smckusic c, cgrp.cg_cs.cs_nifree, n); 4504236Smckusick inosumbad++; 4514236Smckusick } 4524236Smckusick } 4534236Smckusick /* 1b */ 4544236Smckusick if (enddup != &duplist[0]) { 4554236Smckusick if (preen) 4564236Smckusick pfatal("INTERNAL ERROR: dups with -p"); 4574236Smckusick printf("** Phase 1b - Rescan For More DUPS\n"); 4584236Smckusick pfunc = pass1b; 4594236Smckusick inum = 0; 4604236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 4614465Smckusic for (i = 0; i < sblock.fs_ipg; i++, inum++) { 4624465Smckusic dp = ginode(); 4634465Smckusic if (dp == NULL) 4644465Smckusic continue; 4654236Smckusick if (getstate() != USTATE && 4664236Smckusick (ckinode(dp, ADDR) & STOP)) 4674236Smckusick goto out1b; 4684465Smckusic } 4694236Smckusick } 4704236Smckusick } 4714236Smckusick out1b: 4724465Smckusic flush(&dfile, &inoblk); 4734236Smckusick /* 2 */ 4744236Smckusick if (preen == 0) 4754236Smckusick printf("** Phase 2 - Check Pathnames\n"); 4764236Smckusick inum = ROOTINO; 4774236Smckusick thisname = pathp = pathname; 4784236Smckusick pfunc = pass2; 4794236Smckusick switch (getstate()) { 4804236Smckusick 4814236Smckusick case USTATE: 4824236Smckusick errexit("ROOT INODE UNALLOCATED. TERMINATING.\n"); 4834236Smckusick 4844236Smckusick case FSTATE: 4854236Smckusick pfatal("ROOT INODE NOT DIRECTORY"); 4864236Smckusick if (reply("FIX") == 0 || (dp = ginode()) == NULL) 4874236Smckusick errexit(""); 4884236Smckusick dp->di_mode &= ~IFMT; 4894236Smckusick dp->di_mode |= IFDIR; 4904236Smckusick inodirty(); 4914236Smckusick inosumbad++; 4924236Smckusick setstate(DSTATE); 4934236Smckusick /* fall into ... */ 4944236Smckusick 4954236Smckusick case DSTATE: 4964236Smckusick descend(); 4974236Smckusick break; 4984236Smckusick 4994236Smckusick case CLEAR: 5004236Smckusick pfatal("DUPS/BAD IN ROOT INODE"); 5014236Smckusick printf("\n"); 5024236Smckusick if (reply("CONTINUE") == 0) 5034236Smckusick errexit(""); 5044236Smckusick setstate(DSTATE); 5054236Smckusick descend(); 5064236Smckusick } 5074236Smckusick /* 3 */ 5084236Smckusick if (preen == 0) 5094236Smckusick printf("** Phase 3 - Check Connectivity\n"); 5104236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 5114236Smckusick if (getstate() == DSTATE) { 5124236Smckusick pfunc = findino; 5134236Smckusick srchname = ".."; 5144236Smckusick savino = inum; 5154236Smckusick do { 5164236Smckusick orphan = inum; 5174236Smckusick if ((dp = ginode()) == NULL) 5184236Smckusick break; 5194236Smckusick filsize = dp->di_size; 5204236Smckusick parentdir = 0; 5214236Smckusick ckinode(dp, DATA); 5224236Smckusick if ((inum = parentdir) == 0) 5234236Smckusick break; 5244236Smckusick } while (getstate() == DSTATE); 5254236Smckusick inum = orphan; 5264236Smckusick if (linkup() == 1) { 5274236Smckusick thisname = pathp = pathname; 5284236Smckusick *pathp++ = '?'; 5294236Smckusick pfunc = pass2; 5304236Smckusick descend(); 5314236Smckusick } 5324236Smckusick inum = savino; 5334236Smckusick } 5344236Smckusick } 5354236Smckusick /* 4 */ 5364236Smckusick if (preen == 0) 5374236Smckusick printf("** Phase 4 - Check Reference Counts\n"); 5384236Smckusick pfunc = pass4; 5394236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 5404236Smckusick switch (getstate()) { 5414236Smckusick 5424236Smckusick case FSTATE: 5434236Smckusick if (n = getlncnt()) 5444236Smckusick adjust((short)n); 5454236Smckusick else { 5464236Smckusick for (blp = badlncnt;blp < badlnp; blp++) 5474236Smckusick if (*blp == inum) { 5484236Smckusick clri("UNREF", 1); 5494236Smckusick break; 5504236Smckusick } 5514236Smckusick } 5524236Smckusick break; 5534236Smckusick 5544236Smckusick case DSTATE: 5554236Smckusick clri("UNREF", 1); 5564236Smckusick break; 5574236Smckusick 5584236Smckusick case CLEAR: 5594236Smckusick clri("BAD/DUP", 1); 5604236Smckusick break; 5614236Smckusick } 5624236Smckusick } 5635337Smckusic if (imax - ROOTINO - n_files != sblock.fs_cstotal.cs_nifree) { 5644236Smckusick pwarn("FREE INODE COUNT WRONG IN SUPERBLK"); 5654236Smckusick if (preen) 5664236Smckusick printf(" (FIXED)\n"); 5674236Smckusick if (preen || reply("FIX") == 1) { 5684789Smckusic sblock.fs_cstotal.cs_nifree = imax - n_files; 5694236Smckusick sbdirty(); 5704236Smckusick } 5714236Smckusick } 5724236Smckusick flush(&dfile, &fileblk); 5734236Smckusick 5744236Smckusick /* 5 */ 5754236Smckusick if (preen == 0) 5764236Smckusick printf("** Phase 5 - Check Cyl groups\n"); 5774236Smckusick copy(blkmap, freemap, (unsigned)bmapsz); 5784236Smckusick dupblk = 0; 5795381Smckusic n_index = sblock.fs_ncg * (cgdmin(&sblock, 0) - cgtod(&sblock, 0)); 5804236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 5815381Smckusic daddr_t cbase = cgbase(&sblock, c); 5824236Smckusick short bo[MAXCPG][NRPOS]; 5835371Smckusic long botot[MAXCPG]; 5845325Smckusic long frsum[MAXFRAG]; 5854465Smckusic int blk; 5864465Smckusic 5875371Smckusic for (n = 0; n < sblock.fs_cpg; n++) { 5885371Smckusic botot[n] = 0; 5894236Smckusick for (i = 0; i < NRPOS; i++) 5904236Smckusick bo[n][i] = 0; 5915371Smckusic } 5925325Smckusic for (i = 0; i < sblock.fs_frag; i++) { 5934465Smckusic frsum[i] = 0; 5944465Smckusic } 5954465Smckusic /* 5964465Smckusic * need to account for the spare boot and super blocks 5974465Smckusic * which appear (inaccurately) bad 5984465Smckusic */ 5995381Smckusic n_bad += cgtod(&sblock, c) - cbase; 6005381Smckusic if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0) 6014236Smckusick continue; 6025325Smckusic for (b = 0; b < sblock.fs_fpg; b += sblock.fs_frag) { 6035325Smckusic if (isblock(&sblock, cgrp.cg_free, b/sblock.fs_frag)) { 6045325Smckusic if (pass5(cbase+b, sblock.fs_frag) == STOP) 6054236Smckusick goto out5; 6064236Smckusick /* this is clumsy ... */ 6075325Smckusic n_ffree -= sblock.fs_frag; 6084236Smckusick n_bfree++; 6095371Smckusic botot[cbtocylno(&sblock, b)]++; 6105363Smckusic bo[cbtocylno(&sblock, b)] 6115363Smckusic [cbtorpos(&sblock, b)]++; 6124465Smckusic } else { 6135325Smckusic for (d = 0; d < sblock.fs_frag; d++) 6144236Smckusick if (isset(cgrp.cg_free, b+d)) 6154236Smckusick if (pass5(cbase+b+d,1) == STOP) 6164236Smckusick goto out5; 6174465Smckusic blk = ((cgrp.cg_free[b / NBBY] >> (b % NBBY)) & 6185325Smckusic (0xff >> (NBBY - sblock.fs_frag))); 6194465Smckusic if (blk != 0) 6205325Smckusic fragacct(&sblock, blk, frsum, 1); 6214465Smckusic } 6224236Smckusick } 6235325Smckusic for (i = 0; i < sblock.fs_frag; i++) { 6244465Smckusic if (cgrp.cg_frsum[i] != frsum[i]) { 6255381Smckusic if (debug) 6265381Smckusic printf("cg[%d].cg_frsum[%d] have %d calc %d\n", 6275381Smckusic c, i, cgrp.cg_frsum[i], frsum[i]); 6284465Smckusic frsumbad++; 6294465Smckusic } 6304465Smckusic } 6315371Smckusic for (n = 0; n < sblock.fs_cpg; n++) { 6325371Smckusic if (botot[n] != cgrp.cg_btot[n]) { 6335381Smckusic if (debug) 6345381Smckusic printf("cg[%d].cg_btot[%d] have %d calc %d\n", 6355381Smckusic c, n, cgrp.cg_btot[n], botot[n]); 6365371Smckusic offsumbad++; 6375371Smckusic } 6384236Smckusick for (i = 0; i < NRPOS; i++) 6394236Smckusick if (bo[n][i] != cgrp.cg_b[n][i]) { 6405381Smckusic if (debug) 6415381Smckusic printf("cg[%d].cg_b[%d][%d] have %d calc %d\n", 6425381Smckusic c, n, i, cgrp.cg_b[n][i], 6435381Smckusic bo[n][i]); 6444236Smckusick offsumbad++; 6454236Smckusick } 6465371Smckusic } 6474236Smckusick } 6484236Smckusick out5: 6494236Smckusick if (dupblk) 6504236Smckusick pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk); 6514236Smckusick if (fixcg == 0) { 6525325Smckusic if ((b = n_blks+n_ffree+sblock.fs_frag*n_bfree+n_index+n_bad) != fmax) { 6534236Smckusick pwarn("%ld BLK(S) MISSING\n", fmax - b); 6544236Smckusick fixcg = 1; 6554465Smckusic } else if (inosumbad + offsumbad + frsumbad) { 6564465Smckusic pwarn("SUMMARY INFORMATION %s%s%sBAD\n", 6574236Smckusick inosumbad ? "(INODE FREE) " : "", 6584465Smckusic offsumbad ? "(BLOCK OFFSETS) " : "", 6594465Smckusic frsumbad ? "(FRAG SUMMARIES) " : ""); 6604236Smckusick fixcg = 1; 6614789Smckusic } else if (n_ffree != sblock.fs_cstotal.cs_nffree || 6624789Smckusic n_bfree != sblock.fs_cstotal.cs_nbfree) { 6634236Smckusick pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK"); 6644236Smckusick if (preen) 6654236Smckusick printf(" (FIXED)\n"); 6664236Smckusick if (preen || reply("FIX") == 1) { 6674789Smckusic sblock.fs_cstotal.cs_nffree = n_ffree; 6684789Smckusic sblock.fs_cstotal.cs_nbfree = n_bfree; 6694236Smckusick sbdirty(); 6704236Smckusick } 6714236Smckusick } 6724236Smckusick } 6734236Smckusick if (fixcg) { 6744236Smckusick pwarn("BAD CYLINDER GROUPS"); 6754236Smckusick if (preen) 6764236Smckusick printf(" (SALVAGED)\n"); 6774236Smckusick else if (reply("SALVAGE") == 0) 6784236Smckusick fixcg = 0; 6794236Smckusick } 6804236Smckusick 6814236Smckusick if (fixcg) { 6824236Smckusick if (preen == 0) 6834236Smckusick printf("** Phase 6 - Salvage Cylinder Groups\n"); 6844236Smckusick makecg(); 6854789Smckusic n_ffree = sblock.fs_cstotal.cs_nffree; 6864789Smckusic n_bfree = sblock.fs_cstotal.cs_nbfree; 6874236Smckusick } 6884236Smckusick 6894236Smckusick pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n", 6905325Smckusic n_files, n_blks - howmany(sblock.fs_cssize, sblock.fs_bsize) * sblock.fs_frag, 6915325Smckusic n_ffree + sblock.fs_frag * n_bfree, n_ffree, n_bfree); 6924236Smckusick if (dfile.mod) { 6934236Smckusick time(&sblock.fs_time); 6944236Smckusick sbdirty(); 6954236Smckusick } 6964236Smckusick ckfini(); 6974236Smckusick sync(); 6984236Smckusick if (dfile.mod && hotroot) { 6994236Smckusick printf("\n***** BOOT UNIX (NO SYNC!) *****\n"); 7004236Smckusick exit(4); 7014236Smckusick } 7024236Smckusick if (dfile.mod && preen == 0) 7034236Smckusick printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 7044236Smckusick free(blkmap); 7054236Smckusick free(freemap); 7064236Smckusick free(statemap); 7074236Smckusick free(lncntp); 7084236Smckusick } 7094236Smckusick 7104236Smckusick /* VARARGS1 */ 7114236Smckusick error(s1, s2, s3, s4) 7124715Smckusic char *s1; 7134236Smckusick { 7144236Smckusick 7154236Smckusick printf(s1, s2, s3, s4); 7164236Smckusick } 7174236Smckusick 7184236Smckusick /* VARARGS1 */ 7194236Smckusick errexit(s1, s2, s3, s4) 7204715Smckusic char *s1; 7214236Smckusick { 7224236Smckusick error(s1, s2, s3, s4); 7234236Smckusick exit(8); 7244236Smckusick } 7254236Smckusick 7264236Smckusick /* 7274236Smckusick * An inconsistency occured which shouldn't during normal operations. 7284236Smckusick * Die if preening, otw just printf. 7294236Smckusick */ 7304236Smckusick /* VARARGS1 */ 7314236Smckusick pfatal(s, a1, a2, a3) 7324236Smckusick char *s; 7334236Smckusick { 7344236Smckusick 7354236Smckusick if (preen) { 7364236Smckusick printf("%s: ", devname); 7374236Smckusick printf(s, a1, a2, a3); 7384236Smckusick printf("\n"); 7394236Smckusick preendie(); 7404236Smckusick } 7414236Smckusick printf(s, a1, a2, a3); 7424236Smckusick } 7434236Smckusick 7444236Smckusick preendie() 7454236Smckusick { 7464236Smckusick 7474236Smckusick printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); 7484236Smckusick exit(8); 7494236Smckusick } 7504236Smckusick 7514236Smckusick /* 7524236Smckusick * Pwarn is like printf when not preening, 7534236Smckusick * or a warning (preceded by filename) when preening. 7544236Smckusick */ 7554236Smckusick /* VARARGS1 */ 7564236Smckusick pwarn(s, a1, a2, a3, a4, a5) 7574236Smckusick char *s; 7584236Smckusick { 7594236Smckusick 7604236Smckusick if (preen) 7614236Smckusick printf("%s: ", devname); 7624236Smckusick printf(s, a1, a2, a3, a4, a5); 7634236Smckusick } 7644236Smckusick 7654236Smckusick ckinode(dp, flg) 7664236Smckusick DINODE *dp; 7674236Smckusick register flg; 7684236Smckusick { 7694236Smckusick register daddr_t *ap; 7704236Smckusick register ret; 7714236Smckusick int (*func)(), n, ndb, size; 7724236Smckusick 7734236Smckusick if (SPECIAL) 7744236Smckusick return (KEEPON); 7754236Smckusick func = (flg == ADDR) ? pfunc : dirscan; 7765325Smckusic ndb = howmany(dp->di_size, sblock.fs_bsize); 7774428Smckusic for (ap = &dp->di_db[0]; ap < &dp->di_db[NDADDR]; ap++) { 7785325Smckusic if (--ndb == 0 && (dp->di_size % sblock.fs_bsize)) 7795325Smckusic size = howmany(dp->di_size % sblock.fs_bsize, sblock.fs_fsize); 7804236Smckusick else 7815325Smckusic size = sblock.fs_frag; 7824236Smckusick if (*ap && (ret = (*func)(*ap, size)) & STOP) 7834236Smckusick return (ret); 7844236Smckusick } 7854428Smckusic for (ap = &dp->di_ib[0], n = 1; n <= 2; ap++, n++) { 7865325Smckusic if (*ap && (ret = iblock(*ap, n, flg, dp->di_size - sblock.fs_bsize * NDADDR)) & STOP) 7874236Smckusick return (ret); 7884236Smckusick } 7894236Smckusick return (KEEPON); 7904236Smckusick } 7914236Smckusick 7924236Smckusick iblock(blk, ilevel, flg, isize) 7934236Smckusick daddr_t blk; 7944236Smckusick register ilevel; 7954236Smckusick int isize; 7964236Smckusick { 7974236Smckusick register daddr_t *ap; 7984236Smckusick register daddr_t *aplim; 7994428Smckusic register int i, n; 8004236Smckusick int (*func)(), nif; 8014236Smckusick BUFAREA ib; 8024236Smckusick 8034236Smckusick if (flg == ADDR) { 8044236Smckusick func = pfunc; 8055325Smckusic if (((n = (*func)(blk, sblock.fs_frag)) & KEEPON) == 0) 8064236Smckusick return (n); 8074236Smckusick } else 8084236Smckusick func = dirscan; 8094236Smckusick if (outrange(blk)) /* protect thyself */ 8104236Smckusick return (SKIP); 8114236Smckusick initbarea(&ib); 8125325Smckusic if (getblk(&ib, blk, sblock.fs_bsize) == NULL) 8134236Smckusick return (SKIP); 8144236Smckusick ilevel--; 8154428Smckusic if (ilevel == 0) { 8165325Smckusic nif = isize / sblock.fs_bsize + 1; 8174428Smckusic } else /* ilevel == 1 */ { 8185325Smckusic nif = isize / (sblock.fs_bsize * NINDIR(&sblock)) + 1; 8194428Smckusic } 8205325Smckusic if (nif > NINDIR(&sblock)) 8215325Smckusic nif = NINDIR(&sblock); 8224428Smckusic aplim = & ib.b_un.b_indir[nif]; 8234428Smckusic for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++) 8244236Smckusick if (*ap) { 8254236Smckusick if (ilevel > 0) 8265325Smckusic n = iblock(*ap, ilevel, flg, isize - i * NINDIR(&sblock) * sblock.fs_bsize); 8274236Smckusick else 8285325Smckusic n = (*func)(*ap, sblock.fs_frag); 8294236Smckusick if (n & STOP) 8304236Smckusick return (n); 8314236Smckusick } 8324236Smckusick return (KEEPON); 8334236Smckusick } 8344236Smckusick 8354236Smckusick pass1(blk, size) 8364236Smckusick daddr_t blk; 8374236Smckusick int size; 8384236Smckusick { 8394236Smckusick register daddr_t *dlp; 8404236Smckusick int res = KEEPON; 8414236Smckusick 8424236Smckusick for (; size > 0; blk++, size--) { 8434236Smckusick if (outrange(blk)) { 8444236Smckusick blkerr("BAD", blk); 8454236Smckusick if (++badblk >= MAXBAD) { 8464236Smckusick printf("EXCESSIVE BAD BLKS I=%u", inum); 8474236Smckusick if (reply("CONTINUE") == 0) 8484236Smckusick errexit(""); 8494236Smckusick return (STOP); 8504236Smckusick } 8514236Smckusick res = SKIP; 8524236Smckusick } else if (getbmap(blk)) { 8534236Smckusick blkerr("DUP", blk); 8544236Smckusick if (++dupblk >= MAXDUP) { 8554236Smckusick printf("EXCESSIVE DUP BLKS I=%u", inum); 8564236Smckusick if (reply("CONTINUE") == 0) 8574236Smckusick errexit(""); 8584236Smckusick return (STOP); 8594236Smckusick } 8604236Smckusick if (enddup >= &duplist[DUPTBLSIZE]) { 8614236Smckusick printf("DUP TABLE OVERFLOW."); 8624236Smckusick if (reply("CONTINUE") == 0) 8634236Smckusick errexit(""); 8644236Smckusick return (STOP); 8654236Smckusick } 8664236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8674236Smckusick if (*dlp == blk) { 8684236Smckusick *enddup++ = blk; 8694236Smckusick break; 8704236Smckusick } 8714236Smckusick if (dlp >= muldup) { 8724236Smckusick *enddup++ = *muldup; 8734236Smckusick *muldup++ = blk; 8744236Smckusick } 8754236Smckusick } else { 8764236Smckusick n_blks++; 8774236Smckusick setbmap(blk); 8784236Smckusick } 8794236Smckusick filsize++; 8804236Smckusick } 8814236Smckusick return (res); 8824236Smckusick } 8834236Smckusick 8844236Smckusick pass1b(blk, size) 8854236Smckusick daddr_t blk; 8864236Smckusick int size; 8874236Smckusick { 8884236Smckusick register daddr_t *dlp; 8894236Smckusick int res = KEEPON; 8904236Smckusick 8914236Smckusick for (; size > 0; blk++, size--) { 8924236Smckusick if (outrange(blk)) 8934236Smckusick res = SKIP; 8944236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8954236Smckusick if (*dlp == blk) { 8964236Smckusick blkerr("DUP", blk); 8974236Smckusick *dlp = *--muldup; 8984236Smckusick *muldup = blk; 8994236Smckusick if (muldup == duplist) 9004236Smckusick return (STOP); 9014236Smckusick } 9024236Smckusick } 9034236Smckusick return (res); 9044236Smckusick } 9054236Smckusick 9064236Smckusick pass2(dirp) 9074236Smckusick register DIRECT *dirp; 9084236Smckusick { 9094236Smckusick register char *p; 9104236Smckusick register n; 9114236Smckusick DINODE *dp; 9124236Smckusick 9134236Smckusick if ((inum = dirp->d_ino) == 0) 9144236Smckusick return (KEEPON); 9154236Smckusick thisname = pathp; 9164236Smckusick for (p = dirp->d_name; p < &dirp->d_name[DIRSIZ]; ) 9174236Smckusick if ((*pathp++ = *p++) == 0) { 9184236Smckusick --pathp; 9194236Smckusick break; 9204236Smckusick } 9214236Smckusick *pathp = 0; 9224236Smckusick n = 0; 9234715Smckusic if (inum > imax || inum <= 0) 9244236Smckusick n = direrr("I OUT OF RANGE"); 9254236Smckusick else { 9264236Smckusick again: 9274236Smckusick switch (getstate()) { 9284236Smckusick case USTATE: 9294236Smckusick n = direrr("UNALLOCATED"); 9304236Smckusick break; 9314236Smckusick 9324236Smckusick case CLEAR: 9334236Smckusick if ((n = direrr("DUP/BAD")) == 1) 9344236Smckusick break; 9354236Smckusick if ((dp = ginode()) == NULL) 9364236Smckusick break; 9374236Smckusick setstate(DIR ? DSTATE : FSTATE); 9384236Smckusick goto again; 9394236Smckusick 9404236Smckusick case FSTATE: 9414236Smckusick declncnt(); 9424236Smckusick break; 9434236Smckusick 9444236Smckusick case DSTATE: 9454236Smckusick declncnt(); 9464236Smckusick descend(); 9474236Smckusick break; 9484236Smckusick } 9494236Smckusick } 9504236Smckusick pathp = thisname; 9514236Smckusick if (n == 0) 9524236Smckusick return (KEEPON); 9534236Smckusick dirp->d_ino = 0; 9544236Smckusick return (KEEPON|ALTERD); 9554236Smckusick } 9564236Smckusick 9574236Smckusick pass4(blk, size) 9584715Smckusic daddr_t blk; 9594236Smckusick { 9604236Smckusick register daddr_t *dlp; 9614236Smckusick int res = KEEPON; 9624236Smckusick 9634236Smckusick for (; size > 0; blk++, size--) { 9644236Smckusick if (outrange(blk)) 9654236Smckusick res = SKIP; 9664236Smckusick else if (getbmap(blk)) { 9674236Smckusick for (dlp = duplist; dlp < enddup; dlp++) 9684236Smckusick if (*dlp == blk) { 9694236Smckusick *dlp = *--enddup; 9704236Smckusick return (KEEPON); 9714236Smckusick } 9724236Smckusick clrbmap(blk); 9734236Smckusick n_blks--; 9744236Smckusick } 9754236Smckusick } 9764236Smckusick return (res); 9774236Smckusick } 9784236Smckusick 9794236Smckusick pass5(blk, size) 9804236Smckusick daddr_t blk; 9814236Smckusick int size; 9824236Smckusick { 9834236Smckusick int res = KEEPON; 9844236Smckusick 9854236Smckusick for (; size > 0; blk++, size--) { 9864236Smckusick if (outrange(blk)) { 9874236Smckusick fixcg = 1; 9884236Smckusick if (preen) 9894236Smckusick pfatal("BAD BLOCKS IN BIT MAPS."); 9904236Smckusick if (++badblk >= MAXBAD) { 9914236Smckusick printf("EXCESSIVE BAD BLKS IN BIT MAPS."); 9924236Smckusick if (reply("CONTINUE") == 0) 9934236Smckusick errexit(""); 9944236Smckusick return (STOP); 9954236Smckusick } 9964236Smckusick } else if (getfmap(blk)) { 9974236Smckusick fixcg = 1; 9984236Smckusick if (++dupblk >= DUPTBLSIZE) { 9994236Smckusick printf("EXCESSIVE DUP BLKS IN BIT MAPS."); 10004236Smckusick if (reply("CONTINUE") == 0) 10014236Smckusick errexit(""); 10024236Smckusick return (STOP); 10034236Smckusick } 10044236Smckusick } else { 10054236Smckusick n_ffree++; 10064236Smckusick setfmap(blk); 10074236Smckusick } 10084236Smckusick } 10094236Smckusick return (res); 10104236Smckusick } 10114236Smckusick 10124236Smckusick outrange(blk) 10134236Smckusick daddr_t blk; 10144236Smckusick { 10154236Smckusick register int c; 10164236Smckusick 10175381Smckusic c = dtog(&sblock, blk); 10185381Smckusic if (blk >= fmax || blk < cgdmin(&sblock, c)) { 10194236Smckusick return (1); 10204428Smckusic } 10214236Smckusick return (0); 10224236Smckusick } 10234236Smckusick 10244236Smckusick blkerr(s, blk) 10254236Smckusick daddr_t blk; 10264236Smckusick char *s; 10274236Smckusick { 10284236Smckusick pfatal("%ld %s I=%u", blk, s, inum); 10294236Smckusick printf("\n"); 10304236Smckusick setstate(CLEAR); /* mark for possible clearing */ 10314236Smckusick } 10324236Smckusick 10334236Smckusick descend() 10344236Smckusick { 10354236Smckusick register DINODE *dp; 10364236Smckusick register char *savname; 10374236Smckusick off_t savsize; 10384236Smckusick 10394236Smckusick setstate(FSTATE); 10404236Smckusick if ((dp = ginode()) == NULL) 10414236Smckusick return; 10424236Smckusick savname = thisname; 10434236Smckusick *pathp++ = '/'; 10444236Smckusick savsize = filsize; 10454236Smckusick filsize = dp->di_size; 10464236Smckusick ckinode(dp, DATA); 10474236Smckusick thisname = savname; 10484236Smckusick *--pathp = 0; 10494236Smckusick filsize = savsize; 10504236Smckusick } 10514236Smckusick 10524236Smckusick dirscan(blk, nf) 10534715Smckusic daddr_t blk; 10544715Smckusic int nf; 10554236Smckusick { 10564236Smckusick register DIRECT *dirp; 10574236Smckusick register DIRECT *edirp; 10584236Smckusick register char *p1, *p2; 10594236Smckusick register n; 10604236Smckusick DIRECT direntry; 10614236Smckusick 10624236Smckusick if (outrange(blk)) { 10635325Smckusic filsize -= sblock.fs_bsize; 10644236Smckusick return (SKIP); 10654236Smckusick } 10665325Smckusic edirp = &dirblk.b_dir[NDIRECT(&sblock)*nf/sblock.fs_frag]; 10674236Smckusick for (dirp = dirblk.b_dir; dirp < edirp && 10684236Smckusick filsize > 0; dirp++, filsize -= sizeof(DIRECT)) { 10695325Smckusic if (getblk(&fileblk, blk, nf * sblock.fs_fsize) == NULL) { 10705325Smckusic filsize -= (&dirblk.b_dir[NDIRECT(&sblock)]-dirp)*sizeof(DIRECT); 10714236Smckusick return (SKIP); 10724236Smckusick } 10734236Smckusick p1 = &dirp->d_name[DIRSIZ]; 10744236Smckusick p2 = &direntry.d_name[DIRSIZ]; 10754236Smckusick while (p1 > (char *)dirp) 10764236Smckusick *--p2 = *--p1; 10774236Smckusick if ((n = (*pfunc)(&direntry)) & ALTERD) { 10785325Smckusic if (getblk(&fileblk, blk, nf * sblock.fs_fsize) != NULL) { 10794236Smckusick p1 = &dirp->d_name[DIRSIZ]; 10804236Smckusick p2 = &direntry.d_name[DIRSIZ]; 10814236Smckusick while (p1 > (char *)dirp) 10824236Smckusick *--p1 = *--p2; 10834715Smckusic dirty(&fileblk); 10844236Smckusick sbdirty(); 10854236Smckusick } else 10864236Smckusick n &= ~ALTERD; 10874236Smckusick } 10884236Smckusick if (n & STOP) 10894236Smckusick return (n); 10904236Smckusick } 10914236Smckusick return (filsize > 0 ? KEEPON : STOP); 10924236Smckusick } 10934236Smckusick 10944236Smckusick direrr(s) 10954715Smckusic char *s; 10964236Smckusick { 10974236Smckusick register DINODE *dp; 10984236Smckusick 10994236Smckusick pwarn("%s ", s); 11004236Smckusick pinode(); 11014236Smckusick printf("\n"); 11024236Smckusick if ((dp = ginode()) != NULL && ftypeok(dp)) 11034236Smckusick pfatal("%s=%s", DIR?"DIR":"FILE", pathname); 11044236Smckusick else 11054236Smckusick pfatal("NAME=%s", pathname); 11064236Smckusick return (reply("REMOVE")); 11074236Smckusick } 11084236Smckusick 11094236Smckusick adjust(lcnt) 11104465Smckusic register short lcnt; 11114236Smckusick { 11124236Smckusick register DINODE *dp; 11134236Smckusick 11144236Smckusick if ((dp = ginode()) == NULL) 11154236Smckusick return; 11164236Smckusick if (dp->di_nlink == lcnt) { 11174236Smckusick if (linkup() == 0) 11184236Smckusick clri("UNREF", 0); 11194236Smckusick } 11204236Smckusick else { 11214236Smckusick pwarn("LINK COUNT %s", 11224236Smckusick (lfdir==inum)?lfname:(DIR?"DIR":"FILE")); 11234236Smckusick pinode(); 11244236Smckusick printf(" COUNT %d SHOULD BE %d", 11254236Smckusick dp->di_nlink, dp->di_nlink-lcnt); 11264236Smckusick if (preen) { 11274236Smckusick if (lcnt < 0) { 11284236Smckusick printf("\n"); 11294236Smckusick preendie(); 11304236Smckusick } 11314236Smckusick printf(" (ADJUSTED)\n"); 11324236Smckusick } 11334236Smckusick if (preen || reply("ADJUST") == 1) { 11344236Smckusick dp->di_nlink -= lcnt; 11354236Smckusick inodirty(); 11364236Smckusick } 11374236Smckusick } 11384236Smckusick } 11394236Smckusick 11404236Smckusick clri(s, flg) 11414715Smckusic char *s; 11424236Smckusick { 11434236Smckusick register DINODE *dp; 11444236Smckusick 11454236Smckusick if ((dp = ginode()) == NULL) 11464236Smckusick return; 11474236Smckusick if (flg == 1) { 11484236Smckusick pwarn("%s %s", s, DIR?"DIR":"FILE"); 11494236Smckusick pinode(); 11504236Smckusick } 11514236Smckusick if (preen || reply("CLEAR") == 1) { 11524236Smckusick if (preen) 11534236Smckusick printf(" (CLEARED)\n"); 11544236Smckusick n_files--; 11554236Smckusick pfunc = pass4; 11564236Smckusick ckinode(dp, ADDR); 11574236Smckusick zapino(dp); 11584465Smckusic setstate(USTATE); 11594236Smckusick inodirty(); 11604236Smckusick inosumbad++; 11614236Smckusick } 11624236Smckusick } 11634236Smckusick 11644236Smckusick setup(dev) 11654715Smckusic char *dev; 11664236Smckusick { 11674236Smckusick dev_t rootdev; 11684878Smckusic struct ostat statb; 11694236Smckusick int super = bflag ? bflag : SBLOCK; 11704236Smckusick 11714236Smckusick bflag = 0; 11724236Smckusick if (stat("/", &statb) < 0) 11734236Smckusick errexit("Can't stat root\n"); 11744236Smckusick rootdev = statb.st_dev; 11754236Smckusick if (stat(dev, &statb) < 0) { 11764236Smckusick error("Can't stat %s\n", dev); 11774236Smckusick return (0); 11784236Smckusick } 11794236Smckusick rawflg = 0; 11804236Smckusick if ((statb.st_mode & S_IFMT) == S_IFBLK) 11814236Smckusick ; 11824236Smckusick else if ((statb.st_mode & S_IFMT) == S_IFCHR) 11834236Smckusick rawflg++; 11844236Smckusick else { 11854236Smckusick if (reply("file is not a block or character device; OK") == 0) 11864236Smckusick return (0); 11874236Smckusick } 11884236Smckusick if (rootdev == statb.st_rdev) 11894236Smckusick hotroot++; 11904236Smckusick if ((dfile.rfdes = open(dev, 0)) < 0) { 11914236Smckusick error("Can't open %s\n", dev); 11924236Smckusick return (0); 11934236Smckusick } 11944236Smckusick if (preen == 0) 11954236Smckusick printf("** %s", dev); 11964236Smckusick if (nflag || (dfile.wfdes = open(dev, 1)) < 0) { 11974236Smckusick dfile.wfdes = -1; 11984236Smckusick if (preen) 11994236Smckusick pfatal("NO WRITE ACCESS"); 12004236Smckusick printf(" (NO WRITE)"); 12014236Smckusick } 12024236Smckusick if (preen == 0) 12034236Smckusick printf("\n"); 12044465Smckusic fixcg = 0; inosumbad = 0; offsumbad = 0; frsumbad = 0; 12054236Smckusick dfile.mod = 0; 12064236Smckusick n_files = n_blks = n_ffree = n_bfree = 0; 12074236Smckusick muldup = enddup = &duplist[0]; 12084236Smckusick badlnp = &badlncnt[0]; 12094236Smckusick lfdir = 0; 12104236Smckusick rplyflag = 0; 12114236Smckusick initbarea(&sblk); 12124236Smckusick initbarea(&fileblk); 12134236Smckusick initbarea(&inoblk); 12144236Smckusick initbarea(&cgblk); 12155347Smckusic if (bread(&dfile, &sblock, super, SBSIZE) == 0) 12164236Smckusick return (0); 12174465Smckusic sblk.b_bno = super; 12185347Smckusic sblk.b_size = SBSIZE; 12195363Smckusic /* 12205363Smckusic * run a few consistency checks of the super block 12215363Smckusic */ 12224236Smckusick if (sblock.fs_magic != FS_MAGIC) 12234236Smckusick { badsb("MAGIC NUMBER WRONG"); return (0); } 12244236Smckusick if (sblock.fs_ncg < 1) 12254236Smckusick { badsb("NCG OUT OF RANGE"); return (0); } 12264236Smckusick if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG) 12274236Smckusick { badsb("CPG OUT OF RANGE"); return (0); } 12284236Smckusick if (sblock.fs_nsect < 1) 12294236Smckusick { badsb("NSECT < 1"); return (0); } 12304236Smckusick if (sblock.fs_ntrak < 1) 12314236Smckusick { badsb("NTRAK < 1"); return (0); } 12325363Smckusic if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak) 12335363Smckusic { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); } 12345363Smckusic if (sblock.fs_ipg % INOPB(&sblock)) 12355363Smckusic { badsb("INODES NOT MULTIPLE OF A BLOCK"); return (0); } 12365381Smckusic if (cgdmin(&sblock, 0) >= sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock)) 12374236Smckusick { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); } 12385363Smckusic if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl || 12395363Smckusic (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) 12404236Smckusick { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); } 12415325Smckusic if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock)) 12424236Smckusick { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); } 12435363Smckusic if (sblock.fs_size * NSPF(&sblock) <= 12445363Smckusic (sblock.fs_ncyl - 1) * sblock.fs_spc) 12454236Smckusick { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); } 12465363Smckusic if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) 12474236Smckusick { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); } 12484236Smckusick /* rest we COULD repair... */ 12494236Smckusick if (sblock.fs_sblkno != SBLOCK) 12505363Smckusic { badsb("SBLKNO CORRUPTED"); return (0); } 12515363Smckusic if (sblock.fs_cblkno != 12525363Smckusic roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag)) 12535363Smckusic { badsb("CBLKNO CORRUPTED"); return (0); } 12545363Smckusic if (sblock.fs_iblkno != sblock.fs_cblkno + sblock.fs_frag) 12555363Smckusic { badsb("IBLKNO CORRUPTED"); return (0); } 12565363Smckusic if (sblock.fs_dblkno != 12575363Smckusic sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock)) 12585363Smckusic { badsb("DBLKNO CORRUPTED"); return (0); } 12595337Smckusic if (sblock.fs_cgsize != 12605347Smckusic roundup(sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY), 12615347Smckusic sblock.fs_fsize)) 12624236Smckusick { badsb("CGSIZE INCORRECT"); return (0); } 12635325Smckusic if (sblock.fs_cssize != sblock.fs_ncg * sizeof(struct csum)) 12644236Smckusick { badsb("CSSIZE INCORRECT"); return (0); } 12654236Smckusick fmax = sblock.fs_size; 12664236Smckusick imax = sblock.fs_ncg * sblock.fs_ipg; 12675363Smckusic /* 12685363Smckusic * allocate the necessary maps 12695363Smckusic */ 12704236Smckusick bmapsz = roundup(howmany(fmax, NBBY), sizeof(short)); 12714236Smckusick blkmap = (char *)calloc(bmapsz, sizeof (char)); 12724236Smckusick freemap = (char *)calloc(bmapsz, sizeof (char)); 12734236Smckusick statemap = (char *)calloc(imax+1, sizeof(char)); 12744236Smckusick lncntp = (short *)calloc(imax+1, sizeof(short)); 12754236Smckusick 12764465Smckusic startinum = imax + 1; 12774236Smckusick return (1); 12784236Smckusick 12794236Smckusick badsb: 12804236Smckusick ckfini(); 12814236Smckusick return (0); 12824236Smckusick } 12834236Smckusick 12844236Smckusick badsb(s) 12854236Smckusick char *s; 12864236Smckusick { 12874236Smckusick 12884236Smckusick if (preen) 12894236Smckusick printf("%s: ", devname); 12904236Smckusick printf("BAD SUPER BLOCK: %s\n", s); 12914236Smckusick pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n"); 12924236Smckusick pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n"); 12934236Smckusick } 12944236Smckusick 12954236Smckusick DINODE * 12964236Smckusick ginode() 12974236Smckusick { 12984236Smckusick daddr_t iblk; 12994236Smckusick 13005337Smckusic if (inum < ROOTINO || inum > imax) 13014236Smckusick return (NULL); 13025325Smckusic if (inum < startinum || inum >= startinum + INOPB(&sblock)) { 13035381Smckusic iblk = itod(&sblock, inum); 13045325Smckusic if (getblk(&inoblk, iblk, sblock.fs_bsize) == NULL) { 13054236Smckusick return (NULL); 13064236Smckusick } 13075325Smckusic startinum = (inum / INOPB(&sblock)) * INOPB(&sblock); 13084236Smckusick } 13095325Smckusic return (&inoblk.b_un.b_dinode[inum % INOPB(&sblock)]); 13104236Smckusick } 13114236Smckusick 13124236Smckusick ftypeok(dp) 13134236Smckusick DINODE *dp; 13144236Smckusick { 13154236Smckusick switch (dp->di_mode & IFMT) { 13164236Smckusick 13174236Smckusick case IFDIR: 13184236Smckusick case IFREG: 13194236Smckusick case IFBLK: 13204236Smckusick case IFCHR: 13214236Smckusick case IFMPC: 13224236Smckusick case IFMPB: 13234236Smckusick return (1); 13244236Smckusick 13254236Smckusick default: 13264236Smckusick return (0); 13274236Smckusick } 13284236Smckusick } 13294236Smckusick 13304236Smckusick reply(s) 13314236Smckusick char *s; 13324236Smckusick { 13334236Smckusick char line[80]; 13344236Smckusick 13354236Smckusick if (preen) 13364236Smckusick pfatal("INTERNAL ERROR: GOT TO reply()"); 13374236Smckusick rplyflag = 1; 13384236Smckusick printf("\n%s? ", s); 13394236Smckusick if (nflag || dfile.wfdes < 0) { 13404236Smckusick printf(" no\n\n"); 13414236Smckusick return (0); 13424236Smckusick } 13434236Smckusick if (yflag) { 13444236Smckusick printf(" yes\n\n"); 13454236Smckusick return (1); 13464236Smckusick } 13474236Smckusick if (getline(stdin, line, sizeof(line)) == EOF) 13484236Smckusick errexit("\n"); 13494236Smckusick printf("\n"); 13504236Smckusick if (line[0] == 'y' || line[0] == 'Y') 13514236Smckusick return (1); 13524236Smckusick else 13534236Smckusick return (0); 13544236Smckusick } 13554236Smckusick 13564236Smckusick getline(fp, loc, maxlen) 13574236Smckusick FILE *fp; 13584236Smckusick char *loc; 13594236Smckusick { 13604236Smckusick register n; 13614236Smckusick register char *p, *lastloc; 13624236Smckusick 13634236Smckusick p = loc; 13644236Smckusick lastloc = &p[maxlen-1]; 13654236Smckusick while ((n = getc(fp)) != '\n') { 13664236Smckusick if (n == EOF) 13674236Smckusick return (EOF); 13684236Smckusick if (!isspace(n) && p < lastloc) 13694236Smckusick *p++ = n; 13704236Smckusick } 13714236Smckusick *p = 0; 13724236Smckusick return (p - loc); 13734236Smckusick } 13744236Smckusick 13754236Smckusick BUFAREA * 13764236Smckusick getblk(bp, blk, size) 13774236Smckusick daddr_t blk; 13784236Smckusick register BUFAREA *bp; 13794236Smckusick int size; 13804236Smckusick { 13814236Smckusick register struct filecntl *fcp; 13825325Smckusic daddr_t dblk; 13834236Smckusick 13844236Smckusick fcp = &dfile; 13855325Smckusic dblk = fsbtodb(&sblock, blk); 13865325Smckusic if (bp->b_bno == dblk) 13874236Smckusick return (bp); 13884236Smckusick flush(fcp, bp); 13895325Smckusic if (bread(fcp, bp->b_un.b_buf, dblk, size) != 0) { 13905325Smckusic bp->b_bno = dblk; 13914236Smckusick bp->b_size = size; 13924236Smckusick return (bp); 13934236Smckusick } 13944236Smckusick bp->b_bno = (daddr_t)-1; 13954236Smckusick return (NULL); 13964236Smckusick } 13974236Smckusick 13984236Smckusick flush(fcp, bp) 13994236Smckusick struct filecntl *fcp; 14004236Smckusick register BUFAREA *bp; 14014236Smckusick { 14024236Smckusick 14034236Smckusick if (bp->b_dirty) 14044236Smckusick bwrite(fcp, bp->b_un.b_buf, bp->b_bno, bp->b_size); 14054236Smckusick bp->b_dirty = 0; 14064236Smckusick } 14074236Smckusick 14084236Smckusick rwerr(s, blk) 14094236Smckusick char *s; 14104236Smckusick daddr_t blk; 14114236Smckusick { 14124236Smckusick 14134236Smckusick if (preen == 0) 14144236Smckusick printf("\n"); 14154236Smckusick pfatal("CANNOT %s: BLK %ld", s, blk); 14164236Smckusick if (reply("CONTINUE") == 0) 14174236Smckusick errexit("Program terminated\n"); 14184236Smckusick } 14194236Smckusick 14204236Smckusick ckfini() 14214236Smckusick { 14224236Smckusick 14234236Smckusick flush(&dfile, &fileblk); 14244236Smckusick flush(&dfile, &sblk); 14254465Smckusic if (sblk.b_bno != SBLOCK) { 14264465Smckusic sblk.b_bno = SBLOCK; 14274465Smckusic sbdirty(); 14284465Smckusic flush(&dfile, &sblk); 14294465Smckusic } 14304236Smckusick flush(&dfile, &inoblk); 14314236Smckusick close(dfile.rfdes); 14324236Smckusick close(dfile.wfdes); 14334236Smckusick } 14344236Smckusick 14354236Smckusick pinode() 14364236Smckusick { 14374236Smckusick register DINODE *dp; 14384236Smckusick register char *p; 14394236Smckusick char uidbuf[200]; 14404236Smckusick char *ctime(); 14414236Smckusick 14424236Smckusick printf(" I=%u ", inum); 14434236Smckusick if ((dp = ginode()) == NULL) 14444236Smckusick return; 14454236Smckusick printf(" OWNER="); 14464236Smckusick if (getpw((int)dp->di_uid, uidbuf) == 0) { 14474236Smckusick for (p = uidbuf; *p != ':'; p++); 14484236Smckusick *p = 0; 14494236Smckusick printf("%s ", uidbuf); 14504236Smckusick } 14514236Smckusick else { 14524236Smckusick printf("%d ", dp->di_uid); 14534236Smckusick } 14544236Smckusick printf("MODE=%o\n", dp->di_mode); 14554236Smckusick if (preen) 14564236Smckusick printf("%s: ", devname); 14574236Smckusick printf("SIZE=%ld ", dp->di_size); 14584236Smckusick p = ctime(&dp->di_mtime); 14594236Smckusick printf("MTIME=%12.12s %4.4s ", p+4, p+20); 14604236Smckusick } 14614236Smckusick 14624236Smckusick copy(fp, tp, size) 14634236Smckusick register char *tp, *fp; 14644236Smckusick unsigned size; 14654236Smckusick { 14664236Smckusick 14674236Smckusick while (size--) 14684236Smckusick *tp++ = *fp++; 14694236Smckusick } 14704236Smckusick 14714236Smckusick makecg() 14724236Smckusick { 14734465Smckusic int c, blk; 14744236Smckusick daddr_t dbase, d, dmin, dmax; 14754236Smckusick long i, j, s; 1476*5401Smckusic int x; 14774236Smckusick register struct csum *cs; 14784465Smckusic register DINODE *dp; 14794236Smckusick 14804789Smckusic sblock.fs_cstotal.cs_nbfree = 0; 14814789Smckusic sblock.fs_cstotal.cs_nffree = 0; 14824789Smckusic sblock.fs_cstotal.cs_nifree = 0; 14834789Smckusic sblock.fs_cstotal.cs_ndir = 0; 14845325Smckusic for (i = 0; i < howmany(sblock.fs_cssize, sblock.fs_bsize); i++) { 14855325Smckusic sblock.fs_csp[i] = (struct csum *)calloc(1, sblock.fs_bsize); 14865097Smckusic getblk((char *)sblock.fs_csp[i], 14875325Smckusic sblock.fs_csaddr + (i * sblock.fs_frag), sblock.fs_bsize); 14885097Smckusic } 14894236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 14905381Smckusic dbase = cgbase(&sblock, c); 14914236Smckusick dmax = dbase + sblock.fs_fpg; 14924236Smckusick if (dmax > sblock.fs_size) 1493*5401Smckusic for ( ; dmax > sblock.fs_size ; dmax--) 1494*5401Smckusic clrbit(cgrp.cg_free, dmax - dbase); 1495*5401Smckusic dmin = sblock.fs_dblkno; 14965325Smckusic cs = &sblock.fs_cs(&sblock, c); 14974236Smckusick cgrp.cg_time = time(0); 14984236Smckusick cgrp.cg_magic = CG_MAGIC; 14994236Smckusick cgrp.cg_cgx = c; 15004236Smckusick cgrp.cg_ncyl = sblock.fs_cpg; 15014236Smckusick cgrp.cg_niblk = sblock.fs_ipg; 15024236Smckusick cgrp.cg_ndblk = dmax - dbase; 15034789Smckusic cgrp.cg_cs.cs_ndir = 0; 15044789Smckusic cgrp.cg_cs.cs_nffree = 0; 15054789Smckusic cgrp.cg_cs.cs_nbfree = 0; 15064789Smckusic cgrp.cg_cs.cs_nifree = 0; 15074465Smckusic cgrp.cg_rotor = dmin; 15084465Smckusic cgrp.cg_frotor = dmin; 15094258Smckusic cgrp.cg_irotor = 0; 15105325Smckusic for (i = 0; i < sblock.fs_frag; i++) 15114465Smckusic cgrp.cg_frsum[i] = 0; 15124236Smckusick inum = sblock.fs_ipg * c; 15134465Smckusic for (i = 0; i < sblock.fs_ipg; inum++, i++) { 15144465Smckusic dp = ginode(); 15154465Smckusic if (dp == NULL) 15164465Smckusic continue; 15174465Smckusic if (ALLOC) { 15184465Smckusic if (DIR) 15194789Smckusic cgrp.cg_cs.cs_ndir++; 15204465Smckusic setbit(cgrp.cg_iused, i); 15214465Smckusic continue; 15224465Smckusic } 15234789Smckusic cgrp.cg_cs.cs_nifree++; 15244236Smckusick clrbit(cgrp.cg_iused, i); 15254236Smckusick } 15264236Smckusick while (i < MAXIPG) { 15274236Smckusick clrbit(cgrp.cg_iused, i); 15284236Smckusick i++; 15294236Smckusick } 15305371Smckusic for (s = 0; s < MAXCPG; s++) { 15315371Smckusic cgrp.cg_btot[s] = 0; 15324236Smckusick for (i = 0; i < NRPOS; i++) 15334236Smckusick cgrp.cg_b[s][i] = 0; 15345371Smckusic } 15354236Smckusick if (c == 0) { 15365325Smckusic dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) * sblock.fs_frag; 15374236Smckusick } 15384236Smckusick for (d = 0; d < dmin; d++) 15394236Smckusick clrbit(cgrp.cg_free, d); 15405325Smckusic for (; (d + sblock.fs_frag) <= dmax - dbase; d += sblock.fs_frag) { 15414236Smckusick j = 0; 15425325Smckusic for (i = 0; i < sblock.fs_frag; i++) { 15434236Smckusick if (!getbmap(dbase+d+i)) { 15444236Smckusick setbit(cgrp.cg_free, d+i); 15454236Smckusick j++; 15464236Smckusick } else 15474236Smckusick clrbit(cgrp.cg_free, d+i); 15484236Smckusick } 15495325Smckusic if (j == sblock.fs_frag) { 15504789Smckusic cgrp.cg_cs.cs_nbfree++; 15515371Smckusic cgrp.cg_btot[cbtocylno(&sblock, d)]++; 15525363Smckusic cgrp.cg_b[cbtocylno(&sblock, d)] 15535363Smckusic [cbtorpos(&sblock, d)]++; 15544465Smckusic } else if (j > 0) { 15554789Smckusic cgrp.cg_cs.cs_nffree += j; 15564465Smckusic blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) & 15575325Smckusic (0xff >> (NBBY - sblock.fs_frag))); 15585325Smckusic fragacct(&sblock, blk, cgrp.cg_frsum, 1); 15594465Smckusic } 15604236Smckusick } 1561*5401Smckusic x = 0; 15624465Smckusic for (j = d; d < dmax - dbase; d++) { 15634236Smckusick if (!getbmap(dbase+d)) { 15644236Smckusick setbit(cgrp.cg_free, d); 15654789Smckusic cgrp.cg_cs.cs_nffree++; 1566*5401Smckusic x++; 15674236Smckusick } else 15684236Smckusick clrbit(cgrp.cg_free, d); 15694236Smckusick } 15704465Smckusic if (j != d) { 15714465Smckusic blk = ((cgrp.cg_free[j / NBBY] >> (j % NBBY)) & 15725325Smckusic (0xff >> (NBBY - sblock.fs_frag))); 15735325Smckusic fragacct(&sblock, blk, cgrp.cg_frsum, 1); 15744465Smckusic } 15755325Smckusic for (; d < MAXBPG(&sblock); d++) 15764236Smckusick clrbit(cgrp.cg_free, d); 15774789Smckusic sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree; 15784789Smckusic sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree; 15794789Smckusic sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree; 15804789Smckusic sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir; 15814789Smckusic *cs = cgrp.cg_cs; 15825381Smckusic bwrite(&dfile, &cgrp, fsbtodb(&sblock, cgtod(&sblock, c)), 15835325Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE)); 15844236Smckusick } 15855325Smckusic for (i = 0; i < howmany(sblock.fs_cssize, sblock.fs_bsize); i++) { 15865097Smckusic bwrite(&dfile, (char *)sblock.fs_csp[i], 15875325Smckusic fsbtodb(&sblock, sblock.fs_csaddr + (i * sblock.fs_frag)), 15885325Smckusic sblock.fs_bsize); 15895097Smckusic } 15904236Smckusick sblock.fs_ronly = 0; 15914236Smckusick sblock.fs_fmod = 0; 15924236Smckusick sbdirty(); 15934236Smckusick } 15944236Smckusick 15954465Smckusic /* 15964465Smckusic * update the frsum fields to reflect addition or deletion 15974465Smckusic * of some frags 15984465Smckusic */ 15995325Smckusic fragacct(fs, fragmap, fraglist, cnt) 16005325Smckusic struct fs *fs; 16014470Smckusic int fragmap; 16024789Smckusic long fraglist[]; 16034465Smckusic int cnt; 16044465Smckusic { 16054465Smckusic int inblk; 16064465Smckusic register int field, subfield; 16074465Smckusic register int siz, pos; 16084465Smckusic 16095325Smckusic inblk = (int)(fragtbl[fs->fs_frag][fragmap] << 1); 16104465Smckusic fragmap <<= 1; 16115325Smckusic for (siz = 1; siz < fs->fs_frag; siz++) { 16124465Smckusic if (((1 << siz) & inblk) == 0) 16134465Smckusic continue; 16144465Smckusic field = around[siz]; 16154465Smckusic subfield = inside[siz]; 16165325Smckusic for (pos = siz; pos <= fs->fs_frag; pos++) { 16174465Smckusic if ((fragmap & field) == subfield) { 16184465Smckusic fraglist[siz] += cnt; 16194465Smckusic pos += siz; 16204465Smckusic field <<= siz; 16214465Smckusic subfield <<= siz; 16224465Smckusic } 16234465Smckusic field <<= 1; 16244465Smckusic subfield <<= 1; 16254465Smckusic } 16264465Smckusic } 16274465Smckusic } 16284465Smckusic 16294236Smckusick findino(dirp) 16304236Smckusick register DIRECT *dirp; 16314236Smckusick { 16324236Smckusick register char *p1, *p2; 16334236Smckusick 16344236Smckusick if (dirp->d_ino == 0) 16354236Smckusick return (KEEPON); 16364236Smckusick for (p1 = dirp->d_name, p2 = srchname;*p2++ == *p1; p1++) { 16374236Smckusick if (*p1 == 0 || p1 == &dirp->d_name[DIRSIZ-1]) { 16384236Smckusick if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) 16394236Smckusick parentdir = dirp->d_ino; 16404236Smckusick return (STOP); 16414236Smckusick } 16424236Smckusick } 16434236Smckusick return (KEEPON); 16444236Smckusick } 16454236Smckusick 16464236Smckusick mkentry(dirp) 16474236Smckusick register DIRECT *dirp; 16484236Smckusick { 16494236Smckusick register ino_t in; 16504236Smckusick register char *p; 16514236Smckusick 16524236Smckusick if (dirp->d_ino) 16534236Smckusick return (KEEPON); 16544236Smckusick dirp->d_ino = orphan; 16554236Smckusick in = orphan; 16564236Smckusick p = &dirp->d_name[8]; 16574236Smckusick *--p = 0; 16584236Smckusick while (p > dirp->d_name) { 16594236Smckusick *--p = (in % 10) + '0'; 16604236Smckusick in /= 10; 16614236Smckusick } 16624236Smckusick *p = '#'; 16634236Smckusick return (ALTERD|STOP); 16644236Smckusick } 16654236Smckusick 16664236Smckusick chgdd(dirp) 16674236Smckusick register DIRECT *dirp; 16684236Smckusick { 16694236Smckusick if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' && 16704236Smckusick dirp->d_name[2] == 0) { 16714236Smckusick dirp->d_ino = lfdir; 16724236Smckusick return (ALTERD|STOP); 16734236Smckusick } 16744236Smckusick return (KEEPON); 16754236Smckusick } 16764236Smckusick 16774236Smckusick linkup() 16784236Smckusick { 16794236Smckusick register DINODE *dp; 16804236Smckusick register lostdir; 16814236Smckusick register ino_t pdir; 16824236Smckusick 16834236Smckusick if ((dp = ginode()) == NULL) 16844236Smckusick return (0); 16854236Smckusick lostdir = DIR; 16864236Smckusick pdir = parentdir; 16874236Smckusick pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); 16884236Smckusick pinode(); 16894236Smckusick if (preen && dp->di_size == 0) 16904236Smckusick return (0); 16914236Smckusick if (preen) 16924236Smckusick printf(" (RECONNECTED)\n"); 16934236Smckusick else 16944236Smckusick if (reply("RECONNECT") == 0) 16954236Smckusick return (0); 16964236Smckusick orphan = inum; 16974236Smckusick if (lfdir == 0) { 16984236Smckusick inum = ROOTINO; 16994236Smckusick if ((dp = ginode()) == NULL) { 17004236Smckusick inum = orphan; 17014236Smckusick return (0); 17024236Smckusick } 17034236Smckusick pfunc = findino; 17044236Smckusick srchname = lfname; 17054236Smckusick filsize = dp->di_size; 17064236Smckusick parentdir = 0; 17074236Smckusick ckinode(dp, DATA); 17084236Smckusick inum = orphan; 17094236Smckusick if ((lfdir = parentdir) == 0) { 17104236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 17114236Smckusick printf("\n\n"); 17124236Smckusick return (0); 17134236Smckusick } 17144236Smckusick } 17154236Smckusick inum = lfdir; 17164236Smckusick if ((dp = ginode()) == NULL || !DIR || getstate() != FSTATE) { 17174236Smckusick inum = orphan; 17184236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 17194236Smckusick printf("\n\n"); 17204236Smckusick return (0); 17214236Smckusick } 17225325Smckusic if (dp->di_size % sblock.fs_bsize) { 17235325Smckusic dp->di_size = roundup(dp->di_size, sblock.fs_bsize); 17244236Smckusick inodirty(); 17254236Smckusick } 17264236Smckusick filsize = dp->di_size; 17274236Smckusick inum = orphan; 17284236Smckusick pfunc = mkentry; 17294236Smckusick if ((ckinode(dp, DATA) & ALTERD) == 0) { 17304236Smckusick pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); 17314236Smckusick printf("\n\n"); 17324236Smckusick return (0); 17334236Smckusick } 17344236Smckusick declncnt(); 17354236Smckusick if (lostdir) { 17364236Smckusick pfunc = chgdd; 17374236Smckusick dp = ginode(); 17384236Smckusick filsize = dp->di_size; 17394236Smckusick ckinode(dp, DATA); 17404236Smckusick inum = lfdir; 17414236Smckusick if ((dp = ginode()) != NULL) { 17424236Smckusick dp->di_nlink++; 17434236Smckusick inodirty(); 17444236Smckusick setlncnt(getlncnt()+1); 17454236Smckusick } 17464236Smckusick inum = orphan; 17474236Smckusick pwarn("DIR I=%u CONNECTED. ", orphan); 17484236Smckusick printf("PARENT WAS I=%u\n", pdir); 17494236Smckusick if (preen == 0) 17504236Smckusick printf("\n"); 17514236Smckusick } 17524236Smckusick return (1); 17534236Smckusick } 17544236Smckusick 17554236Smckusick bread(fcp, buf, blk, size) 17564236Smckusick daddr_t blk; 17574236Smckusick register struct filecntl *fcp; 17584236Smckusick register size; 17594236Smckusick char *buf; 17604236Smckusick { 17615325Smckusic if (lseek(fcp->rfdes, blk * DEV_BSIZE, 0) < 0) 17624236Smckusick rwerr("SEEK", blk); 17634236Smckusick else if (read(fcp->rfdes, buf, size) == size) 17644236Smckusick return (1); 17654236Smckusick rwerr("READ", blk); 17664236Smckusick return (0); 17674236Smckusick } 17684236Smckusick 17694236Smckusick bwrite(fcp, buf, blk, size) 17704236Smckusick daddr_t blk; 17714236Smckusick register struct filecntl *fcp; 17724236Smckusick register size; 17734236Smckusick char *buf; 17744236Smckusick { 17754236Smckusick 17764236Smckusick if (fcp->wfdes < 0) 17774236Smckusick return (0); 17785325Smckusic if (lseek(fcp->wfdes, blk * DEV_BSIZE, 0) < 0) 17794236Smckusick rwerr("SEEK", blk); 17804236Smckusick else if (write(fcp->wfdes, buf, size) == size) { 17814236Smckusick fcp->mod = 1; 17824236Smckusick return (1); 17834236Smckusick } 17844236Smckusick rwerr("WRITE", blk); 17854236Smckusick return (0); 17864236Smckusick } 17874236Smckusick 17884236Smckusick catch() 17894236Smckusick { 17904236Smckusick 17914236Smckusick ckfini(); 17924236Smckusick exit(12); 17934236Smckusick } 17945325Smckusic 17955325Smckusic /* 17965325Smckusic * block operations 17975325Smckusic */ 17985325Smckusic 17995325Smckusic isblock(fs, cp, h) 18005325Smckusic struct fs *fs; 18015325Smckusic unsigned char *cp; 18025325Smckusic int h; 18035325Smckusic { 18045325Smckusic unsigned char mask; 18055325Smckusic 18065325Smckusic switch (fs->fs_frag) { 18075325Smckusic case 8: 18085325Smckusic return (cp[h] == 0xff); 18095325Smckusic case 4: 18105325Smckusic mask = 0x0f << ((h & 0x1) << 2); 18115325Smckusic return ((cp[h >> 1] & mask) == mask); 18125325Smckusic case 2: 18135325Smckusic mask = 0x03 << ((h & 0x3) << 1); 18145325Smckusic return ((cp[h >> 2] & mask) == mask); 18155325Smckusic case 1: 18165325Smckusic mask = 0x01 << (h & 0x7); 18175325Smckusic return ((cp[h >> 3] & mask) == mask); 18185325Smckusic default: 18195381Smckusic error("isblock bad fs_frag %d\n", fs->fs_frag); 18205381Smckusic return (0); 18215325Smckusic } 18225325Smckusic } 1823