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