X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=e2fsck%2Funix.c;h=72091f882c79b2a6e79c7d57f0292a79d1900fa1;hb=058ad1c70c9a097d282270c6f76d3c3493e15fe2;hp=5f1aaa23185bd3def96ceaa6c24b305a4eec90db;hpb=8dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9a;p=tools%2Fe2fsprogs.git diff --git a/e2fsck/unix.c b/e2fsck/unix.c index 5f1aaa2..72091f8 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -98,7 +98,8 @@ static void usage(e2fsck_t ctx) static void show_stats(e2fsck_t ctx) { ext2_filsys fs = ctx->fs; - int inodes, inodes_used, blocks, blocks_used; + ext2_ino_t inodes, inodes_used; + blk_t blocks, blocks_used; int dir_links; int num_files, num_links; int frag_percent; @@ -117,49 +118,48 @@ static void show_stats(e2fsck_t ctx) frag_percent = (frag_percent + 5) / 10; if (!verbose) { - printf(_("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n"), + printf(_("%s: %u/%u files (%0d.%d%% non-contiguous), %u/%u blocks\n"), ctx->device_name, inodes_used, inodes, frag_percent / 10, frag_percent % 10, blocks_used, blocks); return; } - printf (P_("\n%8d inode used (%d%%)\n", "\n%8d inodes used (%d%%)\n", - inodes_used), inodes_used, 100 * inodes_used / inodes); - printf (P_("%8d non-contiguous inode (%0d.%d%%)\n", - "%8d non-contiguous inodes (%0d.%d%%)\n", + printf (P_("\n%8u inode used (%2.2f%%)\n", "\n%8u inodes used (%2.2f%%)\n", + inodes_used), inodes_used, 100.0 * inodes_used / inodes); + printf (P_("%8u non-contiguous inode (%0d.%d%%)\n", + "%8u non-contiguous inodes (%0d.%d%%)\n", ctx->fs_fragmented), ctx->fs_fragmented, frag_percent / 10, frag_percent % 10); - printf (_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"), + printf (_(" # of inodes with ind/dind/tind blocks: %u/%u/%u\n"), ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count); - printf (P_("%8d block used (%d%%)\n", "%8d blocks used (%d%%)\n", - blocks_used), - blocks_used, (int) ((long long) 100 * blocks_used / blocks)); - printf (P_("%8d bad block\n", "%8d bad blocks\n", + printf (P_("%8u block used (%2.2f%%)\n", "%8u blocks used (%2.2f%%)\n", + blocks_used), blocks_used, 100.0 * blocks_used / blocks); + printf (P_("%8u bad block\n", "%8u bad blocks\n", ctx->fs_badblocks_count), ctx->fs_badblocks_count); - printf (P_("%8d large file\n", "%8d large files\n", + printf (P_("%8u large file\n", "%8u large files\n", ctx->large_files), ctx->large_files); - printf (P_("\n%8d regular file\n", "\n%8d regular files\n", + printf (P_("\n%8u regular file\n", "\n%8u regular files\n", ctx->fs_regular_count), ctx->fs_regular_count); - printf (P_("%8d directory\n", "%8d directories\n", + printf (P_("%8u directory\n", "%8u directories\n", ctx->fs_directory_count), ctx->fs_directory_count); - printf (P_("%8d character device file\n", - "%8d character device files\n", ctx->fs_chardev_count), + printf (P_("%8u character device file\n", + "%8u character device files\n", ctx->fs_chardev_count), ctx->fs_chardev_count); - printf (P_("%8d block device file\n", "%8d block device files\n", + printf (P_("%8u block device file\n", "%8u block device files\n", ctx->fs_blockdev_count), ctx->fs_blockdev_count); - printf (P_("%8d fifo\n", "%8d fifos\n", ctx->fs_fifo_count), + printf (P_("%8u fifo\n", "%8u fifos\n", ctx->fs_fifo_count), ctx->fs_fifo_count); - printf (P_("%8d link\n", "%8d links\n", + printf (P_("%8u link\n", "%8u links\n", ctx->fs_links_count - dir_links), ctx->fs_links_count - dir_links); - printf (P_("%8d symbolic link", "%8d symbolic links", + printf (P_("%8u symbolic link", "%8u symbolic links", ctx->fs_symlinks_count), ctx->fs_symlinks_count); - printf (P_(" (%d fast symbolic link)\n", " (%d fast symbolic links)\n", + printf (P_(" (%u fast symbolic link)\n", " (%u fast symbolic links)\n", ctx->fs_fast_symlinks_count), ctx->fs_fast_symlinks_count); - printf (P_("%8d socket\n", "%8d sockets\n", ctx->fs_sockets_count), + printf (P_("%8u socket\n", "%8u sockets\n", ctx->fs_sockets_count), ctx->fs_sockets_count); printf ("--------\n"); - printf (P_("%8d file\n", "%8d files\n", + printf (P_("%8u file\n", "%8u files\n", ctx->fs_total_count - dir_links), ctx->fs_total_count - dir_links); } @@ -179,15 +179,18 @@ static void check_mount(e2fsck_t ctx) } /* - * If the filesystem isn't mounted, or it's the root filesystem - * and it's mounted read-only, then everything's fine. + * If the filesystem isn't mounted, or it's the root + * filesystem and it's mounted read-only, and we're not doing + * a read/write check, then everything's fine. */ if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) || ((ctx->mount_flags & EXT2_MF_ISROOT) && - (ctx->mount_flags & EXT2_MF_READONLY))) + (ctx->mount_flags & EXT2_MF_READONLY) && + !(ctx->options & E2F_OPT_WRITECHECK))) return; - if (ctx->options & E2F_OPT_READONLY) { + if ((ctx->options & E2F_OPT_READONLY) && + !(ctx->options & E2F_OPT_WRITECHECK)) { printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name); return; } @@ -256,7 +259,14 @@ static void check_if_skip(e2fsck_t ctx) unsigned int reason_arg = 0; long next_check; int batt = is_on_batt(); - + int defer_check_on_battery; + + profile_get_boolean(ctx->profile, "options", + "defer_check_on_battery", 0, 1, + &defer_check_on_battery); + if (!defer_check_on_battery) + batt = 0; + if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file || cflag || swapfs) return; @@ -289,7 +299,7 @@ static void check_if_skip(e2fsck_t ctx) fputs(_(", check forced.\n"), stdout); return; } - printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name, + printf(_("%s: clean, %u/%u files, %u/%u blocks"), ctx->device_name, fs->super->s_inodes_count - fs->super->s_free_inodes_count, fs->super->s_inodes_count, fs->super->s_blocks_count - fs->super->s_free_blocks_count, @@ -304,9 +314,13 @@ static void check_if_skip(e2fsck_t ctx) ((ctx->now - fs->super->s_lastcheck) >= fs->super->s_checkinterval)) next_check = 1; if (next_check <= 5) { - if (next_check == 1) - fputs(_(" (check after next mount)"), stdout); - else + if (next_check == 1) { + if (batt) + fputs(_(" (check deferred; on battery)"), + stdout); + else + fputs(_(" (check after next mount)"), stdout); + } else printf(_(" (check in %ld mounts)"), next_check); } fputc('\n', stdout); @@ -509,7 +523,7 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) if (p) { *p = 0; next = p+1; - } + } arg = strchr(token, '='); if (arg) { *arg = 0; @@ -535,6 +549,8 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) extended_usage++; } } + free(buf); + if (extended_usage) { fputs(("\nExtended options are separated by commas, " "and may take an argument which\n" @@ -543,8 +559,17 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) "\tea_ver=\n\n"), stderr); exit(1); } -} +} +static void syntax_err_report(const char *filename, long err, int line_num) +{ + fprintf(stderr, + _("Syntax error in e2fsck config file (%s, line #%d)\n\t%s\n"), + filename, line_num, error_message(err)); + exit(FSCK_ERROR); +} + +static const char *config_fn[] = { ROOT_SYSCONFDIR "/e2fsck.conf", 0 }; static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) { @@ -559,6 +584,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) struct sigaction sa; #endif char *extended_opts = 0; + char *cp; retval = e2fsck_allocate_context(&ctx); if (retval) @@ -576,7 +602,8 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) } memset(bar, '=', sizeof(bar)-1); memset(spaces, ' ', sizeof(spaces)-1); - initialize_ext2_error_table(); + add_error_table(&et_ext2_error_table); + add_error_table(&et_prof_error_table); blkid_get_cache(&ctx->blkid, NULL); if (argc && *argv) @@ -613,7 +640,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) { conflict_opt: fatal_error(ctx, - _("Only one the options -p/-a, -n or -y may be specified.")); + _("Only one of the options -p/-a, -n or -y may be specified.")); } ctx->options |= E2F_OPT_PREEN; break; @@ -728,7 +755,12 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) } if (extended_opts) parse_extended_opts(ctx, extended_opts); - + + if ((cp = getenv("E2FSCK_CONFIG")) != NULL) + config_fn[0] = cp; + profile_set_syntax_err_cb(syntax_err_report); + profile_init(config_fn, &ctx->profile); + if (flush) { fd = open(ctx->filesystem_name, O_RDONLY, 0); if (fd < 0) { @@ -780,19 +812,22 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) /* Update our PATH to include /sbin if we need to run badblocks */ if (cflag) { char *oldpath = getenv("PATH"); + char *newpath; + int len = sizeof(PATH_SET) + 1; + + if (oldpath) + len += strlen(oldpath); + + newpath = malloc(len); + if (!newpath) + fatal_error(ctx, "Couldn't malloc() newpath"); + strcpy(newpath, PATH_SET); + if (oldpath) { - char *newpath; - - newpath = (char *) malloc(sizeof (PATH_SET) + 1 + - strlen (oldpath)); - if (!newpath) - fatal_error(ctx, "Couldn't malloc() newpath"); - strcpy (newpath, PATH_SET); - strcat (newpath, ":"); - strcat (newpath, oldpath); - putenv (newpath); - } else - putenv (PATH_SET); + strcat(newpath, ":"); + strcat(newpath, oldpath); + } + putenv(newpath); } #ifdef CONFIG_JBD_DEBUG if (getenv("E2FSCK_JBD_DEBUG")) @@ -880,6 +915,8 @@ restart: flags = 0; if ((ctx->options & E2F_OPT_READONLY) == 0) flags |= EXT2_FLAG_RW; + if ((ctx->mount_flags & EXT2_MF_MOUNTED) == 0) + flags |= EXT2_FLAG_EXCLUSIVE; if (ctx->superblock && ctx->blocksize) { retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options, @@ -931,6 +968,9 @@ restart: "r/o" : "r/w"); else if (retval == ENXIO) printf(_("Possibly non-existent or swap device?\n")); + else if (retval == EBUSY) + printf(_("Filesystem mounted or opened exclusively " + "by another program?\n")); #ifdef EROFS else if (retval == EROFS) printf(_("Disk write-protected; use the -n option " @@ -941,6 +981,54 @@ restart: fix_problem(ctx, PR_0_SB_CORRUPT, &pctx); fatal_error(ctx, 0); } + /* + * We only update the master superblock because (a) paranoia; + * we don't want to corrupt the backup superblocks, and (b) we + * don't need to update the mount count and last checked + * fields in the backup superblock (the kernel doesn't update + * the backup superblocks anyway). With newer versions of the + * library this flag is set by ext2fs_open2(), but we set this + * here just to be sure. (No, we don't support e2fsck running + * with some other libext2fs than the one that it was shipped + * with, but just in case....) + */ + fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; + + if (!(ctx->flags & E2F_FLAG_GOT_DEVSIZE)) { + __u32 blocksize = EXT2_BLOCK_SIZE(fs->super); + int need_restart = 0; + + pctx.errcode = ext2fs_get_device_size(ctx->filesystem_name, + blocksize, + &ctx->num_blocks); + /* + * The floppy driver refuses to allow anyone else to + * open the device if has been opened with O_EXCL; + * this is unlike other block device drivers in Linux. + * To handle this, we close the filesystem and then + * reopen the filesystem after we get the device size. + */ + if (pctx.errcode == EBUSY) { + ext2fs_close(fs); + need_restart++; + pctx.errcode = + ext2fs_get_device_size(ctx->filesystem_name, + blocksize, + &ctx->num_blocks); + } + if (pctx.errcode == EXT2_ET_UNIMPLEMENTED) + ctx->num_blocks = 0; + else if (pctx.errcode) { + fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + fatal_error(ctx, 0); + return; + } + ctx->flags |= E2F_FLAG_GOT_DEVSIZE; + if (need_restart) + goto restart; + } + ctx->fs = fs; fs->priv_data = ctx; fs->now = ctx->now; @@ -1051,15 +1139,6 @@ restart: !(ctx->options & E2F_OPT_READONLY)) ext2fs_mark_super_dirty(fs); - /* - * We only update the master superblock because (a) paranoia; - * we don't want to corrupt the backup superblocks, and (b) we - * don't need to update the mount count and last checked - * fields in the backup superblock (the kernel doesn't - * update the backup superblocks anyway). - */ - fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; - ehandler_init(fs->io); if (ctx->superblock) @@ -1140,15 +1219,26 @@ restart: exit_value |= FSCK_REBOOT; } } - if (!ext2fs_test_valid(fs)) { + if (!ext2fs_test_valid(fs) || + ((exit_value & FSCK_CANCELED) && + (sb->s_state & EXT2_ERROR_FS))) { printf(_("\n%s: ********** WARNING: Filesystem still has " "errors **********\n\n"), ctx->device_name); exit_value |= FSCK_UNCORRECTED; exit_value &= ~FSCK_NONDESTRUCT; } - if (exit_value & FSCK_CANCELED) + if (exit_value & FSCK_CANCELED) { + int allow_cancellation; + + profile_get_boolean(ctx->profile, "options", + "allow_cancellation", 0, 0, + &allow_cancellation); exit_value &= ~FSCK_NONDESTRUCT; - else { + if (allow_cancellation && ext2fs_test_valid(fs) && + (sb->s_state & EXT2_VALID_FS) && + !(sb->s_state & EXT2_ERROR_FS)) + exit_value = 0; + } else { show_stats(ctx); if (!(ctx->options & E2F_OPT_READONLY)) { if (ext2fs_test_valid(fs)) { @@ -1175,5 +1265,7 @@ restart: print_resource_track(NULL, &ctx->global_rtrack); #endif e2fsck_free_context(ctx); + remove_error_table(&et_ext2_error_table); + remove_error_table(&et_prof_error_table); return exit_value; }