1*4258Smckusic static char *sccsid = "@(#)main.c 1.4 (Berkeley) 08/29/81"; 24236Smckusick #include <stdio.h> 34236Smckusick #include <ctype.h> 44236Smckusick #include "../h/param.h" 54236Smckusick #include "../h/fs.h" 64236Smckusick #include "../h/dir.h" 74236Smckusick #include "../h/inode.h" 84236Smckusick #include "../h/stat.h" 94236Smckusick #include <fstab.h> 104236Smckusick 114236Smckusick typedef int (*SIG_TYP)(); 124236Smckusick 134236Smckusick #define NDIRECT (BSIZE/sizeof(struct direct)) 144236Smckusick #define SPERB (BSIZE/sizeof(short)) 154236Smckusick 164236Smckusick #define MAXDUP 10 /* limit on dup blks (per inode) */ 174236Smckusick #define MAXBAD 10 /* limit on bad blks (per inode) */ 184236Smckusick 194236Smckusick #define USTATE 0 /* inode not allocated */ 204236Smckusick #define FSTATE 01 /* inode is file */ 214236Smckusick #define DSTATE 02 /* inode is directory */ 224236Smckusick #define CLEAR 03 /* inode is to be cleared */ 234236Smckusick 244236Smckusick typedef struct dinode DINODE; 254236Smckusick typedef struct direct DIRECT; 264236Smckusick 274236Smckusick #define ALLOC ((dp->di_mode & IFMT) != 0) 284236Smckusick #define DIR ((dp->di_mode & IFMT) == IFDIR) 294236Smckusick #define REG ((dp->di_mode & IFMT) == IFREG) 304236Smckusick #define BLK ((dp->di_mode & IFMT) == IFBLK) 314236Smckusick #define CHR ((dp->di_mode & IFMT) == IFCHR) 324236Smckusick #define MPC ((dp->di_mode & IFMT) == IFMPC) 334236Smckusick #define MPB ((dp->di_mode & IFMT) == IFMPB) 344236Smckusick #define SPECIAL (BLK || CHR || MPC || MPB) 354236Smckusick 364236Smckusick daddr_t startib; /* blk num of first in raw area */ 374236Smckusick struct dinode ibase[MAXIPG]; 384236Smckusick int niblk; 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; 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(); 1754236Smckusick 1764236Smckusick char *devname; 1774236Smckusick 1784236Smckusick main(argc, argv) 1794236Smckusick int argc; 1804236Smckusick char *argv[]; 1814236Smckusick { 1824236Smckusick struct fstab *fsp; 1834236Smckusick int pid, passno, anygtr, sumstatus; 1844236Smckusick 1854236Smckusick sync(); 1864236Smckusick while (--argc > 0 && **++argv == '-') { 1874236Smckusick switch (*++*argv) { 1884236Smckusick 1894236Smckusick case 'p': 1904236Smckusick preen++; 1914236Smckusick break; 1924236Smckusick 1934236Smckusick case 'b': 1944236Smckusick bflag = atoi(argv[0]+1); 1954236Smckusick printf("Alternate super block location: %d\n", bflag); 1964236Smckusick break; 1974236Smckusick 1984236Smckusick case 'n': /* default no answer flag */ 1994236Smckusick case 'N': 2004236Smckusick nflag++; 2014236Smckusick yflag = 0; 2024236Smckusick break; 2034236Smckusick 2044236Smckusick case 'y': /* default yes answer flag */ 2054236Smckusick case 'Y': 2064236Smckusick yflag++; 2074236Smckusick nflag = 0; 2084236Smckusick break; 2094236Smckusick 2104236Smckusick default: 2114236Smckusick errexit("%c option?\n", **argv); 2124236Smckusick } 2134236Smckusick } 2144236Smckusick if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2154236Smckusick signal(SIGINT, catch); 2164236Smckusick if (argc) { 2174236Smckusick while (argc-- > 0) { 2184236Smckusick hotroot = 0; 2194236Smckusick check(*argv++); 2204236Smckusick } 2214236Smckusick exit(0); 2224236Smckusick } 2234236Smckusick sumstatus = 0; 2244236Smckusick passno = 1; 2254236Smckusick do { 2264236Smckusick anygtr = 0; 2274236Smckusick if (setfsent() == 0) 2284236Smckusick errexit("Can't open checklist file: %s\n", FSTAB); 2294236Smckusick while ((fsp = getfsent()) != 0) { 2304236Smckusick if (strcmp(fsp->fs_type, FSTAB_RW) && 2314236Smckusick strcmp(fsp->fs_type, FSTAB_RO)) 2324236Smckusick continue; 2334236Smckusick if (preen == 0 || 2344236Smckusick passno == 1 && fsp->fs_passno == passno) { 2354236Smckusick if (blockcheck(fsp->fs_spec) == 0 && preen) 2364236Smckusick exit(8); 2374236Smckusick } else if (fsp->fs_passno > passno) 2384236Smckusick anygtr = 1; 2394236Smckusick else if (fsp->fs_passno == passno) { 2404236Smckusick pid = fork(); 2414236Smckusick if (pid < 0) { 2424236Smckusick perror("fork"); 2434236Smckusick exit(8); 2444236Smckusick } 2454236Smckusick if (pid == 0) 2464236Smckusick if (blockcheck(fsp->fs_spec)==0) 2474236Smckusick exit(8); 2484236Smckusick else 2494236Smckusick exit(0); 2504236Smckusick } 2514236Smckusick } 2524236Smckusick if (preen) { 2534236Smckusick int status; 2544236Smckusick while (wait(&status) != -1) 2554236Smckusick sumstatus |= status; 2564236Smckusick } 2574236Smckusick passno++; 2584236Smckusick } while (anygtr); 2594236Smckusick if (sumstatus) 2604236Smckusick exit(8); 2614236Smckusick endfsent(); 2624236Smckusick exit(0); 2634236Smckusick } 2644236Smckusick 2654236Smckusick blockcheck(name) 2664236Smckusick char *name; 2674236Smckusick { 2684236Smckusick struct stat stslash, stblock, stchar; 2694236Smckusick char *raw; 2704236Smckusick int looped = 0; 2714236Smckusick 2724236Smckusick hotroot = 0; 2734236Smckusick if (stat("/", &stslash) < 0){ 2744236Smckusick error("Can't stat root\n"); 2754236Smckusick return (0); 2764236Smckusick } 2774236Smckusick retry: 2784236Smckusick if (stat(name, &stblock) < 0){ 2794236Smckusick error("Can't stat %s\n", name); 2804236Smckusick return (0); 2814236Smckusick } 2824236Smckusick if (stblock.st_mode & S_IFBLK) { 2834236Smckusick raw = rawname(name); 2844236Smckusick if (stat(raw, &stchar) < 0){ 2854236Smckusick error("Can't stat %s\n", raw); 2864236Smckusick return (0); 2874236Smckusick } 2884236Smckusick if (stchar.st_mode & S_IFCHR) { 2894236Smckusick if (stslash.st_dev == stblock.st_rdev) { 2904236Smckusick hotroot++; 2914236Smckusick raw = unrawname(name); 2924236Smckusick } 2934236Smckusick check(raw); 2944236Smckusick return (1); 2954236Smckusick } else { 2964236Smckusick error("%s is not a character device\n", raw); 2974236Smckusick return (0); 2984236Smckusick } 2994236Smckusick } else if (stblock.st_mode & S_IFCHR) { 3004236Smckusick if (looped) { 3014236Smckusick error("Can't make sense out of name %s\n", name); 3024236Smckusick return (0); 3034236Smckusick } 3044236Smckusick name = unrawname(name); 3054236Smckusick looped++; 3064236Smckusick goto retry; 3074236Smckusick } 3084236Smckusick error("Can't make sense out of name %s\n", name); 3094236Smckusick return (0); 3104236Smckusick } 3114236Smckusick 3124236Smckusick char * 3134236Smckusick unrawname(cp) 3144236Smckusick char *cp; 3154236Smckusick { 3164236Smckusick char *dp = rindex(cp, '/'); 3174236Smckusick struct stat stb; 3184236Smckusick 3194236Smckusick if (dp == 0) 3204236Smckusick return (cp); 3214236Smckusick if (stat(cp, &stb) < 0) 3224236Smckusick return (cp); 3234236Smckusick if ((stb.st_mode&S_IFMT) != S_IFCHR) 3244236Smckusick return (cp); 3254236Smckusick if (*(dp+1) != 'r') 3264236Smckusick return (cp); 3274236Smckusick strcpy(dp+1, dp+2); 3284236Smckusick return (cp); 3294236Smckusick } 3304236Smckusick 3314236Smckusick char * 3324236Smckusick rawname(cp) 3334236Smckusick char *cp; 3344236Smckusick { 3354236Smckusick static char rawbuf[32]; 3364236Smckusick char *dp = rindex(cp, '/'); 3374236Smckusick 3384236Smckusick if (dp == 0) 3394236Smckusick return (0); 3404236Smckusick *dp = 0; 3414236Smckusick strcpy(rawbuf, cp); 3424236Smckusick *dp = '/'; 3434236Smckusick strcat(rawbuf, "/r"); 3444236Smckusick strcat(rawbuf, dp+1); 3454236Smckusick return (rawbuf); 3464236Smckusick } 3474236Smckusick 3484236Smckusick check(dev) 3494236Smckusick char *dev; 3504236Smckusick { 3514236Smckusick register DINODE *dp; 3524236Smckusick register ino_t *blp; 3534236Smckusick register int i, n; 3544236Smckusick ino_t savino; 3554236Smckusick int b, c; 3564236Smckusick daddr_t d, s; 3574236Smckusick 3584236Smckusick devname = dev; 3594236Smckusick if (setup(dev) == 0) { 3604236Smckusick if (preen) 3614236Smckusick pfatal("CAN'T CHECK DEVICE."); 3624236Smckusick return; 3634236Smckusick } 3644236Smckusick /* 1 */ 3654236Smckusick if (preen==0) { 3664236Smckusick if (hotroot) 3674236Smckusick printf("** Root file system\n"); 3684236Smckusick printf("** Phase 1 - Check Blocks and Sizes\n"); 3694236Smckusick } 3704236Smckusick pfunc = pass1; 3714236Smckusick inum = 0; 3724236Smckusick n_blks += roundup(sblock.fs_ncg * sizeof (struct csum), BSIZE) 3734236Smckusick / 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 dp = ginode(); 3784236Smckusick if (dp == NULL) 3794236Smckusick continue; 3804236Smckusick n = 0; 3814236Smckusick for (i = 0; i < sblock.fs_ipg; i++, inum++, dp++) { 3824236Smckusick if (ALLOC) { 3834236Smckusick if (!isset(cgrp.cg_iused, i)) { 3844236Smckusick printf("%d bad, not used\n", inum); 3854236Smckusick inosumbad++; 3864236Smckusick } 3874236Smckusick lastino = inum; 3884236Smckusick if (ftypeok(dp) == 0) { 3894236Smckusick pfatal("UNKNOWN FILE TYPE I=%u", inum); 3904236Smckusick if (reply("CLEAR") == 1) { 3914236Smckusick zapino(dp); 3924236Smckusick inodirty(); 3934236Smckusick inosumbad++; 3944236Smckusick } 3954236Smckusick continue; 3964236Smckusick } 3974236Smckusick n_files++; 3984236Smckusick if (setlncnt(dp->di_nlink) <= 0) { 3994236Smckusick if (badlnp < &badlncnt[MAXLNCNT]) 4004236Smckusick *badlnp++ = inum; 4014236Smckusick else { 4024236Smckusick pfatal("LINK COUNT TABLE OVERFLOW"); 4034236Smckusick if (reply("CONTINUE") == 0) 4044236Smckusick errexit(""); 4054236Smckusick } 4064236Smckusick } 4074236Smckusick setstate(DIR ? DSTATE : FSTATE); 4084236Smckusick badblk = dupblk = 0; filsize = 0; maxblk = 0; 4094236Smckusick ckinode(dp, ADDR); 4104236Smckusick if (DIR && dp->di_size % sizeof(DIRECT)) { 4114236Smckusick pwarn("DIRECTORY MISALIGNED I=%u\n", 4124236Smckusick inum); 4134236Smckusick if (preen == 0) 4144236Smckusick printf("\n"); 4154236Smckusick } 4164236Smckusick } else { 4174236Smckusick n++; 4184236Smckusick if (isset(cgrp.cg_iused, i)) { 4194236Smckusick printf("%d bad, marked used\n", inum); 4204236Smckusick inosumbad++; 4214236Smckusick } 4224236Smckusick if (dp->di_mode != 0) { 4234236Smckusick pfatal("PARTIALLY ALLOCATED INODE I=%u", inum); 4244236Smckusick if (reply("CLEAR") == 1) { 4254236Smckusick zapino(dp); 4264236Smckusick inodirty(); 4274236Smckusick inosumbad++; 4284236Smckusick } 4294236Smckusick } 4304236Smckusick } 4314236Smckusick } 4324236Smckusick if (n != cgrp.cg_nifree) { 4334236Smckusick printf("cg[%d].cg_nifree is %d not %d\n", 4344236Smckusick c, cgrp.cg_nifree, n); 4354236Smckusick inosumbad++; 4364236Smckusick } 4374236Smckusick } 4384236Smckusick /* 1b */ 4394236Smckusick if (enddup != &duplist[0]) { 4404236Smckusick if (preen) 4414236Smckusick pfatal("INTERNAL ERROR: dups with -p"); 4424236Smckusick printf("** Phase 1b - Rescan For More DUPS\n"); 4434236Smckusick pfunc = pass1b; 4444236Smckusick inum = 0; 4454236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 4464236Smckusick dp = ginode(); 4474236Smckusick if (dp == NULL) 4484236Smckusick continue; 4494236Smckusick for (i = 0; i < sblock.fs_ipg; i++, inum++, dp++) 4504236Smckusick if (getstate() != USTATE && 4514236Smckusick (ckinode(dp, ADDR) & STOP)) 4524236Smckusick goto out1b; 4534236Smckusick } 4544236Smckusick } 4554236Smckusick out1b: 4564236Smckusick if (inoblk.b_dirty) { 4574236Smckusick bwrite(&dfile, (char *)ibase, startib, niblk*BSIZE); 4584236Smckusick inoblk.b_dirty = 0; 4594236Smckusick } 4604236Smckusick /* 2 */ 4614236Smckusick if (preen == 0) 4624236Smckusick printf("** Phase 2 - Check Pathnames\n"); 4634236Smckusick inum = ROOTINO; 4644236Smckusick thisname = pathp = pathname; 4654236Smckusick pfunc = pass2; 4664236Smckusick switch (getstate()) { 4674236Smckusick 4684236Smckusick case USTATE: 4694236Smckusick errexit("ROOT INODE UNALLOCATED. TERMINATING.\n"); 4704236Smckusick 4714236Smckusick case FSTATE: 4724236Smckusick pfatal("ROOT INODE NOT DIRECTORY"); 4734236Smckusick if (reply("FIX") == 0 || (dp = ginode()) == NULL) 4744236Smckusick errexit(""); 4754236Smckusick dp->di_mode &= ~IFMT; 4764236Smckusick dp->di_mode |= IFDIR; 4774236Smckusick inodirty(); 4784236Smckusick inosumbad++; 4794236Smckusick setstate(DSTATE); 4804236Smckusick /* fall into ... */ 4814236Smckusick 4824236Smckusick case DSTATE: 4834236Smckusick descend(); 4844236Smckusick break; 4854236Smckusick 4864236Smckusick case CLEAR: 4874236Smckusick pfatal("DUPS/BAD IN ROOT INODE"); 4884236Smckusick printf("\n"); 4894236Smckusick if (reply("CONTINUE") == 0) 4904236Smckusick errexit(""); 4914236Smckusick setstate(DSTATE); 4924236Smckusick descend(); 4934236Smckusick } 4944236Smckusick /* 3 */ 4954236Smckusick if (preen == 0) 4964236Smckusick printf("** Phase 3 - Check Connectivity\n"); 4974236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 4984236Smckusick if (getstate() == DSTATE) { 4994236Smckusick pfunc = findino; 5004236Smckusick srchname = ".."; 5014236Smckusick savino = inum; 5024236Smckusick do { 5034236Smckusick orphan = inum; 5044236Smckusick if ((dp = ginode()) == NULL) 5054236Smckusick break; 5064236Smckusick filsize = dp->di_size; 5074236Smckusick parentdir = 0; 5084236Smckusick ckinode(dp, DATA); 5094236Smckusick if ((inum = parentdir) == 0) 5104236Smckusick break; 5114236Smckusick } while (getstate() == DSTATE); 5124236Smckusick inum = orphan; 5134236Smckusick if (linkup() == 1) { 5144236Smckusick thisname = pathp = pathname; 5154236Smckusick *pathp++ = '?'; 5164236Smckusick pfunc = pass2; 5174236Smckusick descend(); 5184236Smckusick } 5194236Smckusick inum = savino; 5204236Smckusick } 5214236Smckusick } 5224236Smckusick /* 4 */ 5234236Smckusick if (preen == 0) 5244236Smckusick printf("** Phase 4 - Check Reference Counts\n"); 5254236Smckusick pfunc = pass4; 5264236Smckusick for (inum = ROOTINO; inum <= lastino; inum++) { 5274236Smckusick switch (getstate()) { 5284236Smckusick 5294236Smckusick case FSTATE: 5304236Smckusick if (n = getlncnt()) 5314236Smckusick adjust((short)n); 5324236Smckusick else { 5334236Smckusick for (blp = badlncnt;blp < badlnp; blp++) 5344236Smckusick if (*blp == inum) { 5354236Smckusick clri("UNREF", 1); 5364236Smckusick break; 5374236Smckusick } 5384236Smckusick } 5394236Smckusick break; 5404236Smckusick 5414236Smckusick case DSTATE: 5424236Smckusick clri("UNREF", 1); 5434236Smckusick break; 5444236Smckusick 5454236Smckusick case CLEAR: 5464236Smckusick clri("BAD/DUP", 1); 5474236Smckusick break; 5484236Smckusick } 5494236Smckusick } 5504236Smckusick if (imax - n_files != sblock.fs_nifree) { 5514236Smckusick pwarn("FREE INODE COUNT WRONG IN SUPERBLK"); 5524236Smckusick if (preen) 5534236Smckusick printf(" (FIXED)\n"); 5544236Smckusick if (preen || reply("FIX") == 1) { 5554236Smckusick sblock.fs_nifree = imax - n_files; 5564236Smckusick sbdirty(); 5574236Smckusick } 5584236Smckusick } 5594236Smckusick flush(&dfile, &fileblk); 5604236Smckusick 5614236Smckusick /* 5 */ 5624236Smckusick if (preen == 0) 5634236Smckusick printf("** Phase 5 - Check Cyl groups\n"); 5644236Smckusick copy(blkmap, freemap, (unsigned)bmapsz); 5654236Smckusick dupblk = 0; 5664236Smckusick n_index = sblock.fs_ncg * (cgdmin(0, &sblock) - cgtod(0, &sblock)); 5674236Smckusick n_index += SBLOCK; /* super-block and boot block */ 5684236Smckusick n_bad = -SBLOCK; /* ... which appear (inaccurately) bad */ 5694236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 5704236Smckusick daddr_t cbase = cgbase(c,&sblock); 5714236Smckusick short bo[MAXCPG][NRPOS]; 5724236Smckusick for (n = 0; n < sblock.fs_cpg; n++) 5734236Smckusick for (i = 0; i < NRPOS; i++) 5744236Smckusick bo[n][i] = 0; 5754236Smckusick n_bad += cgtod(c, &sblock) - cbase; 5764236Smckusick if (getblk(&cgblk, cgtod(c, &sblock), sblock.fs_cgsize) == 0) 5774236Smckusick continue; 5784236Smckusick for (b = 0; b < sblock.fs_fpg; b += FRAG) { 5794236Smckusick if (isblock(cgrp.cg_free, b/FRAG)) { 5804236Smckusick if (pass5(cbase+b, FRAG) == STOP) 5814236Smckusick goto out5; 5824236Smckusick /* this is clumsy ... */ 5834236Smckusick n_ffree -= FRAG; 5844236Smckusick n_bfree++; 5854236Smckusick s = b * NSPF; 5864236Smckusick bo[s/sblock.fs_spc] 5874236Smckusick [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 5884236Smckusick } else 5894236Smckusick for (d = 0; d < FRAG; d++) 5904236Smckusick if (isset(cgrp.cg_free, b+d)) 5914236Smckusick if (pass5(cbase+b+d,1) == STOP) 5924236Smckusick goto out5; 5934236Smckusick } 5944236Smckusick for (n = 0; n < sblock.fs_cpg; n++) 5954236Smckusick for (i = 0; i < NRPOS; i++) 5964236Smckusick if (bo[n][i] != cgrp.cg_b[n][i]) { 5974236Smckusick printf("[%d][%d] have %d calc %d\n", 5984236Smckusick n, i, cgrp.cg_b[n][i], bo[n][i]); 5994236Smckusick offsumbad++; 6004236Smckusick } 6014236Smckusick } 6024236Smckusick out5: 6034236Smckusick if (dupblk) 6044236Smckusick pwarn("%d DUP BLKS IN BIT MAPS\n", dupblk); 6054236Smckusick if (fixcg == 0) { 6064236Smckusick if ((b = n_blks+n_ffree+FRAG*n_bfree+n_index+n_bad) != fmax) { 6074236Smckusick pwarn("%ld BLK(S) MISSING\n", fmax - b); 6084236Smckusick fixcg = 1; 6094236Smckusick } else if (inosumbad+offsumbad) { 6104236Smckusick pwarn("SUMMARY INFORMATION %s%sBAD\n", 6114236Smckusick inosumbad ? "(INODE FREE) " : "", 6124236Smckusick offsumbad ? "(BLOCK OFFSETS) " : ""); 6134236Smckusick fixcg = 1; 6144236Smckusick } else if (n_ffree != sblock.fs_nffree || 6154236Smckusick n_bfree != sblock.fs_nbfree) { 6164236Smckusick pwarn("FREE BLK COUNT(S) WRONG IN SUPERBLK"); 6174236Smckusick if (preen) 6184236Smckusick printf(" (FIXED)\n"); 6194236Smckusick if (preen || reply("FIX") == 1) { 6204236Smckusick sblock.fs_nffree = n_ffree; 6214236Smckusick sblock.fs_nbfree = n_bfree; 6224236Smckusick sbdirty(); 6234236Smckusick } 6244236Smckusick } 6254236Smckusick } 6264236Smckusick if (fixcg) { 6274236Smckusick pwarn("BAD CYLINDER GROUPS"); 6284236Smckusick if (preen) 6294236Smckusick printf(" (SALVAGED)\n"); 6304236Smckusick else if (reply("SALVAGE") == 0) 6314236Smckusick fixcg = 0; 6324236Smckusick } 6334236Smckusick 6344236Smckusick if (fixcg) { 6354236Smckusick if (preen == 0) 6364236Smckusick printf("** Phase 6 - Salvage Cylinder Groups\n"); 6374236Smckusick sblock.fs_cs = (struct csum *) 6384236Smckusick calloc(sblock.fs_ncg, roundup(sizeof (struct csum), BSIZE)); 6394236Smckusick makecg(); 6404236Smckusick for (i = 0; i < cssize(&sblock); i += BSIZE) 6414236Smckusick bwrite(&dfile, ((char *)sblock.fs_cs) + i, 6424236Smckusick csaddr(&sblock) + i / BSIZE, BSIZE); 6434236Smckusick n_ffree = sblock.fs_nffree; 6444236Smckusick n_bfree = sblock.fs_nbfree; 6454236Smckusick } 6464236Smckusick 6474236Smckusick pwarn("%d files, %d used, %d free (%d frags, %d blocks)\n", 6484236Smckusick n_files, n_blks, n_ffree + FRAG * n_bfree, n_ffree, n_bfree); 6494236Smckusick if (dfile.mod) { 6504236Smckusick time(&sblock.fs_time); 6514236Smckusick sbdirty(); 6524236Smckusick } 6534236Smckusick ckfini(); 6544236Smckusick sync(); 6554236Smckusick if (dfile.mod && hotroot) { 6564236Smckusick printf("\n***** BOOT UNIX (NO SYNC!) *****\n"); 6574236Smckusick exit(4); 6584236Smckusick } 6594236Smckusick if (dfile.mod && preen == 0) 6604236Smckusick printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 6614236Smckusick free(blkmap); 6624236Smckusick free(freemap); 6634236Smckusick free(statemap); 6644236Smckusick free(lncntp); 6654236Smckusick } 6664236Smckusick 6674236Smckusick /* VARARGS1 */ 6684236Smckusick error(s1, s2, s3, s4) 6694236Smckusick char *s1; 6704236Smckusick { 6714236Smckusick 6724236Smckusick printf(s1, s2, s3, s4); 6734236Smckusick } 6744236Smckusick 6754236Smckusick /* VARARGS1 */ 6764236Smckusick errexit(s1, s2, s3, s4) 6774236Smckusick char *s1; 6784236Smckusick { 6794236Smckusick error(s1, s2, s3, s4); 6804236Smckusick exit(8); 6814236Smckusick } 6824236Smckusick 6834236Smckusick /* 6844236Smckusick * An inconsistency occured which shouldn't during normal operations. 6854236Smckusick * Die if preening, otw just printf. 6864236Smckusick */ 6874236Smckusick /* VARARGS1 */ 6884236Smckusick pfatal(s, a1, a2, a3) 6894236Smckusick char *s; 6904236Smckusick { 6914236Smckusick 6924236Smckusick if (preen) { 6934236Smckusick printf("%s: ", devname); 6944236Smckusick printf(s, a1, a2, a3); 6954236Smckusick printf("\n"); 6964236Smckusick preendie(); 6974236Smckusick } 6984236Smckusick printf(s, a1, a2, a3); 6994236Smckusick } 7004236Smckusick 7014236Smckusick preendie() 7024236Smckusick { 7034236Smckusick 7044236Smckusick printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); 7054236Smckusick exit(8); 7064236Smckusick } 7074236Smckusick 7084236Smckusick /* 7094236Smckusick * Pwarn is like printf when not preening, 7104236Smckusick * or a warning (preceded by filename) when preening. 7114236Smckusick */ 7124236Smckusick /* VARARGS1 */ 7134236Smckusick pwarn(s, a1, a2, a3, a4, a5) 7144236Smckusick char *s; 7154236Smckusick { 7164236Smckusick 7174236Smckusick if (preen) 7184236Smckusick printf("%s: ", devname); 7194236Smckusick printf(s, a1, a2, a3, a4, a5); 7204236Smckusick } 7214236Smckusick 7224236Smckusick ckinode(dp, flg) 7234236Smckusick DINODE *dp; 7244236Smckusick register flg; 7254236Smckusick { 7264236Smckusick register daddr_t *ap; 7274236Smckusick register ret; 7284236Smckusick int (*func)(), n, ndb, size; 7294236Smckusick 7304236Smckusick if (SPECIAL) 7314236Smckusick return (KEEPON); 7324236Smckusick func = (flg == ADDR) ? pfunc : dirscan; 7334236Smckusick ndb = howmany(dp->di_size, BSIZE); 7344252Smckusic for (ap = dp->di_db; ap < &dp->di_db[NDADDR]; ap++) { 7354236Smckusick if (--ndb == 0 && (dp->di_size&BMASK)) 7364236Smckusick size = howmany(dp->di_size&BMASK, FSIZE); 7374236Smckusick else 7384236Smckusick size = FRAG; 7394236Smckusick if (*ap && (ret = (*func)(*ap, size)) & STOP) 7404236Smckusick return (ret); 7414236Smckusick } 7424236Smckusick for (n = 1; n <= 2; n++) { 7434236Smckusick if (*ap && (ret = iblock(*ap, n, flg, dp->di_size)) & STOP) 7444236Smckusick return (ret); 7454236Smckusick ap++; 7464236Smckusick } 7474236Smckusick return (KEEPON); 7484236Smckusick } 7494236Smckusick 7504236Smckusick iblock(blk, ilevel, flg, isize) 7514236Smckusick daddr_t blk; 7524236Smckusick register ilevel; 7534236Smckusick int isize; 7544236Smckusick { 7554236Smckusick register daddr_t *ap; 7564236Smckusick register daddr_t *aplim; 7574236Smckusick register n; 7584236Smckusick int (*func)(), nif; 7594236Smckusick BUFAREA ib; 7604236Smckusick 7614236Smckusick nif = howmany(isize - NDADDR*BSIZE, NINDIR / FRAG * BSIZE); 7624236Smckusick if (nif > FRAG || ilevel > 1) 7634236Smckusick nif = FRAG; 7644236Smckusick if (flg == ADDR) { 7654236Smckusick func = pfunc; 7664236Smckusick if (((n = (*func)(blk, nif)) & KEEPON) == 0) 7674236Smckusick return (n); 7684236Smckusick } else 7694236Smckusick func = dirscan; 7704236Smckusick if (outrange(blk)) /* protect thyself */ 7714236Smckusick return (SKIP); 7724236Smckusick initbarea(&ib); 7734236Smckusick if (getblk(&ib, blk, nif * FSIZE) == NULL) 7744236Smckusick return (SKIP); 7754236Smckusick ilevel--; 7764236Smckusick aplim = & ib.b_un.b_indir[NINDIR*nif/FRAG]; 7774236Smckusick for (ap = ib.b_un.b_indir; ap < aplim; ap++) 7784236Smckusick if (*ap) { 7794236Smckusick if (ilevel > 0) 7804236Smckusick n = iblock(*ap, ilevel, flg, BSIZE); 7814236Smckusick else 7824236Smckusick n = (*func)(*ap, BSIZE); 7834236Smckusick if (n & STOP) 7844236Smckusick return (n); 7854236Smckusick } 7864236Smckusick return (KEEPON); 7874236Smckusick } 7884236Smckusick 7894236Smckusick pass1(blk, size) 7904236Smckusick daddr_t blk; 7914236Smckusick int size; 7924236Smckusick { 7934236Smckusick register daddr_t *dlp; 7944236Smckusick int res = KEEPON; 7954236Smckusick 7964236Smckusick for (; size > 0; blk++, size--) { 7974236Smckusick if (outrange(blk)) { 7984236Smckusick blkerr("BAD", blk); 7994236Smckusick if (++badblk >= MAXBAD) { 8004236Smckusick printf("EXCESSIVE BAD BLKS I=%u", inum); 8014236Smckusick if (reply("CONTINUE") == 0) 8024236Smckusick errexit(""); 8034236Smckusick return (STOP); 8044236Smckusick } 8054236Smckusick res = SKIP; 8064236Smckusick } else if (getbmap(blk)) { 8074236Smckusick blkerr("DUP", blk); 8084236Smckusick if (++dupblk >= MAXDUP) { 8094236Smckusick printf("EXCESSIVE DUP BLKS I=%u", inum); 8104236Smckusick if (reply("CONTINUE") == 0) 8114236Smckusick errexit(""); 8124236Smckusick return (STOP); 8134236Smckusick } 8144236Smckusick if (enddup >= &duplist[DUPTBLSIZE]) { 8154236Smckusick printf("DUP TABLE OVERFLOW."); 8164236Smckusick if (reply("CONTINUE") == 0) 8174236Smckusick errexit(""); 8184236Smckusick return (STOP); 8194236Smckusick } 8204236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8214236Smckusick if (*dlp == blk) { 8224236Smckusick *enddup++ = blk; 8234236Smckusick break; 8244236Smckusick } 8254236Smckusick if (dlp >= muldup) { 8264236Smckusick *enddup++ = *muldup; 8274236Smckusick *muldup++ = blk; 8284236Smckusick } 8294236Smckusick } else { 8304236Smckusick n_blks++; 8314236Smckusick setbmap(blk); 8324236Smckusick } 8334236Smckusick filsize++; 8344236Smckusick } 8354236Smckusick return (res); 8364236Smckusick } 8374236Smckusick 8384236Smckusick pass1b(blk, size) 8394236Smckusick daddr_t blk; 8404236Smckusick int size; 8414236Smckusick { 8424236Smckusick register daddr_t *dlp; 8434236Smckusick int res = KEEPON; 8444236Smckusick 8454236Smckusick for (; size > 0; blk++, size--) { 8464236Smckusick if (outrange(blk)) 8474236Smckusick res = SKIP; 8484236Smckusick for (dlp = duplist; dlp < muldup; dlp++) 8494236Smckusick if (*dlp == blk) { 8504236Smckusick blkerr("DUP", blk); 8514236Smckusick *dlp = *--muldup; 8524236Smckusick *muldup = blk; 8534236Smckusick if (muldup == duplist) 8544236Smckusick return (STOP); 8554236Smckusick } 8564236Smckusick } 8574236Smckusick return (res); 8584236Smckusick } 8594236Smckusick 8604236Smckusick pass2(dirp) 8614236Smckusick register DIRECT *dirp; 8624236Smckusick { 8634236Smckusick register char *p; 8644236Smckusick register n; 8654236Smckusick DINODE *dp; 8664236Smckusick 8674236Smckusick if ((inum = dirp->d_ino) == 0) 8684236Smckusick return (KEEPON); 8694236Smckusick thisname = pathp; 8704236Smckusick for (p = dirp->d_name; p < &dirp->d_name[DIRSIZ]; ) 8714236Smckusick if ((*pathp++ = *p++) == 0) { 8724236Smckusick --pathp; 8734236Smckusick break; 8744236Smckusick } 8754236Smckusick *pathp = 0; 8764236Smckusick n = 0; 8774236Smckusick if (inum > imax || inum < ROOTINO) 8784236Smckusick n = direrr("I OUT OF RANGE"); 8794236Smckusick else { 8804236Smckusick again: 8814236Smckusick switch (getstate()) { 8824236Smckusick case USTATE: 8834236Smckusick n = direrr("UNALLOCATED"); 8844236Smckusick break; 8854236Smckusick 8864236Smckusick case CLEAR: 8874236Smckusick if ((n = direrr("DUP/BAD")) == 1) 8884236Smckusick break; 8894236Smckusick if ((dp = ginode()) == NULL) 8904236Smckusick break; 8914236Smckusick setstate(DIR ? DSTATE : FSTATE); 8924236Smckusick goto again; 8934236Smckusick 8944236Smckusick case FSTATE: 8954236Smckusick declncnt(); 8964236Smckusick break; 8974236Smckusick 8984236Smckusick case DSTATE: 8994236Smckusick declncnt(); 9004236Smckusick descend(); 9014236Smckusick break; 9024236Smckusick } 9034236Smckusick } 9044236Smckusick pathp = thisname; 9054236Smckusick if (n == 0) 9064236Smckusick return (KEEPON); 9074236Smckusick dirp->d_ino = 0; 9084236Smckusick return (KEEPON|ALTERD); 9094236Smckusick } 9104236Smckusick 9114236Smckusick pass4(blk, size) 9124236Smckusick daddr_t blk; 9134236Smckusick { 9144236Smckusick register daddr_t *dlp; 9154236Smckusick int res = KEEPON; 9164236Smckusick 9174236Smckusick for (; size > 0; blk++, size--) { 9184236Smckusick if (outrange(blk)) 9194236Smckusick res = SKIP; 9204236Smckusick else if (getbmap(blk)) { 9214236Smckusick for (dlp = duplist; dlp < enddup; dlp++) 9224236Smckusick if (*dlp == blk) { 9234236Smckusick *dlp = *--enddup; 9244236Smckusick return (KEEPON); 9254236Smckusick } 9264236Smckusick clrbmap(blk); 9274236Smckusick n_blks--; 9284236Smckusick } 9294236Smckusick } 9304236Smckusick return (res); 9314236Smckusick } 9324236Smckusick 9334236Smckusick pass5(blk, size) 9344236Smckusick daddr_t blk; 9354236Smckusick int size; 9364236Smckusick { 9374236Smckusick int res = KEEPON; 9384236Smckusick 9394236Smckusick for (; size > 0; blk++, size--) { 9404236Smckusick if (outrange(blk)) { 9414236Smckusick fixcg = 1; 9424236Smckusick if (preen) 9434236Smckusick pfatal("BAD BLOCKS IN BIT MAPS."); 9444236Smckusick if (++badblk >= MAXBAD) { 9454236Smckusick printf("EXCESSIVE BAD BLKS IN BIT MAPS."); 9464236Smckusick if (reply("CONTINUE") == 0) 9474236Smckusick errexit(""); 9484236Smckusick return (STOP); 9494236Smckusick } 9504236Smckusick } else if (getfmap(blk)) { 9514236Smckusick fixcg = 1; 9524236Smckusick if (++dupblk >= DUPTBLSIZE) { 9534236Smckusick printf("EXCESSIVE DUP BLKS IN BIT MAPS."); 9544236Smckusick if (reply("CONTINUE") == 0) 9554236Smckusick errexit(""); 9564236Smckusick return (STOP); 9574236Smckusick } 9584236Smckusick } else { 9594236Smckusick n_ffree++; 9604236Smckusick setfmap(blk); 9614236Smckusick } 9624236Smckusick } 9634236Smckusick return (res); 9644236Smckusick } 9654236Smckusick 9664236Smckusick outrange(blk) 9674236Smckusick daddr_t blk; 9684236Smckusick { 9694236Smckusick register int c; 9704236Smckusick 9714236Smckusick c = dtog(blk, &sblock); 9724236Smckusick if (blk >= fmax || blk < cgdmin(c, &sblock)) 9734236Smckusick return (1); 9744236Smckusick return (0); 9754236Smckusick } 9764236Smckusick 9774236Smckusick blkerr(s, blk) 9784236Smckusick daddr_t blk; 9794236Smckusick char *s; 9804236Smckusick { 9814236Smckusick pfatal("%ld %s I=%u", blk, s, inum); 9824236Smckusick printf("\n"); 9834236Smckusick setstate(CLEAR); /* mark for possible clearing */ 9844236Smckusick } 9854236Smckusick 9864236Smckusick descend() 9874236Smckusick { 9884236Smckusick register DINODE *dp; 9894236Smckusick register char *savname; 9904236Smckusick off_t savsize; 9914236Smckusick 9924236Smckusick setstate(FSTATE); 9934236Smckusick if ((dp = ginode()) == NULL) 9944236Smckusick return; 9954236Smckusick savname = thisname; 9964236Smckusick *pathp++ = '/'; 9974236Smckusick savsize = filsize; 9984236Smckusick filsize = dp->di_size; 9994236Smckusick ckinode(dp, DATA); 10004236Smckusick thisname = savname; 10014236Smckusick *--pathp = 0; 10024236Smckusick filsize = savsize; 10034236Smckusick } 10044236Smckusick 10054236Smckusick dirscan(blk, nf) 10064236Smckusick daddr_t blk; 10074236Smckusick int nf; 10084236Smckusick { 10094236Smckusick register DIRECT *dirp; 10104236Smckusick register DIRECT *edirp; 10114236Smckusick register char *p1, *p2; 10124236Smckusick register n; 10134236Smckusick DIRECT direntry; 10144236Smckusick 10154236Smckusick if (outrange(blk)) { 10164236Smckusick filsize -= BSIZE; 10174236Smckusick return (SKIP); 10184236Smckusick } 10194236Smckusick edirp = &dirblk.b_dir[NDIRECT*nf/FRAG]; 10204236Smckusick for (dirp = dirblk.b_dir; dirp < edirp && 10214236Smckusick filsize > 0; dirp++, filsize -= sizeof(DIRECT)) { 10224236Smckusick if (getblk(&fileblk, blk, nf * FSIZE) == NULL) { 10234236Smckusick filsize -= (&dirblk.b_dir[NDIRECT]-dirp)*sizeof(DIRECT); 10244236Smckusick return (SKIP); 10254236Smckusick } 10264236Smckusick p1 = &dirp->d_name[DIRSIZ]; 10274236Smckusick p2 = &direntry.d_name[DIRSIZ]; 10284236Smckusick while (p1 > (char *)dirp) 10294236Smckusick *--p2 = *--p1; 10304236Smckusick if ((n = (*pfunc)(&direntry)) & ALTERD) { 10314236Smckusick if (getblk(&fileblk, blk, nf * FSIZE) != NULL) { 10324236Smckusick p1 = &dirp->d_name[DIRSIZ]; 10334236Smckusick p2 = &direntry.d_name[DIRSIZ]; 10344236Smckusick while (p1 > (char *)dirp) 10354236Smckusick *--p1 = *--p2; 10364236Smckusick sbdirty(); 10374236Smckusick } else 10384236Smckusick n &= ~ALTERD; 10394236Smckusick } 10404236Smckusick if (n & STOP) 10414236Smckusick return (n); 10424236Smckusick } 10434236Smckusick return (filsize > 0 ? KEEPON : STOP); 10444236Smckusick } 10454236Smckusick 10464236Smckusick direrr(s) 10474236Smckusick char *s; 10484236Smckusick { 10494236Smckusick register DINODE *dp; 10504236Smckusick 10514236Smckusick pwarn("%s ", s); 10524236Smckusick pinode(); 10534236Smckusick printf("\n"); 10544236Smckusick if ((dp = ginode()) != NULL && ftypeok(dp)) 10554236Smckusick pfatal("%s=%s", DIR?"DIR":"FILE", pathname); 10564236Smckusick else 10574236Smckusick pfatal("NAME=%s", pathname); 10584236Smckusick return (reply("REMOVE")); 10594236Smckusick } 10604236Smckusick 10614236Smckusick adjust(lcnt) 10624236Smckusick register short lcnt; 10634236Smckusick { 10644236Smckusick register DINODE *dp; 10654236Smckusick 10664236Smckusick if ((dp = ginode()) == NULL) 10674236Smckusick return; 10684236Smckusick if (dp->di_nlink == lcnt) { 10694236Smckusick if (linkup() == 0) 10704236Smckusick clri("UNREF", 0); 10714236Smckusick } 10724236Smckusick else { 10734236Smckusick pwarn("LINK COUNT %s", 10744236Smckusick (lfdir==inum)?lfname:(DIR?"DIR":"FILE")); 10754236Smckusick pinode(); 10764236Smckusick printf(" COUNT %d SHOULD BE %d", 10774236Smckusick dp->di_nlink, dp->di_nlink-lcnt); 10784236Smckusick if (preen) { 10794236Smckusick if (lcnt < 0) { 10804236Smckusick printf("\n"); 10814236Smckusick preendie(); 10824236Smckusick } 10834236Smckusick printf(" (ADJUSTED)\n"); 10844236Smckusick } 10854236Smckusick if (preen || reply("ADJUST") == 1) { 10864236Smckusick dp->di_nlink -= lcnt; 10874236Smckusick inodirty(); 10884236Smckusick } 10894236Smckusick } 10904236Smckusick } 10914236Smckusick 10924236Smckusick clri(s, flg) 10934236Smckusick char *s; 10944236Smckusick { 10954236Smckusick register DINODE *dp; 10964236Smckusick 10974236Smckusick if ((dp = ginode()) == NULL) 10984236Smckusick return; 10994236Smckusick if (flg == 1) { 11004236Smckusick pwarn("%s %s", s, DIR?"DIR":"FILE"); 11014236Smckusick pinode(); 11024236Smckusick } 11034236Smckusick if (preen || reply("CLEAR") == 1) { 11044236Smckusick if (preen) 11054236Smckusick printf(" (CLEARED)\n"); 11064236Smckusick n_files--; 11074236Smckusick pfunc = pass4; 11084236Smckusick ckinode(dp, ADDR); 11094236Smckusick zapino(dp); 11104236Smckusick inodirty(); 11114236Smckusick inosumbad++; 11124236Smckusick } 11134236Smckusick } 11144236Smckusick 11154236Smckusick setup(dev) 11164236Smckusick char *dev; 11174236Smckusick { 11184236Smckusick dev_t rootdev; 11194236Smckusick struct stat statb; 11204236Smckusick int super = bflag ? bflag : SBLOCK; 11214236Smckusick 11224236Smckusick bflag = 0; 11234236Smckusick if (stat("/", &statb) < 0) 11244236Smckusick errexit("Can't stat root\n"); 11254236Smckusick rootdev = statb.st_dev; 11264236Smckusick if (stat(dev, &statb) < 0) { 11274236Smckusick error("Can't stat %s\n", dev); 11284236Smckusick return (0); 11294236Smckusick } 11304236Smckusick rawflg = 0; 11314236Smckusick if ((statb.st_mode & S_IFMT) == S_IFBLK) 11324236Smckusick ; 11334236Smckusick else if ((statb.st_mode & S_IFMT) == S_IFCHR) 11344236Smckusick rawflg++; 11354236Smckusick else { 11364236Smckusick if (reply("file is not a block or character device; OK") == 0) 11374236Smckusick return (0); 11384236Smckusick } 11394236Smckusick if (rootdev == statb.st_rdev) 11404236Smckusick hotroot++; 11414236Smckusick if ((dfile.rfdes = open(dev, 0)) < 0) { 11424236Smckusick error("Can't open %s\n", dev); 11434236Smckusick return (0); 11444236Smckusick } 11454236Smckusick if (preen == 0) 11464236Smckusick printf("** %s", dev); 11474236Smckusick if (nflag || (dfile.wfdes = open(dev, 1)) < 0) { 11484236Smckusick dfile.wfdes = -1; 11494236Smckusick if (preen) 11504236Smckusick pfatal("NO WRITE ACCESS"); 11514236Smckusick printf(" (NO WRITE)"); 11524236Smckusick } 11534236Smckusick if (preen == 0) 11544236Smckusick printf("\n"); 11554236Smckusick fixcg = 0; inosumbad = 0; offsumbad = 0; 11564236Smckusick dfile.mod = 0; 11574236Smckusick n_files = n_blks = n_ffree = n_bfree = 0; 11584236Smckusick muldup = enddup = &duplist[0]; 11594236Smckusick badlnp = &badlncnt[0]; 11604236Smckusick lfdir = 0; 11614236Smckusick rplyflag = 0; 11624236Smckusick initbarea(&sblk); 11634236Smckusick initbarea(&fileblk); 11644236Smckusick initbarea(&inoblk); 11654236Smckusick initbarea(&cgblk); 11664236Smckusick if (getblk(&sblk, super, BSIZE) == NULL) { 11674236Smckusick ckfini(); 11684236Smckusick return (0); 11694236Smckusick } 11704236Smckusick sblk.b_bno = SBLOCK; 11714236Smckusick if (sblock.fs_magic != FS_MAGIC) 11724236Smckusick { badsb("MAGIC NUMBER WRONG"); return (0); } 11734236Smckusick if (sblock.fs_ncg < 1) 11744236Smckusick { badsb("NCG OUT OF RANGE"); return (0); } 11754236Smckusick if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG) 11764236Smckusick { badsb("CPG OUT OF RANGE"); return (0); } 11774236Smckusick if (sblock.fs_nsect < 1) 11784236Smckusick { badsb("NSECT < 1"); return (0); } 11794236Smckusick if (sblock.fs_ntrak < 1) 11804236Smckusick { badsb("NTRAK < 1"); return (0); } 11814236Smckusick if (sblock.fs_ipg*sblock.fs_ncg > 65535 || sblock.fs_ipg%INOPB) 11824236Smckusick { badsb("TOO MANY INODES IMPLIED"); return (0); } 11834236Smckusick if (sblock.fs_ipg/INOPF+IBLOCK >= 11844236Smckusick sblock.fs_cpg*sblock.fs_nsect*sblock.fs_ntrak/NSPF) 11854236Smckusick { badsb("IMPLIES MORE INODE THAN DATA BLOCKS"); return (0); } 11864236Smckusick /* THE FOLLOWING COULD BE CHECKED MORE CLOSELY... */ 11874236Smckusick if ((sblock.fs_ncg + 1) * sblock.fs_cpg < sblock.fs_ncyl || 11884236Smckusick (sblock.fs_ncg - 1) * sblock.fs_cpg > sblock.fs_ncyl) 11894236Smckusick { badsb("NCYL DOES NOT JIVE WITH NCG*CPG"); return (0); } 11904236Smckusick if (sblock.fs_fpg != sblock.fs_cpg * sblock.fs_spc / NSPF) 11914236Smckusick { badsb("FPG DOES NOT JIVE WITH CPG & SPC"); return (0); } 11924236Smckusick if (sblock.fs_size <= 11934236Smckusick (sblock.fs_ncg-1)*sblock.fs_fpg+IBLOCK+sblock.fs_ipg/INOPF) 11944236Smckusick { badsb("SIZE PREPOSTEROUSLY SMALL"); return (0); } 11954236Smckusick if (sblock.fs_size*NSPF > 11964236Smckusick (sblock.fs_ncg+2)*sblock.fs_cpg*sblock.fs_spc) 11974236Smckusick { badsb("SIZE PREPOSTEROUSLY LARGE"); return (0); } 11984236Smckusick /* rest we COULD repair... */ 11994236Smckusick if (sblock.fs_sblkno != SBLOCK) 12004236Smckusick { badsb("BLKNO CORRUPTED"); return (0); } 12014236Smckusick if (sblock.fs_spc != sblock.fs_nsect * sblock.fs_ntrak) 12024236Smckusick { badsb("SPC DOES NOT JIVE w/NTRAK*NSECT"); return (0); } 12034236Smckusick if (sblock.fs_cgsize != cgsize(&sblock)) 12044236Smckusick { badsb("CGSIZE INCORRECT"); return (0); } 12054236Smckusick if (sblock.fs_cssize != cssize(&sblock)) 12064236Smckusick { badsb("CSSIZE INCORRECT"); return (0); } 12074236Smckusick fmax = sblock.fs_size; 12084236Smckusick imax = sblock.fs_ncg * sblock.fs_ipg; 12094236Smckusick 12104236Smckusick bmapsz = roundup(howmany(fmax, NBBY), sizeof(short)); 12114236Smckusick blkmap = (char *)calloc(bmapsz, sizeof (char)); 12124236Smckusick freemap = (char *)calloc(bmapsz, sizeof (char)); 12134236Smckusick statemap = (char *)calloc(imax+1, sizeof(char)); 12144236Smckusick lncntp = (short *)calloc(imax+1, sizeof(short)); 12154236Smckusick 12164236Smckusick niblk = sblock.fs_ipg / INOPB; 12174236Smckusick startib = fmax; 12184236Smckusick return (1); 12194236Smckusick 12204236Smckusick badsb: 12214236Smckusick ckfini(); 12224236Smckusick return (0); 12234236Smckusick } 12244236Smckusick 12254236Smckusick badsb(s) 12264236Smckusick char *s; 12274236Smckusick { 12284236Smckusick 12294236Smckusick if (preen) 12304236Smckusick printf("%s: ", devname); 12314236Smckusick printf("BAD SUPER BLOCK: %s\n", s); 12324236Smckusick pwarn("USE -b OPTION TO FSCK TO SPECIFY LOCATION OF AN ALTERNATE\n"); 12334236Smckusick pfatal("SUPER-BLOCK TO SUPPLY NEEDED INFORMATION; SEE fsck(8).\n"); 12344236Smckusick } 12354236Smckusick 12364236Smckusick DINODE * 12374236Smckusick ginode() 12384236Smckusick { 12394236Smckusick daddr_t iblk; 12404236Smckusick 12414236Smckusick if (inum > imax) 12424236Smckusick return (NULL); 12434236Smckusick iblk = itod(inum, &sblock); 12444236Smckusick if (iblk < startib || iblk >= startib+niblk) { 12454236Smckusick if (inoblk.b_dirty) 12464236Smckusick bwrite(&dfile, (char *)ibase, startib, niblk*BSIZE); 12474236Smckusick inoblk.b_dirty = 0; 12484236Smckusick startib = cgimin(inum/sblock.fs_ipg, &sblock); 12494236Smckusick if (bread(&dfile, (char *)ibase, iblk, niblk*BSIZE) == 0) { 12504236Smckusick startib = fmax; 12514236Smckusick return (NULL); 12524236Smckusick } 12534236Smckusick startib = iblk; 12544236Smckusick } 12554236Smckusick return (&ibase[(iblk - startib)*INOPB + itoo(inum)]); 12564236Smckusick } 12574236Smckusick 12584236Smckusick ftypeok(dp) 12594236Smckusick DINODE *dp; 12604236Smckusick { 12614236Smckusick switch (dp->di_mode & IFMT) { 12624236Smckusick 12634236Smckusick case IFDIR: 12644236Smckusick case IFREG: 12654236Smckusick case IFBLK: 12664236Smckusick case IFCHR: 12674236Smckusick case IFMPC: 12684236Smckusick case IFMPB: 12694236Smckusick return (1); 12704236Smckusick 12714236Smckusick default: 12724236Smckusick return (0); 12734236Smckusick } 12744236Smckusick } 12754236Smckusick 12764236Smckusick reply(s) 12774236Smckusick char *s; 12784236Smckusick { 12794236Smckusick char line[80]; 12804236Smckusick 12814236Smckusick if (preen) 12824236Smckusick pfatal("INTERNAL ERROR: GOT TO reply()"); 12834236Smckusick rplyflag = 1; 12844236Smckusick printf("\n%s? ", s); 12854236Smckusick if (nflag || dfile.wfdes < 0) { 12864236Smckusick printf(" no\n\n"); 12874236Smckusick return (0); 12884236Smckusick } 12894236Smckusick if (yflag) { 12904236Smckusick printf(" yes\n\n"); 12914236Smckusick return (1); 12924236Smckusick } 12934236Smckusick if (getline(stdin, line, sizeof(line)) == EOF) 12944236Smckusick errexit("\n"); 12954236Smckusick printf("\n"); 12964236Smckusick if (line[0] == 'y' || line[0] == 'Y') 12974236Smckusick return (1); 12984236Smckusick else 12994236Smckusick return (0); 13004236Smckusick } 13014236Smckusick 13024236Smckusick getline(fp, loc, maxlen) 13034236Smckusick FILE *fp; 13044236Smckusick char *loc; 13054236Smckusick { 13064236Smckusick register n; 13074236Smckusick register char *p, *lastloc; 13084236Smckusick 13094236Smckusick p = loc; 13104236Smckusick lastloc = &p[maxlen-1]; 13114236Smckusick while ((n = getc(fp)) != '\n') { 13124236Smckusick if (n == EOF) 13134236Smckusick return (EOF); 13144236Smckusick if (!isspace(n) && p < lastloc) 13154236Smckusick *p++ = n; 13164236Smckusick } 13174236Smckusick *p = 0; 13184236Smckusick return (p - loc); 13194236Smckusick } 13204236Smckusick 13214236Smckusick BUFAREA * 13224236Smckusick getblk(bp, blk, size) 13234236Smckusick daddr_t blk; 13244236Smckusick register BUFAREA *bp; 13254236Smckusick int size; 13264236Smckusick { 13274236Smckusick register struct filecntl *fcp; 13284236Smckusick 13294236Smckusick fcp = &dfile; 13304236Smckusick if (bp->b_bno == blk) 13314236Smckusick return (bp); 13324236Smckusick flush(fcp, bp); 13334236Smckusick if (bread(fcp, bp->b_un.b_buf, blk, size) != 0) { 13344236Smckusick bp->b_bno = blk; 13354236Smckusick bp->b_size = size; 13364236Smckusick return (bp); 13374236Smckusick } 13384236Smckusick bp->b_bno = (daddr_t)-1; 13394236Smckusick return (NULL); 13404236Smckusick } 13414236Smckusick 13424236Smckusick flush(fcp, bp) 13434236Smckusick struct filecntl *fcp; 13444236Smckusick register BUFAREA *bp; 13454236Smckusick { 13464236Smckusick 13474236Smckusick if (bp->b_dirty) 13484236Smckusick bwrite(fcp, bp->b_un.b_buf, bp->b_bno, bp->b_size); 13494236Smckusick bp->b_dirty = 0; 13504236Smckusick } 13514236Smckusick 13524236Smckusick rwerr(s, blk) 13534236Smckusick char *s; 13544236Smckusick daddr_t blk; 13554236Smckusick { 13564236Smckusick 13574236Smckusick if (preen == 0) 13584236Smckusick printf("\n"); 13594236Smckusick pfatal("CANNOT %s: BLK %ld", s, blk); 13604236Smckusick if (reply("CONTINUE") == 0) 13614236Smckusick errexit("Program terminated\n"); 13624236Smckusick } 13634236Smckusick 13644236Smckusick ckfini() 13654236Smckusick { 13664236Smckusick 13674236Smckusick flush(&dfile, &fileblk); 13684236Smckusick flush(&dfile, &sblk); 13694236Smckusick flush(&dfile, &inoblk); 13704236Smckusick close(dfile.rfdes); 13714236Smckusick close(dfile.wfdes); 13724236Smckusick } 13734236Smckusick 13744236Smckusick pinode() 13754236Smckusick { 13764236Smckusick register DINODE *dp; 13774236Smckusick register char *p; 13784236Smckusick char uidbuf[200]; 13794236Smckusick char *ctime(); 13804236Smckusick 13814236Smckusick printf(" I=%u ", inum); 13824236Smckusick if ((dp = ginode()) == NULL) 13834236Smckusick return; 13844236Smckusick printf(" OWNER="); 13854236Smckusick if (getpw((int)dp->di_uid, uidbuf) == 0) { 13864236Smckusick for (p = uidbuf; *p != ':'; p++); 13874236Smckusick *p = 0; 13884236Smckusick printf("%s ", uidbuf); 13894236Smckusick } 13904236Smckusick else { 13914236Smckusick printf("%d ", dp->di_uid); 13924236Smckusick } 13934236Smckusick printf("MODE=%o\n", dp->di_mode); 13944236Smckusick if (preen) 13954236Smckusick printf("%s: ", devname); 13964236Smckusick printf("SIZE=%ld ", dp->di_size); 13974236Smckusick p = ctime(&dp->di_mtime); 13984236Smckusick printf("MTIME=%12.12s %4.4s ", p+4, p+20); 13994236Smckusick } 14004236Smckusick 14014236Smckusick copy(fp, tp, size) 14024236Smckusick register char *tp, *fp; 14034236Smckusick unsigned size; 14044236Smckusick { 14054236Smckusick 14064236Smckusick while (size--) 14074236Smckusick *tp++ = *fp++; 14084236Smckusick } 14094236Smckusick 14104236Smckusick makecg() 14114236Smckusick { 14124236Smckusick int c; 14134236Smckusick daddr_t dbase, d, dmin, dmax; 14144236Smckusick long i, j, s; 14154236Smckusick register struct csum *cs; 14164236Smckusick 14174236Smckusick sblock.fs_nbfree = 0; 14184236Smckusick sblock.fs_nffree = 0; 14194236Smckusick for (c = 0; c < sblock.fs_ncg; c++) { 14204236Smckusick dbase = cgbase(c, &sblock); 14214236Smckusick dmax = dbase + sblock.fs_fpg; 14224236Smckusick if (dmax > sblock.fs_size) 14234236Smckusick dmax = sblock.fs_size; 14244236Smckusick cs = &sblock.fs_cs[c]; 14254236Smckusick cgrp.cg_time = time(0); 14264236Smckusick cgrp.cg_magic = CG_MAGIC; 14274236Smckusick cgrp.cg_cgx = c; 14284236Smckusick cgrp.cg_ncyl = sblock.fs_cpg; 14294236Smckusick cgrp.cg_niblk = sblock.fs_ipg; 14304236Smckusick cgrp.cg_ndblk = dmax - dbase; 14314236Smckusick cgrp.cg_ndir = 0; 14324236Smckusick cgrp.cg_nffree = 0; 14334236Smckusick cgrp.cg_nbfree = 0; 14344236Smckusick cgrp.cg_nifree = 0; 14354236Smckusick cgrp.cg_rotor = 0; 1436*4258Smckusic cgrp.cg_irotor = 0; 14374236Smckusick inum = sblock.fs_ipg * c; 14384236Smckusick for (i = 0; i < sblock.fs_ipg; inum++, i++) 14394236Smckusick switch (getstate()) { 14404236Smckusick 14414236Smckusick case USTATE: 14424236Smckusick cgrp.cg_nifree++; 14434236Smckusick clrbit(cgrp.cg_iused, i); 14444236Smckusick continue; 14454236Smckusick 14464236Smckusick case DSTATE: 14474236Smckusick cgrp.cg_ndir++; 14484236Smckusick /* fall into ... */ 14494236Smckusick 14504236Smckusick case FSTATE: 14514236Smckusick setbit(cgrp.cg_iused, i); 14524236Smckusick continue; 14534236Smckusick 14544236Smckusick default: 14554236Smckusick errexit("internal error: inode state %d in makecg()\n", 14564236Smckusick getstate()); 14574236Smckusick } 14584236Smckusick while (i < MAXIPG) { 14594236Smckusick clrbit(cgrp.cg_iused, i); 14604236Smckusick i++; 14614236Smckusick } 14624236Smckusick for (s = 0; s < MAXCPG; s++) 14634236Smckusick for (i = 0; i < NRPOS; i++) 14644236Smckusick cgrp.cg_b[s][i] = 0; 14654236Smckusick dmin = cgdmin(c, &sblock) - dbase; 14664236Smckusick if (c == 0) { 14674236Smckusick dmin += howmany(cssize(&sblock), BSIZE) * FRAG; 14684236Smckusick } 14694236Smckusick for (d = 0; d < dmin; d++) 14704236Smckusick clrbit(cgrp.cg_free, d); 14714236Smckusick for (; (d + FRAG) <= dmax - dbase; d += FRAG) { 14724236Smckusick j = 0; 14734236Smckusick for (i = 0; i < FRAG; i++) { 14744236Smckusick if (!getbmap(dbase+d+i)) { 14754236Smckusick setbit(cgrp.cg_free, d+i); 14764236Smckusick j++; 14774236Smckusick } else 14784236Smckusick clrbit(cgrp.cg_free, d+i); 14794236Smckusick } 14804236Smckusick if (j == FRAG) { 14814236Smckusick cgrp.cg_nbfree++; 14824236Smckusick s = d * NSPF; 14834236Smckusick cgrp.cg_b[s/sblock.fs_spc] 14844236Smckusick [s%sblock.fs_nsect*NRPOS/sblock.fs_nsect]++; 14854236Smckusick } else 14864236Smckusick cgrp.cg_nffree += j; 14874236Smckusick } 14884236Smckusick for (; d < dmax - dbase; d++) { 14894236Smckusick if (!getbmap(dbase+d)) { 14904236Smckusick setbit(cgrp.cg_free, d); 14914236Smckusick cgrp.cg_nffree++; 14924236Smckusick } else 14934236Smckusick clrbit(cgrp.cg_free, d); 14944236Smckusick } 14954236Smckusick for (; d < MAXBPG; d++) 14964236Smckusick clrbit(cgrp.cg_free, d); 14974236Smckusick sblock.fs_nffree += cgrp.cg_nffree; 14984236Smckusick sblock.fs_nbfree += cgrp.cg_nbfree; 14994236Smckusick cs->cs_ndir = cgrp.cg_ndir; 15004236Smckusick cs->cs_nifree = cgrp.cg_nifree; 15014236Smckusick cs->cs_nbfree = cgrp.cg_nbfree; 15024236Smckusick bwrite(&dfile, &cgrp, cgtod(c, &sblock), sblock.fs_cgsize); 15034236Smckusick } 15044236Smckusick sblock.fs_ronly = 0; 15054236Smckusick sblock.fs_fmod = 0; 15064236Smckusick sbdirty(); 15074236Smckusick } 15084236Smckusick 15094236Smckusick findino(dirp) 15104236Smckusick register DIRECT *dirp; 15114236Smckusick { 15124236Smckusick register char *p1, *p2; 15134236Smckusick 15144236Smckusick if (dirp->d_ino == 0) 15154236Smckusick return (KEEPON); 15164236Smckusick for (p1 = dirp->d_name, p2 = srchname;*p2++ == *p1; p1++) { 15174236Smckusick if (*p1 == 0 || p1 == &dirp->d_name[DIRSIZ-1]) { 15184236Smckusick if (dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) 15194236Smckusick parentdir = dirp->d_ino; 15204236Smckusick return (STOP); 15214236Smckusick } 15224236Smckusick } 15234236Smckusick return (KEEPON); 15244236Smckusick } 15254236Smckusick 15264236Smckusick mkentry(dirp) 15274236Smckusick register DIRECT *dirp; 15284236Smckusick { 15294236Smckusick register ino_t in; 15304236Smckusick register char *p; 15314236Smckusick 15324236Smckusick if (dirp->d_ino) 15334236Smckusick return (KEEPON); 15344236Smckusick dirp->d_ino = orphan; 15354236Smckusick in = orphan; 15364236Smckusick p = &dirp->d_name[8]; 15374236Smckusick *--p = 0; 15384236Smckusick while (p > dirp->d_name) { 15394236Smckusick *--p = (in % 10) + '0'; 15404236Smckusick in /= 10; 15414236Smckusick } 15424236Smckusick *p = '#'; 15434236Smckusick return (ALTERD|STOP); 15444236Smckusick } 15454236Smckusick 15464236Smckusick chgdd(dirp) 15474236Smckusick register DIRECT *dirp; 15484236Smckusick { 15494236Smckusick if (dirp->d_name[0] == '.' && dirp->d_name[1] == '.' && 15504236Smckusick dirp->d_name[2] == 0) { 15514236Smckusick dirp->d_ino = lfdir; 15524236Smckusick return (ALTERD|STOP); 15534236Smckusick } 15544236Smckusick return (KEEPON); 15554236Smckusick } 15564236Smckusick 15574236Smckusick linkup() 15584236Smckusick { 15594236Smckusick register DINODE *dp; 15604236Smckusick register lostdir; 15614236Smckusick register ino_t pdir; 15624236Smckusick 15634236Smckusick if ((dp = ginode()) == NULL) 15644236Smckusick return (0); 15654236Smckusick lostdir = DIR; 15664236Smckusick pdir = parentdir; 15674236Smckusick pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); 15684236Smckusick pinode(); 15694236Smckusick if (preen && dp->di_size == 0) 15704236Smckusick return (0); 15714236Smckusick if (preen) 15724236Smckusick printf(" (RECONNECTED)\n"); 15734236Smckusick else 15744236Smckusick if (reply("RECONNECT") == 0) 15754236Smckusick return (0); 15764236Smckusick orphan = inum; 15774236Smckusick if (lfdir == 0) { 15784236Smckusick inum = ROOTINO; 15794236Smckusick if ((dp = ginode()) == NULL) { 15804236Smckusick inum = orphan; 15814236Smckusick return (0); 15824236Smckusick } 15834236Smckusick pfunc = findino; 15844236Smckusick srchname = lfname; 15854236Smckusick filsize = dp->di_size; 15864236Smckusick parentdir = 0; 15874236Smckusick ckinode(dp, DATA); 15884236Smckusick inum = orphan; 15894236Smckusick if ((lfdir = parentdir) == 0) { 15904236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 15914236Smckusick printf("\n\n"); 15924236Smckusick return (0); 15934236Smckusick } 15944236Smckusick } 15954236Smckusick inum = lfdir; 15964236Smckusick if ((dp = ginode()) == NULL || !DIR || getstate() != FSTATE) { 15974236Smckusick inum = orphan; 15984236Smckusick pfatal("SORRY. NO lost+found DIRECTORY"); 15994236Smckusick printf("\n\n"); 16004236Smckusick return (0); 16014236Smckusick } 16024236Smckusick if (dp->di_size & BMASK) { 16034236Smckusick dp->di_size = roundup(dp->di_size, BSIZE); 16044236Smckusick inodirty(); 16054236Smckusick } 16064236Smckusick filsize = dp->di_size; 16074236Smckusick inum = orphan; 16084236Smckusick pfunc = mkentry; 16094236Smckusick if ((ckinode(dp, DATA) & ALTERD) == 0) { 16104236Smckusick pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); 16114236Smckusick printf("\n\n"); 16124236Smckusick return (0); 16134236Smckusick } 16144236Smckusick declncnt(); 16154236Smckusick if (lostdir) { 16164236Smckusick pfunc = chgdd; 16174236Smckusick dp = ginode(); 16184236Smckusick filsize = dp->di_size; 16194236Smckusick ckinode(dp, DATA); 16204236Smckusick inum = lfdir; 16214236Smckusick if ((dp = ginode()) != NULL) { 16224236Smckusick dp->di_nlink++; 16234236Smckusick inodirty(); 16244236Smckusick setlncnt(getlncnt()+1); 16254236Smckusick } 16264236Smckusick inum = orphan; 16274236Smckusick pwarn("DIR I=%u CONNECTED. ", orphan); 16284236Smckusick printf("PARENT WAS I=%u\n", pdir); 16294236Smckusick if (preen == 0) 16304236Smckusick printf("\n"); 16314236Smckusick } 16324236Smckusick return (1); 16334236Smckusick } 16344236Smckusick 16354236Smckusick bread(fcp, buf, blk, size) 16364236Smckusick daddr_t blk; 16374236Smckusick register struct filecntl *fcp; 16384236Smckusick register size; 16394236Smckusick char *buf; 16404236Smckusick { 16414236Smckusick if (lseek(fcp->rfdes, blk*FSIZE, 0) < 0) 16424236Smckusick rwerr("SEEK", blk); 16434236Smckusick else if (read(fcp->rfdes, buf, size) == size) 16444236Smckusick return (1); 16454236Smckusick rwerr("READ", blk); 16464236Smckusick return (0); 16474236Smckusick } 16484236Smckusick 16494236Smckusick bwrite(fcp, buf, blk, size) 16504236Smckusick daddr_t blk; 16514236Smckusick register struct filecntl *fcp; 16524236Smckusick register size; 16534236Smckusick char *buf; 16544236Smckusick { 16554236Smckusick 16564236Smckusick if (fcp->wfdes < 0) 16574236Smckusick return (0); 16584236Smckusick if (lseek(fcp->wfdes, blk*FSIZE, 0) < 0) 16594236Smckusick rwerr("SEEK", blk); 16604236Smckusick else if (write(fcp->wfdes, buf, size) == size) { 16614236Smckusick fcp->mod = 1; 16624236Smckusick return (1); 16634236Smckusick } 16644236Smckusick rwerr("WRITE", blk); 16654236Smckusick return (0); 16664236Smckusick } 16674236Smckusick 16684236Smckusick catch() 16694236Smckusick { 16704236Smckusick 16714236Smckusick ckfini(); 16724236Smckusick exit(12); 16734236Smckusick } 1674