1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 11 * All rights reserved. 12 * 13 * Redistribution and use in source and binary forms are permitted 14 * provided that: (1) source distributions retain this entire copyright 15 * notice and comment, and (2) distributions including binaries display 16 * the following acknowledgement: ``This product includes software 17 * developed by the University of California, Berkeley and its contributors'' 18 * in the documentation or other materials provided with the distribution 19 * and in all advertising materials mentioning features or use of this 20 * software. Neither the name of the University nor the names of its 21 * contributors may be used to endorse or promote products derived 22 * from this software without specific prior written permission. 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #define DKTYPENAMES 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <errno.h> 34 #include <sys/param.h> 35 #include <sys/types.h> 36 #include <sys/sysmacros.h> 37 #include <sys/mntent.h> 38 #include <sys/mnttab.h> 39 #include <sys/dkio.h> 40 #include <sys/filio.h> 41 #include <sys/isa_defs.h> /* for ENDIAN defines */ 42 43 #define bcopy(f, t, n) memcpy(t, f, n) 44 #define bzero(s, n) memset(s, 0, n) 45 #define bcmp(s, d, n) memcmp(s, d, n) 46 47 #define index(s, r) strchr(s, r) 48 #define rindex(s, r) strrchr(s, r) 49 50 #include <sys/int_const.h> 51 #include <sys/fs/ufs_fs.h> 52 #include <sys/vnode.h> 53 #include <sys/fs/ufs_inode.h> 54 #include <sys/fs/ufs_log.h> 55 #include <sys/stat.h> 56 #include <sys/file.h> 57 #include <sys/fcntl.h> 58 #include <string.h> 59 #include <unistd.h> 60 #include <ustat.h> 61 #include <fcntl.h> 62 63 #include "fsck.h" 64 #include <sys/vfstab.h> 65 #include <sys/ustat.h> 66 #include "roll_log.h" 67 68 struct bufarea asblk; 69 #define altsblock (*asblk.b_un.b_fs) 70 #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 71 72 static void badsb(int, char *); 73 static int checksb(int); 74 75 struct shadowclientinfo *shadowclientinfo = NULL; 76 struct shadowclientinfo *attrclientinfo = NULL; 77 int maxshadowclients = 1024; 78 79 /* 80 * The size of a cylinder group is calculated by CGSIZE. The maximum size 81 * is limited by the fact that cylinder groups are at most one block. 82 * Its size is derived from the size of the maps maintained in the 83 * cylinder group and the (struct cg) size. 84 */ 85 #define CGSIZE(fs) \ 86 /* base cg */ (sizeof (struct cg) + \ 87 /* blktot size */ (fs)->fs_cpg * sizeof (long) + \ 88 /* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof (short) + \ 89 /* inode map */ howmany((fs)->fs_ipg, NBBY) + \ 90 /* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY)) 91 92 extern int mflag; 93 extern char hotroot; 94 extern char *mount_point; 95 96 static int 97 read_super_block() 98 { 99 int fd; 100 101 if (mount_point) { 102 fd = open(mount_point, O_RDONLY); 103 if (fd == -1) { 104 perror("fsck: open mount point error"); 105 exit(39); 106 } 107 /* get the latest super block */ 108 if (ioctl(fd, _FIOGETSUPERBLOCK, &sblock)) { 109 perror("fsck: ioctl _FIOGETSUPERBLOCK error"); 110 exit(39); 111 } 112 close(fd); 113 } else { 114 (void) bread(fsreadfd, (char *)&sblock, 115 bflag != 0 ? (diskaddr_t)bflag : (diskaddr_t)SBLOCK, 116 (long)SBSIZE); 117 } 118 119 /* 120 * rudimental consistency checks 121 */ 122 if ((sblock.fs_magic != FS_MAGIC) && 123 (sblock.fs_magic != MTB_UFS_MAGIC)) { 124 badsb(1, "MAGIC NUMBER WRONG"); 125 return (0); 126 } 127 if (sblock.fs_magic == MTB_UFS_MAGIC && 128 (sblock.fs_version > MTB_UFS_VERSION_1 || 129 sblock.fs_version < MTB_UFS_VERSION_MIN)) { 130 badsb(1, "UNRECOGNIZED VERSION"); 131 return (0); 132 } 133 if (sblock.fs_ncg < 1) { 134 badsb(1, "NCG OUT OF RANGE"); 135 return (0); 136 } 137 if (sblock.fs_cpg < 1) { 138 badsb(1, "CPG OUT OF RANGE"); 139 return (0); 140 } 141 if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl || 142 (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) { 143 badsb(1, "NCYL IS INCONSISTENT WITH NCG*CPG"); 144 return (0); 145 } 146 if (sblock.fs_sbsize < 0 || sblock.fs_sbsize > SBSIZE) { 147 badsb(1, "SIZE TOO LARGE"); 148 return (0); 149 } 150 151 return (1); 152 } 153 154 void 155 flush_fs() 156 { 157 int fd; 158 159 if (mount_point) { 160 fd = open(mount_point, O_RDONLY); 161 if (fd == -1) { 162 perror("fsck: open mount point error"); 163 exit(39); 164 } 165 if (ioctl(fd, _FIOFFS, NULL)) { /* flush file system */ 166 perror("fsck: ioctl _FIOFFS error"); 167 exit(39); 168 } 169 close(fd); 170 } 171 } 172 173 /* 174 * Roll the embedded log, if any, and set up the global variables 175 * islog, islogok, and ismdd. 176 */ 177 static int 178 logsetup(char *devstr) 179 { 180 void *buf; 181 struct dk_cinfo dkcinfo; 182 extent_block_t *ebp; 183 ml_unit_t *ul; 184 ml_odunit_t *ud; 185 void *ud_buf; 186 int badlog; 187 188 ismdd = islog = islogok = 0; 189 if (bflag) 190 return (1); /* can't roll log while alternate sb specified */ 191 192 /* Roll the log, if any */ 193 sblock.fs_logbno = 0; 194 badlog = 0; 195 if (!read_super_block()) 196 return (0); 197 198 /* 199 * Roll the log in 3 cases: 200 * 1. If it's unmounted (mount_point == NULL) and it's not marked 201 * as fully rolled (sblock.fs_rolled != FS_ALL_ROLLED) 202 * 2. If it's mounted and anything other than a sanity 203 * check fsck (mflag) is being done, as we have the current 204 * super block. Note, only a sanity check is done for 205 * root/usr at boot. If a roll were done then the expensive 206 * ufs_flush() gets called, leading to a slower boot. 207 * 3. If anything other then a sanity check (mflag) is being done 208 * to a mounted filesystem while it is in read-only state 209 * (e.g. root during early boot stages) we have to detect this 210 * and have to roll the log as well. NB. the read-only mount 211 * will flip fs_clean from FSLOG to FSSTABLE and marks the 212 * log as FS_NEED_ROLL. 213 */ 214 if (sblock.fs_logbno && 215 (((mount_point == NULL) && (sblock.fs_rolled != FS_ALL_ROLLED)) || 216 (mount_point && !mflag))) { 217 int roll_log_err = 0; 218 219 if (sblock.fs_ronly && (sblock.fs_clean == FSSTABLE) && 220 (sblock.fs_state + sblock.fs_time == FSOKAY)) { 221 /* 222 * roll the log without a mount 223 */ 224 flush_fs(); 225 } 226 if (sblock.fs_clean == FSLOG && 227 (sblock.fs_state + sblock.fs_time == FSOKAY)) { 228 if (rl_roll_log(devstr) != RL_SUCCESS) 229 roll_log_err = 1; 230 } 231 if (roll_log_err) { 232 (void) printf("Can't roll the log for %s.\n", devstr); 233 /* 234 * There are two cases where we want to set 235 * an error code and return: 236 * - We're preening 237 * - We're not on a live root and the user 238 * chose *not* to ignore the log 239 * Otherwise, we want to mark the log as bad 240 * and continue to check the filesystem. This 241 * has the side effect of destroying the log. 242 */ 243 if (preen || (!hotroot && 244 reply( 245 "DISCARDING THE LOG MAY DISCARD PENDING TRANSACTIONS.\n" 246 "DISCARD THE LOG AND CONTINUE") == 0)) { 247 exitstat = 39; 248 return (0); 249 } 250 ++badlog; 251 } 252 } 253 254 /* MDD (disksuite) device */ 255 if (ioctl(fsreadfd, DKIOCINFO, &dkcinfo) == 0) 256 if (dkcinfo.dki_ctype == DKC_MD) 257 ++ismdd; 258 259 /* Logging UFS may be enabled */ 260 if (sblock.fs_logbno) { 261 ++islog; 262 263 /* log is not okay; check the fs */ 264 if (FSOKAY != (sblock.fs_state + sblock.fs_time)) 265 return (1); 266 267 /* 268 * If logging or (stable and mounted) then continue 269 */ 270 if ((sblock.fs_clean != FSLOG) && 271 ((sblock.fs_clean != FSSTABLE) || !(mount_point))) 272 return (1); 273 274 /* get the log allocation block */ 275 buf = malloc((size_t)dev_bsize); 276 if (buf == (void *) NULL) { 277 return (1); 278 } 279 ud_buf = malloc((size_t)dev_bsize); 280 if (ud_buf == (void *) NULL) { 281 free(buf); 282 return (1); 283 } 284 (void) bread(fsreadfd, buf, 285 logbtodb(&sblock, sblock.fs_logbno), 286 (long)dev_bsize); 287 ebp = (extent_block_t *)buf; 288 289 /* log allocation block is not okay; check the fs */ 290 if (ebp->type != LUFS_EXTENTS) { 291 free(buf); 292 free(ud_buf); 293 return (1); 294 } 295 296 /* get the log state block(s) */ 297 if (bread(fsreadfd, ud_buf, 298 (logbtodb(&sblock, ebp->extents[0].pbno)), 299 (long)dev_bsize)) { 300 (void) bread(fsreadfd, ud_buf, 301 (logbtodb(&sblock, ebp->extents[0].pbno)) + 1, 302 (long)dev_bsize); 303 } 304 ud = (ml_odunit_t *)ud_buf; 305 ul = (ml_unit_t *)malloc(sizeof (*ul)); 306 if (ul == NULL) { 307 free(buf); 308 free(ud_buf); 309 return (1); 310 } 311 ul->un_ondisk = *ud; 312 313 /* log state is okay; don't need to check the fs */ 314 if ((ul->un_chksum == ul->un_head_ident + ul->un_tail_ident) && 315 (ul->un_version == LUFS_VERSION_LATEST) && 316 (ul->un_badlog == 0) && (!badlog)) 317 ++islogok; 318 free(ud_buf); 319 free(buf); 320 free(ul); 321 } else if (ismdd) { 322 /* if it is a logging device and there are no errors */ 323 if (ioctl(fsreadfd, _FIOISLOG, NULL) == 0) { 324 islog++; 325 if (ioctl(fsreadfd, _FIOISLOGOK, NULL) == 0) 326 islogok++; 327 } 328 } 329 330 return (1); 331 } 332 333 char * 334 setup(char *dev) 335 { 336 dev_t rootdev; 337 int size, i, j; 338 int64_t bmapsize; 339 struct stat64 statb; 340 static char devstr[MAXPATHLEN]; 341 char *raw, *rawname(), *unrawname(); 342 void write_altsb(); 343 struct ustat ustatb; 344 caddr_t sip; 345 int mountchk; 346 347 havesb = 0; 348 if (stat64("/", &statb) < 0) 349 errexit("Can't stat root\n"); 350 rootdev = statb.st_dev; 351 352 devname = devstr; 353 strncpy(devstr, dev, sizeof (devstr)); 354 restat: 355 if (stat64(devstr, &statb) < 0) { 356 printf("Can't stat %s\n", devstr); 357 exitstat = 34; 358 return (0); 359 } 360 /* 361 * A mount point is specified. But the mount point doesn't 362 * match entries in the /etc/vfstab. 363 * Search mnttab, because if the fs is error locked, it is 364 * allowed to be fsck'd while mounted. 365 */ 366 if ((statb.st_mode & S_IFMT) == S_IFDIR) { 367 if (errorlocked) { 368 FILE *mnttab; 369 struct mnttab mnt, mntpref, 370 *mntp = &mnt, 371 *mpref = &mntpref; 372 373 if ((mnttab = fopen(MNTTAB, "r")) == NULL) { 374 printf("Can't open %s\n", MNTTAB); 375 perror(MNTTAB); 376 return (0); 377 } 378 379 mntnull(mpref); 380 mpref->mnt_fstype = malloc(strlen(MNTTYPE_UFS)+1); 381 mpref->mnt_mountp = malloc(strlen(devstr)+1); 382 strcpy(mpref->mnt_fstype, MNTTYPE_UFS); 383 strcpy(mpref->mnt_mountp, devstr); 384 mntnull(mntp); 385 386 if (getmntany(mnttab, mntp, mpref) == 0) { 387 raw = rawname(unrawname(mntp->mnt_special)); 388 strcpy(devstr, raw); 389 fclose(mnttab); 390 goto restat; 391 } 392 fclose(mnttab); 393 } 394 printf("%s is not a block or character device\n", dev); 395 return (0); 396 } 397 398 if ((statb.st_mode & S_IFMT) == S_IFBLK) { 399 if (rootdev == statb.st_rdev) { 400 mount_point = "/"; 401 hotroot++; 402 } else if (ustat(statb.st_rdev, &ustatb) == 0 && !errorlocked) { 403 printf("%s is a mounted file system, ignored\n", dev); 404 exitstat = 33; 405 return (0); 406 } 407 } 408 if ((statb.st_mode & S_IFMT) == S_IFDIR) { 409 FILE *vfstab; 410 struct vfstab vfsbuf; 411 /* 412 * Check vfstab for a mount point with this name 413 */ 414 if ((vfstab = fopen(VFSTAB, "r")) == NULL) { 415 errexit("Can't open checklist file: %s\n", VFSTAB); 416 } 417 while (getvfsent(vfstab, &vfsbuf) == NULL) { 418 if (strcmp(devstr, vfsbuf.vfs_mountp) == 0) { 419 if (strcmp(vfsbuf.vfs_fstype, 420 MNTTYPE_UFS) != 0) { 421 /* 422 * found the entry but it is not a 423 * ufs filesystem, don't check it 424 */ 425 fclose(vfstab); 426 return (0); 427 } 428 strcpy(devstr, vfsbuf.vfs_special); 429 if (rflag) { 430 raw = rawname( 431 unrawname(vfsbuf.vfs_special)); 432 strcpy(devstr, raw); 433 } 434 goto restat; 435 } 436 } 437 fclose(vfstab); 438 439 } else if (((statb.st_mode & S_IFMT) != S_IFBLK) && 440 ((statb.st_mode & S_IFMT) != S_IFCHR)) { 441 if (preen) 442 pwarn("file is not a block or character device.\n"); 443 else if (reply("file is not a block or character device; OK") 444 == 0) 445 return (0); 446 /* 447 * To fsck regular files (fs images) 448 * we need to clear the rflag since 449 * regular files don't have raw names. --CW 450 */ 451 rflag = 0; 452 } 453 454 if (mountchk = mounted(devstr)) { 455 if (rflag) { 456 mountedfs++; 457 /* 458 * Get confirmation we should continue UNLESS: 459 * this is the root (since that is always 460 * mounted), we are running in preen mode, we 461 * are running in "just say no" mode, the fs is 462 * mounted read-only, or we are running in check 463 * only mode. 464 */ 465 if (rootdev != statb.st_rdev && !preen && !nflag && 466 !mflag && mountchk != 2) { 467 if (reply("FILE SYSTEM IS CURRENTLY MOUNTED." 468 " CONTINUE") == 0) { 469 exitstat = 33; 470 return (0); 471 } 472 } 473 } else { 474 printf("%s is mounted, fsck on BLOCK device ignored\n", 475 devstr); 476 exit(33); 477 } 478 if (!errorlocked) 479 sync(); /* call sync, only when devstr's mounted */ 480 } 481 if (rflag) { 482 char blockname[MAXPATHLEN]; 483 /* 484 * For root device check, must check 485 * block devices. 486 */ 487 strcpy(blockname, devstr); 488 if (stat64(unrawname(blockname), &statb) < 0) { 489 printf("Can't stat %s\n", blockname); 490 exitstat = 34; 491 return (0); 492 } 493 } 494 if (rootdev == statb.st_rdev) { 495 hotroot++; 496 mount_point = "/"; 497 } 498 if ((fsreadfd = open64(devstr, O_RDONLY)) < 0) { 499 printf("Can't open %s\n", devstr); 500 exitstat = 34; 501 return (0); 502 } 503 if (preen == 0 || debug != 0) 504 printf("** %s", devstr); 505 506 if (errorlocked) { 507 if (debug && elock_combuf) 508 printf(" error-lock comment: \"%s\" ", elock_combuf); 509 fflag = 1; 510 } 511 pid = getpid(); 512 if (nflag || (fswritefd = open64(devstr, O_WRONLY)) < 0) { 513 fswritefd = -1; 514 if (preen && !debug) 515 pfatal("(NO WRITE ACCESS)\n"); 516 printf(" (NO WRITE)"); 517 } 518 if (preen == 0) 519 printf("\n"); 520 else if (debug) 521 printf(" pid %d\n", pid); 522 if (debug && (hotroot || mountedfs)) { 523 printf("** %s", devstr); 524 if (hotroot) 525 printf(" is root fs%s", 526 mountedfs || errorlocked? " and": ""); 527 if (mountedfs) 528 printf(" is mounted%s", errorlocked? " and": ""); 529 if (errorlocked) 530 printf(" is error-locked"); 531 532 printf(".\n"); 533 } 534 fsmodified = 0; 535 if (errorlocked) 536 isdirty = 1; 537 lfdir = 0; 538 initbarea(&sblk); 539 initbarea(&asblk); 540 sblk.b_un.b_buf = malloc(SBSIZE); 541 asblk.b_un.b_buf = malloc(SBSIZE); 542 if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) 543 errexit("cannot allocate space for superblock\n"); 544 dev_bsize = secsize = DEV_BSIZE; 545 546 /* Check log state (embedded and SDS) */ 547 if (!logsetup(devstr)) 548 return (0); 549 550 /* 551 * Flush fs if we're going to do anything other than a sanity check. 552 * Note, if logging then the fs was flushed if needed in logsetup(). 553 */ 554 if (!islog && !mflag) 555 flush_fs(); 556 557 if (!read_super_block()) /* re-read sb after possibly rolling the log */ 558 return (0); 559 /* 560 * Check the superblock, looking for alternates if necessary 561 */ 562 if (checksb(1) == 0) 563 return (0); 564 maxfsblock = sblock.fs_size; 565 maxino = sblock.fs_ncg * sblock.fs_ipg; 566 /* 567 * Check and potentially fix certain fields in the super block. 568 */ 569 if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { 570 pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); 571 if (reply("SET TO DEFAULT") == 1) { 572 sblock.fs_optim = FS_OPTTIME; 573 sbdirty(); 574 } 575 } 576 if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) { 577 pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", 578 sblock.fs_minfree); 579 if (reply("SET TO DEFAULT") == 1) { 580 sblock.fs_minfree = 10; 581 sbdirty(); 582 } 583 } 584 if (cvtflag) { 585 if (sblock.fs_postblformat == FS_42POSTBLFMT) { 586 /* 587 * Requested to convert from old format to new format 588 */ 589 if (preen) 590 pwarn("CONVERTING TO NEW FILE SYSTEM FORMAT\n"); 591 else if (!reply("CONVERT TO NEW FILE SYSTEM FORMAT")) 592 return (0); 593 isconvert = 1; 594 sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; 595 sblock.fs_nrpos = 8; 596 sblock.fs_npsect = sblock.fs_nsect; 597 sblock.fs_postbloff = 598 (char *)(&sblock.fs_opostbl[0][0]) - 599 (char *)(&sblock.fs_link); 600 sblock.fs_rotbloff = &sblock.fs_space[0] - 601 (uchar_t *)(&sblock.fs_link); 602 sblock.fs_cgsize = 603 fragroundup(&sblock, CGSIZE(&sblock)); 604 /* 605 * Planning now for future expansion. 606 */ 607 #if defined(_BIG_ENDIAN) 608 sblock.fs_qbmask.val[0] = 0; 609 sblock.fs_qbmask.val[1] = ~sblock.fs_bmask; 610 sblock.fs_qfmask.val[0] = 0; 611 sblock.fs_qfmask.val[1] = ~sblock.fs_fmask; 612 #endif 613 #if defined(_LITTLE_ENDIAN) 614 sblock.fs_qbmask.val[0] = ~sblock.fs_bmask; 615 sblock.fs_qbmask.val[1] = 0; 616 sblock.fs_qfmask.val[0] = ~sblock.fs_fmask; 617 sblock.fs_qfmask.val[1] = 0; 618 #endif 619 /* make mountable */ 620 sblock.fs_state = FSOKAY - sblock.fs_time; 621 sblock.fs_clean = FSCLEAN; 622 sbdirty(); 623 write_altsb(fswritefd); 624 } else if (sblock.fs_postblformat == FS_DYNAMICPOSTBLFMT) { 625 /* 626 * Requested to convert from new format to old format 627 */ 628 if (sblock.fs_nrpos != 8 || sblock.fs_ipg > 2048 || 629 sblock.fs_cpg > 32 || sblock.fs_cpc > 16) { 630 printf( 631 "PARAMETERS OF CURRENT FILE SYSTEM DO NOT\n\t"); 632 errexit( 633 "ALLOW CONVERSION TO OLD FILE SYSTEM FORMAT\n"); 634 } 635 if (preen) 636 pwarn("CONVERTING TO OLD FILE SYSTEM FORMAT\n"); 637 else if (!reply("CONVERT TO OLD FILE SYSTEM FORMAT")) 638 return (0); 639 isconvert = 1; 640 sblock.fs_postblformat = FS_42POSTBLFMT; 641 sblock.fs_cgsize = fragroundup(&sblock, 642 sizeof (struct ocg) + howmany(sblock.fs_fpg, NBBY)); 643 sblock.fs_npsect = 0; 644 /* make mountable */ 645 sblock.fs_state = FSOKAY - sblock.fs_time; 646 sblock.fs_clean = FSCLEAN; 647 sbdirty(); 648 write_altsb(fswritefd); 649 } else { 650 errexit("UNKNOWN FILE SYSTEM FORMAT\n"); 651 } 652 } 653 if (errorlocked) { 654 /* do this right away to prevent any other fscks on this fs */ 655 switch (sblock.fs_clean) { 656 case FSBAD: 657 break; 658 case FSFIX: 659 if (preen) 660 errexit("ERROR-LOCKED; MARKED \"FSFIX\"\n"); 661 if (reply("marked FSFIX, CONTINUE") == 0) 662 return (0); 663 break; 664 case FSCLEAN: 665 if (preen) 666 errexit("ERROR-LOCKED; MARKED \"FSCLEAN\"\n"); 667 if (reply("marked FSCLEAN, CONTINUE") == 0) 668 return (0); 669 break; 670 default: 671 if (preen) { 672 if (debug) 673 pwarn("ERRORLOCKED; NOT MARKED \"FSBAD\"\n"); 674 else 675 errexit("ERRORLOCKED; NOT MARKED \"FSBAD\"\n"); 676 } else { 677 if (reply("error-locked, but not marked \"FSBAD\"; CONTINUE") == 0) 678 return (0); 679 } 680 break; 681 } 682 683 if (!do_errorlock(LOCKFS_ELOCK)) { 684 if (preen) 685 return (0); 686 if (reply("error-lock reset failed; CONTINUE") == 0) 687 return (0); 688 } 689 690 sblock.fs_state = FSOKAY - (long)sblock.fs_time; 691 sblock.fs_clean = FSFIX; 692 sbdirty(); 693 write_altsb(fswritefd); 694 } 695 /* 696 * read in the summary info. 697 */ 698 sip = calloc(1, sblock.fs_cssize); 699 if (sip == NULL) 700 errexit("cannot allocate space for cylinder group summary\n"); 701 sblock.fs_u.fs_csp = (struct csum *)((void *)sip); 702 for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { 703 size = sblock.fs_cssize - i < sblock.fs_bsize ? 704 sblock.fs_cssize - i : sblock.fs_bsize; 705 if (bread(fsreadfd, sip, 706 fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), 707 (long)size) != 0) 708 return (0); 709 sip += size; 710 } 711 /* 712 * if not error-locked, 713 * not bad log, not forced, preening, not converting, and is clean; 714 * stop checking 715 */ 716 if (!errorlocked && 717 ((!islog || islogok) && 718 (fflag == 0) && preen && (isconvert == 0) && 719 (FSOKAY == (sblock.fs_state + sblock.fs_time)) && 720 ((sblock.fs_clean == FSLOG && islog) || 721 ((sblock.fs_clean == FSCLEAN) || (sblock.fs_clean == FSSTABLE))))) { 722 iscorrupt = 0; 723 printclean(); 724 return (0); 725 } 726 /* 727 * allocate and initialize the necessary maps 728 */ 729 bmapsize = roundup(howmany((uint64_t)maxfsblock, NBBY), 730 sizeof (short)); 731 blockmap = calloc((size_t)bmapsize, sizeof (char)); 732 if (blockmap == NULL) { 733 printf("cannot alloc %lld bytes for blockmap\n", bmapsize); 734 goto badsb; 735 } 736 statemap = calloc((size_t)(maxino + 1), sizeof (char)); 737 if (statemap == NULL) { 738 printf("cannot alloc %d bytes for statemap\n", maxino + 1); 739 goto badsb; 740 } 741 lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof (short)); 742 if (lncntp == NULL) { 743 printf("cannot alloc %d bytes for lncntp\n", 744 (maxino + 1) * sizeof (short)); 745 goto badsb; 746 } 747 numdirs = sblock.fs_cstotal.cs_ndir; 748 listmax = numdirs + 10; 749 inpsort = (struct inoinfo **)calloc((unsigned)listmax, 750 sizeof (struct inoinfo *)); 751 inphead = (struct inoinfo **)calloc((unsigned)numdirs, 752 sizeof (struct inoinfo *)); 753 if (inpsort == NULL || inphead == NULL) { 754 printf("cannot alloc %d bytes for inphead\n", 755 numdirs * sizeof (struct inoinfo *)); 756 goto badsb; 757 } 758 numacls = numdirs; 759 aclmax = numdirs + 10; 760 aclpsort = (struct aclinfo **)calloc((unsigned)aclmax, 761 sizeof (struct aclinfo *)); 762 aclphead = (struct aclinfo **)calloc((unsigned)numacls, 763 sizeof (struct aclinfo *)); 764 if (aclpsort == NULL || aclphead == NULL) { 765 printf("cannot alloc %d bytes for aclphead\n", 766 numacls * sizeof (struct inoinfo *)); 767 goto badsb; 768 } 769 aclplast = 0L; 770 inplast = 0L; 771 bufinit(); 772 return (devstr); 773 774 badsb: 775 ckfini(); 776 exitstat = 39; 777 return (0); 778 } 779 780 /* 781 * mkfs limits the size of the inode map to be no more than a third of 782 * the cylinder group space. We'll use that value for sanity checking 783 * the superblock's inode per group value. 784 */ 785 #define MAXIpG (roundup(sblock.fs_bsize * NBBY / 3, sblock.fs_inopb)) 786 787 /* 788 * Check the super block and its summary info. 789 */ 790 static int 791 checksb(int listerr) 792 { 793 /* 794 * When the fs check is successfully completed, the alternate super 795 * block at sblk.b_bno will be overwritten by ckfini() with the 796 * repaired super block. 797 */ 798 sblk.b_bno = bflag ? bflag : SBOFF / dev_bsize; 799 sblk.b_size = SBSIZE; 800 801 /* 802 * Add some extra hardening checks per bug 1253090. Also sanity 803 * check some of the values we are going to use later in allocation 804 * requests. 805 */ 806 if (sblock.fs_cstotal.cs_ndir < 1 || 807 sblock.fs_cstotal.cs_ndir > sblock.fs_ncg * sblock.fs_ipg) { 808 badsb(listerr, "NUMBER OF DIRECTORIES OUT OF RANGE"); 809 return (0); 810 } 811 812 if (sblock.fs_nrpos <= 0 || sblock.fs_postbloff < 0 || 813 sblock.fs_cpc < 0 || 814 (sblock.fs_postbloff + 815 (sblock.fs_nrpos * sblock.fs_cpc * sizeof (short))) > 816 sblock.fs_sbsize) { 817 badsb(listerr, "ROTATIONAL POSITION TABLE SIZE OUT OF RANGE"); 818 return (0); 819 } 820 821 if (sblock.fs_cssize != 822 fragroundup(&sblock, sblock.fs_ncg * sizeof (struct csum))) { 823 badsb(listerr, "SIZE OF CYLINDER GROUP SUMMARY AREA WRONG"); 824 return (0); 825 } 826 827 if (sblock.fs_inopb != (sblock.fs_bsize / sizeof (struct dinode))) { 828 badsb(listerr, "INOPB NONSENSICAL RELATIVE TO BSIZE"); 829 return (0); 830 } 831 832 if (sblock.fs_bsize != (sblock.fs_frag * sblock.fs_fsize)) { 833 badsb(listerr, "FRAGS PER BLOCK OR FRAG SIZE WRONG"); 834 return (0); 835 } 836 837 if (sblock.fs_dsize >= sblock.fs_size) { 838 badsb(listerr, "NUMBER OF DATA BLOCKS OUT OF RANGE"); 839 return (0); 840 } 841 842 /* 843 * Check that the number of inodes per group isn't less than or 844 * equal to zero. Also makes sure it isn't more than the 845 * maximum number mkfs enforces. 846 */ 847 if (sblock.fs_ipg <= 0 || sblock.fs_ipg > MAXIpG) { 848 badsb(listerr, "INODES PER GROUP OUT OF RANGE"); 849 return (0); 850 } 851 852 /* 853 * Set all possible fields that could differ, then do check 854 * of whole super block against an alternate super block. 855 * When an alternate super-block is specified this check is skipped. 856 */ 857 getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), 858 sblock.fs_sbsize); 859 if (asblk.b_errs) 860 return (0); 861 if (bflag) { 862 /* 863 * Invalidate clean flag and state information 864 */ 865 sblock.fs_clean = FSACTIVE; 866 sblock.fs_state = (long)sblock.fs_time; 867 sblock.fs_reclaim = 0; 868 sbdirty(); 869 havesb = 1; 870 return (1); 871 } 872 /* 873 * fsck should ignore deleted files because the reclaim thread 874 * will run at mount and reclaim them 875 */ 876 isreclaim = (sblock.fs_reclaim & (FS_RECLAIMING | FS_RECLAIM)); 877 willreclaim = (isreclaim && islog && islogok && !fflag); 878 879 altsblock.fs_link = sblock.fs_link; 880 altsblock.fs_rolled = sblock.fs_rolled; 881 altsblock.fs_time = sblock.fs_time; 882 altsblock.fs_state = sblock.fs_state; 883 altsblock.fs_cstotal = sblock.fs_cstotal; 884 altsblock.fs_cgrotor = sblock.fs_cgrotor; 885 altsblock.fs_fmod = sblock.fs_fmod; 886 altsblock.fs_clean = sblock.fs_clean; 887 altsblock.fs_ronly = sblock.fs_ronly; 888 altsblock.fs_flags = sblock.fs_flags; 889 altsblock.fs_maxcontig = sblock.fs_maxcontig; 890 altsblock.fs_minfree = sblock.fs_minfree; 891 altsblock.fs_optim = sblock.fs_optim; 892 altsblock.fs_rotdelay = sblock.fs_rotdelay; 893 altsblock.fs_maxbpg = sblock.fs_maxbpg; 894 altsblock.fs_logbno = sblock.fs_logbno; 895 altsblock.fs_reclaim = sblock.fs_reclaim; 896 altsblock.fs_si = sblock.fs_si; 897 bcopy((char *)sblock.fs_fsmnt, (char *)altsblock.fs_fsmnt, 898 sizeof (sblock.fs_fsmnt)); 899 bcopy((char *)sblock.fs_u.fs_csp_pad, (char *)altsblock.fs_u.fs_csp_pad, 900 sizeof (sblock.fs_u.fs_csp_pad)); 901 /* 902 * The following should not have to be copied. 903 */ 904 altsblock.fs_fsbtodb = sblock.fs_fsbtodb; 905 altsblock.fs_npsect = sblock.fs_npsect; 906 altsblock.fs_nrpos = sblock.fs_nrpos; 907 if (bcmp((char *)&sblock, (char *)&altsblock, 908 (size_t)sblock.fs_sbsize)) { 909 badsb(listerr, "BAD VALUES IN SUPER BLOCK"); return (0); 910 } 911 havesb = 1; 912 return (1); 913 } 914 915 static void 916 badsb(int listerr, char *s) 917 { 918 if (!listerr) 919 return; 920 if (preen) 921 printf("%s: ", devname); 922 printf("BAD SUPER BLOCK: %s\n", s); 923 pwarn("USE AN ALTERNATE SUPER-BLOCK TO SUPPLY NEEDED INFORMATION;\n"); 924 pwarn("eg. fsck [-F ufs] -o b=# [special ...] \n"); 925 pfatal("where # is the alternate super block. SEE fsck_ufs(1M). \n"); 926 exitstat = 39; 927 } 928 929 /* 930 * Write out the super block into each of the alternate super blocks. 931 */ 932 void 933 write_altsb(int fd) 934 { 935 int cylno; 936 937 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 938 bwrite(fd, (char *)&sblock, fsbtodb(&sblock, 939 cgsblock(&sblock, cylno)), sblock.fs_sbsize); 940 } 941