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