1*4715Smckusic static char *sccsid = "@(#)main.c 1.10 (Berkeley) 11/01/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" 104236Smckusick #include <fstab.h> 114236Smckusick 124236Smckusick typedef int (*SIG_TYP)(); 134236Smckusick 144236Smckusick #define NDIRECT (BSIZE/sizeof(struct direct)) 154236Smckusick #define SPERB (BSIZE/sizeof(short)) 164236Smckusick 174236Smckusick #define MAXDUP 10 /* limit on dup blks (per inode) */ 184236Smckusick #define MAXBAD 10 /* limit on bad blks (per inode) */ 194236Smckusick 204236Smckusick #define USTATE 0 /* inode not allocated */ 214236Smckusick #define FSTATE 01 /* inode is file */ 224236Smckusick #define DSTATE 02 /* inode is directory */ 234236Smckusick #define CLEAR 03 /* inode is to be cleared */ 244236Smckusick 254236Smckusick typedef struct dinode DINODE; 264236Smckusick typedef struct direct DIRECT; 274236Smckusick 284236Smckusick #define ALLOC ((dp->di_mode & IFMT) != 0) 294236Smckusick #define DIR ((dp->di_mode & IFMT) == IFDIR) 304236Smckusick #define REG ((dp->di_mode & IFMT) == IFREG) 314236Smckusick #define BLK ((dp->di_mode & IFMT) == IFBLK) 324236Smckusick #define CHR ((dp->di_mode & IFMT) == IFCHR) 334236Smckusick #define MPC ((dp->di_mode & IFMT) == IFMPC) 344236Smckusick #define MPB ((dp->di_mode & IFMT) == IFMPB) 354236Smckusick #define SPECIAL (BLK || CHR || MPC || MPB) 364236Smckusick 374465Smckusic ino_t startinum; /* blk num of first in raw area */ 384236Smckusick 394236Smckusick struct bufarea { 404236Smckusick struct bufarea *b_next; /* must be first */ 414236Smckusick daddr_t b_bno; 424236Smckusick int b_size; 434236Smckusick union { 444236Smckusick char b_buf[BSIZE]; /* buffer space */ 454236Smckusick short b_lnks[SPERB]; /* link counts */ 464236Smckusick daddr_t b_indir[NINDIR]; /* indirect block */ 474236Smckusick struct fs b_fs; /* super block */ 484236Smckusick struct cg b_cg; /* cylinder group */ 494236Smckusick struct dinode b_dinode[INOPB]; /* inode block */ 504236Smckusick DIRECT b_dir[NDIRECT]; /* directory */ 514236Smckusick } b_un; 524236Smckusick char b_dirty; 534236Smckusick }; 544236Smckusick 554236Smckusick typedef struct bufarea BUFAREA; 564236Smckusick 574236Smckusick BUFAREA inoblk; /* inode blocks */ 584236Smckusick BUFAREA fileblk; /* other blks in filesys */ 594236Smckusick BUFAREA sblk; /* file system superblock */ 604236Smckusick BUFAREA cgblk; 614236Smckusick 624236Smckusick #define initbarea(x) (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1 634236Smckusick #define dirty(x) (x)->b_dirty = 1 644236Smckusick #define inodirty() inoblk.b_dirty = 1 654236Smckusick #define sbdirty() sblk.b_dirty = 1 664236Smckusick #define cgdirty() cgblk.b_dirty = 1 674236Smckusick 684236Smckusick #define dirblk fileblk.b_un 694236Smckusick #define sblock sblk.b_un.b_fs 704236Smckusick #define cgrp cgblk.b_un.b_cg 714236Smckusick 724236Smckusick struct filecntl { 734236Smckusick int rfdes; 744236Smckusick int wfdes; 754236Smckusick int mod; 764236Smckusick } dfile; /* file descriptors for filesys */ 774236Smckusick 784236Smckusick #define DUPTBLSIZE 100 /* num of dup blocks to remember */ 794236Smckusick daddr_t duplist[DUPTBLSIZE]; /* dup block table */ 804236Smckusick daddr_t *enddup; /* next entry in dup table */ 814236Smckusick daddr_t *muldup; /* multiple dups part of table */ 824236Smckusick 834236Smckusick #define MAXLNCNT 20 /* num zero link cnts to remember */ 844236Smckusick ino_t badlncnt[MAXLNCNT]; /* table of inos with zero link cnts */ 854236Smckusick ino_t *badlnp; /* next entry in table */ 864236Smckusick 874236Smckusick char rawflg; 884236Smckusick char nflag; /* assume a no response */ 894236Smckusick char yflag; /* assume a yes response */ 904236Smckusick int bflag; /* location of alternate super block */ 914236Smckusick char preen; /* just fix normal inconsistencies */ 924236Smckusick char rplyflag; /* any questions asked? */ 934236Smckusick char hotroot; /* checking root device */ 944236Smckusick char fixcg; /* corrupted free list bit maps */ 954236Smckusick 964236Smckusick char *blkmap; /* ptr to primary blk allocation map */ 974236Smckusick char *freemap; /* ptr to secondary blk allocation map */ 984236Smckusick char *statemap; /* ptr to inode state table */ 994236Smckusick short *lncntp; /* ptr to link count table */ 1004236Smckusick 1014236Smckusick char *pathp; /* pointer to pathname position */ 1024236Smckusick char *thisname; /* ptr to current pathname component */ 1034236Smckusick char *srchname; /* name being searched for in dir */ 1044236Smckusick char pathname[200]; 1054236Smckusick 1064236Smckusick char *lfname = "lost+found"; 1074236Smckusick 1084236Smckusick ino_t inum; /* inode we are currently working on */ 1094236Smckusick ino_t imax; /* number of inodes */ 1104236Smckusick ino_t parentdir; /* i number of parent directory */ 1114236Smckusick ino_t lastino; /* hiwater mark of inodes */ 1124236Smckusick ino_t lfdir; /* lost & found directory */ 1134236Smckusick ino_t orphan; /* orphaned inode */ 1144236Smckusick 1154236Smckusick off_t filsize; /* num blks seen in file */ 1164236Smckusick off_t maxblk; /* largest logical blk in file */ 1174236Smckusick off_t bmapsz; /* num chars in blkmap */ 1184236Smckusick 1194236Smckusick daddr_t n_ffree; /* number of small free blocks */ 1204236Smckusick daddr_t n_bfree; /* number of large free blocks */ 1214236Smckusick daddr_t n_blks; /* number of blocks used */ 1224236Smckusick daddr_t n_files; /* number of files seen */ 1234236Smckusick daddr_t n_index; 1244236Smckusick daddr_t n_bad; 1254236Smckusick daddr_t fmax; /* number of blocks in the volume */ 1264236Smckusick 1274236Smckusick daddr_t badblk; 1284236Smckusick daddr_t dupblk; 1294236Smckusick 1304236Smckusick int inosumbad; 1314236Smckusick int offsumbad; 1324465Smckusic int frsumbad; 1334236Smckusick 1344236Smckusick #define howmany(x, y) (((x)+((y)-1))/(y)) 1354236Smckusick #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 1364236Smckusick #define zapino(x) (*(x) = zino) 1374236Smckusick struct dinode zino; 1384236Smckusick 1394236Smckusick #define setlncnt(x) (lncntp[inum] = x) 1404236Smckusick #define getlncnt() (lncntp[inum]) 1414236Smckusick #define declncnt() (--lncntp[inum]) 1424236Smckusick 1434236Smckusick #define setbmap(x) setbit(blkmap, x) 1444236Smckusick #define getbmap(x) isset(blkmap, x) 1454236Smckusick #define clrbmap(x) clrbit(blkmap, x) 1464236Smckusick 1474236Smckusick #define setfmap(x) setbit(freemap, x) 1484236Smckusick #define getfmap(x) isset(freemap, x) 1494236Smckusick #define clrfmap(x) clrbit(freemap, x) 1504236Smckusick 1514236Smckusick #define setstate(x) (statemap[inum] = x) 1524236Smckusick #define getstate() statemap[inum] 1534236Smckusick 1544236Smckusick #define DATA 1 1554236Smckusick #define ADDR 0 1564236Smckusick 1574236Smckusick #define ALTERD 010 1584236Smckusick #define KEEPON 04 1594236Smckusick #define SKIP 02 1604236Smckusick #define STOP 01 1614236Smckusick 1624236Smckusick int (*signal())(); 1634236Smckusick long lseek(); 1644236Smckusick time_t time(); 1654236Smckusick DINODE *ginode(); 1664236Smckusick BUFAREA *getblk(); 1674236Smckusick int dirscan(); 1684236Smckusick int findino(); 1694236Smckusick int catch(); 1704236Smckusick int mkentry(); 1714236Smckusick int chgdd(); 1724236Smckusick int pass1(), pass1b(), pass2(), pass4(), pass5(); 1734236Smckusick int (*pfunc)(); 1744236Smckusick char *rawname(), *rindex(), *unrawname(); 1754606Smckusic extern int inside[], around[]; 1764606Smckusic extern unsigned char fragtbl[]; 1774236Smckusick 1784236Smckusick char *devname; 1794236Smckusick 1804236Smckusick main(argc, argv) 181*4715Smckusic int argc; 182*4715Smckusic char *argv[]; 1834236Smckusick { 1844236Smckusick struct fstab *fsp; 1854236Smckusick int pid, passno, anygtr, sumstatus; 1864236Smckusick 1874236Smckusick sync(); 1884236Smckusick while (--argc > 0 && **++argv == '-') { 1894236Smckusick switch (*++*argv) { 1904236Smckusick 1914236Smckusick case 'p': 1924236Smckusick preen++; 1934236Smckusick break; 1944236Smckusick 1954236Smckusick case 'b': 1964236Smckusick bflag = atoi(argv[0]+1); 1974236Smckusick printf("Alternate super block location: %d\n", bflag); 1984236Smckusick break; 1994236Smckusick 2004236Smckusick case 'n': /* default no answer flag */ 2014236Smckusick case 'N': 2024236Smckusick nflag++; 2034236Smckusick yflag = 0; 2044236Smckusick break; 2054236Smckusick 2064236Smckusick case 'y': /* default yes answer flag */ 2074236Smckusick case 'Y': 2084236Smckusick yflag++; 2094236Smckusick nflag = 0; 2104236Smckusick break; 2114236Smckusick 2124236Smckusick default: 2134236Smckusick errexit("%c option?\n", **argv); 2144236Smckusick } 2154236Smckusick } 2164236Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2174236Smckusick signal(SIGINT, catch); 2184236Smckusick if (argc) { 2194236Smckusick while (argc-- > 0) { 2204236Smckusick hotroot = 0; 2214236Smckusick check(*argv++); 2224236Smckusick } 2234236Smckusick exit(0); 2244236Smckusick } 2254236Smckusick sumstatus = 0; 2264236Smckusick passno = 1; 2274236Smckusick do { 2284236Smckusick anygtr = 0; 2294236Smckusick if (setfsent() == 0) 2304236Smckusick errexit("Can't open checklist file: %s\n", FSTAB); 2314236Smckusick while ((fsp = getfsent()) != 0) { 2324236Smckusick if (strcmp(fsp->fs_type, FSTAB_RW) && 2334236Smckusick strcmp(fsp->fs_type, FSTAB_RO)) 2344236Smckusick continue; 2354236Smckusick if (preen == 0 || 2364236Smckusick passno == 1 && fsp->fs_passno == passno) { 2374236Smckusick if (blockcheck(fsp->fs_spec) == 0 && preen) 2384236Smckusick exit(8); 2394236Smckusick } else if (fsp->fs_passno > passno) 2404236Smckusick anygtr = 1; 2414236Smckusick else if (fsp->fs_passno == passno) { 2424236Smckusick pid = fork(); 2434236Smckusick if (pid < 0) { 2444236Smckusick perror("fork"); 2454236Smckusick exit(8); 2464236Smckusick } 2474236Smckusick if (pid == 0) 2484236Smckusick if (blockcheck(fsp->fs_spec)==0) 2494236Smckusick exit(8); 2504236Smckusick else 2514236Smckusick exit(0); 2524236Smckusick } 2534236Smckusick } 2544236Smckusick if (preen) { 2554236Smckusick int status; 2564236Smckusick while (wait(&status) != -1) 2574236Smckusick sumstatus |= status; 2584236Smckusick } 2594236Smckusick passno++; 2604236Smckusick } while (anygtr); 2614236Smckusick if (sumstatus) 2624236Smckusick exit(8); 2634236Smckusick endfsent(); 2644236Smckusick exit(0); 2654236Smckusick } 2664236Smckusick 2674236Smckusick blockcheck(name) 2684236Smckusick char *name; 2694236Smckusick { 2704236Smckusick struct stat stslash, stblock, stchar; 2714236Smckusick char *raw; 2724236Smckusick int looped = 0; 2734236Smckusick 2744236Smckusick hotroot = 0; 2754236Smckusick if (stat("/", &stslash) < 0){ 2764236Smckusick error("Can't stat root\n"); 2774236Smckusick return (0); 2784236Smckusick } 2794236Smckusick retry: 2804236Smckusick if (stat(name, &stblock) < 0){ 2814236Smckusick error("Can't stat %s\n", name); 2824236Smckusick return (0); 2834236Smckusick } 2844236Smckusick if (stblock.st_mode & S_IFBLK) { 2854236Smckusick raw = rawname(name); 2864236Smckusick if (stat(raw, &stchar) < 0){ 2874236Smckusick error("Can't stat %s\n", raw); 2884236Smckusick return (0); 2894236Smckusick } 2904236Smckusick if (stchar.st_mode & S_IFCHR) { 2914236Smckusick if (stslash.st_dev == stblock.st_rdev) { 2924236Smckusick hotroot++; 2934236Smckusick raw = unrawname(name); 2944236Smckusick } 2954236Smckusick check(raw); 2964236Smckusick return (1); 2974236Smckusick } else { 2984236Smckusick error("%s is not a character device\n", raw); 2994236Smckusick return (0); 3004236Smckusick } 3014236Smckusick } else if (stblock.st_mode & S_IFCHR) { 3024236Smckusick if (looped) { 3034236Smckusick error("Can't make sense out of name %s\n", name); 3044236Smckusick return (0); 3054236Smckusick } 3064236Smckusick name = unrawname(name); 3074236Smckusick looped++; 3084236Smckusick goto retry; 3094236Smckusick } 3104236Smckusick error("Can't make sense out of name %s\n", name); 3114236Smckusick return (0); 3124236Smckusick } 3134236Smckusick 3144236Smckusick char * 3154236Smckusick unrawname(cp) 3164236Smckusick char *cp; 3174236Smckusick { 3184236Smckusick char *dp = rindex(cp, '/'); 3194236Smckusick struct stat stb; 3204236Smckusick 3214236Smckusick if (dp == 0) 3224236Smckusick return (cp); 3234236Smckusick if (stat(cp, &stb) < 0) 3244236Smckusick return (cp); 3254236Smckusick if ((stb.st_mode&S_IFMT) != S_IFCHR) 3264236Smckusick return (cp); 3274236Smckusick if (*(dp+1) != 'r') 3284236Smckusick return (cp); 3294236Smckusick strcpy(dp+1, dp+2); 3304236Smckusick return (cp); 3314236Smckusick } 3324236Smckusick 3334236Smckusick char * 3344236Smckusick rawname(cp) 3354236Smckusick char *cp; 3364236Smckusick { 3374236Smckusick static char rawbuf[32]; 3384236Smckusick char *dp = rindex(cp, '/'); 3394236Smckusick 3404236Smckusick if (dp == 0) 3414236Smckusick return (0); 3424236Smckusick *dp = 0; 3434236Smckusick strcpy(rawbuf, cp); 3444236Smckusick *dp = '/'; 3454236Smckusick strcat(rawbuf, "/r"); 3464236Smckusick strcat(rawbuf, dp+1); 3474236Smckusick return (rawbuf); 3484236Smckusick } 3494236Smckusick 3504236Smckusick check(dev) 3514236Smckusick char *dev; 3524236Smckusick { 3534236Smckusick register DINODE *dp; 3544236Smckusick register ino_t *blp; 3554236Smckusick register int i, n; 3564236Smckusick ino_t savino; 3574236Smckusick int b, c; 3584236Smckusick daddr_t d, s; 3594236Smckusick 3604236Smckusick devname = dev; 3614236Smckusick if (setup(dev) == 0) { 3624236Smckusick if (preen) 3634236Smckusick pfatal("CAN'T CHECK DEVICE."); 3644236Smckusick return; 3654236Smckusick } 3664236Smckusick /* 1 */ 3674236Smckusick if (preen==0) { 3684236Smckusick if (hotroot) 3694236Smckusick printf("** Root file system\n"); 3704236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 3714236Smckusick } 3724236Smckusick pfunc = pass1; 3734236Smckusick inum = 0; 3744236Smckusick n_blks += roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE) 3754236Smckusick / BSIZE * FRAG; 3764236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 3774236Smckusick if (getblk(&cgblk, cgtod(c, &sblock), sblock.fs_cgsize) == 0) 3784236Smckusick continue; 3794236Smckusick n = 0; 3804465Smckusic for (i = 0; i < sblock.fs_ipg; i++, inum++) { 3814465Smckusic dp = ginode(); 3824465Smckusic if (dp == NULL) 3834465Smckusic continue; 3844236Smckusick if (ALLOC) { 3854236Smckusick if (!isset(cgrp.cg_iused, i)) { 3864465Smckusic /* 3874236Smckusick printf("%d bad, not used\n", inum); 3884465Smckusic */ 3894236Smckusick inosumbad++; 3904465Smckusic n++; 3914236Smckusick } 3924236Smckusick lastino = inum; 3934236Smckusick if (ftypeok(dp) == 0) { 3944236Smckusick pfatal("UNKNOWN FILE TYPE I=%u", inum); 3954236Smckusick if (reply("CLEAR") == 1) { 3964236Smckusick zapino(dp); 3974236Smckusick inodirty(); 3984236Smckusick inosumbad++; 3994236Smckusick } 4004236Smckusick continue; 4014236Smckusick } 4024236Smckusick n_files++; 4034236Smckusick if (setlncnt(dp->di_nlink) <= 0) { 4044236Smckusick if (badlnp < &badlncnt[MAXLNCNT]) 4054236Smckusick *badlnp++ = inum; 4064236Smckusick else { 4074236Smckusick pfatal("LINK COUNT TABLE OVERFLOW"); 4084236Smckusick if (reply("CONTINUE") == 0) 4094236Smckusick errexit(""); 4104236Smckusick } 4114236Smckusick } 4124236Smckusick setstate(DIR ? DSTATE : FSTATE); 4134236Smckusick badblk = dupblk = 0; filsize = 0; maxblk = 0; 4144236Smckusick ckinode(dp, ADDR); 4154236Smckusick if (DIR && dp->di_size % sizeof(DIRECT)) { 4164236Smckusick pwarn("DIRECTORY MISALIGNED I=%u\n", 4174236Smckusick inum); 4184236Smckusick if (preen == 0) 4194236Smckusick printf("\n"); 4204236Smckusick } 4214236Smckusick } else { 4224236Smckusick n++; 4234236Smckusick if (isset(cgrp.cg_iused, i)) { 4244465Smckusic /* 4254236Smckusick printf("%d bad, marked used\n", inum); 4264465Smckusic */ 4274236Smckusick inosumbad++; 4284465Smckusic n--; 4294236Smckusick } 4304236Smckusick if (dp->di_mode != 0) { 4314236Smckusick pfatal("PARTIALLY ALLOCATED INODE I=%u", inum); 4324236Smckusick if (reply("CLEAR") == 1) { 4334236Smckusick zapino(dp); 4344236Smckusick inodirty(); 4354236Smckusick inosumbad++; 4364236Smckusick } 4374236Smckusick } 4384236Smckusick } 4394236Smckusick } 4404236Smckusick if (n != cgrp.cg_nifree) { 4414236Smckusick printf("cg[%d].cg_nifree is %d not %d\n", 4424236Smckusick c, cgrp.cg_nifree, n); 4434236Smckusick inosumbad++; 4444236Smckusick } 4454236Smckusick } 4464236Smckusick /* 1b */ 4474236Smckusick if (enddup != &duplist[0]) { 4484236Smckusick if (preen) 4494236Smckusick pfatal("INTERNAL ERROR: dups with -p"); 4504236Smckusick printf("** Phase 1b - Rescan For More DUPS\n"); 4514236Smckusick pfunc = pass1b; 4524236Smckusick inum = 0; 4534236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 4544465Smckusic for (i = 0; i < sblock.fs_ipg; i++, inum++) { 4554465Smckusic dp = ginode(); 4564465Smckusic if (dp == NULL) 4574465Smckusic continue; 4584236Smckusick if (getstate() != USTATE && 4594236Smckusick (ckinode(dp, ADDR) & STOP)) 4604236Smckusick goto out1b; 4614465Smckusic } 4624236Smckusick } 4634236Smckusick } 4644236Smckusick out1b: 4654465Smckusic flush(&dfile, &inoblk); 4664236Smckusick /* 2 */ 4674236Smckusick if (preen == 0) 4684236Smckusick printf("** Phase 2 - Check Pathnames\n"); 4694236Smckusick inum = ROOTINO; 4704236Smckusick thisname = pathp = pathname; 4714236Smckusick pfunc = pass2; 4724236Smckusick switch (getstate()) { 4734236Smckusick 4744236Smckusick case USTATE: 4754236Smckusick errexit("ROOT INODE UNALLOCATED. TERMINATING.\n"); 4764236Smckusick 4774236Smckusick case FSTATE: 4784236Smckusick pfatal("ROOT INODE NOT DIRECTORY"); 4794236Smckusick if (reply("FIX") == 0 || (dp = ginode()) == NULL) 4804236Smckusick errexit(""); 4814236Smckusick dp->di_mode &= ~IFMT; 4824236Smckusick dp->di_mode |= IFDIR; 4834236Smckusick inodirty(); 4844236Smckusick inosumbad++; 4854236Smckusick setstate(DSTATE); 4864236Smckusick /* fall into ... */ 4874236Smckusick 4884236Smckusick case DSTATE: 4894236Smckusick descend(); 4904236Smckusick break; 4914236Smckusick 4924236Smckusick case CLEAR: 4934236Smckusick pfatal("DUPS/BAD IN ROOT INODE"); 4944236Smckusick printf("\n"); 4954236Smckusick if (reply("CONTINUE") == 0) 4964236Smckusick errexit(""); 4974236Smckusick setstate(DSTATE); 4984236Smckusick descend(); 4994236Smckusick } 5004236Smckusick /* 3 */ 5014236Smckusick if (preen == 0) 5024236Smckusick printf("** Phase 3 - Check Connectivity\n"); 5034236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 5044236Smckusick if (getstate() == DSTATE) { 5054236Smckusick pfunc = findino; 5064236Smckusick srchname = ".."; 5074236Smckusick savino = inum; 5084236Smckusick do { 5094236Smckusick orphan = inum; 5104236Smckusick if ((dp = ginode()) == NULL) 5114236Smckusick break; 5124236Smckusick filsize = dp->di_size; 5134236Smckusick parentdir = 0; 5144236Smckusick ckinode(dp, DATA); 5154236Smckusick if ((inum = parentdir) == 0) 5164236Smckusick break; 5174236Smckusick } while (getstate() == DSTATE); 5184236Smckusick inum = orphan; 5194236Smckusick if (linkup() == 1) { 5204236Smckusick thisname = pathp = pathname; 5214236Smckusick *pathp++ = '?'; 5224236Smckusick pfunc = pass2; 5234236Smckusick descend(); 5244236Smckusick } 5254236Smckusick inum = savino; 5264236Smckusick } 5274236Smckusick } 5284236Smckusick /* 4 */ 5294236Smckusick if (preen == 0) 5304236Smckusick printf("** Phase 4 - Check Reference Counts\n"); 5314236Smckusick pfunc = pass4; 5324236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 5334236Smckusick switch (getstate()) { 5344236Smckusick 5354236Smckusick case FSTATE: 5364236Smckusick if (n = getlncnt()) 5374236Smckusick adjust((short)n); 5384236Smckusick else { 5394236Smckusick for (blp = badlncnt;blp < badlnp; blp++) 5404236Smckusick if (*blp == inum) { 5414236Smckusick clri("UNREF", 1); 5424236Smckusick break; 5434236Smckusick } 5444236Smckusick } 5454236Smckusick break; 5464236Smckusick 5474236Smckusick case DSTATE: 5484236Smckusick clri("UNREF", 1); 5494236Smckusick break; 5504236Smckusick 5514236Smckusick case CLEAR: 5524236Smckusick clri("BAD/DUP", 1); 5534236Smckusick break; 5544236Smckusick } 5554236Smckusick } 5564236Smckusick if (imax - n_files != sblock.fs_nifree) { 5574236Smckusick pwarn("FREE INODE COUNT WRONG IN SUPERBLK"); 5584236Smckusick if (preen) 5594236Smckusick printf(" (FIXED)\n"); 5604236Smckusick if (preen || reply("FIX") == 1) { 5614236Smckusick sblock.fs_nifree = imax - n_files; 5624236Smckusick sbdirty(); 5634236Smckusick } 5644236Smckusick } 5654236Smckusick flush(&dfile, &fileblk); 5664236Smckusick 5674236Smckusick /* 5 */ 5684236Smckusick if (preen == 0) 5694236Smckusick printf("** Phase 5 - Check Cyl groups\n"); 5704236Smckusick copy(blkmap, freemap, (unsigned)bmapsz); 5714236Smckusick dupblk = 0; 5724236Smckusick n_index = sblock.fs_ncg * (cgdmin(0, &sblock) - cgtod(0, &sblock)); 5734236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 5744236Smckusick daddr_t cbase = cgbase(c,&sblock); 5754236Smckusick short bo[MAXCPG][NRPOS]; 5764465Smckusic short frsum[FRAG]; 5774465Smckusic int blk; 5784465Smckusic 5794236Smckusick for (n = 0; n < sblock.fs_cpg; n++) 5804236Smckusick for (i = 0; i < NRPOS; i++) 5814236Smckusick bo[n][i] = 0; 5824465Smckusic for (i = 0; i < FRAG; i++) { 5834465Smckusic frsum[i] = 0; 5844465Smckusic } 5854465Smckusic /* 5864465Smckusic * need to account for the spare boot and super blocks 5874465Smckusic * which appear (inaccurately) bad 5884465Smckusic */ 5894236Smckusick n_bad += cgtod(c, &sblock) - cbase; 5904236Smckusick if (getblk(&cgblk, cgtod(c, &sblock), sblock.fs_cgsize) == 0) 5914236Smckusick continue; 5924236Smckusick for (b = 0; b < sblock.fs_fpg; b += FRAG) { 5934236Smckusick if (isblock(cgrp.cg_free, b/FRAG)) { 5944236Smckusick if (pass5(cbase+b, FRAG) == STOP) 5954236Smckusick goto out5; 5964236Smckusick /* this is clumsy ... */ 5974236Smckusick n_ffree -= FRAG; 5984236Smckusick n_bfree++; 5994236Smckusick s = b * NSPF; 6004236Smckusick bo[s/sblock.fs_spc] 6014236Smckusick [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 6024465Smckusic } else { 6034236Smckusick for (d = 0; d < FRAG; d++) 6044236Smckusick if (isset(cgrp.cg_free, b+d)) 6054236Smckusick if (pass5(cbase+b+d,1) == STOP) 6064236Smckusick goto out5; 6074465Smckusic blk = ((cgrp.cg_free[b / NBBY] >> (b % NBBY)) & 6084465Smckusic (0xff >> (NBBY - FRAG))); 6094465Smckusic if (blk != 0) 6104465Smckusic fragacct(blk, frsum, 1); 6114465Smckusic } 6124236Smckusick } 6134465Smckusic for (i = 0; i < FRAG; i++) { 6144465Smckusic if (cgrp.cg_frsum[i] != frsum[i]) { 6154465Smckusic printf("cg[%d].cg_frsum[%d] have %d calc %d\n", 6164465Smckusic c, i, cgrp.cg_frsum[i], frsum[i]); 6174465Smckusic frsumbad++; 6184465Smckusic } 6194465Smckusic } 6204236Smckusick for (n = 0; n < sblock.fs_cpg; n++) 6214236Smckusick for (i = 0; i < NRPOS; i++) 6224236Smckusick if (bo[n][i] != cgrp.cg_b[n][i]) { 6234428Smckusic printf("cg[%d].cg_b[%d][%d] have %d calc %d\n", 6244428Smckusic c, n, i, cgrp.cg_b[n][i], bo[n][i]); 6254236Smckusick offsumbad++; 6264236Smckusick } 6274236Smckusick } 6284236Smckusick out5: 6294236Smckusick if (dupblk) 6304236Smckusick pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk); 6314236Smckusick if (fixcg == 0) { 6324236Smckusick if ((b = n_blks+n_ffree+FRAG*n_bfree+n_index+n_bad) != fmax) { 6334236Smckusick pwarn("%ld BLK(S) MISSING\n", fmax - b); 6344236Smckusick fixcg = 1; 6354465Smckusic } else if (inosumbad + offsumbad + frsumbad) { 6364465Smckusic pwarn("SUMMARY INFORMATION %s%s%sBAD\n", 6374236Smckusick inosumbad ? "(INODE FREE) " : "", 6384465Smckusic offsumbad ? "(BLOCK OFFSETS) " : "", 6394465Smckusic frsumbad ? "(FRAG SUMMARIES) " : ""); 6404236Smckusick fixcg = 1; 6414236Smckusick } else if (n_ffree != sblock.fs_nffree || 6424236Smckusick n_bfree != sblock.fs_nbfree) { 6434236Smckusick pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK"); 6444236Smckusick if (preen) 6454236Smckusick printf(" (FIXED)\n"); 6464236Smckusick if (preen || reply("FIX") == 1) { 6474236Smckusick sblock.fs_nffree = n_ffree; 6484236Smckusick sblock.fs_nbfree = n_bfree; 6494236Smckusick sbdirty(); 6504236Smckusick } 6514236Smckusick } 6524236Smckusick } 6534236Smckusick if (fixcg) { 6544236Smckusick pwarn("BAD CYLINDER GROUPS"); 6554236Smckusick if (preen) 6564236Smckusick printf(" (SALVAGED)\n"); 6574236Smckusick else if (reply("SALVAGE") == 0) 6584236Smckusick fixcg = 0; 6594236Smckusick } 6604236Smckusick 6614236Smckusick if (fixcg) { 6624236Smckusick if (preen == 0) 6634236Smckusick printf("** Phase 6 - Salvage Cylinder Groups\n"); 6644653Smckusic for (i = 0; i < howmany(cssize(&sblock), BSIZE); i++) { 6654653Smckusic sblock.fs_csp[i] = (struct csum *)calloc(1, BSIZE); 6664653Smckusic getblk((char *)sblock.fs_csp[i], 6674653Smckusic csaddr(&sblock) + (i * FRAG), BSIZE); 6684653Smckusic } 6694236Smckusick makecg(); 6704653Smckusic for (i = 0; i < howmany(cssize(&sblock), BSIZE); i++) { 6714653Smckusic bwrite(&dfile, (char *)sblock.fs_csp[i], 6724653Smckusic csaddr(&sblock) + (i * FRAG), BSIZE); 6734653Smckusic } 6744236Smckusick n_ffree = sblock.fs_nffree; 6754236Smckusick n_bfree = sblock.fs_nbfree; 6764236Smckusick } 6774236Smckusick 6784236Smckusick pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n", 6794236Smckusick n_files, n_blks, n_ffree + FRAG * n_bfree, n_ffree, n_bfree); 6804236Smckusick if (dfile.mod) { 6814236Smckusick time(&sblock.fs_time); 6824236Smckusick sbdirty(); 6834236Smckusick } 6844236Smckusick ckfini(); 6854236Smckusick sync(); 6864236Smckusick if (dfile.mod && hotroot) { 6874236Smckusick printf("\n***** BOOT UNIX (NO SYNC!) *****\n"); 6884236Smckusick exit(4); 6894236Smckusick } 6904236Smckusick if (dfile.mod && preen == 0) 6914236Smckusick printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 6924236Smckusick free(blkmap); 6934236Smckusick free(freemap); 6944236Smckusick free(statemap); 6954236Smckusick free(lncntp); 6964236Smckusick } 6974236Smckusick 6984236Smckusick /* VARARGS1 */ 6994236Smckusick error(s1, s2, s3, s4) 700*4715Smckusic char *s1; 7014236Smckusick { 7024236Smckusick 7034236Smckusick printf(s1, s2, s3, s4); 7044236Smckusick } 7054236Smckusick 7064236Smckusick /* VARARGS1 */ 7074236Smckusick errexit(s1, s2, s3, s4) 708*4715Smckusic char *s1; 7094236Smckusick { 7104236Smckusick error(s1, s2, s3, s4); 7114236Smckusick exit(8); 7124236Smckusick } 7134236Smckusick 7144236Smckusick /* 7154236Smckusick * An inconsistency occured which shouldn't during normal operations. 7164236Smckusick * Die if preening, otw just printf. 7174236Smckusick */ 7184236Smckusick /* VARARGS1 */ 7194236Smckusick pfatal(s, a1, a2, a3) 7204236Smckusick char *s; 7214236Smckusick { 7224236Smckusick 7234236Smckusick if (preen) { 7244236Smckusick printf("%s: ", devname); 7254236Smckusick printf(s, a1, a2, a3); 7264236Smckusick printf("\n"); 7274236Smckusick preendie(); 7284236Smckusick } 7294236Smckusick printf(s, a1, a2, a3); 7304236Smckusick } 7314236Smckusick 7324236Smckusick preendie() 7334236Smckusick { 7344236Smckusick 7354236Smckusick printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); 7364236Smckusick exit(8); 7374236Smckusick } 7384236Smckusick 7394236Smckusick /* 7404236Smckusick * Pwarn is like printf when not preening, 7414236Smckusick * or a warning (preceded by filename) when preening. 7424236Smckusick */ 7434236Smckusick /* VARARGS1 */ 7444236Smckusick pwarn(s, a1, a2, a3, a4, a5) 7454236Smckusick char *s; 7464236Smckusick { 7474236Smckusick 7484236Smckusick if (preen) 7494236Smckusick printf("%s: ", devname); 7504236Smckusick printf(s, a1, a2, a3, a4, a5); 7514236Smckusick } 7524236Smckusick 7534236Smckusick ckinode(dp, flg) 7544236Smckusick DINODE *dp; 7554236Smckusick register flg; 7564236Smckusick { 7574236Smckusick register daddr_t *ap; 7584236Smckusick register ret; 7594236Smckusick int (*func)(), n, ndb, size; 7604236Smckusick 7614236Smckusick if (SPECIAL) 7624236Smckusick return (KEEPON); 7634236Smckusick func = (flg == ADDR) ? pfunc : dirscan; 7644236Smckusick ndb = howmany(dp->di_size, BSIZE); 7654428Smckusic for (ap = &dp->di_db[0]; ap < &dp->di_db[NDADDR]; ap++) { 7664236Smckusick if (--ndb == 0 && (dp->di_size&BMASK)) 7674236Smckusick size = howmany(dp->di_size&BMASK, FSIZE); 7684236Smckusick else 7694236Smckusick size = FRAG; 7704236Smckusick if (*ap && (ret = (*func)(*ap, size)) & STOP) 7714236Smckusick return (ret); 7724236Smckusick } 7734428Smckusic for (ap = &dp->di_ib[0], n = 1; n <= 2; ap++, n++) { 7744428Smckusic if (*ap && (ret = iblock(*ap, n, flg, dp->di_size - BSIZE * NDADDR)) & STOP) 7754236Smckusick return (ret); 7764236Smckusick } 7774236Smckusick return (KEEPON); 7784236Smckusick } 7794236Smckusick 7804236Smckusick iblock(blk, ilevel, flg, isize) 7814236Smckusick daddr_t blk; 7824236Smckusick register ilevel; 7834236Smckusick int isize; 7844236Smckusick { 7854236Smckusick register daddr_t *ap; 7864236Smckusick register daddr_t *aplim; 7874428Smckusic register int i, n; 7884236Smckusick int (*func)(), nif; 7894236Smckusick BUFAREA ib; 7904236Smckusick 7914236Smckusick if (flg == ADDR) { 7924236Smckusick func = pfunc; 7934428Smckusic if (((n = (*func)(blk, FRAG)) & KEEPON) == 0) 7944236Smckusick return (n); 7954236Smckusick } else 7964236Smckusick func = dirscan; 7974236Smckusick if (outrange(blk)) /* protect thyself */ 7984236Smckusick return (SKIP); 7994236Smckusick initbarea(&ib); 8004428Smckusic if (getblk(&ib, blk, BSIZE) == NULL) 8014236Smckusick return (SKIP); 8024236Smckusick ilevel--; 8034428Smckusic if (ilevel == 0) { 8044428Smckusic nif = isize / BSIZE + 1; 8054428Smckusic } else /* ilevel == 1 */ { 8064428Smckusic nif = isize / (BSIZE * NINDIR) + 1; 8074428Smckusic } 8084428Smckusic if (nif > NINDIR) 8094428Smckusic nif = NINDIR; 8104428Smckusic aplim = & ib.b_un.b_indir[nif]; 8114428Smckusic for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++) 8124236Smckusick if (*ap) { 8134236Smckusick if (ilevel > 0) 8144428Smckusic n = iblock(*ap, ilevel, flg, isize - i * NINDIR * BSIZE); 8154236Smckusick else 8164428Smckusic n = (*func)(*ap, FRAG); 8174236Smckusick if (n & STOP) 8184236Smckusick return (n); 8194236Smckusick } 8204236Smckusick return (KEEPON); 8214236Smckusick } 8224236Smckusick 8234236Smckusick pass1(blk, size) 8244236Smckusick daddr_t blk; 8254236Smckusick int size; 8264236Smckusick { 8274236Smckusick register daddr_t *dlp; 8284236Smckusick int res = KEEPON; 8294236Smckusick 8304236Smckusick for (; size > 0; blk++, size--) { 8314236Smckusick if (outrange(blk)) { 8324236Smckusick blkerr("BAD", blk); 8334236Smckusick if (++badblk >= MAXBAD) { 8344236Smckusick printf("EXCESSIVE BAD BLKS I=%u", inum); 8354236Smckusick if (reply("CONTINUE") == 0) 8364236Smckusick errexit(""); 8374236Smckusick return (STOP); 8384236Smckusick } 8394236Smckusick res = SKIP; 8404236Smckusick } else if (getbmap(blk)) { 8414236Smckusick blkerr("DUP", blk); 8424236Smckusick if (++dupblk >= MAXDUP) { 8434236Smckusick printf("EXCESSIVE DUP BLKS I=%u", inum); 8444236Smckusick if (reply("CONTINUE") == 0) 8454236Smckusick errexit(""); 8464236Smckusick return (STOP); 8474236Smckusick } 8484236Smckusick if (enddup >= &duplist[DUPTBLSIZE]) { 8494236Smckusick printf("DUP TABLE OVERFLOW."); 8504236Smckusick if (reply("CONTINUE") == 0) 8514236Smckusick errexit(""); 8524236Smckusick return (STOP); 8534236Smckusick } 8544236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8554236Smckusick if (*dlp == blk) { 8564236Smckusick *enddup++ = blk; 8574236Smckusick break; 8584236Smckusick } 8594236Smckusick if (dlp >= muldup) { 8604236Smckusick *enddup++ = *muldup; 8614236Smckusick *muldup++ = blk; 8624236Smckusick } 8634236Smckusick } else { 8644236Smckusick n_blks++; 8654236Smckusick setbmap(blk); 8664236Smckusick } 8674236Smckusick filsize++; 8684236Smckusick } 8694236Smckusick return (res); 8704236Smckusick } 8714236Smckusick 8724236Smckusick pass1b(blk, size) 8734236Smckusick daddr_t blk; 8744236Smckusick int size; 8754236Smckusick { 8764236Smckusick register daddr_t *dlp; 8774236Smckusick int res = KEEPON; 8784236Smckusick 8794236Smckusick for (; size > 0; blk++, size--) { 8804236Smckusick if (outrange(blk)) 8814236Smckusick res = SKIP; 8824236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8834236Smckusick if (*dlp == blk) { 8844236Smckusick blkerr("DUP", blk); 8854236Smckusick *dlp = *--muldup; 8864236Smckusick *muldup = blk; 8874236Smckusick if (muldup == duplist) 8884236Smckusick return (STOP); 8894236Smckusick } 8904236Smckusick } 8914236Smckusick return (res); 8924236Smckusick } 8934236Smckusick 8944236Smckusick pass2(dirp) 8954236Smckusick register DIRECT *dirp; 8964236Smckusick { 8974236Smckusick register char *p; 8984236Smckusick register n; 8994236Smckusick DINODE *dp; 9004236Smckusick 9014236Smckusick if ((inum = dirp->d_ino) == 0) 9024236Smckusick return (KEEPON); 9034236Smckusick thisname = pathp; 9044236Smckusick for (p = dirp->d_name; p < &dirp->d_name[DIRSIZ]; ) 9054236Smckusick if ((*pathp++ = *p++) == 0) { 9064236Smckusick --pathp; 9074236Smckusick break; 9084236Smckusick } 9094236Smckusick *pathp = 0; 9104236Smckusick n = 0; 911*4715Smckusic if (inum > imax || inum <= 0) 9124236Smckusick n = direrr("I OUT OF RANGE"); 9134236Smckusick else { 9144236Smckusick again: 9154236Smckusick switch (getstate()) { 9164236Smckusick case USTATE: 9174236Smckusick n = direrr("UNALLOCATED"); 9184236Smckusick break; 9194236Smckusick 9204236Smckusick case CLEAR: 9214236Smckusick if ((n = direrr("DUP/BAD")) == 1) 9224236Smckusick break; 9234236Smckusick if ((dp = ginode()) == NULL) 9244236Smckusick break; 9254236Smckusick setstate(DIR ? DSTATE : FSTATE); 9264236Smckusick goto again; 9274236Smckusick 9284236Smckusick case FSTATE: 9294236Smckusick declncnt(); 9304236Smckusick break; 9314236Smckusick 9324236Smckusick case DSTATE: 9334236Smckusick declncnt(); 9344236Smckusick descend(); 9354236Smckusick break; 9364236Smckusick } 9374236Smckusick } 9384236Smckusick pathp = thisname; 9394236Smckusick if (n == 0) 9404236Smckusick return (KEEPON); 9414236Smckusick dirp->d_ino = 0; 9424236Smckusick return (KEEPON|ALTERD); 9434236Smckusick } 9444236Smckusick 9454236Smckusick pass4(blk, size) 946*4715Smckusic daddr_t blk; 9474236Smckusick { 9484236Smckusick register daddr_t *dlp; 9494236Smckusick int res = KEEPON; 9504236Smckusick 9514236Smckusick for (; size > 0; blk++, size--) { 9524236Smckusick if (outrange(blk)) 9534236Smckusick res = SKIP; 9544236Smckusick else if (getbmap(blk)) { 9554236Smckusick for (dlp = duplist; dlp < enddup; dlp++) 9564236Smckusick if (*dlp == blk) { 9574236Smckusick *dlp = *--enddup; 9584236Smckusick return (KEEPON); 9594236Smckusick } 9604236Smckusick clrbmap(blk); 9614236Smckusick n_blks--; 9624236Smckusick } 9634236Smckusick } 9644236Smckusick return (res); 9654236Smckusick } 9664236Smckusick 9674236Smckusick pass5(blk, size) 9684236Smckusick daddr_t blk; 9694236Smckusick int size; 9704236Smckusick { 9714236Smckusick int res = KEEPON; 9724236Smckusick 9734236Smckusick for (; size > 0; blk++, size--) { 9744236Smckusick if (outrange(blk)) { 9754236Smckusick fixcg = 1; 9764236Smckusick if (preen) 9774236Smckusick pfatal("BAD BLOCKS IN BIT MAPS."); 9784236Smckusick if (++badblk >= MAXBAD) { 9794236Smckusick printf("EXCESSIVE BAD BLKS IN BIT MAPS."); 9804236Smckusick if (reply("CONTINUE") == 0) 9814236Smckusick errexit(""); 9824236Smckusick return (STOP); 9834236Smckusick } 9844236Smckusick } else if (getfmap(blk)) { 9854236Smckusick fixcg = 1; 9864236Smckusick if (++dupblk >= DUPTBLSIZE) { 9874236Smckusick printf("EXCESSIVE DUP BLKS IN BIT MAPS."); 9884236Smckusick if (reply("CONTINUE") == 0) 9894236Smckusick errexit(""); 9904236Smckusick return (STOP); 9914236Smckusick } 9924236Smckusick } else { 9934236Smckusick n_ffree++; 9944236Smckusick setfmap(blk); 9954236Smckusick } 9964236Smckusick } 9974236Smckusick return (res); 9984236Smckusick } 9994236Smckusick 10004236Smckusick outrange(blk) 10014236Smckusick daddr_t blk; 10024236Smckusick { 10034236Smckusick register int c; 10044236Smckusick 10054236Smckusick c = dtog(blk, &sblock); 10064428Smckusic if (blk >= fmax || blk < cgdmin(c, &sblock)) { 10074236Smckusick return (1); 10084428Smckusic } 10094236Smckusick return (0); 10104236Smckusick } 10114236Smckusick 10124236Smckusick blkerr(s, blk) 10134236Smckusick daddr_t blk; 10144236Smckusick char *s; 10154236Smckusick { 10164236Smckusick pfatal("%ld %s I=%u", blk, s, inum); 10174236Smckusick printf("\n"); 10184236Smckusick setstate(CLEAR); /* mark for possible clearing */ 10194236Smckusick } 10204236Smckusick 10214236Smckusick descend() 10224236Smckusick { 10234236Smckusick register DINODE *dp; 10244236Smckusick register char *savname; 10254236Smckusick off_t savsize; 10264236Smckusick 10274236Smckusick setstate(FSTATE); 10284236Smckusick if ((dp = ginode()) == NULL) 10294236Smckusick return; 10304236Smckusick savname = thisname; 10314236Smckusick *pathp++ = '/'; 10324236Smckusick savsize = filsize; 10334236Smckusick filsize = dp->di_size; 10344236Smckusick ckinode(dp, DATA); 10354236Smckusick thisname = savname; 10364236Smckusick *--pathp = 0; 10374236Smckusick filsize = savsize; 10384236Smckusick } 10394236Smckusick 10404236Smckusick dirscan(blk, nf) 1041*4715Smckusic daddr_t blk; 1042*4715Smckusic int nf; 10434236Smckusick { 10444236Smckusick register DIRECT *dirp; 10454236Smckusick register DIRECT *edirp; 10464236Smckusick register char *p1, *p2; 10474236Smckusick register n; 10484236Smckusick DIRECT direntry; 10494236Smckusick 10504236Smckusick if (outrange(blk)) { 10514236Smckusick filsize -= BSIZE; 10524236Smckusick return (SKIP); 10534236Smckusick } 10544236Smckusick edirp = &dirblk.b_dir[NDIRECT*nf/FRAG]; 10554236Smckusick for (dirp = dirblk.b_dir; dirp < edirp && 10564236Smckusick filsize > 0; dirp++, filsize -= sizeof(DIRECT)) { 10574236Smckusick if (getblk(&fileblk, blk, nf * FSIZE) == NULL) { 10584236Smckusick filsize -= (&dirblk.b_dir[NDIRECT]-dirp)*sizeof(DIRECT); 10594236Smckusick return (SKIP); 10604236Smckusick } 10614236Smckusick p1 = &dirp->d_name[DIRSIZ]; 10624236Smckusick p2 = &direntry.d_name[DIRSIZ]; 10634236Smckusick while (p1 > (char *)dirp) 10644236Smckusick *--p2 = *--p1; 10654236Smckusick if ((n = (*pfunc)(&direntry)) & ALTERD) { 10664236Smckusick if (getblk(&fileblk, blk, nf * FSIZE) != NULL) { 10674236Smckusick p1 = &dirp->d_name[DIRSIZ]; 10684236Smckusick p2 = &direntry.d_name[DIRSIZ]; 10694236Smckusick while (p1 > (char *)dirp) 10704236Smckusick *--p1 = *--p2; 1071*4715Smckusic dirty(&fileblk); 10724236Smckusick sbdirty(); 10734236Smckusick } else 10744236Smckusick n &= ~ALTERD; 10754236Smckusick } 10764236Smckusick if (n & STOP) 10774236Smckusick return (n); 10784236Smckusick } 10794236Smckusick return (filsize > 0 ? KEEPON : STOP); 10804236Smckusick } 10814236Smckusick 10824236Smckusick direrr(s) 1083*4715Smckusic char *s; 10844236Smckusick { 10854236Smckusick register DINODE *dp; 10864236Smckusick 10874236Smckusick pwarn("%s ", s); 10884236Smckusick pinode(); 10894236Smckusick printf("\n"); 10904236Smckusick if ((dp = ginode()) != NULL && ftypeok(dp)) 10914236Smckusick pfatal("%s=%s", DIR?"DIR":"FILE", pathname); 10924236Smckusick else 10934236Smckusick pfatal("NAME=%s", pathname); 10944236Smckusick return (reply("REMOVE")); 10954236Smckusick } 10964236Smckusick 10974236Smckusick adjust(lcnt) 10984465Smckusic register short lcnt; 10994236Smckusick { 11004236Smckusick register DINODE *dp; 11014236Smckusick 11024236Smckusick if ((dp = ginode()) == NULL) 11034236Smckusick return; 11044236Smckusick if (dp->di_nlink == lcnt) { 11054236Smckusick if (linkup() == 0) 11064236Smckusick clri("UNREF", 0); 11074236Smckusick } 11084236Smckusick else { 11094236Smckusick pwarn("LINK COUNT %s", 11104236Smckusick (lfdir==inum)?lfname:(DIR?"DIR":"FILE")); 11114236Smckusick pinode(); 11124236Smckusick printf(" COUNT %d SHOULD BE %d", 11134236Smckusick dp->di_nlink, dp->di_nlink-lcnt); 11144236Smckusick if (preen) { 11154236Smckusick if (lcnt < 0) { 11164236Smckusick printf("\n"); 11174236Smckusick preendie(); 11184236Smckusick } 11194236Smckusick printf(" (ADJUSTED)\n"); 11204236Smckusick } 11214236Smckusick if (preen || reply("ADJUST") == 1) { 11224236Smckusick dp->di_nlink -= lcnt; 11234236Smckusick inodirty(); 11244236Smckusick } 11254236Smckusick } 11264236Smckusick } 11274236Smckusick 11284236Smckusick clri(s, flg) 1129*4715Smckusic char *s; 11304236Smckusick { 11314236Smckusick register DINODE *dp; 11324236Smckusick 11334236Smckusick if ((dp = ginode()) == NULL) 11344236Smckusick return; 11354236Smckusick if (flg == 1) { 11364236Smckusick pwarn("%s %s", s, DIR?"DIR":"FILE"); 11374236Smckusick pinode(); 11384236Smckusick } 11394236Smckusick if (preen || reply("CLEAR") == 1) { 11404236Smckusick if (preen) 11414236Smckusick printf(" (CLEARED)\n"); 11424236Smckusick n_files--; 11434236Smckusick pfunc = pass4; 11444236Smckusick ckinode(dp, ADDR); 11454236Smckusick zapino(dp); 11464465Smckusic setstate(USTATE); 11474236Smckusick inodirty(); 11484236Smckusick inosumbad++; 11494236Smckusick } 11504236Smckusick } 11514236Smckusick 11524236Smckusick setup(dev) 1153*4715Smckusic char *dev; 11544236Smckusick { 11554236Smckusick dev_t rootdev; 11564236Smckusick struct stat statb; 11574236Smckusick int super = bflag ? bflag : SBLOCK; 11584236Smckusick 11594236Smckusick bflag = 0; 11604236Smckusick if (stat("/", &statb) < 0) 11614236Smckusick errexit("Can't stat root\n"); 11624236Smckusick rootdev = statb.st_dev; 11634236Smckusick if (stat(dev, &statb) < 0) { 11644236Smckusick error("Can't stat %s\n", dev); 11654236Smckusick return (0); 11664236Smckusick } 11674236Smckusick rawflg = 0; 11684236Smckusick if ((statb.st_mode & S_IFMT) == S_IFBLK) 11694236Smckusick ; 11704236Smckusick else if ((statb.st_mode & S_IFMT) == S_IFCHR) 11714236Smckusick rawflg++; 11724236Smckusick else { 11734236Smckusick if (reply("file is not a block or character device; OK") == 0) 11744236Smckusick return (0); 11754236Smckusick } 11764236Smckusick if (rootdev == statb.st_rdev) 11774236Smckusick hotroot++; 11784236Smckusick if ((dfile.rfdes = open(dev, 0)) < 0) { 11794236Smckusick error("Can't open %s\n", dev); 11804236Smckusick return (0); 11814236Smckusick } 11824236Smckusick if (preen == 0) 11834236Smckusick printf("** %s", dev); 11844236Smckusick if (nflag || (dfile.wfdes = open(dev, 1)) < 0) { 11854236Smckusick dfile.wfdes = -1; 11864236Smckusick if (preen) 11874236Smckusick pfatal("NO WRITE ACCESS"); 11884236Smckusick printf(" (NO WRITE)"); 11894236Smckusick } 11904236Smckusick if (preen == 0) 11914236Smckusick printf("\n"); 11924465Smckusic fixcg = 0; inosumbad = 0; offsumbad = 0; frsumbad = 0; 11934236Smckusick dfile.mod = 0; 11944236Smckusick n_files = n_blks = n_ffree = n_bfree = 0; 11954236Smckusick muldup = enddup = &duplist[0]; 11964236Smckusick badlnp = &badlncnt[0]; 11974236Smckusick lfdir = 0; 11984236Smckusick rplyflag = 0; 11994236Smckusick initbarea(&sblk); 12004236Smckusick initbarea(&fileblk); 12014236Smckusick initbarea(&inoblk); 12024236Smckusick initbarea(&cgblk); 12034236Smckusick if (getblk(&sblk, super, BSIZE) == NULL) { 12044236Smckusick ckfini(); 12054236Smckusick return (0); 12064236Smckusick } 12074465Smckusic sblk.b_bno = super; 12084236Smckusick if (sblock.fs_magic != FS_MAGIC) 12094236Smckusick { badsb("MAGIC NUMBER WRONG"); return (0); } 12104236Smckusick if (sblock.fs_ncg < 1) 12114236Smckusick { badsb("NCG OUT OF RANGE"); return (0); } 12124236Smckusick if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG) 12134236Smckusick { badsb("CPG OUT OF RANGE"); return (0); } 12144236Smckusick if (sblock.fs_nsect < 1) 12154236Smckusick { badsb("NSECT < 1"); return (0); } 12164236Smckusick if (sblock.fs_ntrak < 1) 12174236Smckusick { badsb("NTRAK < 1"); return (0); } 12184236Smckusick if (sblock.fs_ipg*sblock.fs_ncg > 65535 || sblock.fs_ipg%INOPB) 12194236Smckusick { badsb("TOO MANY INODES IMPLIED"); return (0); } 12204236Smckusick if (sblock.fs_ipg/INOPF+IBLOCK >= 12214236Smckusick sblock.fs_cpg*sblock.fs_nsect*sblock.fs_ntrak/NSPF) 12224236Smckusick { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); } 12234236Smckusick /* THE FOLLOWING COULD BE CHECKED MORE CLOSELY... */ 12244236Smckusick if ((sblock.fs_ncg + 1) * sblock.fs_cpg < sblock.fs_ncyl || 12254236Smckusick (sblock.fs_ncg - 1) * sblock.fs_cpg > sblock.fs_ncyl) 12264236Smckusick { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); } 12274236Smckusick if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF) 12284236Smckusick { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); } 12294236Smckusick if (sblock.fs_size <= 12304236Smckusick (sblock.fs_ncg-1)*sblock.fs_fpg+IBLOCK+sblock.fs_ipg/INOPF) 12314236Smckusick { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); } 12324236Smckusick if (sblock.fs_size*NSPF > 12334236Smckusick (sblock.fs_ncg+2)*sblock.fs_cpg*sblock.fs_spc) 12344236Smckusick { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); } 12354236Smckusick /* rest we COULD repair... */ 12364236Smckusick if (sblock.fs_sblkno != SBLOCK) 12374236Smckusick { badsb("BLKNO CORRUPTED"); return (0); } 12384236Smckusick if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak) 12394236Smckusick { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); } 12404236Smckusick if (sblock.fs_cgsize != cgsize(&sblock)) 12414236Smckusick { badsb("CGSIZE INCORRECT"); return (0); } 12424236Smckusick if (sblock.fs_cssize != cssize(&sblock)) 12434236Smckusick { badsb("CSSIZE INCORRECT"); return (0); } 12444236Smckusick fmax = sblock.fs_size; 12454236Smckusick imax = sblock.fs_ncg * sblock.fs_ipg; 12464236Smckusick 12474236Smckusick bmapsz = roundup(howmany(fmax, NBBY), sizeof(short)); 12484236Smckusick blkmap = (char *)calloc(bmapsz, sizeof (char)); 12494236Smckusick freemap = (char *)calloc(bmapsz, sizeof (char)); 12504236Smckusick statemap = (char *)calloc(imax+1, sizeof(char)); 12514236Smckusick lncntp = (short *)calloc(imax+1, sizeof(short)); 12524236Smckusick 12534465Smckusic startinum = imax + 1; 12544236Smckusick return (1); 12554236Smckusick 12564236Smckusick badsb: 12574236Smckusick ckfini(); 12584236Smckusick return (0); 12594236Smckusick } 12604236Smckusick 12614236Smckusick badsb(s) 12624236Smckusick char *s; 12634236Smckusick { 12644236Smckusick 12654236Smckusick if (preen) 12664236Smckusick printf("%s: ", devname); 12674236Smckusick printf("BAD SUPER BLOCK: %s\n", s); 12684236Smckusick pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n"); 12694236Smckusick pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n"); 12704236Smckusick } 12714236Smckusick 12724236Smckusick DINODE * 12734236Smckusick ginode() 12744236Smckusick { 12754236Smckusick daddr_t iblk; 12764236Smckusick 12774236Smckusick if (inum > imax) 12784236Smckusick return (NULL); 12794465Smckusic if (inum < startinum || inum >= startinum + INOPB) { 12804465Smckusic iblk = itod(inum, &sblock); 12814465Smckusic if (getblk(&inoblk, iblk, BSIZE) == NULL) { 12824236Smckusick return (NULL); 12834236Smckusick } 12844465Smckusic startinum = (inum / INOPB) * INOPB; 12854236Smckusick } 12864465Smckusic return (&inoblk.b_un.b_dinode[inum % INOPB]); 12874236Smckusick } 12884236Smckusick 12894236Smckusick ftypeok(dp) 12904236Smckusick DINODE *dp; 12914236Smckusick { 12924236Smckusick switch (dp->di_mode & IFMT) { 12934236Smckusick 12944236Smckusick case IFDIR: 12954236Smckusick case IFREG: 12964236Smckusick case IFBLK: 12974236Smckusick case IFCHR: 12984236Smckusick case IFMPC: 12994236Smckusick case IFMPB: 13004236Smckusick return (1); 13014236Smckusick 13024236Smckusick default: 13034236Smckusick return (0); 13044236Smckusick } 13054236Smckusick } 13064236Smckusick 13074236Smckusick reply(s) 13084236Smckusick char *s; 13094236Smckusick { 13104236Smckusick char line[80]; 13114236Smckusick 13124236Smckusick if (preen) 13134236Smckusick pfatal("INTERNAL ERROR: GOT TO reply()"); 13144236Smckusick rplyflag = 1; 13154236Smckusick printf("\n%s? ", s); 13164236Smckusick if (nflag || dfile.wfdes < 0) { 13174236Smckusick printf(" no\n\n"); 13184236Smckusick return (0); 13194236Smckusick } 13204236Smckusick if (yflag) { 13214236Smckusick printf(" yes\n\n"); 13224236Smckusick return (1); 13234236Smckusick } 13244236Smckusick if (getline(stdin, line, sizeof(line)) == EOF) 13254236Smckusick errexit("\n"); 13264236Smckusick printf("\n"); 13274236Smckusick if (line[0] == 'y' || line[0] == 'Y') 13284236Smckusick return (1); 13294236Smckusick else 13304236Smckusick return (0); 13314236Smckusick } 13324236Smckusick 13334236Smckusick getline(fp, loc, maxlen) 13344236Smckusick FILE *fp; 13354236Smckusick char *loc; 13364236Smckusick { 13374236Smckusick register n; 13384236Smckusick register char *p, *lastloc; 13394236Smckusick 13404236Smckusick p = loc; 13414236Smckusick lastloc = &p[maxlen-1]; 13424236Smckusick while ((n = getc(fp)) != '\n') { 13434236Smckusick if (n == EOF) 13444236Smckusick return (EOF); 13454236Smckusick if (!isspace(n) && p < lastloc) 13464236Smckusick *p++ = n; 13474236Smckusick } 13484236Smckusick *p = 0; 13494236Smckusick return (p - loc); 13504236Smckusick } 13514236Smckusick 13524236Smckusick BUFAREA * 13534236Smckusick getblk(bp, blk, size) 13544236Smckusick daddr_t blk; 13554236Smckusick register BUFAREA *bp; 13564236Smckusick int size; 13574236Smckusick { 13584236Smckusick register struct filecntl *fcp; 13594236Smckusick 13604236Smckusick fcp = &dfile; 13614236Smckusick if (bp->b_bno == blk) 13624236Smckusick return (bp); 13634236Smckusick flush(fcp, bp); 13644236Smckusick if (bread(fcp, bp->b_un.b_buf, blk, size) != 0) { 13654236Smckusick bp->b_bno = blk; 13664236Smckusick bp->b_size = size; 13674236Smckusick return (bp); 13684236Smckusick } 13694236Smckusick bp->b_bno = (daddr_t)-1; 13704236Smckusick return (NULL); 13714236Smckusick } 13724236Smckusick 13734236Smckusick flush(fcp, bp) 13744236Smckusick struct filecntl *fcp; 13754236Smckusick register BUFAREA *bp; 13764236Smckusick { 13774236Smckusick 13784236Smckusick if (bp->b_dirty) 13794236Smckusick bwrite(fcp, bp->b_un.b_buf, bp->b_bno, bp->b_size); 13804236Smckusick bp->b_dirty = 0; 13814236Smckusick } 13824236Smckusick 13834236Smckusick rwerr(s, blk) 13844236Smckusick char *s; 13854236Smckusick daddr_t blk; 13864236Smckusick { 13874236Smckusick 13884236Smckusick if (preen == 0) 13894236Smckusick printf("\n"); 13904236Smckusick pfatal("CANNOT %s: BLK %ld", s, blk); 13914236Smckusick if (reply("CONTINUE") == 0) 13924236Smckusick errexit("Program terminated\n"); 13934236Smckusick } 13944236Smckusick 13954236Smckusick ckfini() 13964236Smckusick { 13974236Smckusick 13984236Smckusick flush(&dfile, &fileblk); 13994236Smckusick flush(&dfile, &sblk); 14004465Smckusic if (sblk.b_bno != SBLOCK) { 14014465Smckusic sblk.b_bno = SBLOCK; 14024465Smckusic sbdirty(); 14034465Smckusic flush(&dfile, &sblk); 14044465Smckusic } 14054236Smckusick flush(&dfile, &inoblk); 14064236Smckusick close(dfile.rfdes); 14074236Smckusick close(dfile.wfdes); 14084236Smckusick } 14094236Smckusick 14104236Smckusick pinode() 14114236Smckusick { 14124236Smckusick register DINODE *dp; 14134236Smckusick register char *p; 14144236Smckusick char uidbuf[200]; 14154236Smckusick char *ctime(); 14164236Smckusick 14174236Smckusick printf(" I=%u ", inum); 14184236Smckusick if ((dp = ginode()) == NULL) 14194236Smckusick return; 14204236Smckusick printf(" OWNER="); 14214236Smckusick if (getpw((int)dp->di_uid, uidbuf) == 0) { 14224236Smckusick for (p = uidbuf; *p != ':'; p++); 14234236Smckusick *p = 0; 14244236Smckusick printf("%s ", uidbuf); 14254236Smckusick } 14264236Smckusick else { 14274236Smckusick printf("%d ", dp->di_uid); 14284236Smckusick } 14294236Smckusick printf("MODE=%o\n", dp->di_mode); 14304236Smckusick if (preen) 14314236Smckusick printf("%s: ", devname); 14324236Smckusick printf("SIZE=%ld ", dp->di_size); 14334236Smckusick p = ctime(&dp->di_mtime); 14344236Smckusick printf("MTIME=%12.12s %4.4s ", p+4, p+20); 14354236Smckusick } 14364236Smckusick 14374236Smckusick copy(fp, tp, size) 14384236Smckusick register char *tp, *fp; 14394236Smckusick unsigned size; 14404236Smckusick { 14414236Smckusick 14424236Smckusick while (size--) 14434236Smckusick *tp++ = *fp++; 14444236Smckusick } 14454236Smckusick 14464236Smckusick makecg() 14474236Smckusick { 14484465Smckusic int c, blk; 14494236Smckusick daddr_t dbase, d, dmin, dmax; 14504236Smckusick long i, j, s; 14514236Smckusick register struct csum *cs; 14524465Smckusic register DINODE *dp; 14534236Smckusick 14544236Smckusick sblock.fs_nbfree = 0; 14554236Smckusick sblock.fs_nffree = 0; 14564236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 14574236Smckusick dbase = cgbase(c, &sblock); 14584236Smckusick dmax = dbase + sblock.fs_fpg; 14594236Smckusick if (dmax > sblock.fs_size) 14604236Smckusick dmax = sblock.fs_size; 14614465Smckusic dmin = cgdmin(c, &sblock) - dbase; 14624653Smckusic cs = &sblock.fs_cs(c); 14634236Smckusick cgrp.cg_time = time(0); 14644236Smckusick cgrp.cg_magic = CG_MAGIC; 14654236Smckusick cgrp.cg_cgx = c; 14664236Smckusick cgrp.cg_ncyl = sblock.fs_cpg; 14674236Smckusick cgrp.cg_niblk = sblock.fs_ipg; 14684236Smckusick cgrp.cg_ndblk = dmax - dbase; 14694236Smckusick cgrp.cg_ndir = 0; 14704236Smckusick cgrp.cg_nffree = 0; 14714236Smckusick cgrp.cg_nbfree = 0; 14724236Smckusick cgrp.cg_nifree = 0; 14734465Smckusic cgrp.cg_rotor = dmin; 14744465Smckusic cgrp.cg_frotor = dmin; 14754258Smckusic cgrp.cg_irotor = 0; 14764465Smckusic for (i = 0; i < FRAG; i++) 14774465Smckusic cgrp.cg_frsum[i] = 0; 14784236Smckusick inum = sblock.fs_ipg * c; 14794465Smckusic for (i = 0; i < sblock.fs_ipg; inum++, i++) { 14804465Smckusic dp = ginode(); 14814465Smckusic if (dp == NULL) 14824465Smckusic continue; 14834465Smckusic if (ALLOC) { 14844465Smckusic if (DIR) 14854465Smckusic cgrp.cg_ndir++; 14864465Smckusic setbit(cgrp.cg_iused, i); 14874465Smckusic continue; 14884465Smckusic } 14894236Smckusick cgrp.cg_nifree++; 14904236Smckusick clrbit(cgrp.cg_iused, i); 14914236Smckusick } 14924236Smckusick while (i < MAXIPG) { 14934236Smckusick clrbit(cgrp.cg_iused, i); 14944236Smckusick i++; 14954236Smckusick } 14964236Smckusick for (s = 0; s < MAXCPG; s++) 14974236Smckusick for (i = 0; i < NRPOS; i++) 14984236Smckusick cgrp.cg_b[s][i] = 0; 14994236Smckusick if (c == 0) { 15004236Smckusick dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 15014236Smckusick } 15024236Smckusick for (d = 0; d < dmin; d++) 15034236Smckusick clrbit(cgrp.cg_free, d); 15044236Smckusick for (; (d + FRAG) <= dmax - dbase; d += FRAG) { 15054236Smckusick j = 0; 15064236Smckusick for (i = 0; i < FRAG; i++) { 15074236Smckusick if (!getbmap(dbase+d+i)) { 15084236Smckusick setbit(cgrp.cg_free, d+i); 15094236Smckusick j++; 15104236Smckusick } else 15114236Smckusick clrbit(cgrp.cg_free, d+i); 15124236Smckusick } 15134236Smckusick if (j == FRAG) { 15144236Smckusick cgrp.cg_nbfree++; 15154236Smckusick s = d * NSPF; 15164236Smckusick cgrp.cg_b[s/sblock.fs_spc] 15174236Smckusick [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 15184465Smckusic } else if (j > 0) { 15194236Smckusick cgrp.cg_nffree += j; 15204465Smckusic blk = ((cgrp.cg_free[d / NBBY] >> (d % NBBY)) & 15214465Smckusic (0xff >> (NBBY - FRAG))); 15224465Smckusic fragacct(blk, cgrp.cg_frsum, 1); 15234465Smckusic } 15244236Smckusick } 15254465Smckusic for (j = d; d < dmax - dbase; d++) { 15264236Smckusick if (!getbmap(dbase+d)) { 15274236Smckusick setbit(cgrp.cg_free, d); 15284236Smckusick cgrp.cg_nffree++; 15294236Smckusick } else 15304236Smckusick clrbit(cgrp.cg_free, d); 15314236Smckusick } 15324465Smckusic if (j != d) { 15334465Smckusic blk = ((cgrp.cg_free[j / NBBY] >> (j % NBBY)) & 15344465Smckusic (0xff >> (NBBY - FRAG))); 15354465Smckusic fragacct(blk, cgrp.cg_frsum, 1); 15364465Smckusic } 15374236Smckusick for (; d < MAXBPG; d++) 15384236Smckusick clrbit(cgrp.cg_free, d); 15394236Smckusick sblock.fs_nffree += cgrp.cg_nffree; 15404236Smckusick sblock.fs_nbfree += cgrp.cg_nbfree; 15414236Smckusick cs->cs_ndir = cgrp.cg_ndir; 15424236Smckusick cs->cs_nifree = cgrp.cg_nifree; 15434236Smckusick cs->cs_nbfree = cgrp.cg_nbfree; 15444236Smckusick bwrite(&dfile, &cgrp, cgtod(c, &sblock), sblock.fs_cgsize); 15454236Smckusick } 15464236Smckusick sblock.fs_ronly = 0; 15474236Smckusick sblock.fs_fmod = 0; 15484236Smckusick sbdirty(); 15494236Smckusick } 15504236Smckusick 15514465Smckusic /* 15524465Smckusic * update the frsum fields to reflect addition or deletion 15534465Smckusic * of some frags 15544465Smckusic */ 15554465Smckusic fragacct(fragmap, fraglist, cnt) 15564470Smckusic int fragmap; 15574465Smckusic short fraglist[]; 15584465Smckusic int cnt; 15594465Smckusic { 15604465Smckusic int inblk; 15614465Smckusic register int field, subfield; 15624465Smckusic register int siz, pos; 15634465Smckusic 15644465Smckusic inblk = (int)(fragtbl[fragmap] << 1); 15654465Smckusic fragmap <<= 1; 15664465Smckusic for (siz = 1; siz < FRAG; siz++) { 15674465Smckusic if (((1 << siz) & inblk) == 0) 15684465Smckusic continue; 15694465Smckusic field = around[siz]; 15704465Smckusic subfield = inside[siz]; 15714465Smckusic for (pos = siz; pos <= FRAG; pos++) { 15724465Smckusic if ((fragmap & field) == subfield) { 15734465Smckusic fraglist[siz] += cnt; 15744465Smckusic pos += siz; 15754465Smckusic field <<= siz; 15764465Smckusic subfield <<= siz; 15774465Smckusic } 15784465Smckusic field <<= 1; 15794465Smckusic subfield <<= 1; 15804465Smckusic } 15814465Smckusic } 15824465Smckusic } 15834465Smckusic 15844236Smckusick findino(dirp) 15854236Smckusick register DIRECT *dirp; 15864236Smckusick { 15874236Smckusick register char *p1, *p2; 15884236Smckusick 15894236Smckusick if (dirp->d_ino == 0) 15904236Smckusick return (KEEPON); 15914236Smckusick for (p1 = dirp->d_name, p2 = srchname;*p2++ == *p1; p1++) { 15924236Smckusick if (*p1 == 0 || p1 == &dirp->d_name[DIRSIZ-1]) { 15934236Smckusick if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) 15944236Smckusick parentdir = dirp->d_ino; 15954236Smckusick return (STOP); 15964236Smckusick } 15974236Smckusick } 15984236Smckusick return (KEEPON); 15994236Smckusick } 16004236Smckusick 16014236Smckusick mkentry(dirp) 16024236Smckusick register DIRECT *dirp; 16034236Smckusick { 16044236Smckusick register ino_t in; 16054236Smckusick register char *p; 16064236Smckusick 16074236Smckusick if (dirp->d_ino) 16084236Smckusick return (KEEPON); 16094236Smckusick dirp->d_ino = orphan; 16104236Smckusick in = orphan; 16114236Smckusick p = &dirp->d_name[8]; 16124236Smckusick *--p = 0; 16134236Smckusick while (p > dirp->d_name) { 16144236Smckusick *--p = (in % 10) + '0'; 16154236Smckusick in /= 10; 16164236Smckusick } 16174236Smckusick *p = '#'; 16184236Smckusick return (ALTERD|STOP); 16194236Smckusick } 16204236Smckusick 16214236Smckusick chgdd(dirp) 16224236Smckusick register DIRECT *dirp; 16234236Smckusick { 16244236Smckusick if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' && 16254236Smckusick dirp->d_name[2] == 0) { 16264236Smckusick dirp->d_ino = lfdir; 16274236Smckusick return (ALTERD|STOP); 16284236Smckusick } 16294236Smckusick return (KEEPON); 16304236Smckusick } 16314236Smckusick 16324236Smckusick linkup() 16334236Smckusick { 16344236Smckusick register DINODE *dp; 16354236Smckusick register lostdir; 16364236Smckusick register ino_t pdir; 16374236Smckusick 16384236Smckusick if ((dp = ginode()) == NULL) 16394236Smckusick return (0); 16404236Smckusick lostdir = DIR; 16414236Smckusick pdir = parentdir; 16424236Smckusick pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); 16434236Smckusick pinode(); 16444236Smckusick if (preen && dp->di_size == 0) 16454236Smckusick return (0); 16464236Smckusick if (preen) 16474236Smckusick printf(" (RECONNECTED)\n"); 16484236Smckusick else 16494236Smckusick if (reply("RECONNECT") == 0) 16504236Smckusick return (0); 16514236Smckusick orphan = inum; 16524236Smckusick if (lfdir == 0) { 16534236Smckusick inum = ROOTINO; 16544236Smckusick if ((dp = ginode()) == NULL) { 16554236Smckusick inum = orphan; 16564236Smckusick return (0); 16574236Smckusick } 16584236Smckusick pfunc = findino; 16594236Smckusick srchname = lfname; 16604236Smckusick filsize = dp->di_size; 16614236Smckusick parentdir = 0; 16624236Smckusick ckinode(dp, DATA); 16634236Smckusick inum = orphan; 16644236Smckusick if ((lfdir = parentdir) == 0) { 16654236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 16664236Smckusick printf("\n\n"); 16674236Smckusick return (0); 16684236Smckusick } 16694236Smckusick } 16704236Smckusick inum = lfdir; 16714236Smckusick if ((dp = ginode()) == NULL || !DIR || getstate() != FSTATE) { 16724236Smckusick inum = orphan; 16734236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 16744236Smckusick printf("\n\n"); 16754236Smckusick return (0); 16764236Smckusick } 16774236Smckusick if (dp->di_size & BMASK) { 16784236Smckusick dp->di_size = roundup(dp->di_size, BSIZE); 16794236Smckusick inodirty(); 16804236Smckusick } 16814236Smckusick filsize = dp->di_size; 16824236Smckusick inum = orphan; 16834236Smckusick pfunc = mkentry; 16844236Smckusick if ((ckinode(dp, DATA) & ALTERD) == 0) { 16854236Smckusick pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); 16864236Smckusick printf("\n\n"); 16874236Smckusick return (0); 16884236Smckusick } 16894236Smckusick declncnt(); 16904236Smckusick if (lostdir) { 16914236Smckusick pfunc = chgdd; 16924236Smckusick dp = ginode(); 16934236Smckusick filsize = dp->di_size; 16944236Smckusick ckinode(dp, DATA); 16954236Smckusick inum = lfdir; 16964236Smckusick if ((dp = ginode()) != NULL) { 16974236Smckusick dp->di_nlink++; 16984236Smckusick inodirty(); 16994236Smckusick setlncnt(getlncnt()+1); 17004236Smckusick } 17014236Smckusick inum = orphan; 17024236Smckusick pwarn("DIR I=%u CONNECTED. ", orphan); 17034236Smckusick printf("PARENT WAS I=%u\n", pdir); 17044236Smckusick if (preen == 0) 17054236Smckusick printf("\n"); 17064236Smckusick } 17074236Smckusick return (1); 17084236Smckusick } 17094236Smckusick 17104236Smckusick bread(fcp, buf, blk, size) 17114236Smckusick daddr_t blk; 17124236Smckusick register struct filecntl *fcp; 17134236Smckusick register size; 17144236Smckusick char *buf; 17154236Smckusick { 17164236Smckusick if (lseek(fcp->rfdes, blk*FSIZE, 0) < 0) 17174236Smckusick rwerr("SEEK", blk); 17184236Smckusick else if (read(fcp->rfdes, buf, size) == size) 17194236Smckusick return (1); 17204236Smckusick rwerr("READ", blk); 17214236Smckusick return (0); 17224236Smckusick } 17234236Smckusick 17244236Smckusick bwrite(fcp, buf, blk, size) 17254236Smckusick daddr_t blk; 17264236Smckusick register struct filecntl *fcp; 17274236Smckusick register size; 17284236Smckusick char *buf; 17294236Smckusick { 17304236Smckusick 17314236Smckusick if (fcp->wfdes < 0) 17324236Smckusick return (0); 17334236Smckusick if (lseek(fcp->wfdes, blk*FSIZE, 0) < 0) 17344236Smckusick rwerr("SEEK", blk); 17354236Smckusick else if (write(fcp->wfdes, buf, size) == size) { 17364236Smckusick fcp->mod = 1; 17374236Smckusick return (1); 17384236Smckusick } 17394236Smckusick rwerr("WRITE", blk); 17404236Smckusick return (0); 17414236Smckusick } 17424236Smckusick 17434236Smckusick catch() 17444236Smckusick { 17454236Smckusick 17464236Smckusick ckfini(); 17474236Smckusick exit(12); 17484236Smckusick } 1749