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