1 /* 2 * unix.c - The unix-specific code for e2fsck 3 * 4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Public 8 * License. 9 * %End-Header% 10 */ 11 12 #define _XOPEN_SOURCE 600 /* for inclusion of sa_handler in Solaris */ 13 14 #include "config.h" 15 #include <stdio.h> 16 #ifdef HAVE_STDLIB_H 17 #include <stdlib.h> 18 #endif 19 #include <string.h> 20 #include <fcntl.h> 21 #include <ctype.h> 22 #include <time.h> 23 #ifdef HAVE_SIGNAL_H 24 #include <signal.h> 25 #endif 26 #ifdef HAVE_GETOPT_H 27 #include <getopt.h> 28 #else 29 extern char *optarg; 30 extern int optind; 31 #endif 32 #include <unistd.h> 33 #ifdef HAVE_ERRNO_H 34 #include <errno.h> 35 #endif 36 #ifdef HAVE_SYS_IOCTL_H 37 #include <sys/ioctl.h> 38 #endif 39 #ifdef HAVE_MALLOC_H 40 #include <malloc.h> 41 #endif 42 #ifdef HAVE_SYS_TYPES_H 43 #include <sys/types.h> 44 #endif 45 #ifdef HAVE_DIRENT_H 46 #include <dirent.h> 47 #endif 48 #include <libgen.h> 49 50 #include "e2p/e2p.h" 51 #include "et/com_err.h" 52 #include "e2p/e2p.h" 53 #include "support/plausible.h" 54 #include "e2fsck.h" 55 #include "problem.h" 56 #include "jfs_user.h" 57 #include "../version.h" 58 59 /* Command line options */ 60 static int cflag; /* check disk */ 61 static int show_version_only; 62 static int verbose; 63 64 static int replace_bad_blocks; 65 static int keep_bad_blocks; 66 static char *bad_blocks_file; 67 68 e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */ 69 70 #ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jbd-debug */ 71 int journal_enable_debug = -1; 72 #endif 73 74 static void usage(e2fsck_t ctx) 75 { 76 fprintf(stderr, 77 _("Usage: %s [-panyrcdfktvDFV] [-b superblock] [-B blocksize]\n" 78 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n" 79 "\t\t[-E extended-options] [-z undo_file] device\n"), 80 ctx->program_name); 81 82 fprintf(stderr, "%s", _("\nEmergency help:\n" 83 " -p Automatic repair (no questions)\n" 84 " -n Make no changes to the filesystem\n" 85 " -y Assume \"yes\" to all questions\n" 86 " -c Check for bad blocks and add them to the badblock list\n" 87 " -f Force checking even if filesystem is marked clean\n")); 88 fprintf(stderr, "%s", _("" 89 " -v Be verbose\n" 90 " -b superblock Use alternative superblock\n" 91 " -B blocksize Force blocksize when looking for superblock\n" 92 " -j external_journal Set location of the external journal\n" 93 " -l bad_blocks_file Add to badblocks list\n" 94 " -L bad_blocks_file Set badblocks list\n" 95 " -z undo_file Create an undo file\n" 96 )); 97 98 exit(FSCK_USAGE); 99 } 100 101 static void show_stats(e2fsck_t ctx) 102 { 103 ext2_filsys fs = ctx->fs; 104 ext2_ino_t inodes, inodes_used; 105 blk64_t blocks, blocks_used; 106 unsigned int dir_links; 107 unsigned int num_files, num_links; 108 __u32 *mask, m; 109 int frag_percent_file, frag_percent_dir, frag_percent_total; 110 int i, j, printed = 0; 111 112 dir_links = 2 * ctx->fs_directory_count - 1; 113 num_files = ctx->fs_total_count - dir_links; 114 num_links = ctx->fs_links_count - dir_links; 115 inodes = fs->super->s_inodes_count; 116 inodes_used = (fs->super->s_inodes_count - 117 fs->super->s_free_inodes_count); 118 blocks = ext2fs_blocks_count(fs->super); 119 blocks_used = (ext2fs_blocks_count(fs->super) - 120 ext2fs_free_blocks_count(fs->super)); 121 122 frag_percent_file = (10000 * ctx->fs_fragmented) / inodes_used; 123 frag_percent_file = (frag_percent_file + 5) / 10; 124 125 frag_percent_dir = (10000 * ctx->fs_fragmented_dir) / inodes_used; 126 frag_percent_dir = (frag_percent_dir + 5) / 10; 127 128 frag_percent_total = ((10000 * (ctx->fs_fragmented + 129 ctx->fs_fragmented_dir)) 130 / inodes_used); 131 frag_percent_total = (frag_percent_total + 5) / 10; 132 133 if (!verbose) { 134 log_out(ctx, _("%s: %u/%u files (%0d.%d%% non-contiguous), " 135 "%llu/%llu blocks\n"), 136 ctx->device_name, inodes_used, inodes, 137 frag_percent_total / 10, frag_percent_total % 10, 138 blocks_used, blocks); 139 return; 140 } 141 profile_get_boolean(ctx->profile, "options", "report_features", 0, 0, 142 &i); 143 if (verbose && i) { 144 log_out(ctx, "\nFilesystem features:"); 145 mask = &ctx->fs->super->s_feature_compat; 146 for (i = 0; i < 3; i++, mask++) { 147 for (j = 0, m = 1; j < 32; j++, m <<= 1) { 148 if (*mask & m) { 149 log_out(ctx, " %s", 150 e2p_feature2string(i, m)); 151 printed++; 152 } 153 } 154 } 155 if (printed == 0) 156 log_out(ctx, " (none)"); 157 log_out(ctx, "\n"); 158 } 159 160 log_out(ctx, P_("\n%12u inode used (%2.2f%%, out of %u)\n", 161 "\n%12u inodes used (%2.2f%%, out of %u)\n", 162 inodes_used), inodes_used, 163 100.0 * inodes_used / inodes, inodes); 164 log_out(ctx, P_("%12u non-contiguous file (%0d.%d%%)\n", 165 "%12u non-contiguous files (%0d.%d%%)\n", 166 ctx->fs_fragmented), 167 ctx->fs_fragmented, frag_percent_file / 10, 168 frag_percent_file % 10); 169 log_out(ctx, P_("%12u non-contiguous directory (%0d.%d%%)\n", 170 "%12u non-contiguous directories (%0d.%d%%)\n", 171 ctx->fs_fragmented_dir), 172 ctx->fs_fragmented_dir, frag_percent_dir / 10, 173 frag_percent_dir % 10); 174 log_out(ctx, _(" # of inodes with ind/dind/tind blocks: " 175 "%u/%u/%u\n"), 176 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count); 177 178 for (j=MAX_EXTENT_DEPTH_COUNT-1; j >=0; j--) 179 if (ctx->extent_depth_count[j]) 180 break; 181 if (++j) { 182 log_out(ctx, "%s", _(" Extent depth histogram: ")); 183 for (i=0; i < j; i++) { 184 if (i) 185 fputc('/', stdout); 186 log_out(ctx, "%u", ctx->extent_depth_count[i]); 187 } 188 log_out(ctx, "\n"); 189 } 190 191 log_out(ctx, P_("%12llu block used (%2.2f%%, out of %llu)\n", 192 "%12llu blocks used (%2.2f%%, out of %llu)\n", 193 blocks_used), 194 blocks_used, 100.0 * blocks_used / blocks, blocks); 195 log_out(ctx, P_("%12u bad block\n", "%12u bad blocks\n", 196 ctx->fs_badblocks_count), ctx->fs_badblocks_count); 197 log_out(ctx, P_("%12u large file\n", "%12u large files\n", 198 ctx->large_files), ctx->large_files); 199 log_out(ctx, P_("\n%12u regular file\n", "\n%12u regular files\n", 200 ctx->fs_regular_count), ctx->fs_regular_count); 201 log_out(ctx, P_("%12u directory\n", "%12u directories\n", 202 ctx->fs_directory_count), ctx->fs_directory_count); 203 log_out(ctx, P_("%12u character device file\n", 204 "%12u character device files\n", ctx->fs_chardev_count), 205 ctx->fs_chardev_count); 206 log_out(ctx, P_("%12u block device file\n", "%12u block device files\n", 207 ctx->fs_blockdev_count), ctx->fs_blockdev_count); 208 log_out(ctx, P_("%12u fifo\n", "%12u fifos\n", ctx->fs_fifo_count), 209 ctx->fs_fifo_count); 210 log_out(ctx, P_("%12u link\n", "%12u links\n", num_links), 211 ctx->fs_links_count - dir_links); 212 log_out(ctx, P_("%12u symbolic link", "%12u symbolic links", 213 ctx->fs_symlinks_count), ctx->fs_symlinks_count); 214 log_out(ctx, P_(" (%u fast symbolic link)\n", 215 " (%u fast symbolic links)\n", 216 ctx->fs_fast_symlinks_count), 217 ctx->fs_fast_symlinks_count); 218 log_out(ctx, P_("%12u socket\n", "%12u sockets\n", 219 ctx->fs_sockets_count), 220 ctx->fs_sockets_count); 221 log_out(ctx, "------------\n"); 222 log_out(ctx, P_("%12u file\n", "%12u files\n", num_files), 223 num_files); 224 } 225 226 static void check_mount(e2fsck_t ctx) 227 { 228 errcode_t retval; 229 int cont; 230 231 retval = ext2fs_check_if_mounted(ctx->filesystem_name, 232 &ctx->mount_flags); 233 if (retval) { 234 com_err("ext2fs_check_if_mount", retval, 235 _("while determining whether %s is mounted."), 236 ctx->filesystem_name); 237 return; 238 } 239 240 /* 241 * If the filesystem isn't mounted, or it's the root 242 * filesystem and it's mounted read-only, and we're not doing 243 * a read/write check, then everything's fine. 244 */ 245 if ((!(ctx->mount_flags & (EXT2_MF_MOUNTED | EXT2_MF_BUSY))) || 246 ((ctx->mount_flags & EXT2_MF_ISROOT) && 247 (ctx->mount_flags & EXT2_MF_READONLY) && 248 !(ctx->options & E2F_OPT_WRITECHECK))) 249 return; 250 251 if (((ctx->options & E2F_OPT_READONLY) || 252 ((ctx->options & E2F_OPT_FORCE) && 253 (ctx->mount_flags & EXT2_MF_READONLY))) && 254 !(ctx->options & E2F_OPT_WRITECHECK)) { 255 if (ctx->mount_flags & EXT2_MF_MOUNTED) 256 log_out(ctx, _("Warning! %s is mounted.\n"), 257 ctx->filesystem_name); 258 else 259 log_out(ctx, _("Warning! %s is in use.\n"), 260 ctx->filesystem_name); 261 return; 262 } 263 264 if (ctx->mount_flags & EXT2_MF_MOUNTED) 265 log_out(ctx, _("%s is mounted.\n"), ctx->filesystem_name); 266 else 267 log_out(ctx, _("%s is in use.\n"), ctx->filesystem_name); 268 if (!ctx->interactive || ctx->mount_flags & EXT2_MF_BUSY) 269 fatal_error(ctx, _("Cannot continue, aborting.\n\n")); 270 puts("\007\007\007\007"); 271 log_out(ctx, "%s", _("\n\nWARNING!!! " 272 "The filesystem is mounted. " 273 "If you continue you ***WILL***\n" 274 "cause ***SEVERE*** filesystem damage.\n\n")); 275 puts("\007\007\007"); 276 cont = ask_yn(ctx, _("Do you really want to continue"), 0); 277 if (!cont) { 278 printf("%s", _("check aborted.\n")); 279 exit (0); 280 } 281 return; 282 } 283 284 static int is_on_batt(void) 285 { 286 FILE *f; 287 DIR *d; 288 char tmp[80], tmp2[80], fname[80]; 289 unsigned int acflag; 290 struct dirent* de; 291 292 f = fopen("/sys/class/power_supply/AC/online", "r"); 293 if (f) { 294 if (fscanf(f, "%u\n", &acflag) == 1) { 295 fclose(f); 296 return (!acflag); 297 } 298 fclose(f); 299 } 300 f = fopen("/proc/apm", "r"); 301 if (f) { 302 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4) 303 acflag = 1; 304 fclose(f); 305 return (acflag != 1); 306 } 307 d = opendir("/proc/acpi/ac_adapter"); 308 if (d) { 309 while ((de=readdir(d)) != NULL) { 310 if (!strncmp(".", de->d_name, 1)) 311 continue; 312 snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state", 313 de->d_name); 314 f = fopen(fname, "r"); 315 if (!f) 316 continue; 317 if (fscanf(f, "%s %s", tmp2, tmp) != 2) 318 tmp[0] = 0; 319 fclose(f); 320 if (strncmp(tmp, "off-line", 8) == 0) { 321 closedir(d); 322 return 1; 323 } 324 } 325 closedir(d); 326 } 327 return 0; 328 } 329 330 /* 331 * This routine checks to see if a filesystem can be skipped; if so, 332 * it will exit with E2FSCK_OK. Under some conditions it will print a 333 * message explaining why a check is being forced. 334 */ 335 static void check_if_skip(e2fsck_t ctx) 336 { 337 ext2_filsys fs = ctx->fs; 338 struct problem_context pctx; 339 const char *reason = NULL; 340 unsigned int reason_arg = 0; 341 long next_check; 342 int batt = is_on_batt(); 343 int defer_check_on_battery; 344 int broken_system_clock; 345 time_t lastcheck; 346 347 if (ctx->flags & E2F_FLAG_PROBLEMS_FIXED) 348 return; 349 350 profile_get_boolean(ctx->profile, "options", "broken_system_clock", 351 0, 0, &broken_system_clock); 352 if (ctx->flags & E2F_FLAG_TIME_INSANE) 353 broken_system_clock = 1; 354 profile_get_boolean(ctx->profile, "options", 355 "defer_check_on_battery", 0, 1, 356 &defer_check_on_battery); 357 if (!defer_check_on_battery) 358 batt = 0; 359 360 if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file || cflag) 361 return; 362 363 if (ctx->options & E2F_OPT_JOURNAL_ONLY) 364 goto skip; 365 366 lastcheck = fs->super->s_lastcheck; 367 if (lastcheck > ctx->now) 368 lastcheck -= ctx->time_fudge; 369 if ((fs->super->s_state & EXT2_ERROR_FS) || 370 !ext2fs_test_valid(fs)) 371 reason = _(" contains a file system with errors"); 372 else if ((fs->super->s_state & EXT2_VALID_FS) == 0) 373 reason = _(" was not cleanly unmounted"); 374 else if (check_backup_super_block(ctx)) 375 reason = _(" primary superblock features different from backup"); 376 else if ((fs->super->s_max_mnt_count > 0) && 377 (fs->super->s_mnt_count >= 378 (unsigned) fs->super->s_max_mnt_count)) { 379 reason = _(" has been mounted %u times without being checked"); 380 reason_arg = fs->super->s_mnt_count; 381 if (batt && (fs->super->s_mnt_count < 382 (unsigned) fs->super->s_max_mnt_count*2)) 383 reason = 0; 384 } else if (!broken_system_clock && fs->super->s_checkinterval && 385 (ctx->now < lastcheck)) { 386 reason = _(" has filesystem last checked time in the future"); 387 if (batt) 388 reason = 0; 389 } else if (!broken_system_clock && fs->super->s_checkinterval && 390 ((ctx->now - lastcheck) >= 391 ((time_t) fs->super->s_checkinterval))) { 392 reason = _(" has gone %u days without being checked"); 393 reason_arg = (ctx->now - fs->super->s_lastcheck)/(3600*24); 394 if (batt && ((ctx->now - fs->super->s_lastcheck) < 395 fs->super->s_checkinterval*2)) 396 reason = 0; 397 } 398 if (reason) { 399 log_out(ctx, "%s", ctx->device_name); 400 log_out(ctx, reason, reason_arg); 401 log_out(ctx, "%s", _(", check forced.\n")); 402 return; 403 } 404 405 /* 406 * Update the global counts from the block group counts. This 407 * is needed since modern kernels don't update the global 408 * counts so as to avoid locking the entire file system. So 409 * if the filesystem is not unmounted cleanly, the global 410 * counts may not be accurate. Update them here if we can, 411 * for the benefit of users who might examine the file system 412 * using dumpe2fs. (This is for cosmetic reasons only.) 413 */ 414 clear_problem_context(&pctx); 415 pctx.ino = fs->super->s_free_inodes_count; 416 pctx.ino2 = ctx->free_inodes; 417 if ((pctx.ino != pctx.ino2) && 418 !(ctx->options & E2F_OPT_READONLY) && 419 fix_problem(ctx, PR_0_FREE_INODE_COUNT, &pctx)) { 420 fs->super->s_free_inodes_count = ctx->free_inodes; 421 ext2fs_mark_super_dirty(fs); 422 } 423 clear_problem_context(&pctx); 424 pctx.blk = ext2fs_free_blocks_count(fs->super); 425 pctx.blk2 = ctx->free_blocks; 426 if ((pctx.blk != pctx.blk2) && 427 !(ctx->options & E2F_OPT_READONLY) && 428 fix_problem(ctx, PR_0_FREE_BLOCK_COUNT, &pctx)) { 429 ext2fs_free_blocks_count_set(fs->super, ctx->free_blocks); 430 ext2fs_mark_super_dirty(fs); 431 } 432 433 /* Print the summary message when we're skipping a full check */ 434 log_out(ctx, _("%s: clean, %u/%u files, %llu/%llu blocks"), 435 ctx->device_name, 436 fs->super->s_inodes_count - fs->super->s_free_inodes_count, 437 fs->super->s_inodes_count, 438 ext2fs_blocks_count(fs->super) - 439 ext2fs_free_blocks_count(fs->super), 440 ext2fs_blocks_count(fs->super)); 441 next_check = 100000; 442 if (fs->super->s_max_mnt_count > 0) { 443 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count; 444 if (next_check <= 0) 445 next_check = 1; 446 } 447 if (!broken_system_clock && fs->super->s_checkinterval && 448 ((ctx->now - fs->super->s_lastcheck) >= fs->super->s_checkinterval)) 449 next_check = 1; 450 if (next_check <= 5) { 451 if (next_check == 1) { 452 if (batt) 453 log_out(ctx, "%s", 454 _(" (check deferred; on battery)")); 455 else 456 log_out(ctx, "%s", 457 _(" (check after next mount)")); 458 } else 459 log_out(ctx, _(" (check in %ld mounts)"), 460 next_check); 461 } 462 log_out(ctx, "\n"); 463 skip: 464 ext2fs_close_free(&ctx->fs); 465 e2fsck_free_context(ctx); 466 exit(FSCK_OK); 467 } 468 469 /* 470 * For completion notice 471 */ 472 struct percent_tbl { 473 int max_pass; 474 int table[32]; 475 }; 476 static struct percent_tbl e2fsck_tbl = { 477 5, { 0, 70, 90, 92, 95, 100 } 478 }; 479 static char bar[128], spaces[128]; 480 481 static float calc_percent(struct percent_tbl *tbl, int pass, int curr, 482 int max) 483 { 484 float percent; 485 486 if (pass <= 0) 487 return 0.0; 488 if (pass > tbl->max_pass || max == 0) 489 return 100.0; 490 percent = ((float) curr) / ((float) max); 491 return ((percent * (tbl->table[pass] - tbl->table[pass-1])) 492 + tbl->table[pass-1]); 493 } 494 495 void e2fsck_clear_progbar(e2fsck_t ctx) 496 { 497 if (!(ctx->flags & E2F_FLAG_PROG_BAR)) 498 return; 499 500 printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80), 501 ctx->stop_meta); 502 fflush(stdout); 503 ctx->flags &= ~E2F_FLAG_PROG_BAR; 504 } 505 506 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent, 507 unsigned int dpynum) 508 { 509 static const char spinner[] = "\\|/-"; 510 int i; 511 unsigned int tick; 512 struct timeval tv; 513 int dpywidth; 514 int fixed_percent; 515 516 if (ctx->flags & E2F_FLAG_PROG_SUPPRESS) 517 return 0; 518 519 /* 520 * Calculate the new progress position. If the 521 * percentage hasn't changed, then we skip out right 522 * away. 523 */ 524 fixed_percent = (int) ((10 * percent) + 0.5); 525 if (ctx->progress_last_percent == fixed_percent) 526 return 0; 527 ctx->progress_last_percent = fixed_percent; 528 529 /* 530 * If we've already updated the spinner once within 531 * the last 1/8th of a second, no point doing it 532 * again. 533 */ 534 gettimeofday(&tv, NULL); 535 tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8)); 536 if ((tick == ctx->progress_last_time) && 537 (fixed_percent != 0) && (fixed_percent != 1000)) 538 return 0; 539 ctx->progress_last_time = tick; 540 541 /* 542 * Advance the spinner, and note that the progress bar 543 * will be on the screen 544 */ 545 ctx->progress_pos = (ctx->progress_pos+1) & 3; 546 ctx->flags |= E2F_FLAG_PROG_BAR; 547 548 dpywidth = 66 - strlen(label); 549 dpywidth = 8 * (dpywidth / 8); 550 if (dpynum) 551 dpywidth -= 8; 552 553 i = ((percent * dpywidth) + 50) / 100; 554 printf("%s%s: |%s%s", ctx->start_meta, label, 555 bar + (sizeof(bar) - (i+1)), 556 spaces + (sizeof(spaces) - (dpywidth - i + 1))); 557 if (fixed_percent == 1000) 558 fputc('|', stdout); 559 else 560 fputc(spinner[ctx->progress_pos & 3], stdout); 561 printf(" %4.1f%% ", percent); 562 if (dpynum) 563 printf("%u\r", dpynum); 564 else 565 fputs(" \r", stdout); 566 fputs(ctx->stop_meta, stdout); 567 568 if (fixed_percent == 1000) 569 e2fsck_clear_progbar(ctx); 570 fflush(stdout); 571 572 return 0; 573 } 574 575 static int e2fsck_update_progress(e2fsck_t ctx, int pass, 576 unsigned long cur, unsigned long max) 577 { 578 char buf[1024]; 579 float percent; 580 581 if (pass == 0) 582 return 0; 583 584 if (ctx->progress_fd) { 585 snprintf(buf, sizeof(buf), "%d %lu %lu %s\n", 586 pass, cur, max, ctx->device_name); 587 write_all(ctx->progress_fd, buf, strlen(buf)); 588 } else { 589 percent = calc_percent(&e2fsck_tbl, pass, cur, max); 590 e2fsck_simple_progress(ctx, ctx->device_name, 591 percent, 0); 592 } 593 return 0; 594 } 595 596 #define PATH_SET "PATH=/sbin" 597 598 /* 599 * Make sure 0,1,2 file descriptors are open, so that we don't open 600 * the filesystem using the same file descriptor as stdout or stderr. 601 */ 602 static void reserve_stdio_fds(void) 603 { 604 int fd = 0; 605 606 while (fd <= 2) { 607 fd = open("/dev/null", O_RDWR); 608 if (fd < 0) { 609 fprintf(stderr, _("ERROR: Couldn't open " 610 "/dev/null (%s)\n"), 611 strerror(errno)); 612 break; 613 } 614 } 615 } 616 617 #ifdef HAVE_SIGNAL_H 618 static void signal_progress_on(int sig EXT2FS_ATTR((unused))) 619 { 620 e2fsck_t ctx = e2fsck_global_ctx; 621 622 if (!ctx) 623 return; 624 625 ctx->progress = e2fsck_update_progress; 626 } 627 628 static void signal_progress_off(int sig EXT2FS_ATTR((unused))) 629 { 630 e2fsck_t ctx = e2fsck_global_ctx; 631 632 if (!ctx) 633 return; 634 635 e2fsck_clear_progbar(ctx); 636 ctx->progress = 0; 637 } 638 639 static void signal_cancel(int sig EXT2FS_ATTR((unused))) 640 { 641 e2fsck_t ctx = e2fsck_global_ctx; 642 643 if (!ctx) 644 exit(FSCK_CANCELED); 645 646 ctx->flags |= E2F_FLAG_CANCEL; 647 } 648 #endif 649 650 static void parse_extended_opts(e2fsck_t ctx, const char *opts) 651 { 652 char *buf, *token, *next, *p, *arg; 653 int ea_ver; 654 int extended_usage = 0; 655 unsigned long long reada_kb; 656 657 buf = string_copy(ctx, opts, 0); 658 for (token = buf; token && *token; token = next) { 659 p = strchr(token, ','); 660 next = 0; 661 if (p) { 662 *p = 0; 663 next = p+1; 664 } 665 arg = strchr(token, '='); 666 if (arg) { 667 *arg = 0; 668 arg++; 669 } 670 if (strcmp(token, "ea_ver") == 0) { 671 if (!arg) { 672 extended_usage++; 673 continue; 674 } 675 ea_ver = strtoul(arg, &p, 0); 676 if (*p || 677 ((ea_ver != 1) && (ea_ver != 2))) { 678 fprintf(stderr, "%s", 679 _("Invalid EA version.\n")); 680 extended_usage++; 681 continue; 682 } 683 ctx->ext_attr_ver = ea_ver; 684 } else if (strcmp(token, "readahead_kb") == 0) { 685 if (!arg) { 686 extended_usage++; 687 continue; 688 } 689 reada_kb = strtoull(arg, &p, 0); 690 if (*p) { 691 fprintf(stderr, "%s", 692 _("Invalid readahead buffer size.\n")); 693 extended_usage++; 694 continue; 695 } 696 ctx->readahead_kb = reada_kb; 697 } else if (strcmp(token, "fragcheck") == 0) { 698 ctx->options |= E2F_OPT_FRAGCHECK; 699 continue; 700 } else if (strcmp(token, "journal_only") == 0) { 701 if (arg) { 702 extended_usage++; 703 continue; 704 } 705 ctx->options |= E2F_OPT_JOURNAL_ONLY; 706 } else if (strcmp(token, "discard") == 0) { 707 ctx->options |= E2F_OPT_DISCARD; 708 continue; 709 } else if (strcmp(token, "nodiscard") == 0) { 710 ctx->options &= ~E2F_OPT_DISCARD; 711 continue; 712 } else if (strcmp(token, "log_filename") == 0) { 713 if (!arg) 714 extended_usage++; 715 else 716 ctx->log_fn = string_copy(ctx, arg, 0); 717 continue; 718 } else if (strcmp(token, "bmap2extent") == 0) { 719 ctx->options |= E2F_OPT_CONVERT_BMAP; 720 continue; 721 } else if (strcmp(token, "fixes_only") == 0) { 722 ctx->options |= E2F_OPT_FIXES_ONLY; 723 continue; 724 } else { 725 fprintf(stderr, _("Unknown extended option: %s\n"), 726 token); 727 extended_usage++; 728 } 729 } 730 free(buf); 731 732 if (extended_usage) { 733 fputs(("\nExtended options are separated by commas, " 734 "and may take an argument which\n" 735 "is set off by an equals ('=') sign. " 736 "Valid extended options are:\n"), stderr); 737 fputs(("\tea_ver=<ea_version (1 or 2)>\n"), stderr); 738 fputs(("\tfragcheck\n"), stderr); 739 fputs(("\tjournal_only\n"), stderr); 740 fputs(("\tdiscard\n"), stderr); 741 fputs(("\tnodiscard\n"), stderr); 742 fputs(("\treadahead_kb=<buffer size>\n"), stderr); 743 fputs(("\tbmap2extent\n"), stderr); 744 fputc('\n', stderr); 745 exit(1); 746 } 747 } 748 749 static void syntax_err_report(const char *filename, long err, int line_num) 750 { 751 fprintf(stderr, 752 _("Syntax error in e2fsck config file (%s, line #%d)\n\t%s\n"), 753 filename, line_num, error_message(err)); 754 exit(FSCK_ERROR); 755 } 756 757 static const char *config_fn[] = { ROOT_SYSCONFDIR "/e2fsck.conf", 0 }; 758 759 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) 760 { 761 int flush = 0; 762 int c, fd; 763 #ifdef MTRACE 764 extern void *mallwatch; 765 #endif 766 e2fsck_t ctx; 767 errcode_t retval; 768 #ifdef HAVE_SIGNAL_H 769 struct sigaction sa; 770 #endif 771 char *extended_opts = 0; 772 char *cp; 773 int res; /* result of sscanf */ 774 #ifdef CONFIG_JBD_DEBUG 775 char *jbd_debug; 776 #endif 777 unsigned long long phys_mem_kb; 778 779 retval = e2fsck_allocate_context(&ctx); 780 if (retval) 781 return retval; 782 783 *ret_ctx = ctx; 784 e2fsck_global_ctx = ctx; 785 786 setvbuf(stdout, NULL, _IONBF, BUFSIZ); 787 setvbuf(stderr, NULL, _IONBF, BUFSIZ); 788 if (getenv("E2FSCK_FORCE_INTERACTIVE") || (isatty(0) && isatty(1))) { 789 ctx->interactive = 1; 790 } else { 791 ctx->start_meta[0] = '\001'; 792 ctx->stop_meta[0] = '\002'; 793 } 794 memset(bar, '=', sizeof(bar)-1); 795 memset(spaces, ' ', sizeof(spaces)-1); 796 add_error_table(&et_ext2_error_table); 797 add_error_table(&et_prof_error_table); 798 blkid_get_cache(&ctx->blkid, NULL); 799 800 if (argc && *argv) 801 ctx->program_name = *argv; 802 else 803 ctx->program_name = "e2fsck"; 804 805 phys_mem_kb = get_memory_size() / 1024; 806 ctx->readahead_kb = ~0ULL; 807 while ((c = getopt(argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkz:")) != EOF) 808 switch (c) { 809 case 'C': 810 ctx->progress = e2fsck_update_progress; 811 res = sscanf(optarg, "%d", &ctx->progress_fd); 812 if (res != 1) 813 goto sscanf_err; 814 815 if (ctx->progress_fd < 0) { 816 ctx->progress = 0; 817 ctx->progress_fd = ctx->progress_fd * -1; 818 } 819 if (!ctx->progress_fd) 820 break; 821 /* Validate the file descriptor to avoid disasters */ 822 fd = dup(ctx->progress_fd); 823 if (fd < 0) { 824 fprintf(stderr, 825 _("Error validating file descriptor %d: %s\n"), 826 ctx->progress_fd, 827 error_message(errno)); 828 fatal_error(ctx, 829 _("Invalid completion information file descriptor")); 830 } else 831 close(fd); 832 break; 833 case 'D': 834 ctx->options |= E2F_OPT_COMPRESS_DIRS; 835 break; 836 case 'E': 837 extended_opts = optarg; 838 break; 839 case 'p': 840 case 'a': 841 if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) { 842 conflict_opt: 843 fatal_error(ctx, 844 _("Only one of the options -p/-a, -n or -y may be specified.")); 845 } 846 ctx->options |= E2F_OPT_PREEN; 847 break; 848 case 'n': 849 if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN)) 850 goto conflict_opt; 851 ctx->options |= E2F_OPT_NO; 852 break; 853 case 'y': 854 if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO)) 855 goto conflict_opt; 856 ctx->options |= E2F_OPT_YES; 857 break; 858 case 't': 859 #ifdef RESOURCE_TRACK 860 if (ctx->options & E2F_OPT_TIME) 861 ctx->options |= E2F_OPT_TIME2; 862 else 863 ctx->options |= E2F_OPT_TIME; 864 #else 865 fprintf(stderr, _("The -t option is not " 866 "supported on this version of e2fsck.\n")); 867 #endif 868 break; 869 case 'c': 870 if (cflag++) 871 ctx->options |= E2F_OPT_WRITECHECK; 872 ctx->options |= E2F_OPT_CHECKBLOCKS; 873 break; 874 case 'r': 875 /* What we do by default, anyway! */ 876 break; 877 case 'b': 878 res = sscanf(optarg, "%llu", &ctx->use_superblock); 879 if (res != 1) 880 goto sscanf_err; 881 ctx->flags |= E2F_FLAG_SB_SPECIFIED; 882 break; 883 case 'B': 884 ctx->blocksize = atoi(optarg); 885 break; 886 case 'I': 887 res = sscanf(optarg, "%d", &ctx->inode_buffer_blocks); 888 if (res != 1) 889 goto sscanf_err; 890 break; 891 case 'j': 892 ctx->journal_name = blkid_get_devname(ctx->blkid, 893 optarg, NULL); 894 if (!ctx->journal_name) { 895 com_err(ctx->program_name, 0, 896 _("Unable to resolve '%s'"), 897 optarg); 898 fatal_error(ctx, 0); 899 } 900 break; 901 case 'P': 902 res = sscanf(optarg, "%d", &ctx->process_inode_size); 903 if (res != 1) 904 goto sscanf_err; 905 break; 906 case 'L': 907 replace_bad_blocks++; 908 case 'l': 909 if (bad_blocks_file) 910 free(bad_blocks_file); 911 bad_blocks_file = string_copy(ctx, optarg, 0); 912 break; 913 case 'd': 914 ctx->options |= E2F_OPT_DEBUG; 915 break; 916 case 'f': 917 ctx->options |= E2F_OPT_FORCE; 918 break; 919 case 'F': 920 flush = 1; 921 break; 922 case 'v': 923 verbose = 1; 924 break; 925 case 'V': 926 show_version_only = 1; 927 break; 928 #ifdef MTRACE 929 case 'M': 930 mallwatch = (void *) strtol(optarg, NULL, 0); 931 break; 932 #endif 933 case 'N': 934 ctx->device_name = string_copy(ctx, optarg, 0); 935 break; 936 case 'k': 937 keep_bad_blocks++; 938 break; 939 case 'z': 940 ctx->undo_file = optarg; 941 break; 942 default: 943 usage(ctx); 944 } 945 if (show_version_only) 946 return 0; 947 if (optind != argc - 1) 948 usage(ctx); 949 if ((ctx->options & E2F_OPT_NO) && 950 (ctx->options & E2F_OPT_COMPRESS_DIRS)) { 951 com_err(ctx->program_name, 0, "%s", 952 _("The -n and -D options are incompatible.")); 953 fatal_error(ctx, 0); 954 } 955 if ((ctx->options & E2F_OPT_NO) && cflag) { 956 com_err(ctx->program_name, 0, "%s", 957 _("The -n and -c options are incompatible.")); 958 fatal_error(ctx, 0); 959 } 960 if ((ctx->options & E2F_OPT_NO) && bad_blocks_file) { 961 com_err(ctx->program_name, 0, "%s", 962 _("The -n and -l/-L options are incompatible.")); 963 fatal_error(ctx, 0); 964 } 965 if (ctx->options & E2F_OPT_NO) 966 ctx->options |= E2F_OPT_READONLY; 967 968 ctx->io_options = strchr(argv[optind], '?'); 969 if (ctx->io_options) 970 *ctx->io_options++ = 0; 971 ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0); 972 if (!ctx->filesystem_name) { 973 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"), 974 argv[optind]); 975 fatal_error(ctx, 0); 976 } 977 if (extended_opts) 978 parse_extended_opts(ctx, extended_opts); 979 980 /* Complain about mutually exclusive rebuilding activities */ 981 if (getenv("E2FSCK_FIXES_ONLY")) 982 ctx->options |= E2F_OPT_FIXES_ONLY; 983 if ((ctx->options & E2F_OPT_COMPRESS_DIRS) && 984 (ctx->options & E2F_OPT_FIXES_ONLY)) { 985 com_err(ctx->program_name, 0, "%s", 986 _("The -D and -E fixes_only options are incompatible.")); 987 fatal_error(ctx, 0); 988 } 989 if ((ctx->options & E2F_OPT_CONVERT_BMAP) && 990 (ctx->options & E2F_OPT_FIXES_ONLY)) { 991 com_err(ctx->program_name, 0, "%s", 992 _("The -E bmap2extent and fixes_only options are incompatible.")); 993 fatal_error(ctx, 0); 994 } 995 996 if ((cp = getenv("E2FSCK_CONFIG")) != NULL) 997 config_fn[0] = cp; 998 profile_set_syntax_err_cb(syntax_err_report); 999 profile_init(config_fn, &ctx->profile); 1000 1001 profile_get_boolean(ctx->profile, "options", "report_time", 0, 0, 1002 &c); 1003 if (c) 1004 ctx->options |= E2F_OPT_TIME | E2F_OPT_TIME2; 1005 profile_get_boolean(ctx->profile, "options", "report_verbose", 0, 0, 1006 &c); 1007 if (c) 1008 verbose = 1; 1009 1010 if (ctx->readahead_kb == ~0ULL) { 1011 profile_get_integer(ctx->profile, "options", 1012 "readahead_mem_pct", 0, -1, &c); 1013 if (c >= 0 && c <= 100) 1014 ctx->readahead_kb = phys_mem_kb * c / 100; 1015 profile_get_integer(ctx->profile, "options", 1016 "readahead_kb", 0, -1, &c); 1017 if (c >= 0) 1018 ctx->readahead_kb = c; 1019 if (ctx->readahead_kb != ~0ULL && 1020 ctx->readahead_kb > phys_mem_kb) 1021 ctx->readahead_kb = phys_mem_kb; 1022 } 1023 1024 /* Turn off discard in read-only mode */ 1025 if ((ctx->options & E2F_OPT_NO) && 1026 (ctx->options & E2F_OPT_DISCARD)) 1027 ctx->options &= ~E2F_OPT_DISCARD; 1028 1029 if (flush) { 1030 fd = open(ctx->filesystem_name, O_RDONLY, 0); 1031 if (fd < 0) { 1032 com_err("open", errno, 1033 _("while opening %s for flushing"), 1034 ctx->filesystem_name); 1035 fatal_error(ctx, 0); 1036 } 1037 if ((retval = ext2fs_sync_device(fd, 1))) { 1038 com_err("ext2fs_sync_device", retval, 1039 _("while trying to flush %s"), 1040 ctx->filesystem_name); 1041 fatal_error(ctx, 0); 1042 } 1043 close(fd); 1044 } 1045 if (cflag && bad_blocks_file) { 1046 fprintf(stderr, "%s", _("The -c and the -l/-L options may not " 1047 "be both used at the same time.\n")); 1048 exit(FSCK_USAGE); 1049 } 1050 #ifdef HAVE_SIGNAL_H 1051 /* 1052 * Set up signal action 1053 */ 1054 memset(&sa, 0, sizeof(struct sigaction)); 1055 sa.sa_handler = signal_cancel; 1056 sigaction(SIGINT, &sa, 0); 1057 sigaction(SIGTERM, &sa, 0); 1058 #ifdef SA_RESTART 1059 sa.sa_flags = SA_RESTART; 1060 #endif 1061 sa.sa_handler = signal_progress_on; 1062 sigaction(SIGUSR1, &sa, 0); 1063 sa.sa_handler = signal_progress_off; 1064 sigaction(SIGUSR2, &sa, 0); 1065 #endif 1066 1067 /* Update our PATH to include /sbin if we need to run badblocks */ 1068 if (cflag) { 1069 char *oldpath = getenv("PATH"); 1070 char *newpath; 1071 int len = sizeof(PATH_SET) + 1; 1072 1073 if (oldpath) 1074 len += strlen(oldpath); 1075 1076 newpath = malloc(len); 1077 if (!newpath) 1078 fatal_error(ctx, "Couldn't malloc() newpath"); 1079 strcpy(newpath, PATH_SET); 1080 1081 if (oldpath) { 1082 strcat(newpath, ":"); 1083 strcat(newpath, oldpath); 1084 } 1085 putenv(newpath); 1086 } 1087 #ifdef CONFIG_JBD_DEBUG 1088 jbd_debug = getenv("E2FSCK_JBD_DEBUG"); 1089 if (jbd_debug) { 1090 res = sscanf(jbd_debug, "%d", &journal_enable_debug); 1091 if (res != 1) { 1092 fprintf(stderr, 1093 _("E2FSCK_JBD_DEBUG \"%s\" not an integer\n\n"), 1094 jbd_debug); 1095 exit (1); 1096 } 1097 } 1098 #endif 1099 return 0; 1100 1101 sscanf_err: 1102 fprintf(stderr, _("\nInvalid non-numeric argument to -%c (\"%s\")\n\n"), 1103 c, optarg); 1104 exit (1); 1105 } 1106 1107 static errcode_t try_open_fs(e2fsck_t ctx, int flags, io_manager io_ptr, 1108 ext2_filsys *ret_fs) 1109 { 1110 errcode_t retval; 1111 1112 *ret_fs = NULL; 1113 if (ctx->superblock && ctx->blocksize) { 1114 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options, 1115 flags, ctx->superblock, ctx->blocksize, 1116 io_ptr, ret_fs); 1117 } else if (ctx->superblock) { 1118 int blocksize; 1119 for (blocksize = EXT2_MIN_BLOCK_SIZE; 1120 blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) { 1121 if (*ret_fs) { 1122 ext2fs_free(*ret_fs); 1123 *ret_fs = NULL; 1124 } 1125 retval = ext2fs_open2(ctx->filesystem_name, 1126 ctx->io_options, flags, 1127 ctx->superblock, blocksize, 1128 io_ptr, ret_fs); 1129 if (!retval) 1130 break; 1131 } 1132 } else 1133 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options, 1134 flags, 0, 0, io_ptr, ret_fs); 1135 1136 if (retval == 0) { 1137 (*ret_fs)->priv_data = ctx; 1138 e2fsck_set_bitmap_type(*ret_fs, EXT2FS_BMAP64_RBTREE, 1139 "default", NULL); 1140 } 1141 return retval; 1142 } 1143 1144 static const char *my_ver_string = E2FSPROGS_VERSION; 1145 static const char *my_ver_date = E2FSPROGS_DATE; 1146 1147 static errcode_t e2fsck_check_mmp(ext2_filsys fs, e2fsck_t ctx) 1148 { 1149 struct mmp_struct *mmp_s; 1150 unsigned int mmp_check_interval; 1151 errcode_t retval = 0; 1152 struct problem_context pctx; 1153 unsigned int wait_time = 0; 1154 1155 clear_problem_context(&pctx); 1156 if (fs->mmp_buf == NULL) { 1157 retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf); 1158 if (retval) 1159 goto check_error; 1160 } 1161 1162 retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf); 1163 if (retval) 1164 goto check_error; 1165 1166 mmp_s = fs->mmp_buf; 1167 1168 mmp_check_interval = fs->super->s_mmp_update_interval; 1169 if (mmp_check_interval < EXT4_MMP_MIN_CHECK_INTERVAL) 1170 mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL; 1171 1172 /* 1173 * If check_interval in MMP block is larger, use that instead of 1174 * check_interval from the superblock. 1175 */ 1176 if (mmp_s->mmp_check_interval > mmp_check_interval) 1177 mmp_check_interval = mmp_s->mmp_check_interval; 1178 1179 wait_time = mmp_check_interval * 2 + 1; 1180 1181 if (mmp_s->mmp_seq == EXT4_MMP_SEQ_CLEAN) 1182 retval = 0; 1183 else if (mmp_s->mmp_seq == EXT4_MMP_SEQ_FSCK) 1184 retval = EXT2_ET_MMP_FSCK_ON; 1185 else if (mmp_s->mmp_seq > EXT4_MMP_SEQ_MAX) 1186 retval = EXT2_ET_MMP_UNKNOWN_SEQ; 1187 1188 if (retval) 1189 goto check_error; 1190 1191 /* Print warning if e2fck will wait for more than 20 secs. */ 1192 if (verbose || wait_time > EXT4_MMP_MIN_CHECK_INTERVAL * 4) { 1193 log_out(ctx, _("MMP interval is %u seconds and total wait " 1194 "time is %u seconds. Please wait...\n"), 1195 mmp_check_interval, wait_time * 2); 1196 } 1197 1198 return 0; 1199 1200 check_error: 1201 1202 if (retval == EXT2_ET_MMP_BAD_BLOCK) { 1203 if (fix_problem(ctx, PR_0_MMP_INVALID_BLK, &pctx)) { 1204 fs->super->s_mmp_block = 0; 1205 ext2fs_mark_super_dirty(fs); 1206 retval = 0; 1207 } 1208 } else if (retval == EXT2_ET_MMP_FAILED) { 1209 com_err(ctx->program_name, retval, "%s", 1210 _("while checking MMP block")); 1211 dump_mmp_msg(fs->mmp_buf, NULL); 1212 } else if (retval == EXT2_ET_MMP_FSCK_ON || 1213 retval == EXT2_ET_MMP_UNKNOWN_SEQ) { 1214 com_err(ctx->program_name, retval, "%s", 1215 _("while checking MMP block")); 1216 dump_mmp_msg(fs->mmp_buf, 1217 _("If you are sure the filesystem is not " 1218 "in use on any node, run:\n" 1219 "'tune2fs -f -E clear_mmp {device}'\n")); 1220 } else if (retval == EXT2_ET_MMP_MAGIC_INVALID) { 1221 if (fix_problem(ctx, PR_0_MMP_INVALID_MAGIC, &pctx)) { 1222 ext2fs_mmp_clear(fs); 1223 retval = 0; 1224 } 1225 } else if (retval == EXT2_ET_MMP_CSUM_INVALID) { 1226 if (fix_problem(ctx, PR_0_MMP_CSUM_INVALID, &pctx)) { 1227 ext2fs_mmp_clear(fs); 1228 retval = 0; 1229 } 1230 } else 1231 com_err(ctx->program_name, retval, "%s", 1232 _("while reading MMP block")); 1233 return retval; 1234 } 1235 1236 static int e2fsck_setup_tdb(e2fsck_t ctx, io_manager *io_ptr) 1237 { 1238 errcode_t retval = ENOMEM; 1239 char *tdb_dir = NULL, *tdb_file = NULL; 1240 char *dev_name, *tmp_name; 1241 int free_tdb_dir = 0; 1242 1243 /* (re)open a specific undo file */ 1244 if (ctx->undo_file && ctx->undo_file[0] != 0) { 1245 retval = set_undo_io_backing_manager(*io_ptr); 1246 if (retval) 1247 goto err; 1248 *io_ptr = undo_io_manager; 1249 retval = set_undo_io_backup_file(ctx->undo_file); 1250 if (retval) 1251 goto err; 1252 printf(_("Overwriting existing filesystem; this can be undone " 1253 "using the command:\n" 1254 " e2undo %s %s\n\n"), 1255 ctx->undo_file, ctx->filesystem_name); 1256 return retval; 1257 } 1258 1259 /* 1260 * Configuration via a conf file would be 1261 * nice 1262 */ 1263 tdb_dir = getenv("E2FSPROGS_UNDO_DIR"); 1264 if (!tdb_dir) { 1265 profile_get_string(ctx->profile, "defaults", 1266 "undo_dir", 0, "/var/lib/e2fsprogs", 1267 &tdb_dir); 1268 free_tdb_dir = 1; 1269 } 1270 1271 if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) || 1272 access(tdb_dir, W_OK)) { 1273 if (free_tdb_dir) 1274 free(tdb_dir); 1275 return 0; 1276 } 1277 1278 tmp_name = strdup(ctx->filesystem_name); 1279 if (!tmp_name) 1280 goto errout; 1281 dev_name = basename(tmp_name); 1282 tdb_file = malloc(strlen(tdb_dir) + 8 + strlen(dev_name) + 7 + 1); 1283 if (!tdb_file) { 1284 free(tmp_name); 1285 goto errout; 1286 } 1287 sprintf(tdb_file, "%s/e2fsck-%s.e2undo", tdb_dir, dev_name); 1288 free(tmp_name); 1289 1290 if ((unlink(tdb_file) < 0) && (errno != ENOENT)) { 1291 retval = errno; 1292 com_err(ctx->program_name, retval, 1293 _("while trying to delete %s"), tdb_file); 1294 goto errout; 1295 } 1296 1297 retval = set_undo_io_backing_manager(*io_ptr); 1298 if (retval) 1299 goto errout; 1300 *io_ptr = undo_io_manager; 1301 retval = set_undo_io_backup_file(tdb_file); 1302 if (retval) 1303 goto errout; 1304 printf(_("Overwriting existing filesystem; this can be undone " 1305 "using the command:\n" 1306 " e2undo %s %s\n\n"), tdb_file, ctx->filesystem_name); 1307 1308 if (free_tdb_dir) 1309 free(tdb_dir); 1310 free(tdb_file); 1311 return 0; 1312 1313 errout: 1314 if (free_tdb_dir) 1315 free(tdb_dir); 1316 free(tdb_file); 1317 err: 1318 com_err(ctx->program_name, retval, "%s", 1319 _("while trying to setup undo file\n")); 1320 return retval; 1321 } 1322 1323 int main (int argc, char *argv[]) 1324 { 1325 errcode_t retval = 0, retval2 = 0, orig_retval = 0; 1326 int exit_value = FSCK_OK; 1327 ext2_filsys fs = 0; 1328 io_manager io_ptr; 1329 struct ext2_super_block *sb; 1330 const char *lib_ver_date; 1331 int my_ver, lib_ver; 1332 e2fsck_t ctx; 1333 blk64_t orig_superblock; 1334 struct problem_context pctx; 1335 int flags, run_result, was_changed; 1336 int journal_size; 1337 int sysval, sys_page_size = 4096; 1338 int old_bitmaps; 1339 __u32 features[3]; 1340 char *cp; 1341 unsigned int qtype_bits = 0; 1342 enum quota_type qtype; 1343 1344 clear_problem_context(&pctx); 1345 sigcatcher_setup(); 1346 #ifdef MTRACE 1347 mtrace(); 1348 #endif 1349 #ifdef MCHECK 1350 mcheck(0); 1351 #endif 1352 #ifdef ENABLE_NLS 1353 setlocale(LC_MESSAGES, ""); 1354 setlocale(LC_CTYPE, ""); 1355 bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 1356 textdomain(NLS_CAT_NAME); 1357 set_com_err_gettext(gettext); 1358 #endif 1359 my_ver = ext2fs_parse_version_string(my_ver_string); 1360 lib_ver = ext2fs_get_library_version(0, &lib_ver_date); 1361 if (my_ver > lib_ver) { 1362 fprintf( stderr, "%s", 1363 _("Error: ext2fs library version out of date!\n")); 1364 show_version_only++; 1365 } 1366 1367 retval = PRS(argc, argv, &ctx); 1368 if (retval) { 1369 com_err("e2fsck", retval, "%s", 1370 _("while trying to initialize program")); 1371 exit(FSCK_ERROR); 1372 } 1373 reserve_stdio_fds(); 1374 1375 set_up_logging(ctx); 1376 if (ctx->logf) { 1377 int i; 1378 fputs("E2fsck run: ", ctx->logf); 1379 for (i = 0; i < argc; i++) { 1380 if (i) 1381 fputc(' ', ctx->logf); 1382 fputs(argv[i], ctx->logf); 1383 } 1384 fputc('\n', ctx->logf); 1385 } 1386 1387 init_resource_track(&ctx->global_rtrack, NULL); 1388 if (!(ctx->options & E2F_OPT_PREEN) || show_version_only) 1389 log_err(ctx, "e2fsck %s (%s)\n", my_ver_string, 1390 my_ver_date); 1391 1392 if (show_version_only) { 1393 log_err(ctx, _("\tUsing %s, %s\n"), 1394 error_message(EXT2_ET_BASE), lib_ver_date); 1395 exit(FSCK_OK); 1396 } 1397 1398 check_mount(ctx); 1399 1400 if (!(ctx->options & E2F_OPT_PREEN) && 1401 !(ctx->options & E2F_OPT_NO) && 1402 !(ctx->options & E2F_OPT_YES)) { 1403 if (!ctx->interactive) 1404 fatal_error(ctx, 1405 _("need terminal for interactive repairs")); 1406 } 1407 ctx->superblock = ctx->use_superblock; 1408 1409 flags = EXT2_FLAG_SKIP_MMP; 1410 restart: 1411 #ifdef CONFIG_TESTIO_DEBUG 1412 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { 1413 io_ptr = test_io_manager; 1414 test_io_backing_manager = unix_io_manager; 1415 } else 1416 #endif 1417 io_ptr = unix_io_manager; 1418 flags |= EXT2_FLAG_NOFREE_ON_ERROR; 1419 profile_get_boolean(ctx->profile, "options", "old_bitmaps", 0, 0, 1420 &old_bitmaps); 1421 if (!old_bitmaps) 1422 flags |= EXT2_FLAG_64BITS; 1423 if ((ctx->options & E2F_OPT_READONLY) == 0) { 1424 flags |= EXT2_FLAG_RW; 1425 if (!(ctx->mount_flags & EXT2_MF_ISROOT && 1426 ctx->mount_flags & EXT2_MF_READONLY)) 1427 flags |= EXT2_FLAG_EXCLUSIVE; 1428 if ((ctx->mount_flags & EXT2_MF_READONLY) && 1429 (ctx->options & E2F_OPT_FORCE)) 1430 flags &= ~EXT2_FLAG_EXCLUSIVE; 1431 } 1432 1433 if (ctx->undo_file) { 1434 retval = e2fsck_setup_tdb(ctx, &io_ptr); 1435 if (retval) 1436 exit(FSCK_ERROR); 1437 } 1438 1439 ctx->openfs_flags = flags; 1440 retval = try_open_fs(ctx, flags, io_ptr, &fs); 1441 1442 if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) && 1443 !(ctx->flags & E2F_FLAG_SB_SPECIFIED) && 1444 ((retval == EXT2_ET_BAD_MAGIC) || 1445 (retval == EXT2_ET_SB_CSUM_INVALID) || 1446 (retval == EXT2_ET_CORRUPT_SUPERBLOCK) || 1447 ((retval == 0) && (retval2 = ext2fs_check_desc(fs))))) { 1448 if (retval) { 1449 pctx.errcode = retval; 1450 fix_problem(ctx, PR_0_OPEN_FAILED, &pctx); 1451 } 1452 if (retval2) { 1453 pctx.errcode = retval2; 1454 fix_problem(ctx, PR_0_CHECK_DESC_FAILED, &pctx); 1455 } 1456 pctx.errcode = 0; 1457 if (retval2 == ENOMEM || retval2 == EXT2_ET_NO_MEMORY) { 1458 retval = retval2; 1459 goto failure; 1460 } 1461 if (fs->flags & EXT2_FLAG_NOFREE_ON_ERROR) { 1462 ext2fs_free(fs); 1463 fs = NULL; 1464 } 1465 if (!fs || (fs->group_desc_count > 1)) { 1466 log_out(ctx, _("%s: %s trying backup blocks...\n"), 1467 ctx->program_name, 1468 retval ? _("Superblock invalid,") : 1469 _("Group descriptors look bad...")); 1470 orig_superblock = ctx->superblock; 1471 get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr); 1472 if (fs) 1473 ext2fs_close_free(&fs); 1474 orig_retval = retval; 1475 retval = try_open_fs(ctx, flags, io_ptr, &fs); 1476 if ((orig_retval == 0) && retval != 0) { 1477 if (fs) 1478 ext2fs_close_free(&fs); 1479 log_out(ctx, _("%s: %s while using the " 1480 "backup blocks"), 1481 ctx->program_name, 1482 error_message(retval)); 1483 log_out(ctx, _("%s: going back to original " 1484 "superblock\n"), 1485 ctx->program_name); 1486 ctx->superblock = orig_superblock; 1487 retval = try_open_fs(ctx, flags, io_ptr, &fs); 1488 } 1489 } 1490 } 1491 if (((retval == EXT2_ET_UNSUPP_FEATURE) || 1492 (retval == EXT2_ET_RO_UNSUPP_FEATURE)) && 1493 fs && fs->super) { 1494 sb = fs->super; 1495 features[0] = (sb->s_feature_compat & 1496 ~EXT2_LIB_FEATURE_COMPAT_SUPP); 1497 features[1] = (sb->s_feature_incompat & 1498 ~EXT2_LIB_FEATURE_INCOMPAT_SUPP); 1499 features[2] = (sb->s_feature_ro_compat & 1500 ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP); 1501 if (features[0] || features[1] || features[2]) 1502 goto print_unsupp_features; 1503 } 1504 failure: 1505 if (retval) { 1506 if (orig_retval) 1507 retval = orig_retval; 1508 com_err(ctx->program_name, retval, _("while trying to open %s"), 1509 ctx->filesystem_name); 1510 if (retval == EXT2_ET_REV_TOO_HIGH) { 1511 log_out(ctx, "%s", 1512 _("The filesystem revision is apparently " 1513 "too high for this version of e2fsck.\n" 1514 "(Or the filesystem superblock " 1515 "is corrupt)\n\n")); 1516 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx); 1517 } else if (retval == EXT2_ET_SHORT_READ) 1518 log_out(ctx, "%s", 1519 _("Could this be a zero-length partition?\n")); 1520 else if ((retval == EPERM) || (retval == EACCES)) 1521 log_out(ctx, _("You must have %s access to the " 1522 "filesystem or be root\n"), 1523 (ctx->options & E2F_OPT_READONLY) ? 1524 "r/o" : "r/w"); 1525 else if (retval == ENXIO) 1526 log_out(ctx, "%s", 1527 _("Possibly non-existent or swap device?\n")); 1528 else if (retval == EBUSY) 1529 log_out(ctx, "%s", _("Filesystem mounted or opened " 1530 "exclusively by another program?\n")); 1531 else if (retval == ENOENT) 1532 log_out(ctx, "%s", 1533 _("Possibly non-existent device?\n")); 1534 #ifdef EROFS 1535 else if (retval == EROFS) 1536 log_out(ctx, "%s", _("Disk write-protected; use the " 1537 "-n option to do a read-only\n" 1538 "check of the device.\n")); 1539 #endif 1540 else { 1541 fix_problem(ctx, PR_0_SB_CORRUPT, &pctx); 1542 if (retval == EXT2_ET_BAD_MAGIC) 1543 check_plausibility(ctx->filesystem_name, 1544 CHECK_FS_EXIST, NULL); 1545 } 1546 fatal_error(ctx, 0); 1547 } 1548 /* 1549 * We only update the master superblock because (a) paranoia; 1550 * we don't want to corrupt the backup superblocks, and (b) we 1551 * don't need to update the mount count and last checked 1552 * fields in the backup superblock (the kernel doesn't update 1553 * the backup superblocks anyway). With newer versions of the 1554 * library this flag is set by ext2fs_open2(), but we set this 1555 * here just to be sure. (No, we don't support e2fsck running 1556 * with some other libext2fs than the one that it was shipped 1557 * with, but just in case....) 1558 */ 1559 fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 1560 1561 if (!(ctx->flags & E2F_FLAG_GOT_DEVSIZE)) { 1562 __u32 blocksize = EXT2_BLOCK_SIZE(fs->super); 1563 int need_restart = 0; 1564 1565 pctx.errcode = ext2fs_get_device_size2(ctx->filesystem_name, 1566 blocksize, 1567 &ctx->num_blocks); 1568 /* 1569 * The floppy driver refuses to allow anyone else to 1570 * open the device if has been opened with O_EXCL; 1571 * this is unlike other block device drivers in Linux. 1572 * To handle this, we close the filesystem and then 1573 * reopen the filesystem after we get the device size. 1574 */ 1575 if (pctx.errcode == EBUSY) { 1576 ext2fs_close_free(&fs); 1577 need_restart++; 1578 pctx.errcode = 1579 ext2fs_get_device_size2(ctx->filesystem_name, 1580 blocksize, 1581 &ctx->num_blocks); 1582 } 1583 if (pctx.errcode == EXT2_ET_UNIMPLEMENTED) 1584 ctx->num_blocks = 0; 1585 else if (pctx.errcode) { 1586 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx); 1587 ctx->flags |= E2F_FLAG_ABORT; 1588 fatal_error(ctx, 0); 1589 } 1590 ctx->flags |= E2F_FLAG_GOT_DEVSIZE; 1591 if (need_restart) 1592 goto restart; 1593 } 1594 1595 ctx->fs = fs; 1596 fs->now = ctx->now; 1597 sb = fs->super; 1598 1599 if (sb->s_rev_level > E2FSCK_CURRENT_REV) { 1600 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH, 1601 _("while trying to open %s"), 1602 ctx->filesystem_name); 1603 get_newer: 1604 fatal_error(ctx, _("Get a newer version of e2fsck!")); 1605 } 1606 1607 /* 1608 * Set the device name, which is used whenever we print error 1609 * or informational messages to the user. 1610 */ 1611 if (ctx->device_name == 0 && 1612 (sb->s_volume_name[0] != 0)) { 1613 ctx->device_name = string_copy(ctx, sb->s_volume_name, 1614 sizeof(sb->s_volume_name)); 1615 } 1616 if (ctx->device_name == 0) 1617 ctx->device_name = string_copy(ctx, ctx->filesystem_name, 0); 1618 for (cp = ctx->device_name; *cp; cp++) 1619 if (isspace(*cp) || *cp == ':') 1620 *cp = '_'; 1621 1622 ehandler_init(fs->io); 1623 1624 if (ext2fs_has_feature_mmp(fs->super) && 1625 (flags & EXT2_FLAG_SKIP_MMP)) { 1626 if (e2fsck_check_mmp(fs, ctx)) 1627 fatal_error(ctx, 0); 1628 1629 /* 1630 * Restart in order to reopen fs but this time start mmp. 1631 */ 1632 ext2fs_close_free(&ctx->fs); 1633 flags &= ~EXT2_FLAG_SKIP_MMP; 1634 goto restart; 1635 } 1636 1637 if (ctx->logf) 1638 fprintf(ctx->logf, "Filesystem UUID: %s\n", 1639 e2p_uuid2str(sb->s_uuid)); 1640 1641 /* 1642 * Make sure the ext3 superblock fields are consistent. 1643 */ 1644 if ((ctx->mount_flags & (EXT2_MF_MOUNTED | EXT2_MF_BUSY)) == 0) { 1645 retval = e2fsck_check_ext3_journal(ctx); 1646 if (retval) { 1647 com_err(ctx->program_name, retval, 1648 _("while checking journal for %s"), 1649 ctx->device_name); 1650 fatal_error(ctx, 1651 _("Cannot proceed with file system check")); 1652 } 1653 } 1654 1655 /* 1656 * Check to see if we need to do ext3-style recovery. If so, 1657 * do it, and then restart the fsck. 1658 */ 1659 if (ext2fs_has_feature_journal_needs_recovery(sb)) { 1660 if (ctx->options & E2F_OPT_READONLY) { 1661 log_out(ctx, "%s", 1662 _("Warning: skipping journal recovery because " 1663 "doing a read-only filesystem check.\n")); 1664 io_channel_flush(ctx->fs->io); 1665 } else { 1666 if (ctx->flags & E2F_FLAG_RESTARTED) { 1667 /* 1668 * Whoops, we attempted to run the 1669 * journal twice. This should never 1670 * happen, unless the hardware or 1671 * device driver is being bogus. 1672 */ 1673 com_err(ctx->program_name, 0, 1674 _("unable to set superblock flags " 1675 "on %s\n"), ctx->device_name); 1676 fatal_error(ctx, 0); 1677 } 1678 retval = e2fsck_run_ext3_journal(ctx); 1679 if (retval == EFSBADCRC) { 1680 log_out(ctx, _("Journal checksum error " 1681 "found in %s\n"), 1682 ctx->device_name); 1683 } else if (retval == EFSCORRUPTED) { 1684 log_out(ctx, _("Journal corrupted in %s\n"), 1685 ctx->device_name); 1686 } else if (retval) { 1687 com_err(ctx->program_name, retval, 1688 _("while recovering journal of %s"), 1689 ctx->device_name); 1690 } 1691 ext2fs_close_free(&ctx->fs); 1692 ctx->flags |= E2F_FLAG_RESTARTED; 1693 goto restart; 1694 } 1695 } 1696 1697 /* 1698 * Check for compatibility with the feature sets. We need to 1699 * be more stringent than ext2fs_open(). 1700 */ 1701 features[0] = sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP; 1702 features[1] = sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP; 1703 features[2] = (sb->s_feature_ro_compat & 1704 ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP); 1705 print_unsupp_features: 1706 if (features[0] || features[1] || features[2]) { 1707 int i, j; 1708 __u32 *mask = features, m; 1709 1710 log_err(ctx, _("%s has unsupported feature(s):"), 1711 ctx->filesystem_name); 1712 1713 for (i=0; i <3; i++,mask++) { 1714 for (j=0,m=1; j < 32; j++, m<<=1) { 1715 if (*mask & m) 1716 log_err(ctx, " %s", 1717 e2p_feature2string(i, m)); 1718 } 1719 } 1720 log_err(ctx, "\n"); 1721 goto get_newer; 1722 } 1723 1724 /* 1725 * If the user specified a specific superblock, presumably the 1726 * master superblock has been trashed. So we mark the 1727 * superblock as dirty, so it can be written out. 1728 */ 1729 if (ctx->superblock && 1730 !(ctx->options & E2F_OPT_READONLY)) 1731 ext2fs_mark_super_dirty(fs); 1732 1733 /* 1734 * Calculate the number of filesystem blocks per pagesize. If 1735 * fs->blocksize > page_size, set the number of blocks per 1736 * pagesize to 1 to avoid division by zero errors. 1737 */ 1738 #ifdef _SC_PAGESIZE 1739 sysval = sysconf(_SC_PAGESIZE); 1740 if (sysval > 0) 1741 sys_page_size = sysval; 1742 #endif /* _SC_PAGESIZE */ 1743 ctx->blocks_per_page = sys_page_size / fs->blocksize; 1744 if (ctx->blocks_per_page == 0) 1745 ctx->blocks_per_page = 1; 1746 1747 if (ctx->superblock) 1748 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0); 1749 ext2fs_mark_valid(fs); 1750 check_super_block(ctx); 1751 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 1752 fatal_error(ctx, 0); 1753 check_if_skip(ctx); 1754 check_resize_inode(ctx); 1755 if (bad_blocks_file) 1756 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks); 1757 else if (cflag) 1758 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */ 1759 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 1760 fatal_error(ctx, 0); 1761 1762 /* 1763 * Mark the system as valid, 'til proven otherwise 1764 */ 1765 ext2fs_mark_valid(fs); 1766 1767 retval = ext2fs_read_bb_inode(fs, &fs->badblocks); 1768 if (retval) { 1769 log_out(ctx, _("%s: %s while reading bad blocks inode\n"), 1770 ctx->program_name, error_message(retval)); 1771 preenhalt(ctx); 1772 log_out(ctx, "%s", _("This doesn't bode well, " 1773 "but we'll try to go on...\n")); 1774 } 1775 1776 /* 1777 * Save the journal size in megabytes. 1778 * Try and use the journal size from the backup else let e2fsck 1779 * find the default journal size. 1780 */ 1781 if (sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) 1782 journal_size = (sb->s_jnl_blocks[15] << (32 - 20)) | 1783 (sb->s_jnl_blocks[16] >> 20); 1784 else 1785 journal_size = -1; 1786 1787 if (ext2fs_has_feature_quota(sb)) { 1788 /* Quotas were enabled. Do quota accounting during fsck. */ 1789 for (qtype = 0; qtype < MAXQUOTAS; qtype++) { 1790 if (*quota_sb_inump(sb, qtype) != 0) 1791 qtype_bits |= 1 << qtype; 1792 } 1793 1794 clear_problem_context(&pctx); 1795 pctx.errcode = quota_init_context(&ctx->qctx, ctx->fs, 1796 qtype_bits); 1797 if (pctx.errcode) { 1798 fix_problem(ctx, PR_0_QUOTA_INIT_CTX, &pctx); 1799 fatal_error(ctx, 0); 1800 } 1801 } 1802 1803 run_result = e2fsck_run(ctx); 1804 e2fsck_clear_progbar(ctx); 1805 1806 if (!ctx->invalid_bitmaps && 1807 (ctx->flags & E2F_FLAG_JOURNAL_INODE)) { 1808 if (fix_problem(ctx, PR_6_RECREATE_JOURNAL, &pctx)) { 1809 if (journal_size < 1024) 1810 journal_size = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super)); 1811 if (journal_size < 0) { 1812 ext2fs_clear_feature_journal(fs->super); 1813 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 1814 log_out(ctx, "%s: Couldn't determine " 1815 "journal size\n", ctx->program_name); 1816 goto no_journal; 1817 } 1818 log_out(ctx, _("Creating journal (%d blocks): "), 1819 journal_size); 1820 fflush(stdout); 1821 retval = ext2fs_add_journal_inode(fs, 1822 journal_size, 0); 1823 if (retval) { 1824 log_out(ctx, "%s: while trying to create " 1825 "journal\n", error_message(retval)); 1826 goto no_journal; 1827 } 1828 log_out(ctx, "%s", _(" Done.\n")); 1829 log_out(ctx, "%s", 1830 _("\n*** journal has been regenerated ***\n")); 1831 } 1832 } 1833 no_journal: 1834 1835 if (run_result & E2F_FLAG_ABORT) { 1836 fatal_error(ctx, _("aborted")); 1837 } else if (run_result & E2F_FLAG_CANCEL) { 1838 log_out(ctx, _("%s: e2fsck canceled.\n"), ctx->device_name ? 1839 ctx->device_name : ctx->filesystem_name); 1840 exit_value |= FSCK_CANCELED; 1841 } else if (ctx->qctx && !ctx->invalid_bitmaps) { 1842 int needs_writeout; 1843 1844 for (qtype = 0; qtype < MAXQUOTAS; qtype++) { 1845 if (((1 << qtype) & qtype_bits) == 0) 1846 continue; 1847 needs_writeout = 0; 1848 pctx.num = qtype; 1849 retval = quota_compare_and_update(ctx->qctx, qtype, 1850 &needs_writeout); 1851 if ((retval || needs_writeout) && 1852 fix_problem(ctx, PR_6_UPDATE_QUOTAS, &pctx)) { 1853 pctx.errcode = quota_write_inode(ctx->qctx, 1854 1 << qtype); 1855 if (pctx.errcode) 1856 (void) fix_problem(ctx, 1857 PR_6_WRITE_QUOTAS, &pctx); 1858 } 1859 } 1860 quota_release_context(&ctx->qctx); 1861 } 1862 1863 if (run_result == E2F_FLAG_RESTART) { 1864 log_out(ctx, "%s", 1865 _("Restarting e2fsck from the beginning...\n")); 1866 retval = e2fsck_reset_context(ctx); 1867 if (retval) { 1868 com_err(ctx->program_name, retval, "%s", 1869 _("while resetting context")); 1870 fatal_error(ctx, 0); 1871 } 1872 ext2fs_close_free(&ctx->fs); 1873 goto restart; 1874 } 1875 1876 #ifdef MTRACE 1877 mtrace_print("Cleanup"); 1878 #endif 1879 was_changed = ext2fs_test_changed(fs); 1880 if (!(ctx->flags & E2F_FLAG_RUN_RETURN) && 1881 !(ctx->options & E2F_OPT_READONLY)) { 1882 if (ext2fs_test_valid(fs)) { 1883 if (!(sb->s_state & EXT2_VALID_FS)) 1884 exit_value |= FSCK_NONDESTRUCT; 1885 sb->s_state = EXT2_VALID_FS; 1886 if (check_backup_super_block(ctx)) 1887 fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 1888 } else 1889 sb->s_state &= ~EXT2_VALID_FS; 1890 if (!(ctx->flags & E2F_FLAG_TIME_INSANE)) 1891 sb->s_lastcheck = ctx->now; 1892 sb->s_mnt_count = 0; 1893 memset(((char *) sb) + EXT4_S_ERR_START, 0, EXT4_S_ERR_LEN); 1894 pctx.errcode = ext2fs_set_gdt_csum(ctx->fs); 1895 if (pctx.errcode) 1896 fix_problem(ctx, PR_6_SET_BG_CHECKSUM, &pctx); 1897 ext2fs_mark_super_dirty(fs); 1898 } 1899 1900 e2fsck_write_bitmaps(ctx); 1901 if (fs->flags & EXT2_FLAG_DIRTY) { 1902 pctx.errcode = ext2fs_flush(ctx->fs); 1903 if (pctx.errcode) 1904 fix_problem(ctx, PR_6_FLUSH_FILESYSTEM, &pctx); 1905 } 1906 pctx.errcode = io_channel_flush(ctx->fs->io); 1907 if (pctx.errcode) 1908 fix_problem(ctx, PR_6_IO_FLUSH, &pctx); 1909 1910 if (was_changed) { 1911 int fs_fixed = (ctx->flags & E2F_FLAG_PROBLEMS_FIXED); 1912 1913 if (fs_fixed) 1914 exit_value |= FSCK_NONDESTRUCT; 1915 if (!(ctx->options & E2F_OPT_PREEN)) { 1916 #if 0 /* Do this later; it breaks too many tests' golden outputs */ 1917 log_out(ctx, fs_fixed ? 1918 _("\n%s: ***** FILE SYSTEM ERRORS " 1919 "CORRECTED *****\n") : 1920 _("%s: File system was modified.\n"), 1921 ctx->device_name); 1922 #else 1923 log_out(ctx, 1924 _("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"), 1925 ctx->device_name); 1926 #endif 1927 } 1928 if (ctx->mount_flags & EXT2_MF_ISROOT) { 1929 log_out(ctx, _("%s: ***** REBOOT SYSTEM *****\n"), 1930 ctx->device_name); 1931 exit_value |= FSCK_REBOOT; 1932 } 1933 } 1934 if (!ext2fs_test_valid(fs) || 1935 ((exit_value & FSCK_CANCELED) && 1936 (sb->s_state & EXT2_ERROR_FS))) { 1937 log_out(ctx, _("\n%s: ********** WARNING: Filesystem still has " 1938 "errors **********\n\n"), ctx->device_name); 1939 exit_value |= FSCK_UNCORRECTED; 1940 exit_value &= ~FSCK_NONDESTRUCT; 1941 } 1942 if (exit_value & FSCK_CANCELED) { 1943 int allow_cancellation; 1944 1945 profile_get_boolean(ctx->profile, "options", 1946 "allow_cancellation", 0, 0, 1947 &allow_cancellation); 1948 exit_value &= ~FSCK_NONDESTRUCT; 1949 if (allow_cancellation && ext2fs_test_valid(fs) && 1950 (sb->s_state & EXT2_VALID_FS) && 1951 !(sb->s_state & EXT2_ERROR_FS)) 1952 exit_value = 0; 1953 } else 1954 show_stats(ctx); 1955 1956 print_resource_track(ctx, NULL, &ctx->global_rtrack, ctx->fs->io); 1957 1958 ext2fs_close_free(&ctx->fs); 1959 free(ctx->journal_name); 1960 1961 e2fsck_free_context(ctx); 1962 remove_error_table(&et_ext2_error_table); 1963 remove_error_table(&et_prof_error_table); 1964 return exit_value; 1965 } 1966