1 /* 2 * Copyright (c) 1980, 1986 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)pass1.c 5.14 (Berkeley) 06/01/90"; 10 #endif /* not lint */ 11 12 #include <sys/param.h> 13 #include <ufs/dinode.h> 14 #include <ufs/fs.h> 15 #include "fsck.h" 16 17 static daddr_t badblk; 18 static daddr_t dupblk; 19 int pass1check(); 20 struct dinode *getnextinode(); 21 22 pass1() 23 { 24 register int c, i, j; 25 register struct dinode *dp; 26 struct zlncnt *zlnp; 27 int ndb, cgd; 28 struct inodesc idesc; 29 ino_t inumber; 30 31 /* 32 * Set file system reserved blocks in used block map. 33 */ 34 for (c = 0; c < sblock.fs_ncg; c++) { 35 cgd = cgdmin(&sblock, c); 36 if (c == 0) { 37 i = cgbase(&sblock, c); 38 cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); 39 } else 40 i = cgsblock(&sblock, c); 41 for (; i < cgd; i++) 42 setbmap(i); 43 } 44 /* 45 * Find all allocated blocks. 46 */ 47 bzero((char *)&idesc, sizeof(struct inodesc)); 48 idesc.id_type = ADDR; 49 idesc.id_func = pass1check; 50 inumber = 0; 51 n_files = n_blks = 0; 52 resetinodebuf(); 53 for (c = 0; c < sblock.fs_ncg; c++) { 54 for (i = 0; i < sblock.fs_ipg; i++, inumber++) { 55 if (inumber < ROOTINO) 56 continue; 57 dp = getnextinode(inumber); 58 if ((dp->di_mode & IFMT) == 0) { 59 if (bcmp((char *)dp->di_db, (char *)zino.di_db, 60 NDADDR * sizeof(daddr_t)) || 61 bcmp((char *)dp->di_ib, (char *)zino.di_ib, 62 NIADDR * sizeof(daddr_t)) || 63 dp->di_mode || dp->di_size) { 64 pfatal("PARTIALLY ALLOCATED INODE I=%u", 65 inumber); 66 if (reply("CLEAR") == 1) { 67 dp = ginode(inumber); 68 clearinode(dp); 69 inodirty(); 70 } 71 } 72 statemap[inumber] = USTATE; 73 continue; 74 } 75 lastino = inumber; 76 if (dp->di_size < 0 || 77 dp->di_size + sblock.fs_bsize - 1 < 0) { 78 if (debug) 79 printf("bad size %d:", dp->di_size); 80 goto unknown; 81 } 82 if (!preen && (dp->di_mode & IFMT) == IFMT && 83 reply("HOLD BAD BLOCK") == 1) { 84 dp = ginode(inumber); 85 dp->di_size = sblock.fs_fsize; 86 dp->di_mode = IFREG|0600; 87 inodirty(); 88 } 89 ndb = howmany(dp->di_size, sblock.fs_bsize); 90 if (ndb < 0) { 91 if (debug) 92 printf("bad size %d ndb %d:", 93 dp->di_size, ndb); 94 goto unknown; 95 } 96 if ((dp->di_mode & IFMT) == IFBLK || 97 (dp->di_mode & IFMT) == IFCHR) 98 ndb++; 99 for (j = ndb; j < NDADDR; j++) 100 if (dp->di_db[j] != 0) { 101 if (debug) 102 printf("bad direct addr: %d\n", 103 dp->di_db[j]); 104 goto unknown; 105 } 106 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 107 ndb /= NINDIR(&sblock); 108 for (; j < NIADDR; j++) 109 if (dp->di_ib[j] != 0) { 110 if (debug) 111 printf("bad indirect addr: %d\n", 112 dp->di_ib[j]); 113 goto unknown; 114 } 115 if (ftypeok(dp) == 0) 116 goto unknown; 117 n_files++; 118 lncntp[inumber] = dp->di_nlink; 119 if (dp->di_nlink <= 0) { 120 zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 121 if (zlnp == NULL) { 122 pfatal("LINK COUNT TABLE OVERFLOW"); 123 if (reply("CONTINUE") == 0) 124 errexit(""); 125 } else { 126 zlnp->zlncnt = inumber; 127 zlnp->next = zlnhead; 128 zlnhead = zlnp; 129 } 130 } 131 if ((dp->di_mode & IFMT) == IFDIR) { 132 if (dp->di_size == 0) 133 statemap[inumber] = DCLEAR; 134 else 135 statemap[inumber] = DSTATE; 136 cacheino(dp, inumber); 137 } else 138 statemap[inumber] = FSTATE; 139 badblk = dupblk = 0; 140 idesc.id_number = inumber; 141 (void)ckinode(dp, &idesc); 142 idesc.id_entryno *= btodb(sblock.fs_fsize); 143 if (dp->di_blocks != idesc.id_entryno) { 144 pwarn("INCORRECT BLOCK COUNT I=%u (%ld should be %ld)", 145 inumber, dp->di_blocks, idesc.id_entryno); 146 if (preen) 147 printf(" (CORRECTED)\n"); 148 else if (reply("CORRECT") == 0) 149 continue; 150 dp = ginode(inumber); 151 dp->di_blocks = idesc.id_entryno; 152 inodirty(); 153 } 154 continue; 155 unknown: 156 pfatal("UNKNOWN FILE TYPE I=%u", inumber); 157 statemap[inumber] = FCLEAR; 158 if (reply("CLEAR") == 1) { 159 statemap[inumber] = USTATE; 160 dp = ginode(inumber); 161 clearinode(dp); 162 inodirty(); 163 } 164 } 165 } 166 freeinodebuf(); 167 } 168 169 pass1check(idesc) 170 register struct inodesc *idesc; 171 { 172 int res = KEEPON; 173 int anyout, nfrags; 174 daddr_t blkno = idesc->id_blkno; 175 register struct dups *dlp; 176 struct dups *new; 177 178 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 179 blkerror(idesc->id_number, "BAD", blkno); 180 if (++badblk >= MAXBAD) { 181 pwarn("EXCESSIVE BAD 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 } 190 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 191 if (anyout && chkrange(blkno, 1)) { 192 res = SKIP; 193 } else if (!testbmap(blkno)) { 194 n_blks++; 195 setbmap(blkno); 196 } else { 197 blkerror(idesc->id_number, "DUP", blkno); 198 if (++dupblk >= MAXDUP) { 199 pwarn("EXCESSIVE DUP BLKS I=%u", 200 idesc->id_number); 201 if (preen) 202 printf(" (SKIPPING)\n"); 203 else if (reply("CONTINUE") == 0) 204 errexit(""); 205 return (STOP); 206 } 207 new = (struct dups *)malloc(sizeof(struct dups)); 208 if (new == NULL) { 209 pfatal("DUP TABLE OVERFLOW."); 210 if (reply("CONTINUE") == 0) 211 errexit(""); 212 return (STOP); 213 } 214 new->dup = blkno; 215 if (muldup == 0) { 216 duplist = muldup = new; 217 new->next = 0; 218 } else { 219 new->next = muldup->next; 220 muldup->next = new; 221 } 222 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 223 if (dlp->dup == blkno) 224 break; 225 if (dlp == muldup && dlp->dup != blkno) 226 muldup = new; 227 } 228 /* 229 * count the number of blocks found in id_entryno 230 */ 231 idesc->id_entryno++; 232 } 233 return (res); 234 } 235