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