1 /* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 /*static char sccsid[] = "from: @(#)pass1.c 8.1 (Berkeley) 6/5/93";*/ 36 static char *rcsid = "$Id: pass1.c,v 1.12 1994/12/05 20:15:53 cgd Exp $"; 37 #endif /* not lint */ 38 39 #include <sys/param.h> 40 #include <sys/time.h> 41 #include <ufs/ufs/dinode.h> 42 #include <ufs/ufs/dir.h> 43 #include <ufs/ffs/fs.h> 44 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 49 #include "fsck.h" 50 #include "extern.h" 51 52 static daddr_t badblk; 53 static daddr_t dupblk; 54 int pass1check(); 55 struct dinode *getnextinode(); 56 void checkinode __P((ino_t, struct inodesc *)); 57 58 void 59 pass1() 60 { 61 ino_t inumber; 62 int c, i, cgd; 63 struct inodesc idesc; 64 65 /* 66 * Set file system reserved blocks in used block map. 67 */ 68 for (c = 0; c < sblock.fs_ncg; c++) { 69 cgd = cgdmin(&sblock, c); 70 if (c == 0) { 71 i = cgbase(&sblock, c); 72 cgd += howmany(sblock.fs_cssize, sblock.fs_fsize); 73 } else 74 i = cgsblock(&sblock, c); 75 for (; i < cgd; i++) 76 setbmap(i); 77 } 78 /* 79 * Find all allocated blocks. 80 */ 81 memset(&idesc, 0, sizeof(struct inodesc)); 82 idesc.id_type = ADDR; 83 idesc.id_func = pass1check; 84 inumber = 0; 85 n_files = n_blks = 0; 86 resetinodebuf(); 87 for (c = 0; c < sblock.fs_ncg; c++) { 88 for (i = 0; i < sblock.fs_ipg; i++, inumber++) { 89 if (inumber < ROOTINO) 90 continue; 91 checkinode(inumber, &idesc); 92 } 93 } 94 freeinodebuf(); 95 } 96 97 void 98 checkinode(inumber, idesc) 99 ino_t inumber; 100 register struct inodesc *idesc; 101 { 102 register struct dinode *dp; 103 struct zlncnt *zlnp; 104 int ndb, j; 105 mode_t mode; 106 char *symbuf; 107 108 dp = getnextinode(inumber); 109 mode = dp->di_mode & IFMT; 110 if (mode == 0) { 111 if (memcmp(dp->di_db, zino.di_db, NDADDR * sizeof(daddr_t)) || 112 memcmp(dp->di_ib, zino.di_ib, NIADDR * sizeof(daddr_t)) || 113 dp->di_mode || dp->di_size) { 114 pfatal("PARTIALLY ALLOCATED INODE I=%lu", inumber); 115 if (reply("CLEAR") == 1) { 116 dp = ginode(inumber); 117 clearinode(dp); 118 inodirty(); 119 } 120 } 121 statemap[inumber] = USTATE; 122 return; 123 } 124 lastino = inumber; 125 if (/* dp->di_size < 0 || */ 126 dp->di_size + sblock.fs_bsize - 1 < dp->di_size) { 127 if (debug) 128 printf("bad size %qu:", dp->di_size); 129 goto unknown; 130 } 131 if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 132 dp = ginode(inumber); 133 dp->di_size = sblock.fs_fsize; 134 dp->di_mode = IFREG|0600; 135 inodirty(); 136 } 137 ndb = howmany(dp->di_size, sblock.fs_bsize); 138 if (ndb < 0) { 139 if (debug) 140 printf("bad size %qu ndb %d:", 141 dp->di_size, ndb); 142 goto unknown; 143 } 144 if (mode == IFBLK || mode == IFCHR) 145 ndb++; 146 if (mode == IFLNK) { 147 /* 148 * Note that the old fastlink format always had di_blocks set 149 * to 0. Other than that we no longer use the `spare' field 150 * (which is now the extended uid) for sanity checking, the 151 * new format is the same as the old. We simply ignore the 152 * conversion altogether. - mycroft, 19MAY1994 153 */ 154 if (doinglevel2 && 155 dp->di_size > 0 && dp->di_size < MAXSYMLINKLEN && 156 dp->di_blocks != 0) { 157 symbuf = alloca(secsize); 158 if (bread(fsreadfd, symbuf, 159 fsbtodb(&sblock, dp->di_db[0]), 160 (long)secsize) != 0) 161 errexit("cannot read symlink"); 162 if (debug) { 163 symbuf[dp->di_size] = 0; 164 printf("convert symlink %d(%s) of size %d\n", 165 inumber, symbuf, (long)dp->di_size); 166 } 167 dp = ginode(inumber); 168 memcpy(dp->di_shortlink, symbuf, (long)dp->di_size); 169 dp->di_blocks = 0; 170 inodirty(); 171 } 172 /* 173 * Fake ndb value so direct/indirect block checks below 174 * will detect any garbage after symlink string. 175 */ 176 if (dp->di_size < sblock.fs_maxsymlinklen || 177 (sblock.fs_maxsymlinklen == 0 && dp->di_blocks == 0)) { 178 ndb = howmany(dp->di_size, sizeof(daddr_t)); 179 if (ndb > NDADDR) { 180 j = ndb - NDADDR; 181 for (ndb = 1; j > 1; j--) 182 ndb *= NINDIR(&sblock); 183 ndb += NDADDR; 184 } 185 } 186 } 187 for (j = ndb; j < NDADDR; j++) 188 if (dp->di_db[j] != 0) { 189 if (debug) 190 printf("bad direct addr: %ld\n", dp->di_db[j]); 191 goto unknown; 192 } 193 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 194 ndb /= NINDIR(&sblock); 195 for (; j < NIADDR; j++) 196 if (dp->di_ib[j] != 0) { 197 if (debug) 198 printf("bad indirect addr: %ld\n", 199 dp->di_ib[j]); 200 goto unknown; 201 } 202 if (ftypeok(dp) == 0) 203 goto unknown; 204 n_files++; 205 lncntp[inumber] = dp->di_nlink; 206 if (dp->di_nlink <= 0) { 207 zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 208 if (zlnp == NULL) { 209 pfatal("LINK COUNT TABLE OVERFLOW"); 210 if (reply("CONTINUE") == 0) 211 errexit(""); 212 } else { 213 zlnp->zlncnt = inumber; 214 zlnp->next = zlnhead; 215 zlnhead = zlnp; 216 } 217 } 218 if (mode == IFDIR) { 219 if (dp->di_size == 0) 220 statemap[inumber] = DCLEAR; 221 else 222 statemap[inumber] = DSTATE; 223 cacheino(dp, inumber); 224 } else 225 statemap[inumber] = FSTATE; 226 typemap[inumber] = IFTODT(mode); 227 if (doinglevel2 && 228 (dp->di_ouid != (u_short)-1 || dp->di_ogid != (u_short)-1)) { 229 dp = ginode(inumber); 230 dp->di_uid = dp->di_ouid; 231 dp->di_ouid = -1; 232 dp->di_gid = dp->di_ogid; 233 dp->di_ogid = -1; 234 inodirty(); 235 } 236 badblk = dupblk = 0; 237 idesc->id_number = inumber; 238 (void)ckinode(dp, idesc); 239 idesc->id_entryno *= btodb(sblock.fs_fsize); 240 if (dp->di_blocks != idesc->id_entryno) { 241 pwarn("INCORRECT BLOCK COUNT I=%lu (%ld should be %ld)", 242 inumber, dp->di_blocks, idesc->id_entryno); 243 if (preen) 244 printf(" (CORRECTED)\n"); 245 else if (reply("CORRECT") == 0) 246 return; 247 dp = ginode(inumber); 248 dp->di_blocks = idesc->id_entryno; 249 inodirty(); 250 } 251 return; 252 unknown: 253 pfatal("UNKNOWN FILE TYPE I=%lu", inumber); 254 statemap[inumber] = FCLEAR; 255 if (reply("CLEAR") == 1) { 256 statemap[inumber] = USTATE; 257 dp = ginode(inumber); 258 clearinode(dp); 259 inodirty(); 260 } 261 } 262 263 int 264 pass1check(idesc) 265 register struct inodesc *idesc; 266 { 267 int res = KEEPON; 268 int anyout, nfrags; 269 daddr_t blkno = idesc->id_blkno; 270 register struct dups *dlp; 271 struct dups *new; 272 273 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 274 blkerror(idesc->id_number, "BAD", blkno); 275 if (badblk++ >= MAXBAD) { 276 pwarn("EXCESSIVE BAD BLKS I=%lu", 277 idesc->id_number); 278 if (preen) 279 printf(" (SKIPPING)\n"); 280 else if (reply("CONTINUE") == 0) 281 errexit(""); 282 return (STOP); 283 } 284 } 285 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 286 if (anyout && chkrange(blkno, 1)) { 287 res = SKIP; 288 } else if (!testbmap(blkno)) { 289 n_blks++; 290 setbmap(blkno); 291 } else { 292 blkerror(idesc->id_number, "DUP", blkno); 293 if (dupblk++ >= MAXDUP) { 294 pwarn("EXCESSIVE DUP BLKS I=%lu", 295 idesc->id_number); 296 if (preen) 297 printf(" (SKIPPING)\n"); 298 else if (reply("CONTINUE") == 0) 299 errexit(""); 300 return (STOP); 301 } 302 new = (struct dups *)malloc(sizeof(struct dups)); 303 if (new == NULL) { 304 pfatal("DUP TABLE OVERFLOW."); 305 if (reply("CONTINUE") == 0) 306 errexit(""); 307 return (STOP); 308 } 309 new->dup = blkno; 310 if (muldup == 0) { 311 duplist = muldup = new; 312 new->next = 0; 313 } else { 314 new->next = muldup->next; 315 muldup->next = new; 316 } 317 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 318 if (dlp->dup == blkno) 319 break; 320 if (dlp == muldup && dlp->dup != blkno) 321 muldup = new; 322 } 323 /* 324 * count the number of blocks found in id_entryno 325 */ 326 idesc->id_entryno++; 327 } 328 return (res); 329 } 330