1 #ifndef lint 2 static char version[] = "@(#)pass1.c 3.3 (Berkeley) 02/08/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 if ((dp = ginode(inumber)) == NULL) 48 continue; 49 if (!ALLOC(dp)) { 50 if (bcmp((char *)dp->di_db, (char *)zino.di_db, 51 NDADDR * sizeof(daddr_t)) || 52 bcmp((char *)dp->di_ib, (char *)zino.di_ib, 53 NIADDR * sizeof(daddr_t)) || 54 dp->di_mode || dp->di_size) { 55 pfatal("PARTIALLY ALLOCATED INODE I=%u", 56 inumber); 57 if (reply("CLEAR") == 1) { 58 zapino(dp); 59 inodirty(); 60 } 61 } 62 statemap[inumber] = USTATE; 63 continue; 64 } 65 lastino = inumber; 66 if (dp->di_size < 0) { 67 if (debug) 68 printf("bad size %d:", dp->di_size); 69 goto unknown; 70 } 71 ndb = howmany(dp->di_size, sblock.fs_bsize); 72 if (SPECIAL(dp)) 73 ndb++; 74 for (j = ndb; j < NDADDR; j++) 75 if (dp->di_db[j] != 0) { 76 if (debug) 77 printf("bad direct addr: %d\n", 78 dp->di_db[j]); 79 goto unknown; 80 } 81 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 82 ndb /= NINDIR(&sblock); 83 for (; j < NIADDR; j++) 84 if (dp->di_ib[j] != 0) { 85 if (debug) 86 printf("bad indirect addr: %d\n", 87 dp->di_ib[j]); 88 goto unknown; 89 } 90 if (!preen && (dp->di_mode & IFMT) == IFMT && 91 reply("HOLD BAD BLOCK") == 1) { 92 dp->di_size = sblock.fs_fsize; 93 dp->di_mode = IFREG|0600; 94 inodirty(); 95 } else if (ftypeok(dp) == 0) 96 goto unknown; 97 n_files++; 98 lncntp[inumber] = dp->di_nlink; 99 if (dp->di_nlink <= 0) { 100 if (badlnp < &badlncnt[MAXLNCNT]) 101 *badlnp++ = inumber; 102 else { 103 pfatal("LINK COUNT TABLE OVERFLOW"); 104 if (reply("CONTINUE") == 0) 105 errexit(""); 106 } 107 } 108 statemap[inumber] = DIRCT(dp) ? DSTATE : FSTATE; 109 badblk = dupblk = 0; maxblk = 0; 110 idesc.id_number = inumber; 111 idesc.id_filesize = 0; 112 (void)ckinode(dp, &idesc); 113 idesc.id_filesize *= btodb(sblock.fs_fsize); 114 if (dp->di_blocks != idesc.id_filesize) { 115 pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)", 116 inumber, dp->di_blocks, idesc.id_filesize); 117 if (preen) 118 printf(" (CORRECTED)\n"); 119 else if (reply("CORRECT") == 0) 120 continue; 121 dp->di_blocks = idesc.id_filesize; 122 inodirty(); 123 } 124 continue; 125 unknown: 126 pfatal("UNKNOWN FILE TYPE I=%u", inumber); 127 if (reply("CLEAR") == 1) { 128 zapino(dp); 129 inodirty(); 130 } 131 } 132 } 133 } 134 135 pass1check(idesc) 136 register struct inodesc *idesc; 137 { 138 register daddr_t *dlp; 139 int res = KEEPON; 140 int anyout, nfrags; 141 daddr_t blkno = idesc->id_blkno; 142 143 if ((anyout = outrange(blkno, idesc->id_numfrags)) != 0) { 144 blkerr(idesc->id_number, "BAD", blkno); 145 if (++badblk >= MAXBAD) { 146 pwarn("EXCESSIVE BAD BLKS I=%u", 147 idesc->id_number); 148 if (preen) 149 printf(" (SKIPPING)\n"); 150 else if (reply("CONTINUE") == 0) 151 errexit(""); 152 return (STOP); 153 } 154 } 155 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 156 if (anyout && outrange(blkno, 1)) { 157 res = SKIP; 158 } else if (!getbmap(blkno)) { 159 n_blks++; 160 setbmap(blkno); 161 } else { 162 blkerr(idesc->id_number, "DUP", blkno); 163 if (++dupblk >= MAXDUP) { 164 pwarn("EXCESSIVE DUP BLKS I=%u", 165 idesc->id_number); 166 if (preen) 167 printf(" (SKIPPING)\n"); 168 else if (reply("CONTINUE") == 0) 169 errexit(""); 170 return (STOP); 171 } 172 if (enddup >= &duplist[DUPTBLSIZE]) { 173 pfatal("DUP TABLE OVERFLOW."); 174 if (reply("CONTINUE") == 0) 175 errexit(""); 176 return (STOP); 177 } 178 for (dlp = duplist; dlp < muldup; dlp++) 179 if (*dlp == blkno) { 180 *enddup++ = blkno; 181 break; 182 } 183 if (dlp >= muldup) { 184 *enddup++ = *muldup; 185 *muldup++ = blkno; 186 } 187 } 188 idesc->id_filesize++; 189 } 190 return (res); 191 } 192