1 #ifndef lint 2 static char version[] = "@(#)pass1.c 3.1 (Berkeley) 03/31/84"; 3 #endif 4 5 #include <sys/param.h> 6 #include <sys/inode.h> 7 #include <sys/fs.h> 8 #include "fsck.h" 9 10 int pass1check(); 11 12 pass1() 13 { 14 register int c, i, n, j; 15 register DINODE *dp; 16 int ndb, partial; 17 struct inodesc idesc; 18 ino_t inumber; 19 20 bzero((char *)&idesc, sizeof(struct inodesc)); 21 idesc.id_type = ADDR; 22 idesc.id_func = pass1check; 23 inumber = 0; 24 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 25 for (c = 0; c < sblock.fs_ncg; c++) { 26 if (getblk(&cgblk, cgtod(&sblock, c), sblock.fs_cgsize) == 0) 27 continue; 28 if (cgrp.cg_magic != CG_MAGIC) { 29 pfatal("CG %d: BAD MAGIC NUMBER\n", c); 30 bzero((char *)&cgrp, (int)sblock.fs_cgsize); 31 } 32 n = 0; 33 for (i = 0; i < sblock.fs_ipg; i++, inumber++) { 34 dp = ginode(inumber); 35 if (dp == NULL) 36 continue; 37 n++; 38 if (ALLOC) { 39 if (!isset(cgrp.cg_iused, i)) { 40 if (debug) 41 printf("%d bad, not used\n", 42 inumber); 43 inosumbad++; 44 } 45 n--; 46 lastino = inumber; 47 if (!preen && (dp->di_mode & IFMT) == IFMT && 48 reply("HOLD BAD BLOCK") == 1) { 49 dp->di_size = sblock.fs_fsize; 50 dp->di_mode = IFREG|0600; 51 inodirty(); 52 } else if (ftypeok(dp) == 0) 53 goto unknown; 54 if (dp->di_size < 0) { 55 if (debug) 56 printf("bad size %d:", 57 dp->di_size); 58 goto unknown; 59 } 60 ndb = howmany(dp->di_size, sblock.fs_bsize); 61 if (SPECIAL) 62 ndb++; 63 for (j = ndb; j < NDADDR; j++) 64 if (dp->di_db[j] != 0) { 65 if (debug) 66 printf("bad direct addr: %d\n", 67 dp->di_db[j]); 68 goto unknown; 69 } 70 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 71 ndb /= NINDIR(&sblock); 72 for (; j < NIADDR; j++) 73 if (dp->di_ib[j] != 0) { 74 if (debug) 75 printf("bad indirect addr: %d\n", 76 dp->di_ib[j]); 77 goto unknown; 78 } 79 n_files++; 80 lncntp[inumber] = dp->di_nlink; 81 if (dp->di_nlink <= 0) { 82 if (badlnp < &badlncnt[MAXLNCNT]) 83 *badlnp++ = inumber; 84 else { 85 pfatal("LINK COUNT TABLE OVERFLOW"); 86 if (reply("CONTINUE") == 0) 87 errexit(""); 88 } 89 } 90 statemap[inumber] = DIRCT ? DSTATE : FSTATE; 91 badblk = dupblk = 0; maxblk = 0; 92 idesc.id_number = inumber; 93 idesc.id_filesize = 0; 94 (void)ckinode(dp, &idesc); 95 idesc.id_filesize *= btodb(sblock.fs_fsize); 96 if (dp->di_blocks != idesc.id_filesize) { 97 pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)", 98 inumber, dp->di_blocks, 99 idesc.id_filesize); 100 if (preen) 101 printf(" (CORRECTED)\n"); 102 else if (reply("CORRECT") == 0) 103 continue; 104 dp->di_blocks = idesc.id_filesize; 105 inodirty(); 106 } 107 continue; 108 unknown: 109 pfatal("UNKNOWN FILE TYPE I=%u", inumber); 110 if (reply("CLEAR") == 1) { 111 zapino(dp); 112 inodirty(); 113 inosumbad++; 114 } 115 } else { 116 if (isset(cgrp.cg_iused, i)) { 117 if (debug) 118 printf("%d bad, marked used\n", 119 inumber); 120 inosumbad++; 121 n--; 122 } 123 partial = 0; 124 for (j = 0; j < NDADDR; j++) 125 if (dp->di_db[j] != 0) 126 partial++; 127 for (j = 0; j < NIADDR; j++) 128 if (dp->di_ib[j] != 0) 129 partial++; 130 if (partial || dp->di_mode != 0 || 131 dp->di_size != 0) { 132 pfatal("PARTIALLY ALLOCATED INODE I=%u", 133 inumber); 134 if (reply("CLEAR") == 1) { 135 zapino(dp); 136 inodirty(); 137 inosumbad++; 138 } 139 } 140 } 141 } 142 if (n != cgrp.cg_cs.cs_nifree) { 143 if (debug) 144 printf("cg[%d].cg_cs.cs_nifree is %d; calc %d\n", 145 c, cgrp.cg_cs.cs_nifree, n); 146 inosumbad++; 147 } 148 if (cgrp.cg_cs.cs_nbfree != sblock.fs_cs(&sblock, c).cs_nbfree 149 || cgrp.cg_cs.cs_nffree != sblock.fs_cs(&sblock, c).cs_nffree 150 || cgrp.cg_cs.cs_nifree != sblock.fs_cs(&sblock, c).cs_nifree 151 || cgrp.cg_cs.cs_ndir != sblock.fs_cs(&sblock, c).cs_ndir) 152 sbsumbad++; 153 } 154 } 155 156 pass1check(idesc) 157 register struct inodesc *idesc; 158 { 159 register daddr_t *dlp; 160 int res = KEEPON; 161 int anyout, nfrags; 162 daddr_t blkno = idesc->id_blkno; 163 164 anyout = outrange(blkno, idesc->id_numfrags); 165 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 166 if (anyout && outrange(blkno, 1)) { 167 blkerr(idesc->id_number, "BAD", blkno); 168 if (++badblk >= MAXBAD) { 169 pwarn("EXCESSIVE BAD BLKS I=%u", 170 idesc->id_number); 171 if (preen) 172 printf(" (SKIPPING)\n"); 173 else if (reply("CONTINUE") == 0) 174 errexit(""); 175 return (STOP); 176 } 177 res = SKIP; 178 } else if (getbmap(blkno)) { 179 blkerr(idesc->id_number, "DUP", blkno); 180 if (++dupblk >= MAXDUP) { 181 pwarn("EXCESSIVE DUP BLKS I=%u", 182 idesc->id_number); 183 if (preen) 184 printf(" (SKIPPING)\n"); 185 else if (reply("CONTINUE") == 0) 186 errexit(""); 187 return (STOP); 188 } 189 if (enddup >= &duplist[DUPTBLSIZE]) { 190 pfatal("DUP TABLE OVERFLOW."); 191 if (reply("CONTINUE") == 0) 192 errexit(""); 193 return (STOP); 194 } 195 for (dlp = duplist; dlp < muldup; dlp++) 196 if (*dlp == blkno) { 197 *enddup++ = blkno; 198 break; 199 } 200 if (dlp >= muldup) { 201 *enddup++ = *muldup; 202 *muldup++ = blkno; 203 } 204 } else { 205 n_blks++; 206 setbmap(blkno); 207 } 208 idesc->id_filesize++; 209 } 210 return (res); 211 } 212