1*5097Smckusic static char *sccsid = "@(#)main.c 1.13 (Berkeley) 11/27/81"; 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 154236Smckusick #define NDIRECT (BSIZE/sizeof(struct direct)) 164236Smckusick #define SPERB (BSIZE/sizeof(short)) 174236Smckusick 184236Smckusick #define MAXDUP 10 /* limit on dup blks (per inode) */ 194236Smckusick #define MAXBAD 10 /* limit on bad blks (per inode) */ 204236Smckusick 214236Smckusick #define USTATE 0 /* inode not allocated */ 224236Smckusick #define FSTATE 01 /* inode is file */ 234236Smckusick #define DSTATE 02 /* inode is directory */ 244236Smckusick #define CLEAR 03 /* inode is to be cleared */ 254236Smckusick 264236Smckusick typedef struct dinode DINODE; 274236Smckusick typedef struct direct DIRECT; 284236Smckusick 294236Smckusick #define ALLOC ((dp->di_mode & IFMT) != 0) 304236Smckusick #define DIR ((dp->di_mode & IFMT) == IFDIR) 314236Smckusick #define REG ((dp->di_mode & IFMT) == IFREG) 324236Smckusick #define BLK ((dp->di_mode & IFMT) == IFBLK) 334236Smckusick #define CHR ((dp->di_mode & IFMT) == IFCHR) 344236Smckusick #define MPC ((dp->di_mode & IFMT) == IFMPC) 354236Smckusick #define MPB ((dp->di_mode & IFMT) == IFMPB) 364236Smckusick #define SPECIAL (BLK || CHR || MPC || MPB) 374236Smckusick 384465Smckusic ino_t startinum; /* blk num of first in raw area */ 394236Smckusick 404236Smckusick struct bufarea { 414236Smckusick struct bufarea *b_next; /* must be first */ 424236Smckusick daddr_t b_bno; 434236Smckusick int b_size; 444236Smckusick union { 454236Smckusick char b_buf[BSIZE]; /* buffer space */ 464236Smckusick short b_lnks[SPERB]; /* link counts */ 474236Smckusick daddr_t b_indir[NINDIR]; /* indirect block */ 484236Smckusick struct fs b_fs; /* super block */ 494236Smckusick struct cg b_cg; /* cylinder group */ 504236Smckusick struct dinode b_dinode[INOPB]; /* inode block */ 514236Smckusick DIRECT b_dir[NDIRECT]; /* directory */ 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 */ 924236Smckusick char preen; /* just fix normal inconsistencies */ 934236Smckusick char rplyflag; /* any questions asked? */ 944236Smckusick char hotroot; /* checking root device */ 954236Smckusick char fixcg; /* corrupted free list bit maps */ 964236Smckusick 974236Smckusick char *blkmap; /* ptr to primary blk allocation map */ 984236Smckusick char *freemap; /* ptr to secondary blk allocation map */ 994236Smckusick char *statemap; /* ptr to inode state table */ 1004236Smckusick short *lncntp; /* ptr to link count table */ 1014236Smckusick 1024236Smckusick char *pathp; /* pointer to pathname position */ 1034236Smckusick char *thisname; /* ptr to current pathname component */ 1044236Smckusick char *srchname; /* name being searched for in dir */ 1054236Smckusick char pathname[200]; 1064236Smckusick 1074236Smckusick char *lfname = "lost+found"; 1084236Smckusick 1094236Smckusick ino_t inum; /* inode we are currently working on */ 1104236Smckusick ino_t imax; /* number of inodes */ 1114236Smckusick ino_t parentdir; /* i number of parent directory */ 1124236Smckusick ino_t lastino; /* hiwater mark of inodes */ 1134236Smckusick ino_t lfdir; /* lost & found directory */ 1144236Smckusick ino_t orphan; /* orphaned inode */ 1154236Smckusick 1164236Smckusick off_t filsize; /* num blks seen in file */ 1174236Smckusick off_t maxblk; /* largest logical blk in file */ 1184236Smckusick off_t bmapsz; /* num chars in blkmap */ 1194236Smckusick 1204236Smckusick daddr_t n_ffree; /* number of small free blocks */ 1214236Smckusick daddr_t n_bfree; /* number of large free blocks */ 1224236Smckusick daddr_t n_blks; /* number of blocks used */ 1234236Smckusick daddr_t n_files; /* number of files seen */ 1244236Smckusick daddr_t n_index; 1254236Smckusick daddr_t n_bad; 1264236Smckusick daddr_t fmax; /* number of blocks in the volume */ 1274236Smckusick 1284236Smckusick daddr_t badblk; 1294236Smckusick daddr_t dupblk; 1304236Smckusick 1314236Smckusick int inosumbad; 1324236Smckusick int offsumbad; 1334465Smckusic int frsumbad; 1344236Smckusick 1354236Smckusick #define zapino(x) (*(x) = zino) 1364236Smckusick struct dinode zino; 1374236Smckusick 1384236Smckusick #define setlncnt(x) (lncntp[inum] = x) 1394236Smckusick #define getlncnt() (lncntp[inum]) 1404236Smckusick #define declncnt() (--lncntp[inum]) 1414236Smckusick 1424236Smckusick #define setbmap(x) setbit(blkmap, x) 1434236Smckusick #define getbmap(x) isset(blkmap, x) 1444236Smckusick #define clrbmap(x) clrbit(blkmap, x) 1454236Smckusick 1464236Smckusick #define setfmap(x) setbit(freemap, x) 1474236Smckusick #define getfmap(x) isset(freemap, x) 1484236Smckusick #define clrfmap(x) clrbit(freemap, x) 1494236Smckusick 1504236Smckusick #define setstate(x) (statemap[inum] = x) 1514236Smckusick #define getstate() statemap[inum] 1524236Smckusick 1534236Smckusick #define DATA 1 1544236Smckusick #define ADDR 0 1554236Smckusick 1564236Smckusick #define ALTERD 010 1574236Smckusick #define KEEPON 04 1584236Smckusick #define SKIP 02 1594236Smckusick #define STOP 01 1604236Smckusick 1614236Smckusick int (*signal())(); 1624236Smckusick long lseek(); 1634236Smckusick time_t time(); 1644236Smckusick DINODE *ginode(); 1654236Smckusick BUFAREA *getblk(); 1664236Smckusick int dirscan(); 1674236Smckusick int findino(); 1684236Smckusick int catch(); 1694236Smckusick int mkentry(); 1704236Smckusick int chgdd(); 1714236Smckusick int pass1(), pass1b(), pass2(), pass4(), pass5(); 1724236Smckusick int (*pfunc)(); 1734236Smckusick char *rawname(), *rindex(), *unrawname(); 1744606Smckusic extern int inside[], around[]; 1754606Smckusic extern unsigned char fragtbl[]; 1764236Smckusick 1774236Smckusick char *devname; 1784236Smckusick 1794236Smckusick main(argc, argv) 1804715Smckusic int argc; 1814715Smckusic char *argv[]; 1824236Smckusick { 1834236Smckusick struct fstab *fsp; 1844236Smckusick int pid, passno, anygtr, sumstatus; 1854236Smckusick 1864236Smckusick sync(); 1874236Smckusick while (--argc > 0 && **++argv == '-') { 1884236Smckusick switch (*++*argv) { 1894236Smckusick 1904236Smckusick case 'p': 1914236Smckusick preen++; 1924236Smckusick break; 1934236Smckusick 1944236Smckusick case 'b': 1954236Smckusick bflag = atoi(argv[0]+1); 1964236Smckusick printf("Alternate super block location: %d\n", bflag); 1974236Smckusick break; 1984236Smckusick 1994236Smckusick case 'n': /* default no answer flag */ 2004236Smckusick case 'N': 2014236Smckusick nflag++; 2024236Smckusick yflag = 0; 2034236Smckusick break; 2044236Smckusick 2054236Smckusick case 'y': /* default yes answer flag */ 2064236Smckusick case 'Y': 2074236Smckusick yflag++; 2084236Smckusick nflag = 0; 2094236Smckusick break; 2104236Smckusick 2114236Smckusick default: 2124236Smckusick errexit("%c option?\n", **argv); 2134236Smckusick } 2144236Smckusick } 2154236Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2164236Smckusick signal(SIGINT, catch); 2174236Smckusick if (argc) { 2184236Smckusick while (argc-- > 0) { 2194236Smckusick hotroot = 0; 2204236Smckusick check(*argv++); 2214236Smckusick } 2224236Smckusick exit(0); 2234236Smckusick } 2244236Smckusick sumstatus = 0; 2254236Smckusick passno = 1; 2264236Smckusick do { 2274236Smckusick anygtr = 0; 2284236Smckusick if (setfsent() == 0) 2294236Smckusick errexit("Can't open checklist file: %s\n", FSTAB); 2304236Smckusick while ((fsp = getfsent()) != 0) { 2314236Smckusick if (strcmp(fsp->fs_type, FSTAB_RW) && 2324236Smckusick strcmp(fsp->fs_type, FSTAB_RO)) 2334236Smckusick continue; 2344236Smckusick if (preen == 0 || 2354236Smckusick passno == 1 && fsp->fs_passno == passno) { 2364236Smckusick if (blockcheck(fsp->fs_spec) == 0 && preen) 2374236Smckusick exit(8); 2384236Smckusick } else if (fsp->fs_passno > passno) 2394236Smckusick anygtr = 1; 2404236Smckusick else if (fsp->fs_passno == passno) { 2414236Smckusick pid = fork(); 2424236Smckusick if (pid < 0) { 2434236Smckusick perror("fork"); 2444236Smckusick exit(8); 2454236Smckusick } 2464236Smckusick if (pid == 0) 2474236Smckusick if (blockcheck(fsp->fs_spec)==0) 2484236Smckusick exit(8); 2494236Smckusick else 2504236Smckusick exit(0); 2514236Smckusick } 2524236Smckusick } 2534236Smckusick if (preen) { 2544236Smckusick int status; 2554236Smckusick while (wait(&status) != -1) 2564236Smckusick sumstatus |= status; 2574236Smckusick } 2584236Smckusick passno++; 2594236Smckusick } while (anygtr); 2604236Smckusick if (sumstatus) 2614236Smckusick exit(8); 2624236Smckusick endfsent(); 2634236Smckusick exit(0); 2644236Smckusick } 2654236Smckusick 2664236Smckusick blockcheck(name) 2674236Smckusick char *name; 2684236Smckusick { 2694878Smckusic struct ostat stslash, stblock, stchar; 2704236Smckusick char *raw; 2714236Smckusick int looped = 0; 2724236Smckusick 2734236Smckusick hotroot = 0; 2744236Smckusick if (stat("/", &stslash) < 0){ 2754236Smckusick error("Can't stat root\n"); 2764236Smckusick return (0); 2774236Smckusick } 2784236Smckusick retry: 2794236Smckusick if (stat(name, &stblock) < 0){ 2804236Smckusick error("Can't stat %s\n", name); 2814236Smckusick return (0); 2824236Smckusick } 2834236Smckusick if (stblock.st_mode & S_IFBLK) { 2844236Smckusick raw = rawname(name); 2854236Smckusick if (stat(raw, &stchar) < 0){ 2864236Smckusick error("Can't stat %s\n", raw); 2874236Smckusick return (0); 2884236Smckusick } 2894236Smckusick if (stchar.st_mode & S_IFCHR) { 2904236Smckusick if (stslash.st_dev == stblock.st_rdev) { 2914236Smckusick hotroot++; 2924236Smckusick raw = unrawname(name); 2934236Smckusick } 2944236Smckusick check(raw); 2954236Smckusick return (1); 2964236Smckusick } else { 2974236Smckusick error("%s is not a character device\n", raw); 2984236Smckusick return (0); 2994236Smckusick } 3004236Smckusick } else if (stblock.st_mode & S_IFCHR) { 3014236Smckusick if (looped) { 3024236Smckusick error("Can't make sense out of name %s\n", name); 3034236Smckusick return (0); 3044236Smckusick } 3054236Smckusick name = unrawname(name); 3064236Smckusick looped++; 3074236Smckusick goto retry; 3084236Smckusick } 3094236Smckusick error("Can't make sense out of name %s\n", name); 3104236Smckusick return (0); 3114236Smckusick } 3124236Smckusick 3134236Smckusick char * 3144236Smckusick unrawname(cp) 3154236Smckusick char *cp; 3164236Smckusick { 3174236Smckusick char *dp = rindex(cp, '/'); 3184878Smckusic struct ostat stb; 3194236Smckusick 3204236Smckusick if (dp == 0) 3214236Smckusick return (cp); 3224236Smckusick if (stat(cp, &stb) < 0) 3234236Smckusick return (cp); 3244236Smckusick if ((stb.st_mode&S_IFMT) != S_IFCHR) 3254236Smckusick return (cp); 3264236Smckusick if (*(dp+1) != 'r') 3274236Smckusick return (cp); 3284236Smckusick strcpy(dp+1, dp+2); 3294236Smckusick return (cp); 3304236Smckusick } 3314236Smckusick 3324236Smckusick char * 3334236Smckusick rawname(cp) 3344236Smckusick char *cp; 3354236Smckusick { 3364236Smckusick static char rawbuf[32]; 3374236Smckusick char *dp = rindex(cp, '/'); 3384236Smckusick 3394236Smckusick if (dp == 0) 3404236Smckusick return (0); 3414236Smckusick *dp = 0; 3424236Smckusick strcpy(rawbuf, cp); 3434236Smckusick *dp = '/'; 3444236Smckusick strcat(rawbuf, "/r"); 3454236Smckusick strcat(rawbuf, dp+1); 3464236Smckusick return (rawbuf); 3474236Smckusick } 3484236Smckusick 3494236Smckusick check(dev) 3504236Smckusick char *dev; 3514236Smckusick { 3524236Smckusick register DINODE *dp; 3534236Smckusick register ino_t *blp; 3544236Smckusick register int i, n; 3554236Smckusick ino_t savino; 3564236Smckusick int b, c; 3574236Smckusick daddr_t d, s; 3584236Smckusick 3594236Smckusick devname = dev; 3604236Smckusick if (setup(dev) == 0) { 3614236Smckusick if (preen) 3624236Smckusick pfatal("CAN'T CHECK DEVICE."); 3634236Smckusick return; 3644236Smckusick } 3654236Smckusick /* 1 */ 3664236Smckusick if (preen==0) { 3674236Smckusick if (hotroot) 3684236Smckusick printf("** Root file system\n"); 3694236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 3704236Smckusick } 3714236Smckusick pfunc = pass1; 3724236Smckusick inum = 0; 3734789Smckusic n_blks += howmany(sblock.fs_cssize, BSIZE) * FRAG; 3744236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 3754236Smckusick if (getblk(&cgblk, cgtod(c, &sblock), sblock.fs_cgsize) == 0) 3764236Smckusick continue; 3774236Smckusick n = 0; 3784465Smckusic for (i = 0; i < sblock.fs_ipg; i++, inum++) { 3794465Smckusic dp = ginode(); 3804465Smckusic if (dp == NULL) 3814465Smckusic continue; 3824236Smckusick if (ALLOC) { 3834236Smckusick if (!isset(cgrp.cg_iused, i)) { 3844465Smckusic /* 3854236Smckusick printf("%d bad, not used\n", inum); 3864465Smckusic */ 3874236Smckusick inosumbad++; 3884465Smckusic n++; 3894236Smckusick } 3904236Smckusick lastino = inum; 3914236Smckusick if (ftypeok(dp) == 0) { 3924236Smckusick pfatal("UNKNOWN FILE TYPE I=%u", inum); 3934236Smckusick if (reply("CLEAR") == 1) { 3944236Smckusick zapino(dp); 3954236Smckusick inodirty(); 3964236Smckusick inosumbad++; 3974236Smckusick } 3984236Smckusick continue; 3994236Smckusick } 4004236Smckusick n_files++; 4014236Smckusick if (setlncnt(dp->di_nlink) <= 0) { 4024236Smckusick if (badlnp < &badlncnt[MAXLNCNT]) 4034236Smckusick *badlnp++ = inum; 4044236Smckusick else { 4054236Smckusick pfatal("LINK COUNT TABLE OVERFLOW"); 4064236Smckusick if (reply("CONTINUE") == 0) 4074236Smckusick errexit(""); 4084236Smckusick } 4094236Smckusick } 4104236Smckusick setstate(DIR ? DSTATE : FSTATE); 4114236Smckusick badblk = dupblk = 0; filsize = 0; maxblk = 0; 4124236Smckusick ckinode(dp, ADDR); 4134236Smckusick if (DIR && dp->di_size % sizeof(DIRECT)) { 4144236Smckusick pwarn("DIRECTORY MISALIGNED I=%u\n", 4154236Smckusick inum); 4164236Smckusick if (preen == 0) 4174236Smckusick printf("\n"); 4184236Smckusick } 4194236Smckusick } else { 4204236Smckusick n++; 4214236Smckusick if (isset(cgrp.cg_iused, i)) { 4224465Smckusic /* 4234236Smckusick printf("%d bad, marked used\n", inum); 4244465Smckusic */ 4254236Smckusick inosumbad++; 4264465Smckusic n--; 4274236Smckusick } 4284236Smckusick if (dp->di_mode != 0) { 4294236Smckusick pfatal("PARTIALLY ALLOCATED INODE I=%u", inum); 4304236Smckusick if (reply("CLEAR") == 1) { 4314236Smckusick zapino(dp); 4324236Smckusick inodirty(); 4334236Smckusick inosumbad++; 4344236Smckusick } 4354236Smckusick } 4364236Smckusick } 4374236Smckusick } 4384789Smckusic if (n != cgrp.cg_cs.cs_nifree) { 4394789Smckusic printf("cg[%d].cg_cs.cs_nifree is %d not %d\n", 4404789Smckusic 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 } 5544789Smckusic if (imax - 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) { 5594789Smckusic sblock.fs_cstotal.cs_nifree = imax - 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; 5704236Smckusick n_index = sblock.fs_ncg * (cgdmin(0, &sblock) - cgtod(0, &sblock)); 5714236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 5724236Smckusick daddr_t cbase = cgbase(c,&sblock); 5734236Smckusick short bo[MAXCPG][NRPOS]; 5744789Smckusic long frsum[FRAG]; 5754465Smckusic int blk; 5764465Smckusic 5774236Smckusick for (n = 0; n < sblock.fs_cpg; n++) 5784236Smckusick for (i = 0; i < NRPOS; i++) 5794236Smckusick bo[n][i] = 0; 5804465Smckusic for (i = 0; i < FRAG; i++) { 5814465Smckusic frsum[i] = 0; 5824465Smckusic } 5834465Smckusic /* 5844465Smckusic * need to account for the spare boot and super blocks 5854465Smckusic * which appear (inaccurately) bad 5864465Smckusic */ 5874236Smckusick n_bad += cgtod(c, &sblock) - cbase; 5884236Smckusick if (getblk(&cgblk, cgtod(c, &sblock), sblock.fs_cgsize) == 0) 5894236Smckusick continue; 5904236Smckusick for (b = 0; b < sblock.fs_fpg; b += FRAG) { 5914236Smckusick if (isblock(cgrp.cg_free, b/FRAG)) { 5924236Smckusick if (pass5(cbase+b, FRAG) == STOP) 5934236Smckusick goto out5; 5944236Smckusick /* this is clumsy ... */ 5954236Smckusick n_ffree -= FRAG; 5964236Smckusick n_bfree++; 5974236Smckusick s = b * NSPF; 5984236Smckusick bo[s/sblock.fs_spc] 5994236Smckusick [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 6004465Smckusic } else { 6014236Smckusick for (d = 0; d < FRAG; d++) 6024236Smckusick if (isset(cgrp.cg_free, b+d)) 6034236Smckusick if (pass5(cbase+b+d,1) == STOP) 6044236Smckusick goto out5; 6054465Smckusic blk = ((cgrp.cg_free[b / NBBY] >> (b % NBBY)) & 6064465Smckusic (0xff >> (NBBY - FRAG))); 6074465Smckusic if (blk != 0) 6084465Smckusic fragacct(blk, frsum, 1); 6094465Smckusic } 6104236Smckusick } 6114465Smckusic for (i = 0; i < FRAG; i++) { 6124465Smckusic if (cgrp.cg_frsum[i] != frsum[i]) { 6134465Smckusic printf("cg[%d].cg_frsum[%d] have %d calc %d\n", 6144465Smckusic c, i, cgrp.cg_frsum[i], frsum[i]); 6154465Smckusic frsumbad++; 6164465Smckusic } 6174465Smckusic } 6184236Smckusick for (n = 0; n < sblock.fs_cpg; n++) 6194236Smckusick for (i = 0; i < NRPOS; i++) 6204236Smckusick if (bo[n][i] != cgrp.cg_b[n][i]) { 6214428Smckusic printf("cg[%d].cg_b[%d][%d] have %d calc %d\n", 6224428Smckusic c, n, i, cgrp.cg_b[n][i], bo[n][i]); 6234236Smckusick offsumbad++; 6244236Smckusick } 6254236Smckusick } 6264236Smckusick out5: 6274236Smckusick if (dupblk) 6284236Smckusick pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk); 6294236Smckusick if (fixcg == 0) { 6304236Smckusick if ((b = n_blks+n_ffree+FRAG*n_bfree+n_index+n_bad) != fmax) { 6314236Smckusick pwarn("%ld BLK(S) MISSING\n", fmax - b); 6324236Smckusick fixcg = 1; 6334465Smckusic } else if (inosumbad + offsumbad + frsumbad) { 6344465Smckusic pwarn("SUMMARY INFORMATION %s%s%sBAD\n", 6354236Smckusick inosumbad ? "(INODE FREE) " : "", 6364465Smckusic offsumbad ? "(BLOCK OFFSETS) " : "", 6374465Smckusic frsumbad ? "(FRAG SUMMARIES) " : ""); 6384236Smckusick fixcg = 1; 6394789Smckusic } else if (n_ffree != sblock.fs_cstotal.cs_nffree || 6404789Smckusic n_bfree != sblock.fs_cstotal.cs_nbfree) { 6414236Smckusick pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK"); 6424236Smckusick if (preen) 6434236Smckusick printf(" (FIXED)\n"); 6444236Smckusick if (preen || reply("FIX") == 1) { 6454789Smckusic sblock.fs_cstotal.cs_nffree = n_ffree; 6464789Smckusic sblock.fs_cstotal.cs_nbfree = n_bfree; 6474236Smckusick sbdirty(); 6484236Smckusick } 6494236Smckusick } 6504236Smckusick } 6514236Smckusick if (fixcg) { 6524236Smckusick pwarn("BAD CYLINDER GROUPS"); 6534236Smckusick if (preen) 6544236Smckusick printf(" (SALVAGED)\n"); 6554236Smckusick else if (reply("SALVAGE") == 0) 6564236Smckusick fixcg = 0; 6574236Smckusick } 6584236Smckusick 6594236Smckusick if (fixcg) { 6604236Smckusick if (preen == 0) 6614236Smckusick printf("** Phase 6 - Salvage Cylinder Groups\n"); 6624236Smckusick makecg(); 6634789Smckusic n_ffree = sblock.fs_cstotal.cs_nffree; 6644789Smckusic n_bfree = sblock.fs_cstotal.cs_nbfree; 6654236Smckusick } 6664236Smckusick 6674236Smckusick pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n", 6684789Smckusic n_files, n_blks - howmany(sblock.fs_cssize, BSIZE) * FRAG, 6694789Smckusic n_ffree + FRAG * n_bfree, n_ffree, n_bfree); 6704236Smckusick if (dfile.mod) { 6714236Smckusick time(&sblock.fs_time); 6724236Smckusick sbdirty(); 6734236Smckusick } 6744236Smckusick ckfini(); 6754236Smckusick sync(); 6764236Smckusick if (dfile.mod && hotroot) { 6774236Smckusick printf("\n***** BOOT UNIX (NO SYNC!) *****\n"); 6784236Smckusick exit(4); 6794236Smckusick } 6804236Smckusick if (dfile.mod && preen == 0) 6814236Smckusick printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 6824236Smckusick free(blkmap); 6834236Smckusick free(freemap); 6844236Smckusick free(statemap); 6854236Smckusick free(lncntp); 6864236Smckusick } 6874236Smckusick 6884236Smckusick /* VARARGS1 */ 6894236Smckusick error(s1, s2, s3, s4) 6904715Smckusic char *s1; 6914236Smckusick { 6924236Smckusick 6934236Smckusick printf(s1, s2, s3, s4); 6944236Smckusick } 6954236Smckusick 6964236Smckusick /* VARARGS1 */ 6974236Smckusick errexit(s1, s2, s3, s4) 6984715Smckusic char *s1; 6994236Smckusick { 7004236Smckusick error(s1, s2, s3, s4); 7014236Smckusick exit(8); 7024236Smckusick } 7034236Smckusick 7044236Smckusick /* 7054236Smckusick * An inconsistency occured which shouldn't during normal operations. 7064236Smckusick * Die if preening, otw just printf. 7074236Smckusick */ 7084236Smckusick /* VARARGS1 */ 7094236Smckusick pfatal(s, a1, a2, a3) 7104236Smckusick char *s; 7114236Smckusick { 7124236Smckusick 7134236Smckusick if (preen) { 7144236Smckusick printf("%s: ", devname); 7154236Smckusick printf(s, a1, a2, a3); 7164236Smckusick printf("\n"); 7174236Smckusick preendie(); 7184236Smckusick } 7194236Smckusick printf(s, a1, a2, a3); 7204236Smckusick } 7214236Smckusick 7224236Smckusick preendie() 7234236Smckusick { 7244236Smckusick 7254236Smckusick printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); 7264236Smckusick exit(8); 7274236Smckusick } 7284236Smckusick 7294236Smckusick /* 7304236Smckusick * Pwarn is like printf when not preening, 7314236Smckusick * or a warning (preceded by filename) when preening. 7324236Smckusick */ 7334236Smckusick /* VARARGS1 */ 7344236Smckusick pwarn(s, a1, a2, a3, a4, a5) 7354236Smckusick char *s; 7364236Smckusick { 7374236Smckusick 7384236Smckusick if (preen) 7394236Smckusick printf("%s: ", devname); 7404236Smckusick printf(s, a1, a2, a3, a4, a5); 7414236Smckusick } 7424236Smckusick 7434236Smckusick ckinode(dp, flg) 7444236Smckusick DINODE *dp; 7454236Smckusick register flg; 7464236Smckusick { 7474236Smckusick register daddr_t *ap; 7484236Smckusick register ret; 7494236Smckusick int (*func)(), n, ndb, size; 7504236Smckusick 7514236Smckusick if (SPECIAL) 7524236Smckusick return (KEEPON); 7534236Smckusick func = (flg == ADDR) ? pfunc : dirscan; 7544236Smckusick ndb = howmany(dp->di_size, BSIZE); 7554428Smckusic for (ap = &dp->di_db[0]; ap < &dp->di_db[NDADDR]; ap++) { 7564236Smckusick if (--ndb == 0 && (dp->di_size&BMASK)) 7574236Smckusick size = howmany(dp->di_size&BMASK, FSIZE); 7584236Smckusick else 7594236Smckusick size = FRAG; 7604236Smckusick if (*ap && (ret = (*func)(*ap, size)) & STOP) 7614236Smckusick return (ret); 7624236Smckusick } 7634428Smckusic for (ap = &dp->di_ib[0], n = 1; n <= 2; ap++, n++) { 7644428Smckusic if (*ap && (ret = iblock(*ap, n, flg, dp->di_size - BSIZE * NDADDR)) & STOP) 7654236Smckusick return (ret); 7664236Smckusick } 7674236Smckusick return (KEEPON); 7684236Smckusick } 7694236Smckusick 7704236Smckusick iblock(blk, ilevel, flg, isize) 7714236Smckusick daddr_t blk; 7724236Smckusick register ilevel; 7734236Smckusick int isize; 7744236Smckusick { 7754236Smckusick register daddr_t *ap; 7764236Smckusick register daddr_t *aplim; 7774428Smckusic register int i, n; 7784236Smckusick int (*func)(), nif; 7794236Smckusick BUFAREA ib; 7804236Smckusick 7814236Smckusick if (flg == ADDR) { 7824236Smckusick func = pfunc; 7834428Smckusic if (((n = (*func)(blk, FRAG)) & KEEPON) == 0) 7844236Smckusick return (n); 7854236Smckusick } else 7864236Smckusick func = dirscan; 7874236Smckusick if (outrange(blk)) /* protect thyself */ 7884236Smckusick return (SKIP); 7894236Smckusick initbarea(&ib); 7904428Smckusic if (getblk(&ib, blk, BSIZE) == NULL) 7914236Smckusick return (SKIP); 7924236Smckusick ilevel--; 7934428Smckusic if (ilevel == 0) { 7944428Smckusic nif = isize / BSIZE + 1; 7954428Smckusic } else /* ilevel == 1 */ { 7964428Smckusic nif = isize / (BSIZE * NINDIR) + 1; 7974428Smckusic } 7984428Smckusic if (nif > NINDIR) 7994428Smckusic nif = NINDIR; 8004428Smckusic aplim = & ib.b_un.b_indir[nif]; 8014428Smckusic for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++) 8024236Smckusick if (*ap) { 8034236Smckusick if (ilevel > 0) 8044428Smckusic n = iblock(*ap, ilevel, flg, isize - i * NINDIR * BSIZE); 8054236Smckusick else 8064428Smckusic n = (*func)(*ap, FRAG); 8074236Smckusick if (n & STOP) 8084236Smckusick return (n); 8094236Smckusick } 8104236Smckusick return (KEEPON); 8114236Smckusick } 8124236Smckusick 8134236Smckusick pass1(blk, size) 8144236Smckusick daddr_t blk; 8154236Smckusick int size; 8164236Smckusick { 8174236Smckusick register daddr_t *dlp; 8184236Smckusick int res = KEEPON; 8194236Smckusick 8204236Smckusick for (; size > 0; blk++, size--) { 8214236Smckusick if (outrange(blk)) { 8224236Smckusick blkerr("BAD", blk); 8234236Smckusick if (++badblk >= MAXBAD) { 8244236Smckusick printf("EXCESSIVE BAD BLKS I=%u", inum); 8254236Smckusick if (reply("CONTINUE") == 0) 8264236Smckusick errexit(""); 8274236Smckusick return (STOP); 8284236Smckusick } 8294236Smckusick res = SKIP; 8304236Smckusick } else if (getbmap(blk)) { 8314236Smckusick blkerr("DUP", blk); 8324236Smckusick if (++dupblk >= MAXDUP) { 8334236Smckusick printf("EXCESSIVE DUP BLKS I=%u", inum); 8344236Smckusick if (reply("CONTINUE") == 0) 8354236Smckusick errexit(""); 8364236Smckusick return (STOP); 8374236Smckusick } 8384236Smckusick if (enddup >= &duplist[DUPTBLSIZE]) { 8394236Smckusick printf("DUP TABLE OVERFLOW."); 8404236Smckusick if (reply("CONTINUE") == 0) 8414236Smckusick errexit(""); 8424236Smckusick return (STOP); 8434236Smckusick } 8444236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8454236Smckusick if (*dlp == blk) { 8464236Smckusick *enddup++ = blk; 8474236Smckusick break; 8484236Smckusick } 8494236Smckusick if (dlp >= muldup) { 8504236Smckusick *enddup++ = *muldup; 8514236Smckusick *muldup++ = blk; 8524236Smckusick } 8534236Smckusick } else { 8544236Smckusick n_blks++; 8554236Smckusick setbmap(blk); 8564236Smckusick } 8574236Smckusick filsize++; 8584236Smckusick } 8594236Smckusick return (res); 8604236Smckusick } 8614236Smckusick 8624236Smckusick pass1b(blk, size) 8634236Smckusick daddr_t blk; 8644236Smckusick int size; 8654236Smckusick { 8664236Smckusick register daddr_t *dlp; 8674236Smckusick int res = KEEPON; 8684236Smckusick 8694236Smckusick for (; size > 0; blk++, size--) { 8704236Smckusick if (outrange(blk)) 8714236Smckusick res = SKIP; 8724236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8734236Smckusick if (*dlp == blk) { 8744236Smckusick blkerr("DUP", blk); 8754236Smckusick *dlp = *--muldup; 8764236Smckusick *muldup = blk; 8774236Smckusick if (muldup == duplist) 8784236Smckusick return (STOP); 8794236Smckusick } 8804236Smckusick } 8814236Smckusick return (res); 8824236Smckusick } 8834236Smckusick 8844236Smckusick pass2(dirp) 8854236Smckusick register DIRECT *dirp; 8864236Smckusick { 8874236Smckusick register char *p; 8884236Smckusick register n; 8894236Smckusick DINODE *dp; 8904236Smckusick 8914236Smckusick if ((inum = dirp->d_ino) == 0) 8924236Smckusick return (KEEPON); 8934236Smckusick thisname = pathp; 8944236Smckusick for (p = dirp->d_name; p < &dirp->d_name[DIRSIZ]; ) 8954236Smckusick if ((*pathp++ = *p++) == 0) { 8964236Smckusick --pathp; 8974236Smckusick break; 8984236Smckusick } 8994236Smckusick *pathp = 0; 9004236Smckusick n = 0; 9014715Smckusic if (inum > imax || inum <= 0) 9024236Smckusick n = direrr("I OUT OF RANGE"); 9034236Smckusick else { 9044236Smckusick again: 9054236Smckusick switch (getstate()) { 9064236Smckusick case USTATE: 9074236Smckusick n = direrr("UNALLOCATED"); 9084236Smckusick break; 9094236Smckusick 9104236Smckusick case CLEAR: 9114236Smckusick if ((n = direrr("DUP/BAD")) == 1) 9124236Smckusick break; 9134236Smckusick if ((dp = ginode()) == NULL) 9144236Smckusick break; 9154236Smckusick setstate(DIR ? DSTATE : FSTATE); 9164236Smckusick goto again; 9174236Smckusick 9184236Smckusick case FSTATE: 9194236Smckusick declncnt(); 9204236Smckusick break; 9214236Smckusick 9224236Smckusick case DSTATE: 9234236Smckusick declncnt(); 9244236Smckusick descend(); 9254236Smckusick break; 9264236Smckusick } 9274236Smckusick } 9284236Smckusick pathp = thisname; 9294236Smckusick if (n == 0) 9304236Smckusick return (KEEPON); 9314236Smckusick dirp->d_ino = 0; 9324236Smckusick return (KEEPON|ALTERD); 9334236Smckusick } 9344236Smckusick 9354236Smckusick pass4(blk, size) 9364715Smckusic daddr_t blk; 9374236Smckusick { 9384236Smckusick register daddr_t *dlp; 9394236Smckusick int res = KEEPON; 9404236Smckusick 9414236Smckusick for (; size > 0; blk++, size--) { 9424236Smckusick if (outrange(blk)) 9434236Smckusick res = SKIP; 9444236Smckusick else if (getbmap(blk)) { 9454236Smckusick for (dlp = duplist; dlp < enddup; dlp++) 9464236Smckusick if (*dlp == blk) { 9474236Smckusick *dlp = *--enddup; 9484236Smckusick return (KEEPON); 9494236Smckusick } 9504236Smckusick clrbmap(blk); 9514236Smckusick n_blks--; 9524236Smckusick } 9534236Smckusick } 9544236Smckusick return (res); 9554236Smckusick } 9564236Smckusick 9574236Smckusick pass5(blk, size) 9584236Smckusick daddr_t blk; 9594236Smckusick int size; 9604236Smckusick { 9614236Smckusick int res = KEEPON; 9624236Smckusick 9634236Smckusick for (; size > 0; blk++, size--) { 9644236Smckusick if (outrange(blk)) { 9654236Smckusick fixcg = 1; 9664236Smckusick if (preen) 9674236Smckusick pfatal("BAD BLOCKS IN BIT MAPS."); 9684236Smckusick if (++badblk >= MAXBAD) { 9694236Smckusick printf("EXCESSIVE BAD BLKS IN BIT MAPS."); 9704236Smckusick if (reply("CONTINUE") == 0) 9714236Smckusick errexit(""); 9724236Smckusick return (STOP); 9734236Smckusick } 9744236Smckusick } else if (getfmap(blk)) { 9754236Smckusick fixcg = 1; 9764236Smckusick if (++dupblk >= DUPTBLSIZE) { 9774236Smckusick printf("EXCESSIVE DUP BLKS IN BIT MAPS."); 9784236Smckusick if (reply("CONTINUE") == 0) 9794236Smckusick errexit(""); 9804236Smckusick return (STOP); 9814236Smckusick } 9824236Smckusick } else { 9834236Smckusick n_ffree++; 9844236Smckusick setfmap(blk); 9854236Smckusick } 9864236Smckusick } 9874236Smckusick return (res); 9884236Smckusick } 9894236Smckusick 9904236Smckusick outrange(blk) 9914236Smckusick daddr_t blk; 9924236Smckusick { 9934236Smckusick register int c; 9944236Smckusick 9954236Smckusick c = dtog(blk, &sblock); 9964428Smckusic if (blk >= fmax || blk < cgdmin(c, &sblock)) { 9974236Smckusick return (1); 9984428Smckusic } 9994236Smckusick return (0); 10004236Smckusick } 10014236Smckusick 10024236Smckusick blkerr(s, blk) 10034236Smckusick daddr_t blk; 10044236Smckusick char *s; 10054236Smckusick { 10064236Smckusick pfatal("%ld %s I=%u", blk, s, inum); 10074236Smckusick printf("\n"); 10084236Smckusick setstate(CLEAR); /* mark for possible clearing */ 10094236Smckusick } 10104236Smckusick 10114236Smckusick descend() 10124236Smckusick { 10134236Smckusick register DINODE *dp; 10144236Smckusick register char *savname; 10154236Smckusick off_t savsize; 10164236Smckusick 10174236Smckusick setstate(FSTATE); 10184236Smckusick if ((dp = ginode()) == NULL) 10194236Smckusick return; 10204236Smckusick savname = thisname; 10214236Smckusick *pathp++ = '/'; 10224236Smckusick savsize = filsize; 10234236Smckusick filsize = dp->di_size; 10244236Smckusick ckinode(dp, DATA); 10254236Smckusick thisname = savname; 10264236Smckusick *--pathp = 0; 10274236Smckusick filsize = savsize; 10284236Smckusick } 10294236Smckusick 10304236Smckusick dirscan(blk, nf) 10314715Smckusic daddr_t blk; 10324715Smckusic int nf; 10334236Smckusick { 10344236Smckusick register DIRECT *dirp; 10354236Smckusick register DIRECT *edirp; 10364236Smckusick register char *p1, *p2; 10374236Smckusick register n; 10384236Smckusick DIRECT direntry; 10394236Smckusick 10404236Smckusick if (outrange(blk)) { 10414236Smckusick filsize -= BSIZE; 10424236Smckusick return (SKIP); 10434236Smckusick } 10444236Smckusick edirp = &dirblk.b_dir[NDIRECT*nf/FRAG]; 10454236Smckusick for (dirp = dirblk.b_dir; dirp < edirp && 10464236Smckusick filsize > 0; dirp++, filsize -= sizeof(DIRECT)) { 10474236Smckusick if (getblk(&fileblk, blk, nf * FSIZE) == NULL) { 10484236Smckusick filsize -= (&dirblk.b_dir[NDIRECT]-dirp)*sizeof(DIRECT); 10494236Smckusick return (SKIP); 10504236Smckusick } 10514236Smckusick p1 = &dirp->d_name[DIRSIZ]; 10524236Smckusick p2 = &direntry.d_name[DIRSIZ]; 10534236Smckusick while (p1 > (char *)dirp) 10544236Smckusick *--p2 = *--p1; 10554236Smckusick if ((n = (*pfunc)(&direntry)) & ALTERD) { 10564236Smckusick if (getblk(&fileblk, blk, nf * FSIZE) != NULL) { 10574236Smckusick p1 = &dirp->d_name[DIRSIZ]; 10584236Smckusick p2 = &direntry.d_name[DIRSIZ]; 10594236Smckusick while (p1 > (char *)dirp) 10604236Smckusick *--p1 = *--p2; 10614715Smckusic dirty(&fileblk); 10624236Smckusick sbdirty(); 10634236Smckusick } else 10644236Smckusick n &= ~ALTERD; 10654236Smckusick } 10664236Smckusick if (n & STOP) 10674236Smckusick return (n); 10684236Smckusick } 10694236Smckusick return (filsize > 0 ? KEEPON : STOP); 10704236Smckusick } 10714236Smckusick 10724236Smckusick direrr(s) 10734715Smckusic char *s; 10744236Smckusick { 10754236Smckusick register DINODE *dp; 10764236Smckusick 10774236Smckusick pwarn("%s ", s); 10784236Smckusick pinode(); 10794236Smckusick printf("\n"); 10804236Smckusick if ((dp = ginode()) != NULL && ftypeok(dp)) 10814236Smckusick pfatal("%s=%s", DIR?"DIR":"FILE", pathname); 10824236Smckusick else 10834236Smckusick pfatal("NAME=%s", pathname); 10844236Smckusick return (reply("REMOVE")); 10854236Smckusick } 10864236Smckusick 10874236Smckusick adjust(lcnt) 10884465Smckusic register short lcnt; 10894236Smckusick { 10904236Smckusick register DINODE *dp; 10914236Smckusick 10924236Smckusick if ((dp = ginode()) == NULL) 10934236Smckusick return; 10944236Smckusick if (dp->di_nlink == lcnt) { 10954236Smckusick if (linkup() == 0) 10964236Smckusick clri("UNREF", 0); 10974236Smckusick } 10984236Smckusick else { 10994236Smckusick pwarn("LINK COUNT %s", 11004236Smckusick (lfdir==inum)?lfname:(DIR?"DIR":"FILE")); 11014236Smckusick pinode(); 11024236Smckusick printf(" COUNT %d SHOULD BE %d", 11034236Smckusick dp->di_nlink, dp->di_nlink-lcnt); 11044236Smckusick if (preen) { 11054236Smckusick if (lcnt < 0) { 11064236Smckusick printf("\n"); 11074236Smckusick preendie(); 11084236Smckusick } 11094236Smckusick printf(" (ADJUSTED)\n"); 11104236Smckusick } 11114236Smckusick if (preen || reply("ADJUST") == 1) { 11124236Smckusick dp->di_nlink -= lcnt; 11134236Smckusick inodirty(); 11144236Smckusick } 11154236Smckusick } 11164236Smckusick } 11174236Smckusick 11184236Smckusick clri(s, flg) 11194715Smckusic char *s; 11204236Smckusick { 11214236Smckusick register DINODE *dp; 11224236Smckusick 11234236Smckusick if ((dp = ginode()) == NULL) 11244236Smckusick return; 11254236Smckusick if (flg == 1) { 11264236Smckusick pwarn("%s %s", s, DIR?"DIR":"FILE"); 11274236Smckusick pinode(); 11284236Smckusick } 11294236Smckusick if (preen || reply("CLEAR") == 1) { 11304236Smckusick if (preen) 11314236Smckusick printf(" (CLEARED)\n"); 11324236Smckusick n_files--; 11334236Smckusick pfunc = pass4; 11344236Smckusick ckinode(dp, ADDR); 11354236Smckusick zapino(dp); 11364465Smckusic setstate(USTATE); 11374236Smckusick inodirty(); 11384236Smckusick inosumbad++; 11394236Smckusick } 11404236Smckusick } 11414236Smckusick 11424236Smckusick setup(dev) 11434715Smckusic char *dev; 11444236Smckusick { 11454236Smckusick dev_t rootdev; 11464878Smckusic struct ostat statb; 11474236Smckusick int super = bflag ? bflag : SBLOCK; 11484236Smckusick 11494236Smckusick bflag = 0; 11504236Smckusick if (stat("/", &statb) < 0) 11514236Smckusick errexit("Can't stat root\n"); 11524236Smckusick rootdev = statb.st_dev; 11534236Smckusick if (stat(dev, &statb) < 0) { 11544236Smckusick error("Can't stat %s\n", dev); 11554236Smckusick return (0); 11564236Smckusick } 11574236Smckusick rawflg = 0; 11584236Smckusick if ((statb.st_mode & S_IFMT) == S_IFBLK) 11594236Smckusick ; 11604236Smckusick else if ((statb.st_mode & S_IFMT) == S_IFCHR) 11614236Smckusick rawflg++; 11624236Smckusick else { 11634236Smckusick if (reply("file is not a block or character device; OK") == 0) 11644236Smckusick return (0); 11654236Smckusick } 11664236Smckusick if (rootdev == statb.st_rdev) 11674236Smckusick hotroot++; 11684236Smckusick if ((dfile.rfdes = open(dev, 0)) < 0) { 11694236Smckusick error("Can't open %s\n", dev); 11704236Smckusick return (0); 11714236Smckusick } 11724236Smckusick if (preen == 0) 11734236Smckusick printf("** %s", dev); 11744236Smckusick if (nflag || (dfile.wfdes = open(dev, 1)) < 0) { 11754236Smckusick dfile.wfdes = -1; 11764236Smckusick if (preen) 11774236Smckusick pfatal("NO WRITE ACCESS"); 11784236Smckusick printf(" (NO WRITE)"); 11794236Smckusick } 11804236Smckusick if (preen == 0) 11814236Smckusick printf("\n"); 11824465Smckusic fixcg = 0; inosumbad = 0; offsumbad = 0; frsumbad = 0; 11834236Smckusick dfile.mod = 0; 11844236Smckusick n_files = n_blks = n_ffree = n_bfree = 0; 11854236Smckusick muldup = enddup = &duplist[0]; 11864236Smckusick badlnp = &badlncnt[0]; 11874236Smckusick lfdir = 0; 11884236Smckusick rplyflag = 0; 11894236Smckusick initbarea(&sblk); 11904236Smckusick initbarea(&fileblk); 11914236Smckusick initbarea(&inoblk); 11924236Smckusick initbarea(&cgblk); 11934236Smckusick if (getblk(&sblk, super, BSIZE) == NULL) { 11944236Smckusick ckfini(); 11954236Smckusick return (0); 11964236Smckusick } 11974465Smckusic sblk.b_bno = super; 11984236Smckusick if (sblock.fs_magic != FS_MAGIC) 11994236Smckusick { badsb("MAGIC NUMBER WRONG"); return (0); } 12004236Smckusick if (sblock.fs_ncg < 1) 12014236Smckusick { badsb("NCG OUT OF RANGE"); return (0); } 12024236Smckusick if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG) 12034236Smckusick { badsb("CPG OUT OF RANGE"); return (0); } 12044236Smckusick if (sblock.fs_nsect < 1) 12054236Smckusick { badsb("NSECT < 1"); return (0); } 12064236Smckusick if (sblock.fs_ntrak < 1) 12074236Smckusick { badsb("NTRAK < 1"); return (0); } 12084236Smckusick if (sblock.fs_ipg*sblock.fs_ncg > 65535 || sblock.fs_ipg%INOPB) 12094236Smckusick { badsb("TOO MANY INODES IMPLIED"); return (0); } 12104236Smckusick if (sblock.fs_ipg/INOPF+IBLOCK >= 12114236Smckusick sblock.fs_cpg*sblock.fs_nsect*sblock.fs_ntrak/NSPF) 12124236Smckusick { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); } 12134236Smckusick /* THE FOLLOWING COULD BE CHECKED MORE CLOSELY... */ 12144236Smckusick if ((sblock.fs_ncg + 1) * sblock.fs_cpg < sblock.fs_ncyl || 12154236Smckusick (sblock.fs_ncg - 1) * sblock.fs_cpg > sblock.fs_ncyl) 12164236Smckusick { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); } 12174236Smckusick if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF) 12184236Smckusick { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); } 12194236Smckusick if (sblock.fs_size <= 12204236Smckusick (sblock.fs_ncg-1)*sblock.fs_fpg+IBLOCK+sblock.fs_ipg/INOPF) 12214236Smckusick { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); } 12224236Smckusick if (sblock.fs_size*NSPF > 12234236Smckusick (sblock.fs_ncg+2)*sblock.fs_cpg*sblock.fs_spc) 12244236Smckusick { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); } 12254236Smckusick /* rest we COULD repair... */ 12264236Smckusick if (sblock.fs_sblkno != SBLOCK) 12274236Smckusick { badsb("BLKNO CORRUPTED"); return (0); } 12284236Smckusick if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak) 12294236Smckusick { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); } 12304236Smckusick if (sblock.fs_cgsize != cgsize(&sblock)) 12314236Smckusick { badsb("CGSIZE INCORRECT"); return (0); } 12324236Smckusick if (sblock.fs_cssize != cssize(&sblock)) 12334236Smckusick { badsb("CSSIZE INCORRECT"); return (0); } 12344236Smckusick fmax = sblock.fs_size; 12354236Smckusick imax = sblock.fs_ncg * sblock.fs_ipg; 12364236Smckusick 12374236Smckusick bmapsz = roundup(howmany(fmax, NBBY), sizeof(short)); 12384236Smckusick blkmap = (char *)calloc(bmapsz, sizeof (char)); 12394236Smckusick freemap = (char *)calloc(bmapsz, sizeof (char)); 12404236Smckusick statemap = (char *)calloc(imax+1, sizeof(char)); 12414236Smckusick lncntp = (short *)calloc(imax+1, sizeof(short)); 12424236Smckusick 12434465Smckusic startinum = imax + 1; 12444236Smckusick return (1); 12454236Smckusick 12464236Smckusick badsb: 12474236Smckusick ckfini(); 12484236Smckusick return (0); 12494236Smckusick } 12504236Smckusick 12514236Smckusick badsb(s) 12524236Smckusick char *s; 12534236Smckusick { 12544236Smckusick 12554236Smckusick if (preen) 12564236Smckusick printf("%s: ", devname); 12574236Smckusick printf("BAD SUPER BLOCK: %s\n", s); 12584236Smckusick pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n"); 12594236Smckusick pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n"); 12604236Smckusick } 12614236Smckusick 12624236Smckusick DINODE * 12634236Smckusick ginode() 12644236Smckusick { 12654236Smckusick daddr_t iblk; 12664236Smckusick 12674236Smckusick if (inum > imax) 12684236Smckusick return (NULL); 12694465Smckusic if (inum < startinum || inum >= startinum + INOPB) { 12704465Smckusic iblk = itod(inum, &sblock); 12714465Smckusic if (getblk(&inoblk, iblk, BSIZE) == NULL) { 12724236Smckusick return (NULL); 12734236Smckusick } 12744465Smckusic startinum = (inum / INOPB) * INOPB; 12754236Smckusick } 12764465Smckusic return (&inoblk.b_un.b_dinode[inum % INOPB]); 12774236Smckusick } 12784236Smckusick 12794236Smckusick ftypeok(dp) 12804236Smckusick DINODE *dp; 12814236Smckusick { 12824236Smckusick switch (dp->di_mode & IFMT) { 12834236Smckusick 12844236Smckusick case IFDIR: 12854236Smckusick case IFREG: 12864236Smckusick case IFBLK: 12874236Smckusick case IFCHR: 12884236Smckusick case IFMPC: 12894236Smckusick case IFMPB: 12904236Smckusick return (1); 12914236Smckusick 12924236Smckusick default: 12934236Smckusick return (0); 12944236Smckusick } 12954236Smckusick } 12964236Smckusick 12974236Smckusick reply(s) 12984236Smckusick char *s; 12994236Smckusick { 13004236Smckusick char line[80]; 13014236Smckusick 13024236Smckusick if (preen) 13034236Smckusick pfatal("INTERNAL ERROR: GOT TO reply()"); 13044236Smckusick rplyflag = 1; 13054236Smckusick printf("\n%s? ", s); 13064236Smckusick if (nflag || dfile.wfdes < 0) { 13074236Smckusick printf(" no\n\n"); 13084236Smckusick return (0); 13094236Smckusick } 13104236Smckusick if (yflag) { 13114236Smckusick printf(" yes\n\n"); 13124236Smckusick return (1); 13134236Smckusick } 13144236Smckusick if (getline(stdin, line, sizeof(line)) == EOF) 13154236Smckusick errexit("\n"); 13164236Smckusick printf("\n"); 13174236Smckusick if (line[0] == 'y' || line[0] == 'Y') 13184236Smckusick return (1); 13194236Smckusick else 13204236Smckusick return (0); 13214236Smckusick } 13224236Smckusick 13234236Smckusick getline(fp, loc, maxlen) 13244236Smckusick FILE *fp; 13254236Smckusick char *loc; 13264236Smckusick { 13274236Smckusick register n; 13284236Smckusick register char *p, *lastloc; 13294236Smckusick 13304236Smckusick p = loc; 13314236Smckusick lastloc = &p[maxlen-1]; 13324236Smckusick while ((n = getc(fp)) != '\n') { 13334236Smckusick if (n == EOF) 13344236Smckusick return (EOF); 13354236Smckusick if (!isspace(n) && p < lastloc) 13364236Smckusick *p++ = n; 13374236Smckusick } 13384236Smckusick *p = 0; 13394236Smckusick return (p - loc); 13404236Smckusick } 13414236Smckusick 13424236Smckusick BUFAREA * 13434236Smckusick getblk(bp, blk, size) 13444236Smckusick daddr_t blk; 13454236Smckusick register BUFAREA *bp; 13464236Smckusick int size; 13474236Smckusick { 13484236Smckusick register struct filecntl *fcp; 13494236Smckusick 13504236Smckusick fcp = &dfile; 13514236Smckusick if (bp->b_bno == blk) 13524236Smckusick return (bp); 13534236Smckusick flush(fcp, bp); 13544236Smckusick if (bread(fcp, bp->b_un.b_buf, blk, size) != 0) { 13554236Smckusick bp->b_bno = blk; 13564236Smckusick bp->b_size = size; 13574236Smckusick return (bp); 13584236Smckusick } 13594236Smckusick bp->b_bno = (daddr_t)-1; 13604236Smckusick return (NULL); 13614236Smckusick } 13624236Smckusick 13634236Smckusick flush(fcp, bp) 13644236Smckusick struct filecntl *fcp; 13654236Smckusick register BUFAREA *bp; 13664236Smckusick { 13674236Smckusick 13684236Smckusick if (bp->b_dirty) 13694236Smckusick bwrite(fcp, bp->b_un.b_buf, bp->b_bno, bp->b_size); 13704236Smckusick bp->b_dirty = 0; 13714236Smckusick } 13724236Smckusick 13734236Smckusick rwerr(s, blk) 13744236Smckusick char *s; 13754236Smckusick daddr_t blk; 13764236Smckusick { 13774236Smckusick 13784236Smckusick if (preen == 0) 13794236Smckusick printf("\n"); 13804236Smckusick pfatal("CANNOT %s: BLK %ld", s, blk); 13814236Smckusick if (reply("CONTINUE") == 0) 13824236Smckusick errexit("Program terminated\n"); 13834236Smckusick } 13844236Smckusick 13854236Smckusick ckfini() 13864236Smckusick { 13874236Smckusick 13884236Smckusick flush(&dfile, &fileblk); 13894236Smckusick flush(&dfile, &sblk); 13904465Smckusic if (sblk.b_bno != SBLOCK) { 13914465Smckusic sblk.b_bno = SBLOCK; 13924465Smckusic sbdirty(); 13934465Smckusic flush(&dfile, &sblk); 13944465Smckusic } 13954236Smckusick flush(&dfile, &inoblk); 13964236Smckusick close(dfile.rfdes); 13974236Smckusick close(dfile.wfdes); 13984236Smckusick } 13994236Smckusick 14004236Smckusick pinode() 14014236Smckusick { 14024236Smckusick register DINODE *dp; 14034236Smckusick register char *p; 14044236Smckusick char uidbuf[200]; 14054236Smckusick char *ctime(); 14064236Smckusick 14074236Smckusick printf(" I=%u ", inum); 14084236Smckusick if ((dp = ginode()) == NULL) 14094236Smckusick return; 14104236Smckusick printf(" OWNER="); 14114236Smckusick if (getpw((int)dp->di_uid, uidbuf) == 0) { 14124236Smckusick for (p = uidbuf; *p != ':'; p++); 14134236Smckusick *p = 0; 14144236Smckusick printf("%s ", uidbuf); 14154236Smckusick } 14164236Smckusick else { 14174236Smckusick printf("%d ", dp->di_uid); 14184236Smckusick } 14194236Smckusick printf("MODE=%o\n", dp->di_mode); 14204236Smckusick if (preen) 14214236Smckusick printf("%s: ", devname); 14224236Smckusick printf("SIZE=%ld ", dp->di_size); 14234236Smckusick p = ctime(&dp->di_mtime); 14244236Smckusick printf("MTIME=%12.12s %4.4s ", p+4, p+20); 14254236Smckusick } 14264236Smckusick 14274236Smckusick copy(fp, tp, size) 14284236Smckusick register char *tp, *fp; 14294236Smckusick unsigned size; 14304236Smckusick { 14314236Smckusick 14324236Smckusick while (size--) 14334236Smckusick *tp++ = *fp++; 14344236Smckusick } 14354236Smckusick 14364236Smckusick makecg() 14374236Smckusick { 14384465Smckusic int c, blk; 14394236Smckusick daddr_t dbase, d, dmin, dmax; 14404236Smckusick long i, j, s; 14414236Smckusick register struct csum *cs; 14424465Smckusic register DINODE *dp; 14434236Smckusick 14444789Smckusic sblock.fs_cstotal.cs_nbfree = 0; 14454789Smckusic sblock.fs_cstotal.cs_nffree = 0; 14464789Smckusic sblock.fs_cstotal.cs_nifree = 0; 14474789Smckusic sblock.fs_cstotal.cs_ndir = 0; 1448*5097Smckusic for (i = 0; i < howmany(cssize(&sblock), BSIZE); i++) { 1449*5097Smckusic sblock.fs_csp[i] = (struct csum *)calloc(1, BSIZE); 1450*5097Smckusic getblk((char *)sblock.fs_csp[i], 1451*5097Smckusic csaddr(&sblock) + (i * FRAG), BSIZE); 1452*5097Smckusic } 14534236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 14544236Smckusick dbase = cgbase(c, &sblock); 14554236Smckusick dmax = dbase + sblock.fs_fpg; 14564236Smckusick if (dmax > sblock.fs_size) 14574236Smckusick dmax = sblock.fs_size; 14584465Smckusic dmin = cgdmin(c, &sblock) - dbase; 14594653Smckusic cs = &sblock.fs_cs(c); 14604236Smckusick cgrp.cg_time = time(0); 14614236Smckusick cgrp.cg_magic = CG_MAGIC; 14624236Smckusick cgrp.cg_cgx = c; 14634236Smckusick cgrp.cg_ncyl = sblock.fs_cpg; 14644236Smckusick cgrp.cg_niblk = sblock.fs_ipg; 14654236Smckusick cgrp.cg_ndblk = dmax - dbase; 14664789Smckusic cgrp.cg_cs.cs_ndir = 0; 14674789Smckusic cgrp.cg_cs.cs_nffree = 0; 14684789Smckusic cgrp.cg_cs.cs_nbfree = 0; 14694789Smckusic cgrp.cg_cs.cs_nifree = 0; 14704465Smckusic cgrp.cg_rotor = dmin; 14714465Smckusic cgrp.cg_frotor = dmin; 14724258Smckusic cgrp.cg_irotor = 0; 14734465Smckusic for (i = 0; i < FRAG; i++) 14744465Smckusic cgrp.cg_frsum[i] = 0; 14754236Smckusick inum = sblock.fs_ipg * c; 14764465Smckusic for (i = 0; i < sblock.fs_ipg; inum++, i++) { 14774465Smckusic dp = ginode(); 14784465Smckusic if (dp == NULL) 14794465Smckusic continue; 14804465Smckusic if (ALLOC) { 14814465Smckusic if (DIR) 14824789Smckusic cgrp.cg_cs.cs_ndir++; 14834465Smckusic setbit(cgrp.cg_iused, i); 14844465Smckusic continue; 14854465Smckusic } 14864789Smckusic cgrp.cg_cs.cs_nifree++; 14874236Smckusick clrbit(cgrp.cg_iused, i); 14884236Smckusick } 14894236Smckusick while (i < MAXIPG) { 14904236Smckusick clrbit(cgrp.cg_iused, i); 14914236Smckusick i++; 14924236Smckusick } 14934236Smckusick for (s = 0; s < MAXCPG; s++) 14944236Smckusick for (i = 0; i < NRPOS; i++) 14954236Smckusick cgrp.cg_b[s][i] = 0; 14964236Smckusick if (c == 0) { 14974236Smckusick dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 14984236Smckusick } 14994236Smckusick for (d = 0; d < dmin; d++) 15004236Smckusick clrbit(cgrp.cg_free, d); 15014236Smckusick for (; (d + FRAG) <= dmax - dbase; d += FRAG) { 15024236Smckusick j = 0; 15034236Smckusick for (i = 0; i < FRAG; i++) { 15044236Smckusick if (!getbmap(dbase+d+i)) { 15054236Smckusick setbit(cgrp.cg_free, d+i); 15064236Smckusick j++; 15074236Smckusick } else 15084236Smckusick clrbit(cgrp.cg_free, d+i); 15094236Smckusick } 15104236Smckusick if (j == FRAG) { 15114789Smckusic cgrp.cg_cs.cs_nbfree++; 15124236Smckusick s = d * NSPF; 15134236Smckusick cgrp.cg_b[s/sblock.fs_spc] 15144236Smckusick [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 15154465Smckusic } else if (j > 0) { 15164789Smckusic cgrp.cg_cs.cs_nffree += j; 15174465Smckusic blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) & 15184465Smckusic (0xff >> (NBBY - FRAG))); 15194465Smckusic fragacct(blk, cgrp.cg_frsum, 1); 15204465Smckusic } 15214236Smckusick } 15224465Smckusic for (j = d; d < dmax - dbase; d++) { 15234236Smckusick if (!getbmap(dbase+d)) { 15244236Smckusick setbit(cgrp.cg_free, d); 15254789Smckusic cgrp.cg_cs.cs_nffree++; 15264236Smckusick } else 15274236Smckusick clrbit(cgrp.cg_free, d); 15284236Smckusick } 15294465Smckusic if (j != d) { 15304465Smckusic blk = ((cgrp.cg_free[j / NBBY] >> (j % NBBY)) & 15314465Smckusic (0xff >> (NBBY - FRAG))); 15324465Smckusic fragacct(blk, cgrp.cg_frsum, 1); 15334465Smckusic } 15344236Smckusick for (; d < MAXBPG; d++) 15354236Smckusick clrbit(cgrp.cg_free, d); 15364789Smckusic sblock.fs_cstotal.cs_nffree += cgrp.cg_cs.cs_nffree; 15374789Smckusic sblock.fs_cstotal.cs_nbfree += cgrp.cg_cs.cs_nbfree; 15384789Smckusic sblock.fs_cstotal.cs_nifree += cgrp.cg_cs.cs_nifree; 15394789Smckusic sblock.fs_cstotal.cs_ndir += cgrp.cg_cs.cs_ndir; 15404789Smckusic *cs = cgrp.cg_cs; 15414236Smckusick bwrite(&dfile, &cgrp, cgtod(c, &sblock), sblock.fs_cgsize); 15424236Smckusick } 1543*5097Smckusic for (i = 0; i < howmany(cssize(&sblock), BSIZE); i++) { 1544*5097Smckusic bwrite(&dfile, (char *)sblock.fs_csp[i], 1545*5097Smckusic csaddr(&sblock) + (i * FRAG), BSIZE); 1546*5097Smckusic } 15474236Smckusick sblock.fs_ronly = 0; 15484236Smckusick sblock.fs_fmod = 0; 15494236Smckusick sbdirty(); 15504236Smckusick } 15514236Smckusick 15524465Smckusic /* 15534465Smckusic * update the frsum fields to reflect addition or deletion 15544465Smckusic * of some frags 15554465Smckusic */ 15564465Smckusic fragacct(fragmap, fraglist, cnt) 15574470Smckusic int fragmap; 15584789Smckusic long fraglist[]; 15594465Smckusic int cnt; 15604465Smckusic { 15614465Smckusic int inblk; 15624465Smckusic register int field, subfield; 15634465Smckusic register int siz, pos; 15644465Smckusic 15654465Smckusic inblk = (int)(fragtbl[fragmap] << 1); 15664465Smckusic fragmap <<= 1; 15674465Smckusic for (siz = 1; siz < FRAG; siz++) { 15684465Smckusic if (((1 << siz) & inblk) == 0) 15694465Smckusic continue; 15704465Smckusic field = around[siz]; 15714465Smckusic subfield = inside[siz]; 15724465Smckusic for (pos = siz; pos <= FRAG; pos++) { 15734465Smckusic if ((fragmap & field) == subfield) { 15744465Smckusic fraglist[siz] += cnt; 15754465Smckusic pos += siz; 15764465Smckusic field <<= siz; 15774465Smckusic subfield <<= siz; 15784465Smckusic } 15794465Smckusic field <<= 1; 15804465Smckusic subfield <<= 1; 15814465Smckusic } 15824465Smckusic } 15834465Smckusic } 15844465Smckusic 15854236Smckusick findino(dirp) 15864236Smckusick register DIRECT *dirp; 15874236Smckusick { 15884236Smckusick register char *p1, *p2; 15894236Smckusick 15904236Smckusick if (dirp->d_ino == 0) 15914236Smckusick return (KEEPON); 15924236Smckusick for (p1 = dirp->d_name, p2 = srchname;*p2++ == *p1; p1++) { 15934236Smckusick if (*p1 == 0 || p1 == &dirp->d_name[DIRSIZ-1]) { 15944236Smckusick if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) 15954236Smckusick parentdir = dirp->d_ino; 15964236Smckusick return (STOP); 15974236Smckusick } 15984236Smckusick } 15994236Smckusick return (KEEPON); 16004236Smckusick } 16014236Smckusick 16024236Smckusick mkentry(dirp) 16034236Smckusick register DIRECT *dirp; 16044236Smckusick { 16054236Smckusick register ino_t in; 16064236Smckusick register char *p; 16074236Smckusick 16084236Smckusick if (dirp->d_ino) 16094236Smckusick return (KEEPON); 16104236Smckusick dirp->d_ino = orphan; 16114236Smckusick in = orphan; 16124236Smckusick p = &dirp->d_name[8]; 16134236Smckusick *--p = 0; 16144236Smckusick while (p > dirp->d_name) { 16154236Smckusick *--p = (in % 10) + '0'; 16164236Smckusick in /= 10; 16174236Smckusick } 16184236Smckusick *p = '#'; 16194236Smckusick return (ALTERD|STOP); 16204236Smckusick } 16214236Smckusick 16224236Smckusick chgdd(dirp) 16234236Smckusick register DIRECT *dirp; 16244236Smckusick { 16254236Smckusick if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' && 16264236Smckusick dirp->d_name[2] == 0) { 16274236Smckusick dirp->d_ino = lfdir; 16284236Smckusick return (ALTERD|STOP); 16294236Smckusick } 16304236Smckusick return (KEEPON); 16314236Smckusick } 16324236Smckusick 16334236Smckusick linkup() 16344236Smckusick { 16354236Smckusick register DINODE *dp; 16364236Smckusick register lostdir; 16374236Smckusick register ino_t pdir; 16384236Smckusick 16394236Smckusick if ((dp = ginode()) == NULL) 16404236Smckusick return (0); 16414236Smckusick lostdir = DIR; 16424236Smckusick pdir = parentdir; 16434236Smckusick pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); 16444236Smckusick pinode(); 16454236Smckusick if (preen && dp->di_size == 0) 16464236Smckusick return (0); 16474236Smckusick if (preen) 16484236Smckusick printf(" (RECONNECTED)\n"); 16494236Smckusick else 16504236Smckusick if (reply("RECONNECT") == 0) 16514236Smckusick return (0); 16524236Smckusick orphan = inum; 16534236Smckusick if (lfdir == 0) { 16544236Smckusick inum = ROOTINO; 16554236Smckusick if ((dp = ginode()) == NULL) { 16564236Smckusick inum = orphan; 16574236Smckusick return (0); 16584236Smckusick } 16594236Smckusick pfunc = findino; 16604236Smckusick srchname = lfname; 16614236Smckusick filsize = dp->di_size; 16624236Smckusick parentdir = 0; 16634236Smckusick ckinode(dp, DATA); 16644236Smckusick inum = orphan; 16654236Smckusick if ((lfdir = parentdir) == 0) { 16664236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 16674236Smckusick printf("\n\n"); 16684236Smckusick return (0); 16694236Smckusick } 16704236Smckusick } 16714236Smckusick inum = lfdir; 16724236Smckusick if ((dp = ginode()) == NULL || !DIR || getstate() != FSTATE) { 16734236Smckusick inum = orphan; 16744236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 16754236Smckusick printf("\n\n"); 16764236Smckusick return (0); 16774236Smckusick } 16784236Smckusick if (dp->di_size & BMASK) { 16794236Smckusick dp->di_size = roundup(dp->di_size, BSIZE); 16804236Smckusick inodirty(); 16814236Smckusick } 16824236Smckusick filsize = dp->di_size; 16834236Smckusick inum = orphan; 16844236Smckusick pfunc = mkentry; 16854236Smckusick if ((ckinode(dp, DATA) & ALTERD) == 0) { 16864236Smckusick pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); 16874236Smckusick printf("\n\n"); 16884236Smckusick return (0); 16894236Smckusick } 16904236Smckusick declncnt(); 16914236Smckusick if (lostdir) { 16924236Smckusick pfunc = chgdd; 16934236Smckusick dp = ginode(); 16944236Smckusick filsize = dp->di_size; 16954236Smckusick ckinode(dp, DATA); 16964236Smckusick inum = lfdir; 16974236Smckusick if ((dp = ginode()) != NULL) { 16984236Smckusick dp->di_nlink++; 16994236Smckusick inodirty(); 17004236Smckusick setlncnt(getlncnt()+1); 17014236Smckusick } 17024236Smckusick inum = orphan; 17034236Smckusick pwarn("DIR I=%u CONNECTED. ", orphan); 17044236Smckusick printf("PARENT WAS I=%u\n", pdir); 17054236Smckusick if (preen == 0) 17064236Smckusick printf("\n"); 17074236Smckusick } 17084236Smckusick return (1); 17094236Smckusick } 17104236Smckusick 17114236Smckusick bread(fcp, buf, blk, size) 17124236Smckusick daddr_t blk; 17134236Smckusick register struct filecntl *fcp; 17144236Smckusick register size; 17154236Smckusick char *buf; 17164236Smckusick { 17174236Smckusick if (lseek(fcp->rfdes, blk*FSIZE, 0) < 0) 17184236Smckusick rwerr("SEEK", blk); 17194236Smckusick else if (read(fcp->rfdes, buf, size) == size) 17204236Smckusick return (1); 17214236Smckusick rwerr("READ", blk); 17224236Smckusick return (0); 17234236Smckusick } 17244236Smckusick 17254236Smckusick bwrite(fcp, buf, blk, size) 17264236Smckusick daddr_t blk; 17274236Smckusick register struct filecntl *fcp; 17284236Smckusick register size; 17294236Smckusick char *buf; 17304236Smckusick { 17314236Smckusick 17324236Smckusick if (fcp->wfdes < 0) 17334236Smckusick return (0); 17344236Smckusick if (lseek(fcp->wfdes, blk*FSIZE, 0) < 0) 17354236Smckusick rwerr("SEEK", blk); 17364236Smckusick else if (write(fcp->wfdes, buf, size) == size) { 17374236Smckusick fcp->mod = 1; 17384236Smckusick return (1); 17394236Smckusick } 17404236Smckusick rwerr("WRITE", blk); 17414236Smckusick return (0); 17424236Smckusick } 17434236Smckusick 17444236Smckusick catch() 17454236Smckusick { 17464236Smckusick 17474236Smckusick ckfini(); 17484236Smckusick exit(12); 17494236Smckusick } 1750