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