1 #ifndef lint 2 static char version[] = "@(#)pass1.c 3.6 (Berkeley) 05/31/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 (void)ckinode(dp, &idesc); 111 idesc.id_entryno *= btodb(sblock.fs_fsize); 112 if (dp->di_blocks != idesc.id_entryno) { 113 pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)", 114 inumber, dp->di_blocks, idesc.id_entryno); 115 if (preen) 116 printf(" (CORRECTED)\n"); 117 else if (reply("CORRECT") == 0) 118 continue; 119 dp->di_blocks = idesc.id_entryno; 120 inodirty(); 121 } 122 continue; 123 unknown: 124 pfatal("UNKNOWN FILE TYPE I=%u", inumber); 125 if (reply("CLEAR") == 1) { 126 zapino(dp); 127 inodirty(); 128 } 129 } 130 } 131 } 132 133 pass1check(idesc) 134 register struct inodesc *idesc; 135 { 136 int res = KEEPON; 137 int anyout, nfrags; 138 daddr_t blkno = idesc->id_blkno; 139 register struct dups *dlp; 140 struct dups *new; 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 new = (struct dups *)malloc(sizeof(struct dups)); 172 if (new == NULL) { 173 pfatal("DUP TABLE OVERFLOW."); 174 if (reply("CONTINUE") == 0) 175 errexit(""); 176 return (STOP); 177 } 178 new->dup = blkno; 179 if (muldup == 0) { 180 duplist = muldup = new; 181 new->next = 0; 182 } else { 183 new->next = muldup->next; 184 muldup->next = new; 185 } 186 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 187 if (dlp->dup == blkno) 188 break; 189 if (dlp == muldup && dlp->dup != blkno) 190 muldup = new; 191 } 192 /* 193 * count the number of blocks found in id_entryno 194 */ 195 idesc->id_entryno++; 196 } 197 return (res); 198 } 199