1 /* $NetBSD: pass1.c,v 1.28 2003/04/02 22:27:09 he Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1986, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; 40 #else 41 __RCSID("$NetBSD: pass1.c,v 1.28 2003/04/02 22:27:09 he Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #include <sys/time.h> 47 48 #include <ufs/ufs/dinode.h> 49 #include <ufs/ufs/dir.h> 50 #include <ufs/ffs/fs.h> 51 #include <ufs/ufs/ufs_bswap.h> 52 #include <ufs/ffs/ffs_extern.h> 53 54 #include <err.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 59 #include "fsck.h" 60 #include "extern.h" 61 #include "fsutil.h" 62 63 static daddr_t badblk; 64 static daddr_t dupblk; 65 static void checkinode __P((ino_t, struct inodesc *)); 66 static ino_t lastino; 67 68 void 69 pass1() 70 { 71 ino_t inumber, inosused; 72 int c; 73 daddr_t i, cgd; 74 struct inodesc idesc; 75 struct cg *cgp = cgrp; 76 struct inostat *info; 77 uint8_t *cp; 78 79 /* 80 * Set file system reserved blocks in used block map. 81 */ 82 for (c = 0; c < sblock->fs_ncg; c++) { 83 cgd = cgdmin(sblock, c); 84 if (c == 0) 85 i = cgbase(sblock, c); 86 else 87 i = cgsblock(sblock, c); 88 for (; i < cgd; i++) 89 setbmap(i); 90 } 91 i = sblock->fs_csaddr; 92 cgd = i + howmany(sblock->fs_cssize, sblock->fs_fsize); 93 for (; i < cgd; i++) 94 setbmap(i); 95 /* 96 * Find all allocated blocks. 97 */ 98 memset(&idesc, 0, sizeof(struct inodesc)); 99 idesc.id_type = ADDR; 100 idesc.id_func = pass1check; 101 n_files = n_blks = 0; 102 for (c = 0; c < sblock->fs_ncg; c++) { 103 inumber = c * sblock->fs_ipg; 104 setinodebuf(inumber); 105 getblk(&cgblk, cgtod(sblock, c), sblock->fs_cgsize); 106 memcpy(cgp, cgblk.b_un.b_cg, sblock->fs_cgsize); 107 if((doswap && !needswap) || (!doswap && needswap)) 108 ffs_cg_swap(cgblk.b_un.b_cg, cgp, sblock); 109 if (is_ufs2) 110 inosused = cgp->cg_initediblk; 111 else 112 inosused = sblock->fs_ipg; 113 if (got_siginfo) { 114 printf("%s: phase 1: cyl group %d of %d (%d%%)\n", 115 cdevname(), c, sblock->fs_ncg, 116 c * 100 / sblock->fs_ncg); 117 got_siginfo = 0; 118 } 119 /* 120 * If we are using soft updates, then we can trust the 121 * cylinder group inode allocation maps to tell us which 122 * inodes are allocated. We will scan the used inode map 123 * to find the inodes that are really in use, and then 124 * read only those inodes in from disk. 125 */ 126 if (preen && usedsoftdep) { 127 if (!cg_chkmagic(cgp, 0)) 128 pfatal("CG %d: BAD MAGIC NUMBER\n", c); 129 cp = &cg_inosused(cgp, 0)[(inosused - 1) / CHAR_BIT]; 130 for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) { 131 if (*cp == 0) 132 continue; 133 for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) { 134 if (*cp & i) 135 break; 136 inosused--; 137 } 138 break; 139 } 140 if (inosused < 0) 141 inosused = 0; 142 } 143 /* 144 * Allocate inoinfo structures for the allocated inodes. 145 */ 146 inostathead[c].il_numalloced = inosused; 147 if (inosused == 0) { 148 inostathead[c].il_stat = 0; 149 continue; 150 } 151 info = calloc((unsigned)inosused, sizeof(struct inostat)); 152 if (info == NULL) { 153 pfatal("cannot alloc %u bytes for inoinfo\n", 154 (unsigned)(sizeof(struct inostat) * inosused)); 155 abort(); 156 } 157 inostathead[c].il_stat = info; 158 /* 159 * Scan the allocated inodes. 160 */ 161 for (i = 0; i < inosused; i++, inumber++) { 162 if (inumber < ROOTINO) { 163 (void)getnextinode(inumber); 164 continue; 165 } 166 checkinode(inumber, &idesc); 167 } 168 lastino += 1; 169 if (inosused < sblock->fs_ipg || inumber == lastino) 170 continue; 171 /* 172 * If we were not able to determine in advance which inodes 173 * were in use, then reduce the size of the inoinfo structure 174 * to the size necessary to describe the inodes that we 175 * really found. 176 */ 177 if (lastino < (c * sblock->fs_ipg)) 178 inosused = 0; 179 else 180 inosused = lastino - (c * sblock->fs_ipg); 181 inostathead[c].il_numalloced = inosused; 182 if (inosused == 0) { 183 free(inostathead[c].il_stat); 184 inostathead[c].il_stat = 0; 185 continue; 186 } 187 info = calloc((unsigned)inosused, sizeof(struct inostat)); 188 if (info == NULL) { 189 pfatal("cannot alloc %u bytes for inoinfo\n", 190 (unsigned)(sizeof(struct inostat) * inosused)); 191 abort(); 192 } 193 memmove(info, inostathead[c].il_stat, inosused * sizeof(*info)); 194 free(inostathead[c].il_stat); 195 inostathead[c].il_stat = info; 196 } 197 freeinodebuf(); 198 do_blkswap = 0; /* has been done */ 199 } 200 201 static void 202 checkinode(inumber, idesc) 203 ino_t inumber; 204 struct inodesc *idesc; 205 { 206 union dinode *dp; 207 struct zlncnt *zlnp; 208 daddr_t ndb; 209 int j; 210 mode_t mode; 211 u_int64_t size, kernmaxfilesize; 212 int64_t blocks; 213 char symbuf[MAXSYMLINKLEN_UFS1]; 214 struct inostat *info; 215 216 dp = getnextinode(inumber); 217 info = inoinfo(inumber); 218 mode = iswap16(DIP(dp, mode)) & IFMT; 219 size = iswap64(DIP(dp, size)); 220 if (mode == 0) { 221 if ((is_ufs2 && 222 (memcmp(dp->dp2.di_db, ufs2_zino.di_db, 223 NDADDR * sizeof(int64_t)) || 224 memcmp(dp->dp2.di_ib, ufs2_zino.di_ib, 225 NIADDR * sizeof(int64_t)))) 226 || 227 (!is_ufs2 && 228 (memcmp(dp->dp1.di_db, ufs1_zino.di_db, 229 NDADDR * sizeof(int32_t)) || 230 memcmp(dp->dp1.di_ib, ufs1_zino.di_ib, 231 NIADDR * sizeof(int32_t)))) || 232 mode || size) { 233 pfatal("PARTIALLY ALLOCATED INODE I=%u", inumber); 234 if (reply("CLEAR") == 1) { 235 dp = ginode(inumber); 236 clearinode(dp); 237 inodirty(); 238 } else 239 markclean = 0; 240 } 241 info->ino_state = USTATE; 242 return; 243 } 244 lastino = inumber; 245 /* This should match the file size limit in ffs_mountfs(). */ 246 if (is_ufs2) 247 kernmaxfilesize = sblock->fs_maxfilesize; 248 else 249 kernmaxfilesize = (u_int64_t)0x80000000 * sblock->fs_bsize - 1; 250 if (size > kernmaxfilesize || size + sblock->fs_bsize - 1 < size || 251 (mode == IFDIR && size > MAXDIRSIZE)) { 252 if (debug) 253 printf("bad size %llu:",(unsigned long long)size); 254 goto unknown; 255 } 256 if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) { 257 dp = ginode(inumber); 258 DIP(dp, size) = iswap64(sblock->fs_fsize); 259 size = sblock->fs_fsize; 260 DIP(dp, mode) = iswap16(IFREG|0600); 261 inodirty(); 262 } 263 ndb = howmany(size, sblock->fs_bsize); 264 if (ndb < 0) { 265 if (debug) 266 printf("bad size %llu ndb %lld:", 267 (unsigned long long)size, (long long)ndb); 268 goto unknown; 269 } 270 if (mode == IFBLK || mode == IFCHR) 271 ndb++; 272 if (mode == IFLNK) { 273 /* 274 * Note that the old fastlink format always had di_blocks set 275 * to 0. Other than that we no longer use the `spare' field 276 * (which is now the extended uid) for sanity checking, the 277 * new format is the same as the old. We simply ignore the 278 * conversion altogether. - mycroft, 19MAY1994 279 */ 280 if (!is_ufs2 && doinglevel2 && 281 size > 0 && size < MAXSYMLINKLEN_UFS1 && 282 DIP(dp, blocks) != 0) { 283 if (bread(fsreadfd, symbuf, 284 fsbtodb(sblock, iswap32(DIP(dp, db[0]))), 285 (long)secsize) != 0) 286 errx(EEXIT, "cannot read symlink"); 287 if (debug) { 288 symbuf[size] = 0; 289 printf("convert symlink %u(%s) of size %lld\n", 290 inumber, symbuf, 291 (unsigned long long)size); 292 } 293 dp = ginode(inumber); 294 memmove(dp->dp1.di_db, symbuf, (long)size); 295 DIP(dp, blocks) = 0; 296 inodirty(); 297 } 298 /* 299 * Fake ndb value so direct/indirect block checks below 300 * will detect any garbage after symlink string. 301 */ 302 if (size < sblock->fs_maxsymlinklen || 303 (isappleufs && (size < APPLEUFS_MAXSYMLINKLEN)) || 304 (sblock->fs_maxsymlinklen == 0 && DIP(dp, blocks) == 0)) { 305 if (is_ufs2) 306 ndb = howmany(size, sizeof(int64_t)); 307 else 308 ndb = howmany(size, sizeof(int32_t)); 309 if (ndb > NDADDR) { 310 j = ndb - NDADDR; 311 for (ndb = 1; j > 1; j--) 312 ndb *= NINDIR(sblock); 313 ndb += NDADDR; 314 } 315 } 316 } 317 for (j = ndb; j < NDADDR; j++) 318 if (DIP(dp, db[j]) != 0) { 319 if (debug) { 320 if (!is_ufs2) 321 printf("bad direct addr ix %d: %d [ndb %lld]\n", 322 j, iswap32(dp->dp1.di_db[j]), 323 (long long)ndb); 324 else 325 printf("bad direct addr ix %d: %lld [ndb %lld]\n", 326 j, (long long)iswap64(dp->dp2.di_db[j]), 327 (long long)ndb); 328 } 329 goto unknown; 330 } 331 332 for (j = 0, ndb -= NDADDR; ndb > 0; j++) 333 ndb /= NINDIR(sblock); 334 335 for (; j < NIADDR; j++) 336 if (DIP(dp, ib[j]) != 0) { 337 if (debug) { 338 if (!is_ufs2) 339 printf("bad indirect addr: %d\n", 340 iswap32(dp->dp1.di_ib[j])); 341 else 342 printf("bad indirect addr: %lld\n", 343 (long long)iswap64(dp->dp2.di_ib[j])); 344 } 345 goto unknown; 346 } 347 if (ftypeok(dp) == 0) 348 goto unknown; 349 n_files++; 350 info->ino_linkcnt = iswap16(DIP(dp, nlink)); 351 if (info->ino_linkcnt <= 0) { 352 zlnp = (struct zlncnt *)malloc(sizeof *zlnp); 353 if (zlnp == NULL) { 354 markclean = 0; 355 pfatal("LINK COUNT TABLE OVERFLOW"); 356 if (reply("CONTINUE") == 0) { 357 ckfini(); 358 exit(EEXIT); 359 } 360 } else { 361 zlnp->zlncnt = inumber; 362 zlnp->next = zlnhead; 363 zlnhead = zlnp; 364 } 365 } 366 if (mode == IFDIR) { 367 if (size == 0) 368 info->ino_state = DCLEAR; 369 else 370 info->ino_state = DSTATE; 371 cacheino(dp, inumber); 372 countdirs++; 373 } else 374 info->ino_state = FSTATE; 375 info->ino_type = IFTODT(mode); 376 if (!is_ufs2 && doinglevel2 && 377 (iswap16(dp->dp1.di_ouid) != (u_short)-1 || 378 iswap16(dp->dp1.di_ogid) != (u_short)-1)) { 379 dp = ginode(inumber); 380 dp->dp1.di_uid = iswap32(iswap16(dp->dp1.di_ouid)); 381 dp->dp1.di_ouid = iswap16(-1); 382 dp->dp1.di_gid = iswap32(iswap16(dp->dp1.di_ogid)); 383 dp->dp1.di_ogid = iswap16(-1); 384 inodirty(); 385 } 386 badblk = dupblk = 0; 387 idesc->id_number = inumber; 388 (void)ckinode(dp, idesc); 389 idesc->id_entryno *= btodb(sblock->fs_fsize); 390 if (is_ufs2) 391 blocks = iswap64(dp->dp2.di_blocks); 392 else 393 blocks = iswap32(dp->dp1.di_blocks); 394 if (blocks != idesc->id_entryno) { 395 pwarn("INCORRECT BLOCK COUNT I=%u (%lld should be %lld)", 396 inumber, (long long)blocks, (long long)idesc->id_entryno); 397 if (preen) 398 printf(" (CORRECTED)\n"); 399 else if (reply("CORRECT") == 0) { 400 markclean = 0; 401 return; 402 } 403 dp = ginode(inumber); 404 if (is_ufs2) 405 dp->dp2.di_blocks = iswap64(idesc->id_entryno); 406 else 407 dp->dp1.di_blocks = iswap32((int32_t)idesc->id_entryno); 408 inodirty(); 409 } 410 return; 411 unknown: 412 pfatal("UNKNOWN FILE TYPE I=%u", inumber); 413 info->ino_state = FCLEAR; 414 if (reply("CLEAR") == 1) { 415 info->ino_state = USTATE; 416 dp = ginode(inumber); 417 clearinode(dp); 418 inodirty(); 419 } else 420 markclean = 0; 421 } 422 423 int 424 pass1check(idesc) 425 struct inodesc *idesc; 426 { 427 int res = KEEPON; 428 int anyout, nfrags; 429 daddr_t blkno = idesc->id_blkno; 430 struct dups *dlp; 431 struct dups *new; 432 433 if ((anyout = chkrange(blkno, idesc->id_numfrags)) != 0) { 434 blkerror(idesc->id_number, "BAD", blkno); 435 if (badblk++ >= MAXBAD) { 436 pwarn("EXCESSIVE BAD BLKS I=%u", 437 idesc->id_number); 438 if (preen) 439 printf(" (SKIPPING)\n"); 440 else if (reply("CONTINUE") == 0) { 441 markclean = 0; 442 ckfini(); 443 exit(EEXIT); 444 } 445 return (STOP); 446 } 447 } 448 for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) { 449 if (anyout && chkrange(blkno, 1)) { 450 res = SKIP; 451 } else if (!testbmap(blkno)) { 452 n_blks++; 453 setbmap(blkno); 454 } else { 455 blkerror(idesc->id_number, "DUP", blkno); 456 if (dupblk++ >= MAXDUP) { 457 pwarn("EXCESSIVE DUP BLKS I=%u", 458 idesc->id_number); 459 if (preen) 460 printf(" (SKIPPING)\n"); 461 else if (reply("CONTINUE") == 0) { 462 markclean = 0; 463 ckfini(); 464 exit(EEXIT); 465 } 466 return (STOP); 467 } 468 new = (struct dups *)malloc(sizeof(struct dups)); 469 if (new == NULL) { 470 markclean = 0; 471 pfatal("DUP TABLE OVERFLOW."); 472 if (reply("CONTINUE") == 0) { 473 markclean = 0; 474 ckfini(); 475 exit(EEXIT); 476 } 477 return (STOP); 478 } 479 new->dup = blkno; 480 if (muldup == 0) { 481 duplist = muldup = new; 482 new->next = 0; 483 } else { 484 new->next = muldup->next; 485 muldup->next = new; 486 } 487 for (dlp = duplist; dlp != muldup; dlp = dlp->next) 488 if (dlp->dup == blkno) 489 break; 490 if (dlp == muldup && dlp->dup != blkno) 491 muldup = new; 492 } 493 /* 494 * count the number of blocks found in id_entryno 495 */ 496 idesc->id_entryno++; 497 } 498 return (res); 499 } 500