+Fri Oct 3 13:40:03 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * pass*.c, super.c: Massive changes to avoid using printf and
+ com_err routines. All diagnostic messages are now routed
+ through the fix_problem interface.
+
+Sat Sep 6 17:13:28 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * pass2.c (check_dir_block): Check for duplicate '.' and '..'
+ entries.
+
+ * problem.c, problem.h: Add new problem codes PR_2_DUP_DOT and
+ PR_2_DUP_DOT_DOT.
+
+Tue Sep 2 09:04:51 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * problem.c: Added new problem codes for some of the
+ superblock corruption checks, and for the pass header
+ messages. ("Pass 1: xxxxx")
+
+ * util.c (print_resource_track): Now takes a description
+ argument.
+
+Mon Aug 25 10:23:13 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * super.c, unix.c, e2fsck.c: New files to separate out the
+ operating-specific operations out from e2fsck.c.
+ e2fsck.c now contains the global e2fsck context management
+ routines, and super.c contains the "pass 0" initial
+ validation of the superblock and global block group
+ descriptors.
+
+ * pass1.c, pass2.c, pass3.c, pass4.c, pass5.c, util.c: Eliminate
+ (nearly) all global variables and moved them to the e2fsck
+ context structure.
+
+ * problem.c, problem.h: Added new problem codes PR_0_SB_CORRUPT,
+ PR_0_FS_SIZE_WRONG, PR_0_NO_FRAGMENTS,
+ PR_0_BLOCKS_PER_GROUP, PR_0_FIRST_DATA_BLOCK
+
Thu Aug 14 10:55:21 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* message.c: Add compression for the word "Illegal"
#
#MCHECK= -DMCHECK
-OBJS= e2fsck.o pass1.o pass1b.o pass2.o pass3.o pass4.o pass5.o \
- swapfs.o badblocks.o util.o dirinfo.o ehandler.o problem.o message.o \
- $(MTRACE_OBJ)
+OBJS= unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o pass3.o pass4.o \
+ pass5.o swapfs.o badblocks.o util.o dirinfo.o ehandler.o \
+ problem.o message.o $(MTRACE_OBJ)
-PROFILED_OBJS= profiled/e2fsck.o profiled/pass1.o profiled/pass1b.o \
+PROFILED_OBJS= profiled/unix.o profiled/e2fsck.o profiled/super.o \
+ profiled/pass1.o profiled/pass1b.o \
profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \
profiled/badblocks.o profiled/util.o profiled/dirinfo.o \
profiled/ehandler.o profiled/message.o profiled/problem.o \
profiled/swapfs.o
SRCS= $(srcdir)/e2fsck.c \
+ $(srcdir)/super.c \
$(srcdir)/pass1.c \
$(srcdir)/pass1b.c \
$(srcdir)/pass2.c \
$(srcdir)/pass5.c \
$(srcdir)/badblocks.c \
$(srcdir)/util.c \
+ $(srcdir)/unix.c \
$(srcdir)/dirinfo.c \
$(srcdir)/ehandler.c \
$(srcdir)/problem.c \
return;
}
-void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
+void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
int replace_bad_blocks)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
badblocks_list bb_list = 0;
FILE *f;
char buf[1024];
- read_bitmaps(fs);
+ read_bitmaps(ctx);
/*
* Make sure the bad block inode is sane. If there are any
}
} else {
sprintf(buf, "badblocks -b %d %s%s %d", fs->blocksize,
- preen ? "" : "-s ", fs->device_name,
- fs->super->s_blocks_count);
+ (ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
+ fs->device_name, fs->super->s_blocks_count);
f = popen(buf, "r");
if (!f) {
com_err("read_bad_blocks_file", errno,
return;
}
-void test_disk(ext2_filsys fs)
+void test_disk(e2fsck_t ctx)
{
- read_bad_blocks_file(fs, 0, 1);
+ read_bad_blocks_file(ctx, 0, 1);
}
static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
* %End-Header%
*/
-/* Usage: e2fsck [-dfpnsvy] device
- * -d -- debugging this program
- * -f -- check the fs even if it is marked valid
- * -p -- "preen" the filesystem
- * -n -- open the filesystem r/o mode; never try to fix problems
- * -v -- verbose (tells how many files)
- * -y -- always answer yes to questions
- *
- * The device may be a block device or a image of one, but this isn't
- * enforced (but it's not much fun on a character device :-).
- */
-
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <string.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <termios.h>
-#include <time.h>
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#include <unistd.h>
-#ifdef HAVE_ERRNO_H
#include <errno.h>
-#endif
-#ifdef HAVE_MNTENT_H
-#include <mntent.h>
-#endif
-#include <sys/ioctl.h>
-#include <malloc.h>
#include "et/com_err.h"
-#include "uuid/uuid.h"
+
#include "e2fsck.h"
#include "problem.h"
-#include "../version.h"
-
-extern int isatty(int);
-
-const char * program_name = "e2fsck";
-const char * device_name = NULL;
-const char * filesystem_name = NULL;
-
-/* Command line options */
-int nflag = 0;
-int yflag = 0;
-int tflag = 0; /* Do timing */
-int cflag = 0; /* check disk */
-int preen = 0;
-int rwflag = 1;
-int swapfs = 0;
-int normalize_swapfs = 0;
-int inode_buffer_blocks = 0;
-blk_t use_superblock;
-blk_t superblock;
-int blocksize = 0;
-int verbose = 0;
-int list = 0;
-int debug = 0;
-int force = 0;
-int invalid_bitmaps = 0;
-static int show_version_only = 0;
-
-static int replace_bad_blocks = 0;
-static char *bad_blocks_file = 0;
-
-static int possible_block_sizes[] = { 1024, 2048, 4096, 8192, 0};
-
-struct resource_track global_rtrack;
-
-static int root_filesystem = 0;
-static int read_only_root = 0;
-
-int *invalid_inode_bitmap;
-int *invalid_block_bitmap;
-int *invalid_inode_table;
-int restart_e2fsck = 0;
-
-static void usage(NOARGS)
-{
- fprintf(stderr,
- "Usage: %s [-panyrcdfvstFSV] [-b superblock] [-B blocksize]\n"
- "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
- "\t\t[-l|-L bad_blocks_file] device\n", program_name);
- exit(FSCK_USAGE);
-}
-
-static void show_stats(ext2_filsys fs)
-{
- int inodes, inodes_used, blocks, blocks_used;
- int dir_links;
- int num_files, num_links;
- int frag_percent;
-
- dir_links = 2 * fs_directory_count - 1;
- num_files = fs_total_count - dir_links;
- num_links = fs_links_count - dir_links;
- inodes = fs->super->s_inodes_count;
- inodes_used = (fs->super->s_inodes_count -
- fs->super->s_free_inodes_count);
- blocks = fs->super->s_blocks_count;
- blocks_used = (fs->super->s_blocks_count -
- fs->super->s_free_blocks_count);
-
- frag_percent = (10000 * fs_fragmented) / inodes_used;
- frag_percent = (frag_percent + 5) / 10;
-
- if (!verbose) {
- printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
- device_name, inodes_used, inodes,
- frag_percent / 10, frag_percent % 10,
- blocks_used, blocks);
- return;
- }
- printf ("\n%8d inode%s used (%d%%)\n", inodes_used,
- (inodes_used != 1) ? "s" : "",
- 100 * inodes_used / inodes);
- printf ("%8d non-contiguous inodes (%0d.%d%%)\n",
- fs_fragmented, frag_percent / 10, frag_percent % 10);
- printf (" # of inodes with ind/dind/tind blocks: %d/%d/%d\n",
- fs_ind_count, fs_dind_count, fs_tind_count);
- printf ("%8d block%s used (%d%%)\n"
- "%8d bad block%s\n", blocks_used,
- (blocks_used != 1) ? "s" : "",
- 100 * blocks_used / blocks, fs_badblocks_count,
- fs_badblocks_count != 1 ? "s" : "");
- printf ("\n%8d regular file%s\n"
- "%8d director%s\n"
- "%8d character device file%s\n"
- "%8d block device file%s\n"
- "%8d fifo%s\n"
- "%8d link%s\n"
- "%8d symbolic link%s (%d fast symbolic link%s)\n"
- "%8d socket%s\n"
- "--------\n"
- "%8d file%s\n",
- fs_regular_count, (fs_regular_count != 1) ? "s" : "",
- fs_directory_count, (fs_directory_count != 1) ? "ies" : "y",
- fs_chardev_count, (fs_chardev_count != 1) ? "s" : "",
- fs_blockdev_count, (fs_blockdev_count != 1) ? "s" : "",
- fs_fifo_count, (fs_fifo_count != 1) ? "s" : "",
- fs_links_count - dir_links,
- ((fs_links_count - dir_links) != 1) ? "s" : "",
- fs_symlinks_count, (fs_symlinks_count != 1) ? "s" : "",
- fs_fast_symlinks_count, (fs_fast_symlinks_count != 1) ? "s" : "",
- fs_sockets_count, (fs_sockets_count != 1) ? "s" : "",
- fs_total_count - dir_links,
- ((fs_total_count - dir_links) != 1) ? "s" : "");
-}
-
-static void check_mount(NOARGS)
-{
- errcode_t retval;
- int mount_flags, cont, fd;
-
- retval = ext2fs_check_if_mounted(filesystem_name, &mount_flags);
- if (retval) {
- com_err("ext2fs_check_if_mount", retval,
- "while determining whether %s is mounted.",
- filesystem_name);
- return;
- }
- if (!(mount_flags & EXT2_MF_MOUNTED))
- return;
-
-#if (defined(__linux__) && defined(HAVE_MNTENT_H))
- /*
- * If the root is mounted read-only, then /etc/mtab is
- * probably not correct; so we won't issue a warning based on
- * it.
- */
- fd = open(MOUNTED, O_RDWR);
- if (fd < 0) {
- if (errno == EROFS)
- return;
- } else
- close(fd);
-#endif
-
- if (!rwflag) {
- printf("Warning! %s is mounted.\n", device_name);
- return;
- }
-
- printf("%s is mounted.\n\n", device_name);
- printf("\a\a\a\aWARNING!!! Running e2fsck on a mounted filesystem "
- "may cause\nSEVERE filesystem damage.\a\a\a\n\n");
- if (isatty (0) && isatty (1))
- cont = ask_yn("Do you really want to continue", -1);
- else
- cont = 0;
- if (!cont) {
- printf ("check aborted.\n");
- exit (0);
- }
- return;
-}
-
-static void sync_disks(NOARGS)
-{
- sync();
- sync();
- sleep(1);
- sync();
-}
-
-static blk_t get_backup_sb(ext2_filsys fs)
-{
- if (!fs || !fs->super)
- return 8193;
- return fs->super->s_blocks_per_group + 1;
-}
-
-#define MIN_CHECK 1
-#define MAX_CHECK 2
-
-static const char *corrupt_msg =
-"\nThe superblock could not be read or does not describe a correct ext2\n"
-"filesystem. If the device is valid and it really contains an ext2\n"
-"filesystem (and not swap or ufs or something else), then the superblock\n"
-"is corrupt, and you might try running e2fsck with an alternate superblock:\n"
-" e2fsck -b %d <device>\n\n";
-
-static void check_super_value(ext2_filsys fs, const char *descr,
- unsigned long value, int flags,
- unsigned long min, unsigned long max)
-{
- if (((flags & MIN_CHECK) && (value < min)) ||
- ((flags & MAX_CHECK) && (value > max))) {
- printf("Corruption found in superblock. (%s = %lu).\n",
- descr, value);
- printf(corrupt_msg, get_backup_sb(fs));
- fatal_error(0);
- }
-}
-
-static void relocate_hint(ext2_filsys fs)
-{
- static hint_issued = 0;
-
- /*
- * Only issue the hint once, and only if we're using the
- * primary superblocks.
- */
- if (hint_issued || superblock)
- return;
-
- printf("Note: if there is several inode or block bitmap blocks\n"
- "which require relocation, or one part of the inode table\n"
- "which must be moved, you may wish to try running e2fsck\n"
- "with the '-b %d' option first. The problem may lie only\n"
- "with the primary block group descriptor, and the backup\n"
- "block group descriptor may be OK.\n\n", get_backup_sb(fs));
- hint_issued = 1;
-}
-
-
-static void check_super_block(ext2_filsys fs)
-{
- blk_t first_block, last_block;
- struct ext2fs_sb *s = (struct ext2fs_sb *) fs->super;
- blk_t blocks_per_group = fs->super->s_blocks_per_group;
- int i;
- blk_t should_be;
- errcode_t retval;
- struct problem_context pctx;
-
- clear_problem_context(&pctx);
-
- /*
- * Verify the super block constants...
- */
- check_super_value(fs, "inodes_count", s->s_inodes_count,
- MIN_CHECK, 1, 0);
- check_super_value(fs, "blocks_count", s->s_blocks_count,
- MIN_CHECK, 1, 0);
- check_super_value(fs, "first_data_block", s->s_first_data_block,
- MAX_CHECK, 0, s->s_blocks_count);
- check_super_value(fs, "log_frag_size", s->s_log_frag_size,
- MAX_CHECK, 0, 2);
- check_super_value(fs, "log_block_size", s->s_log_block_size,
- MIN_CHECK | MAX_CHECK, s->s_log_frag_size,
- 2);
- check_super_value(fs, "frags_per_group", s->s_frags_per_group,
- MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
- check_super_value(fs, "blocks_per_group", s->s_blocks_per_group,
- MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
- check_super_value(fs, "inodes_per_group", s->s_inodes_per_group,
- MIN_CHECK, 1, 0);
- check_super_value(fs, "r_blocks_count", s->s_r_blocks_count,
- MAX_CHECK, 0, s->s_blocks_count);
-
- retval = ext2fs_get_device_size(filesystem_name, EXT2_BLOCK_SIZE(s),
- &should_be);
- if (retval) {
- com_err("ext2fs_get_device_size", retval,
- "while trying to check physical size of filesystem");
- fatal_error(0);
- }
- if (should_be < s->s_blocks_count) {
- printf("The filesystem size (according to the superblock) is %d blocks\n", s->s_blocks_count);
- printf("The physical size of the device is %d blocks\n",
- should_be);
- printf("Either the superblock or the partition table is likely to be corrupt!\n");
- preenhalt(fs);
- if (ask("Abort", 1))
- fatal_error(0);
- }
-
- if (s->s_log_block_size != s->s_log_frag_size) {
- printf("Superblock block_size = %d, fragsize = %d.\n",
- EXT2_BLOCK_SIZE(s), EXT2_FRAG_SIZE(s));
- printf("This version of e2fsck does not support fragment "
- "sizes different\n"
- "from the block size.\n");
- fatal_error(0);
- }
-
- should_be = s->s_frags_per_group /
- (s->s_log_block_size - s->s_log_frag_size + 1);
- if (s->s_blocks_per_group != should_be) {
- printf("Superblock blocks_per_group = %u, should "
- "have been %u\n", s->s_blocks_per_group,
- should_be);
- printf(corrupt_msg, get_backup_sb(fs));
- fatal_error(0);
- }
-
- should_be = (s->s_log_block_size == 0) ? 1 : 0;
- if (s->s_first_data_block != should_be) {
- printf("Superblock first_data_block = %u, should "
- "have been %u\n", s->s_first_data_block,
- should_be);
- printf(corrupt_msg, get_backup_sb(fs));
- fatal_error(0);
- }
-
- /*
- * Verify the group descriptors....
- */
- first_block = fs->super->s_first_data_block;
- last_block = first_block + blocks_per_group;
-
- for (i = 0; i < fs->group_desc_count; i++) {
- pctx.group = i;
-
- if (i == fs->group_desc_count - 1)
- last_block = fs->super->s_blocks_count;
- if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
- (fs->group_desc[i].bg_block_bitmap >= last_block)) {
- relocate_hint(fs);
- pctx.blk = fs->group_desc[i].bg_block_bitmap;
- if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) {
- fs->group_desc[i].bg_block_bitmap = 0;
- invalid_block_bitmap[i]++;
- invalid_bitmaps++;
- }
- }
- if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
- (fs->group_desc[i].bg_inode_bitmap >= last_block)) {
- relocate_hint(fs);
- pctx.blk = fs->group_desc[i].bg_inode_bitmap;
- if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) {
- fs->group_desc[i].bg_inode_bitmap = 0;
- invalid_inode_bitmap[i]++;
- invalid_bitmaps++;
- }
- }
- if ((fs->group_desc[i].bg_inode_table < first_block) ||
- ((fs->group_desc[i].bg_inode_table +
- fs->inode_blocks_per_group - 1) >= last_block)) {
- relocate_hint(fs);
- pctx.blk = fs->group_desc[i].bg_inode_table;
- if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) {
- fs->group_desc[i].bg_inode_table = 0;
- invalid_inode_table[i]++;
- invalid_bitmaps++;
- }
- }
- first_block += fs->super->s_blocks_per_group;
- last_block += fs->super->s_blocks_per_group;
- }
- /*
- * If we have invalid bitmaps, set the error state of the
- * filesystem.
- */
- if (invalid_bitmaps && rwflag) {
- fs->super->s_state &= ~EXT2_VALID_FS;
- ext2fs_mark_super_dirty(fs);
- }
-
- /*
- * If the UUID field isn't assigned, assign it.
- */
- if (rwflag && uuid_is_null(s->s_uuid)) {
- if (preen)
- printf("%s: Adding UUID to filesystem.\n",
- device_name);
- else
- printf("Filesystem did not have a UUID; "
- "generating one.\n\n");
- uuid_generate(s->s_uuid);
- ext2fs_mark_super_dirty(fs);
- }
- return;
-}
/*
- * This routine checks to see if a filesystem can be skipped; if so,
- * it will exit with E2FSCK_OK. Under some conditions it will print a
- * message explaining why a check is being forced.
+ * This function allocates an e2fsck context
*/
-static void check_if_skip(ext2_filsys fs)
-{
- const char *reason = NULL;
-
- if (force || bad_blocks_file || cflag || swapfs)
- return;
-
- if (fs->super->s_state & EXT2_ERROR_FS)
- reason = "contains a file system with errors";
- else if (fs->super->s_mnt_count >=
- (unsigned) fs->super->s_max_mnt_count)
- reason = "has reached maximal mount count";
- else if (fs->super->s_checkinterval &&
- time(0) >= (fs->super->s_lastcheck +
- fs->super->s_checkinterval))
- reason = "has gone too long without being checked";
- else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
- reason = "was not cleanly unmounted";
- if (reason) {
- printf("%s %s, check forced.\n", device_name, reason);
- return;
- }
- printf("%s: clean, %d/%d files, %d/%d blocks\n", 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,
- fs->super->s_blocks_count);
- ext2fs_close(fs);
- exit(FSCK_OK);
-}
-
-#define PATH_SET "PATH=/sbin"
-
-static void PRS(int argc, char *argv[])
+errcode_t e2fsck_allocate_context(e2fsck_t *ret)
{
- int flush = 0;
- char c;
-#ifdef MTRACE
- extern void *mallwatch;
-#endif
- char *oldpath = getenv("PATH");
+ e2fsck_t context;
- /* Update our PATH to include /sbin */
- if (oldpath) {
- char *newpath;
+ context = malloc(sizeof(struct e2fsck_struct));
+ if (!context)
+ return ENOMEM;
- newpath = malloc(sizeof (PATH_SET) + 1 + strlen (oldpath));
- if (!newpath)
- fatal_error("Couldn't malloc() newpath");
- strcpy (newpath, PATH_SET);
- strcat (newpath, ":");
- strcat (newpath, oldpath);
- putenv (newpath);
- } else
- putenv (PATH_SET);
+ memset(context, 0, sizeof(struct e2fsck_struct));
- setbuf(stdout, NULL);
- setbuf(stderr, NULL);
- initialize_ext2_error_table();
-
- if (argc && *argv)
- program_name = *argv;
- while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:N:Ss")) != EOF)
- switch (c) {
- case 'p':
- case 'a':
- preen = 1;
- yflag = nflag = 0;
- break;
- case 'n':
- nflag = 1;
- preen = yflag = 0;
- break;
- case 'y':
- yflag = 1;
- preen = nflag = 0;
- break;
- case 't':
- tflag++;
- break;
- case 'c':
- cflag++;
- break;
- case 'r':
- /* What we do by default, anyway! */
- break;
- case 'b':
- use_superblock = atoi(optarg);
- break;
- case 'B':
- blocksize = atoi(optarg);
- break;
- case 'I':
- inode_buffer_blocks = atoi(optarg);
- break;
- case 'P':
- process_inode_size = atoi(optarg);
- break;
- case 'L':
- replace_bad_blocks++;
- case 'l':
- bad_blocks_file = malloc(strlen(optarg)+1);
- if (!bad_blocks_file)
- fatal_error("Couldn't malloc bad_blocks_file");
- strcpy(bad_blocks_file, optarg);
- break;
- case 'd':
- debug = 1;
- break;
- case 'f':
- force = 1;
- break;
- case 'F':
-#ifdef BLKFLSBUF
- flush = 1;
-#else
- fatal_error ("-F not supported");
-#endif
- break;
- case 'v':
- verbose = 1;
- break;
- case 'V':
- show_version_only = 1;
- break;
-#ifdef MTRACE
- case 'M':
- mallwatch = (void *) strtol(optarg, NULL, 0);
- break;
-#endif
- case 'N':
- device_name = optarg;
- break;
- case 's':
- normalize_swapfs = 1;
- case 'S':
- swapfs = 1;
- break;
- default:
- usage ();
- }
- if (show_version_only)
- return;
- if (optind != argc - 1)
- usage ();
- if (nflag && !bad_blocks_file && !cflag && !swapfs)
- rwflag = 0;
- filesystem_name = argv[optind];
- if (device_name == 0)
- device_name = filesystem_name;
- if (flush) {
-#ifdef BLKFLSBUF
- int fd = open(filesystem_name, O_RDONLY, 0);
+ context->process_inode_size = 256;
- if (fd < 0) {
- com_err("open", errno, "while opening %s for flushing",
- filesystem_name);
- exit(FSCK_ERROR);
- }
- if (ioctl(fd, BLKFLSBUF, 0) < 0) {
- com_err("BLKFLSBUF", errno, "while trying to flush %s",
- filesystem_name);
- exit(FSCK_ERROR);
- }
- close(fd);
-#else
- fatal_error ("BLKFLSBUF not supported");
-#endif /* BLKFLSBUF */
- }
- if (swapfs) {
- if (cflag || bad_blocks_file) {
- fprintf(stderr, "Incompatible options not "
- "allowed when byte-swapping.\n");
- fatal_error(0);
- }
- }
+ *ret = context;
+ return 0;
}
-static const char *my_ver_string = E2FSPROGS_VERSION;
-static const char *my_ver_date = E2FSPROGS_DATE;
-
-int main (int argc, char *argv[])
+/*
+ * This function resets an e2fsck context; it is called when e2fsck
+ * needs to be restarted.
+ */
+errcode_t e2fsck_reset_context(e2fsck_t ctx)
{
- errcode_t retval = 0;
- int exit_value = FSCK_OK;
- int i;
- ext2_filsys fs = 0;
- io_manager io_ptr;
- struct ext2fs_sb *s;
- const char *lib_ver_date;
- int my_ver, lib_ver;
-
-#ifdef MTRACE
- mtrace();
-#endif
-#ifdef MCHECK
- mcheck(0);
-#endif
- my_ver = ext2fs_parse_version_string(my_ver_string);
- lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
- if (my_ver > lib_ver) {
- fprintf( stderr, "Error: ext2fs library version "
- "out of date!\n");
- show_version_only++;
- }
-
- init_resource_track(&global_rtrack);
-
- PRS(argc, argv);
-
- if (!preen || show_version_only)
- fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
- my_ver_string, my_ver_date, EXT2FS_VERSION,
- EXT2FS_DATE);
-
- if (show_version_only) {
- fprintf(stderr, "\tUsing %s, %s\n",
- error_message(EXT2_ET_BASE), lib_ver_date);
- exit(0);
+ if (ctx->inode_used_map) {
+ ext2fs_free_inode_bitmap(ctx->inode_used_map);
+ ctx->inode_used_map = 0;
}
-
- check_mount();
-
- if (!preen && !nflag && !yflag) {
- if (!isatty (0) || !isatty (1))
- die ("need terminal for interactive repairs");
+ if (ctx->inode_dir_map) {
+ ext2fs_free_inode_bitmap(ctx->inode_dir_map);
+ ctx->inode_dir_map = 0;
}
- superblock = use_superblock;
-restart:
-#if 1
- io_ptr = unix_io_manager;
-#else
- io_ptr = test_io_manager;
- test_io_backing_manager = unix_io_manager;
-#endif
- sync_disks();
- if (superblock && blocksize) {
- retval = ext2fs_open(filesystem_name,
- rwflag ? EXT2_FLAG_RW : 0,
- superblock, blocksize, io_ptr, &fs);
- } else if (superblock) {
- for (i=0; possible_block_sizes[i]; i++) {
- retval = ext2fs_open(filesystem_name,
- rwflag ? EXT2_FLAG_RW : 0,
- superblock,
- possible_block_sizes[i],
- io_ptr, &fs);
- if (!retval)
- break;
- }
- } else
- retval = ext2fs_open(filesystem_name,
- rwflag ? EXT2_FLAG_RW : 0,
- 0, 0, io_ptr, &fs);
- if (!superblock && !preen &&
- ((retval == EXT2_ET_BAD_MAGIC) ||
- ((retval == 0) && ext2fs_check_desc(fs)))) {
- if (!fs || (fs->group_desc_count > 1)) {
- printf("%s trying backup blocks...\n",
- retval ? "Couldn't find ext2 superblock," :
- "Group descriptors look bad...");
- superblock = get_backup_sb(fs);
- if (fs)
- ext2fs_close(fs);
- goto restart;
- }
+ if (ctx->block_found_map) {
+ ext2fs_free_block_bitmap(ctx->block_found_map);
+ ctx->block_found_map = 0;
}
- if (retval) {
- com_err(program_name, retval, "while trying to open %s",
- filesystem_name);
- if (retval == EXT2_ET_REV_TOO_HIGH)
- printf ("Get a newer version of e2fsck!\n");
- else if (retval == EXT2_ET_SHORT_READ)
- printf ("Could this be a zero-length partition?\n");
- else if ((retval == EPERM) || (retval == EACCES))
- printf("You must have %s access to the "
- "filesystem or be root\n",
- rwflag ? "r/w" : "r/o");
- else if (retval == ENXIO)
- printf("Possibly non-existent or swap device?\n");
- else
- printf(corrupt_msg, get_backup_sb(fs));
- fatal_error(0);
+ if (ctx->inode_link_info) {
+ ext2fs_free_icount(ctx->inode_link_info);
+ ctx->inode_link_info = 0;
}
-#ifdef EXT2_CURRENT_REV
- if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
- com_err(program_name, EXT2_ET_REV_TOO_HIGH,
- "while trying to open %s",
- filesystem_name);
- goto get_newer;
+ if (ctx->fs->dblist) {
+ ext2fs_free_dblist(ctx->fs->dblist);
+ ctx->fs->dblist = 0;
}
-#endif
- /*
- * Check for compatibility with the feature sets. We need to
- * be more stringent than ext2fs_open().
- */
- s = (struct ext2fs_sb *) fs->super;
- if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
- (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
- com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
- "(%s)", filesystem_name);
- get_newer:
- printf ("Get a newer version of e2fsck!\n");
- fatal_error(0);
+ free_dir_info(ctx->fs);
+ if (ctx->block_dup_map) {
+ ext2fs_free_block_bitmap(ctx->block_dup_map);
+ ctx->block_dup_map = 0;
}
- if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
- com_err(program_name, EXT2_ET_RO_UNSUPP_FEATURE,
- "(%s)", filesystem_name);
- goto get_newer;
+ if (ctx->inode_bb_map) {
+ ext2fs_free_inode_bitmap(ctx->inode_bb_map);
+ ctx->inode_bb_map = 0;
}
-
- /*
- * If the user specified a specific superblock, presumably the
- * master superblock has been trashed. So we mark the
- * superblock as dirty, so it can be written out.
- */
- if (superblock && rwflag)
- ext2fs_mark_super_dirty(fs);
-
- /*
- * Don't overwrite the backup superblock and block
- * descriptors, until we're sure the filesystem is OK....
- */
- fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
-
- ehandler_init(fs->io);
-
- invalid_inode_bitmap = allocate_memory(sizeof(int) *
- fs->group_desc_count,
- "invalid_inode_bitmap");
- invalid_block_bitmap = allocate_memory(sizeof(int) *
- fs->group_desc_count,
- "invalid_block_bitmap");
- invalid_inode_table = allocate_memory(sizeof(int) *
- fs->group_desc_count,
- "invalid_inode_table");
-
- check_super_block(fs);
- check_if_skip(fs);
- if (bad_blocks_file)
- read_bad_blocks_file(fs, bad_blocks_file, replace_bad_blocks);
- else if (cflag)
- test_disk(fs);
-
- if (normalize_swapfs) {
- if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ==
- ext2fs_native_flag()) {
- fprintf(stderr, "%s: Filesystem byte order "
- "already normalized.\n", device_name);
- fatal_error(0);
- }
+ if (ctx->inode_bad_map) {
+ ext2fs_free_inode_bitmap(ctx->inode_bad_map);
+ ctx->inode_bad_map = 0;
}
- if (swapfs)
- swap_filesys(fs);
/*
- * Mark the system as valid, 'til proven otherwise
+ * Clear the array of invalid meta-data flags
*/
- ext2fs_mark_valid(fs);
-
- retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
- if (retval) {
- com_err(program_name, retval,
- "while reading bad blocks inode");
- preenhalt(fs);
- printf("This doesn't bode well, but we'll try to go on...\n");
- }
+ if (ctx->invalid_inode_bitmap_flag) {
+ free(ctx->invalid_inode_bitmap_flag);
+ ctx->invalid_inode_bitmap_flag = 0;
+ }
+ if (ctx->invalid_block_bitmap_flag) {
+ free(ctx->invalid_block_bitmap_flag);
+ ctx->invalid_block_bitmap_flag = 0;
+ }
+ if (ctx->invalid_inode_table_flag) {
+ free(ctx->invalid_inode_table_flag);
+ ctx->invalid_inode_table_flag = 0;
+ }
+
+ /* Clear statistic counters */
+ ctx->fs_directory_count = 0;
+ ctx->fs_regular_count = 0;
+ ctx->fs_blockdev_count = 0;
+ ctx->fs_chardev_count = 0;
+ ctx->fs_links_count = 0;
+ ctx->fs_symlinks_count = 0;
+ ctx->fs_fast_symlinks_count = 0;
+ ctx->fs_fifo_count = 0;
+ ctx->fs_total_count = 0;
+ ctx->fs_badblocks_count = 0;
+ ctx->fs_sockets_count = 0;
+ ctx->fs_ind_count = 0;
+ ctx->fs_dind_count = 0;
+ ctx->fs_tind_count = 0;
+ ctx->fs_fragmented = 0;
+
+ /* Reset the superblock to the user's requested value */
+ ctx->superblock = ctx->use_superblock;
- pass1(fs);
- free(invalid_inode_bitmap);
- free(invalid_block_bitmap);
- free(invalid_inode_table);
- if (restart_e2fsck) {
- ext2fs_close(fs);
- printf("Restarting e2fsck from the beginning...\n");
- restart_e2fsck = 0;
- superblock = use_superblock;
- goto restart;
- }
- pass2(fs);
- pass3(fs);
- pass4(fs);
- pass5(fs);
-
-#ifdef MTRACE
- mtrace_print("Cleanup");
-#endif
- if (ext2fs_test_changed(fs)) {
- exit_value = FSCK_NONDESTRUCT;
- if (!preen)
- printf("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n",
- device_name);
- if (root_filesystem && !read_only_root) {
- printf("%s: ***** REBOOT LINUX *****\n", device_name);
- exit_value = FSCK_REBOOT;
- }
- }
- if (ext2fs_test_valid(fs))
- fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
- else
- exit_value = FSCK_UNCORRECTED;
- if (rwflag) {
- if (ext2fs_test_valid(fs)) {
- if (!(fs->super->s_state & EXT2_VALID_FS))
- exit_value = FSCK_NONDESTRUCT;
- fs->super->s_state = EXT2_VALID_FS;
- } else
- fs->super->s_state &= ~EXT2_VALID_FS;
- fs->super->s_mnt_count = 0;
- fs->super->s_lastcheck = time(NULL);
- ext2fs_mark_super_dirty(fs);
- }
- show_stats(fs);
+ return 0;
+}
- write_bitmaps(fs);
- ext2fs_close(fs);
- sync_disks();
+void e2fsck_free_context(e2fsck_t ctx)
+{
+ if (!ctx)
+ return;
- if (tflag)
- print_resource_track(&global_rtrack);
+ e2fsck_reset_context(ctx);
- return exit_value;
+ free(ctx);
}
*/
#define E2FSCK_CURRENT_REV 1
-/*
- * Inode count arrays
- */
-extern ext2_icount_t inode_count;
-extern ext2_icount_t inode_link_info;
-
/*
* The directory information structure; stores directory information
* collected in earlier passes, to avoid disk i/o in fetching the
};
/*
- * Variables
+ * E2fsck options
*/
-extern const char * program_name;
-extern const char * device_name;
+#define E2F_OPT_READONLY 0x0001
+#define E2F_OPT_PREEN 0x0002
+#define E2F_OPT_YES 0x0004
+#define E2F_OPT_NO 0x0008
+#define E2F_OPT_TIME 0x0010
+#define E2F_OPT_TIME2 0x0020
+#define E2F_OPT_CHECKBLOCKS 0x0040
+#define E2F_OPT_DEBUG 0x0080
-extern ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
-extern ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
-extern ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
-extern ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
-
-extern ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
-extern ext2fs_block_bitmap block_dup_map; /* Blocks which are used by more than once */
-extern ext2fs_block_bitmap block_illegal_map; /* Meta-data blocks */
-
-extern const char *fix_msg[2]; /* Fixed or ignored! */
-extern const char *clear_msg[2]; /* Cleared or ignored! */
-
-extern int *invalid_inode_bitmap;
-extern int *invalid_block_bitmap;
-extern int *invalid_inode_table;
-extern int restart_e2fsck;
+/*
+ * This is the global e2fsck structure.
+ */
+struct e2fsck_struct {
+ ext2_filsys fs;
+ const char *program_name;
+ const char *filesystem_name;
+ const char *device_name;
+ int options;
+ blk_t use_superblock; /* sb requested by user */
+ blk_t superblock; /* sb used to open fs */
+
+ ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
+ ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
+ ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
+ ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
+
+ ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
+ ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
+ ext2fs_block_bitmap block_illegal_map; /* Meta-data blocks */
+
+ /*
+ * Inode count arrays
+ */
+ ext2_icount_t inode_count;
+ ext2_icount_t inode_link_info;
+
+ /*
+ * Array of flags indicating whether an inode bitmap, block
+ * bitmap, or inode table is invalid
+ */
+ int *invalid_inode_bitmap_flag;
+ int *invalid_block_bitmap_flag;
+ int *invalid_inode_table_flag;
+ int invalid_bitmaps; /* There are invalid bitmaps/itable */
+
+ /*
+ * For pass1_check_directory and pass1_get_blocks
+ */
+ ino_t stashed_ino;
+ struct ext2_inode *stashed_inode;
+
+ /*
+ * Tuning parameters
+ */
+ int process_inode_size;
+ int inode_buffer_blocks;
+
+ /*
+ * For timing purposes
+ */
+ struct resource_track global_rtrack;
+
+ /* File counts */
+ int fs_directory_count;
+ int fs_regular_count;
+ int fs_blockdev_count;
+ int fs_chardev_count;
+ int fs_links_count;
+ int fs_symlinks_count;
+ int fs_fast_symlinks_count;
+ int fs_fifo_count;
+ int fs_total_count;
+ int fs_badblocks_count;
+ int fs_sockets_count;
+ int fs_ind_count;
+ int fs_dind_count;
+ int fs_tind_count;
+ int fs_fragmented;
+};
-/* Command line options */
-extern int nflag;
-extern int yflag;
-extern int tflag;
-extern int preen;
-extern int verbose;
-extern int list;
-extern int debug;
-extern int force;
-
-extern int rwflag;
-
-extern int inode_buffer_blocks;
-extern int process_inode_size;
-extern int directory_blocks;
-
-extern int no_bad_inode;
-extern int no_lpf;
-extern int lpf_corrupted;
-
-/* Files counts */
-extern int fs_directory_count;
-extern int fs_regular_count;
-extern int fs_blockdev_count;
-extern int fs_chardev_count;
-extern int fs_links_count;
-extern int fs_symlinks_count;
-extern int fs_fast_symlinks_count;
-extern int fs_fifo_count;
-extern int fs_total_count;
-extern int fs_badblocks_count;
-extern int fs_sockets_count;
-extern int fs_ind_count;
-extern int fs_dind_count;
-extern int fs_tind_count;
-extern int fs_fragmented;
-
-extern struct resource_track global_rtrack;
-
-extern int invalid_bitmaps;
+typedef struct e2fsck_struct *e2fsck_t;
/*
- * For pass1_check_directory and pass1_get_blocks
+ * Variables
*/
-extern ino_t stashed_ino;
-extern struct ext2_inode *stashed_inode;
+extern int restart_e2fsck;
/*
* Procedure declarations
*/
-extern void pass1(ext2_filsys fs);
-extern void pass1_dupblocks(ext2_filsys fs, char *block_buf);
-extern void pass2(ext2_filsys fs);
-extern void pass3(ext2_filsys fs);
-extern void pass4(ext2_filsys fs);
-extern void pass5(ext2_filsys fs);
+extern void pass1(e2fsck_t ctx);
+extern void pass1_dupblocks(e2fsck_t ctx, char *block_buf);
+extern void pass2(e2fsck_t ctx);
+extern void pass3(e2fsck_t ctx);
+extern void pass4(e2fsck_t ctx);
+extern void pass5(e2fsck_t ctx);
+
+/* e2fsck.c */
+errcode_t e2fsck_allocate_context(e2fsck_t *ret);
+errcode_t e2fsck_reset_context(e2fsck_t ctx);
+void e2fsck_free_context(e2fsck_t ctx);
/* pass1.c */
extern errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino);
extern int e2fsck_pass1_check_device_inode(struct ext2_inode *inode);
/* badblock.c */
-extern void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
+extern void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
int replace_bad_blocks);
-extern void test_disk(ext2_filsys fs);
+extern void test_disk(e2fsck_t ctx);
/* dirinfo.c */
extern void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent);
extern const char *ehandler_operation(const char *op);
extern void ehandler_init(io_channel channel);
+/* super.c */
+void check_super_block(e2fsck_t ctx);
+
/* swapfs.c */
-void swap_filesys(ext2_filsys fs);
+void swap_filesys(e2fsck_t ctx);
/* util.c */
extern void *allocate_memory(int size, const char *description);
-extern int ask(const char * string, int def);
+extern int ask(e2fsck_t ctx, const char * string, int def);
extern int ask_yn(const char * string, int def);
extern void fatal_error (const char * fmt_string);
-extern void read_bitmaps(ext2_filsys fs);
-extern void write_bitmaps(ext2_filsys fs);
-extern void preenhalt(ext2_filsys fs);
-extern void print_resource_track(struct resource_track *track);
+extern void read_bitmaps(e2fsck_t ctx);
+extern void write_bitmaps(e2fsck_t ctx);
+extern void preenhalt(e2fsck_t ctx);
+extern void print_resource_track(const char *desc,
+ struct resource_track *track);
extern void init_resource_track(struct resource_track *track);
extern int inode_has_valid_blocks(struct ext2_inode *inode);
extern void e2fsck_read_inode(ext2_filsys fs, unsigned long ino,
#ifdef MTRACE
extern void mtrace_print(char *mesg);
#endif
+extern blk_t get_backup_sb(ext2_filsys fs);
#define die(str) fatal_error(str)
/*
* pass3.c
*/
-extern int reconnect_file(ext2_filsys fs, ino_t inode);
+extern int reconnect_file(e2fsck_t ctx, ino_t inode);
{
int i;
char *p;
+ ext2_filsys fs = channel->app_data;
+ e2fsck_t ctx;
+
+ ctx = fs->private;
/*
* If more than one block was read, try reading each block
else
printf("Error reading block %lu (%s). ", block,
error_message(error));
- preenhalt(NULL);
- if (ask("Ignore error", 1))
+ preenhalt(ctx);
+ if (ask(ctx, "Ignore error", 1))
return 0;
return error;
{
int i;
const char *p;
+ ext2_filsys fs = channel->app_data;
+ e2fsck_t ctx;
+ ctx = fs->private;
+
/*
* If more than one block was written, try writing each block
* separately. We could use the actual bytes read to figure
else
printf("Error writing block %lu (%s). ", block,
error_message(error));
- preenhalt(NULL);
- if (ask("Ignore error", 1))
+ preenhalt(ctx);
+ if (ask(ctx, "Ignore error", 1))
return 0;
return error;
num_inodes++;
}
- print_resource_track(&global_rtrack);
+ print_resource_track(NULL, &global_rtrack);
printf("%d inodes scanned.\n", num_inodes);
exit(0);
*
* %b <blk> block number
* %B <blkcount> integer
+ * %c <blk2> block number
* %di <dirent>->ino inode number
* %dn <dirent>->name string
+ * %dr <dirent>->rec_len
+ * %dl <dirent>->name_len
* %D <dir> inode number
* %g <group> integer
* %i <ino> inode number
* %If <inode> -> i_file_acl
* %Id <inode> -> i_dir_acl
* %j <ino2> inode number
+ * %m <com_err error message>
* %N <num>
* %p ext2fs_get_pathname of directory <ino>
* %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
* %q ext2fs_get_pathname of directory <dir>
* %Q ext2fs_get_pathname of directory <ino> with <dir> as
* the containing directory.
+ * %s <str> miscellaneous string
+ * %S backup superblock
*
* The following '@' expansions are supported:
*
* @d directory
* @e entry
* @E Entry '%Dn' in %p (%i)
+ * @f filesystem
* @F for @i %i (%Q) is
* @g group
* @l lost+found
* @L is a link
* @u unattached
* @r root inode
+ * @s should be
+ * @S superblock
* @z zero-length
*/
"ddirectory",
"eentry",
"E@e '%Dn' in %p (%i)",
+ "ffilesystem",
"Ffor @i %i (%Q) is",
"ggroup",
"llost+found",
"uunattached",
"rroot @i",
"sshould be",
+ "Ssuper@b",
"zzero-length",
"@@",
0
* expansion; an @ expression can contain further '@' and '%'
* expressions.
*/
-static _INLINE_ void expand_at_expression(ext2_filsys fs, char ch,
- struct problem_context *ctx,
+static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch,
+ struct problem_context *pctx,
int *first)
{
const char **cpp, *str;
*first = 0;
fputc(toupper(*str++), stdout);
}
- print_e2fsck_message(fs, str, ctx, *first);
+ print_e2fsck_message(ctx, str, pctx, *first);
} else
printf("@%c", ch);
}
len = dirent->rec_len;
printf("%.*s", dirent->name_len, dirent->name);
break;
+ case 'r':
+ printf("%u", dirent->rec_len);
+ break;
+ case 'l':
+ printf("%u", dirent->name_len);
+ break;
default:
no_dirent:
printf("%%D%c", ch);
case 'B':
printf("%d", ctx->blkcount);
break;
+ case 'c':
+ printf("%u", ctx->blk2);
+ break;
case 'd':
printf("%lu", ctx->dir);
break;
case 'j':
printf("%lu", ctx->ino2);
break;
+ case 'm':
+ printf("%s", error_message(ctx->errcode));
+ break;
case 'N':
printf("%u", ctx->num);
break;
case 'Q':
print_pathname(fs, ctx->dir, ctx->ino);
break;
+ case 'S':
+ printf("%d", get_backup_sb(fs));
+ break;
+ case 's':
+ printf("%s", ctx->str);
+ break;
default:
no_context:
printf("%%%c", ch);
}
}
-void print_e2fsck_message(ext2_filsys fs, const char *msg,
- struct problem_context *ctx, int first)
+void print_e2fsck_message(e2fsck_t ctx, const char *msg,
+ struct problem_context *pctx, int first)
{
+ ext2_filsys fs = ctx->fs;
const char * cp;
int i;
for (cp = msg; *cp; cp++) {
if (cp[0] == '@') {
cp++;
- expand_at_expression(fs, *cp, ctx, &first);
+ expand_at_expression(ctx, *cp, pctx, &first);
} else if (cp[0] == '%' && cp[1] == 'I') {
cp += 2;
- expand_inode_expression(*cp, ctx);
+ expand_inode_expression(*cp, pctx);
} else if (cp[0] == '%' && cp[1] == 'D') {
cp += 2;
- expand_dirent_expression(*cp, ctx);
+ expand_dirent_expression(*cp, pctx);
} else if ((cp[0] == '%')) {
cp++;
- expand_percent_expression(fs, *cp, ctx);
+ expand_percent_expression(fs, *cp, pctx);
} else {
for (i=0; cp[i]; i++)
if ((cp[i] == '@') || cp[i] == '%')
#include <errno.h>
#endif
-#include <et/com_err.h>
#include "e2fsck.h"
#include "problem.h"
#define _INLINE_ inline
#endif
-/* Files counts */
-int fs_directory_count = 0;
-int fs_regular_count = 0;
-int fs_blockdev_count = 0;
-int fs_chardev_count = 0;
-int fs_links_count = 0;
-int fs_symlinks_count = 0;
-int fs_fast_symlinks_count = 0;
-int fs_fifo_count = 0;
-int fs_total_count = 0;
-int fs_badblocks_count = 0;
-int fs_sockets_count = 0;
-int fs_ind_count = 0;
-int fs_dind_count = 0;
-int fs_tind_count = 0;
-int fs_fragmented = 0;
-
-ext2fs_inode_bitmap inode_used_map = 0; /* Inodes which are in use */
-ext2fs_inode_bitmap inode_bad_map = 0; /* Inodes which are bad in some way */
-ext2fs_inode_bitmap inode_dir_map = 0; /* Inodes which are directories */
-ext2fs_inode_bitmap inode_bb_map = 0; /* Inodes which are in bad blocks */
-
-ext2fs_block_bitmap block_found_map = 0;
-ext2fs_block_bitmap block_dup_map = 0;
-ext2fs_block_bitmap block_illegal_map = 0;
-
-ext2_icount_t inode_link_info = 0;
-
static int process_block(ext2_filsys fs, blk_t *blocknr,
int blockcnt, blk_t ref_blk,
int ref_offset, void *private);
static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
int blockcnt, blk_t ref_blk,
int ref_offset, void *private);
-static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
+static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
char *block_buf);
-static void mark_table_blocks(ext2_filsys fs);
-static void alloc_bad_map(ext2_filsys fs);
-static void alloc_bb_map(ext2_filsys fs);
-static void handle_fs_bad_blocks(ext2_filsys fs);
-static void process_inodes(ext2_filsys fs, char *block_buf);
+static void mark_table_blocks(e2fsck_t ctx);
+static void alloc_bad_map(e2fsck_t ctx);
+static void alloc_bb_map(e2fsck_t ctx);
+static void handle_fs_bad_blocks(e2fsck_t ctx);
+static void process_inodes(e2fsck_t ctx, char *block_buf);
static int process_inode_cmp(const void *a, const void *b);
static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
dgrp_t group, void * private);
blk_t previous_block;
struct ext2_inode *inode;
struct problem_context *pctx;
+ e2fsck_t ctx;
};
struct process_inode_block {
struct ext2_inode inode;
};
-/*
- * For pass1_check_directory and pass1_get_blocks
- */
-ino_t stashed_ino;
-struct ext2_inode *stashed_inode;
-
/*
* For the inodes to process list.
*/
static struct process_inode_block *inodes_to_process;
static int process_inode_count;
-int process_inode_size = 256;
/*
* Free all memory allocated by pass1 in preparation for restarting
*/
static void unwind_pass1(ext2_filsys fs)
{
- ext2fs_free_inode_bitmap(inode_used_map); inode_used_map = 0;
- ext2fs_free_inode_bitmap(inode_dir_map); inode_dir_map = 0;
- ext2fs_free_block_bitmap(block_found_map); block_found_map = 0;
- ext2fs_free_icount(inode_link_info); inode_link_info = 0;
free(inodes_to_process);inodes_to_process = 0;
- ext2fs_free_dblist(fs->dblist); fs->dblist = 0;
- free_dir_info(fs);
- if (block_dup_map) {
- ext2fs_free_block_bitmap(block_dup_map); block_dup_map = 0;
- }
- if (inode_bb_map) {
- ext2fs_free_inode_bitmap(inode_bb_map); inode_bb_map = 0;
- }
- if (inode_bad_map) {
- ext2fs_free_inode_bitmap(inode_bad_map); inode_bad_map = 0;
- }
-
- /* Clear statistic counters */
- fs_directory_count = 0;
- fs_regular_count = 0;
- fs_blockdev_count = 0;
- fs_chardev_count = 0;
- fs_links_count = 0;
- fs_symlinks_count = 0;
- fs_fast_symlinks_count = 0;
- fs_fifo_count = 0;
- fs_total_count = 0;
- fs_badblocks_count = 0;
- fs_sockets_count = 0;
- fs_ind_count = 0;
- fs_dind_count = 0;
- fs_tind_count = 0;
- fs_fragmented = 0;
}
/*
return 1;
}
-void pass1(ext2_filsys fs)
+void pass1(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
ino_t ino;
struct ext2_inode inode;
ext2_inode_scan scan;
char *block_buf;
- errcode_t retval;
struct resource_track rtrack;
unsigned char frag, fsize;
struct problem_context pctx;
init_resource_track(&rtrack);
-
- if (!preen)
- printf("Pass 1: Checking inodes, blocks, and sizes\n");
+ clear_problem_context(&pctx);
+
+ if (!(ctx->options & E2F_OPT_PREEN))
+ fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
#ifdef MTRACE
mtrace_print("Pass 1");
/*
* Allocate bitmaps structures
*/
- retval = ext2fs_allocate_inode_bitmap(fs, "in-use inode map",
- &inode_used_map);
- if (retval) {
- com_err("ext2fs_allocate_inode_bitmap", retval,
- "while allocating inode_used_map");
+ pctx.errcode = ext2fs_allocate_inode_bitmap(fs, "in-use inode map",
+ &ctx->inode_used_map);
+ if (pctx.errcode) {
+ pctx.num = 1;
+ fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
- retval = ext2fs_allocate_inode_bitmap(fs, "directory inode map",
- &inode_dir_map);
- if (retval) {
- com_err("ext2fs_allocate_inode_bitmap", retval,
- "while allocating inode_dir_map");
+ pctx.errcode = ext2fs_allocate_inode_bitmap(fs, "directory inode map",
+ &ctx->inode_dir_map);
+ if (pctx.errcode) {
+ pctx.num = 2;
+ fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
- retval = ext2fs_allocate_block_bitmap(fs, "in-use block map",
- &block_found_map);
- if (retval) {
- com_err("ext2fs_allocate_block_bitmap", retval,
- "while allocating block_found_map");
+ pctx.errcode = ext2fs_allocate_block_bitmap(fs, "in-use block map",
+ &ctx->block_found_map);
+ if (pctx.errcode) {
+ pctx.num = 1;
+ fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
fatal_error(0);
}
- retval = ext2fs_allocate_block_bitmap(fs, "illegal block map",
- &block_illegal_map);
- if (retval) {
- com_err("ext2fs_allocate_block_bitmap", retval,
- "while allocating block_illegal_map");
+ pctx.errcode = ext2fs_allocate_block_bitmap(fs, "illegal block map",
+ &ctx->block_illegal_map);
+ if (pctx.errcode) {
+ pctx.num = 2;
+ fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
fatal_error(0);
}
- retval = ext2fs_create_icount2(fs, 0, 0, 0, &inode_link_info);
- if (retval) {
- com_err("ext2fs_create_icount", retval,
- "while creating inode_link_info");
+ pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
+ &ctx->inode_link_info);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
fatal_error(0);
}
- inodes_to_process = allocate_memory(process_inode_size *
+ inodes_to_process = allocate_memory(ctx->process_inode_size *
sizeof(struct process_inode_block),
"array of inodes to process");
process_inode_count = 0;
- retval = ext2fs_init_dblist(fs, 0);
- if (retval) {
- com_err(program_name, retval,
- "while allocating directory block information");
+ pctx.errcode = ext2fs_init_dblist(fs, 0);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
fatal_error(0);
}
- mark_table_blocks(fs);
+ mark_table_blocks(ctx);
block_buf = allocate_memory(fs->blocksize * 3, "block interate buffer");
fs->get_blocks = pass1_get_blocks;
fs->check_directory = pass1_check_directory;
fs->read_inode = pass1_read_inode;
fs->write_inode = pass1_write_inode;
ehandler_operation("doing inode scan");
- retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan);
- if (retval) {
- com_err(program_name, retval, "while opening inode scan");
+ pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
+ &scan);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
fatal_error(0);
}
ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
- retval = ext2fs_get_next_inode(scan, &ino, &inode);
- if (retval) {
- com_err(program_name, retval, "while starting inode scan");
+ pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
fatal_error(0);
}
- stashed_inode = &inode;
+ ctx->stashed_inode = &inode;
ext2fs_set_inode_callback(scan, scan_callback, block_buf);
- clear_problem_context(&pctx);
while (ino) {
- stashed_ino = ino;
- if (inode.i_links_count)
- retval = ext2fs_icount_store(inode_link_info, ino,
- inode.i_links_count);
- if (retval) {
- com_err("ext2fs_icount_fetch", retval,
- "while adding inode %u", ino);
- fatal_error(0);
- }
pctx.ino = ino;
pctx.inode = &inode;
+ ctx->stashed_ino = ino;
+ if (inode.i_links_count) {
+ pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
+ ino, inode.i_links_count);
+ if (pctx.errcode) {
+ pctx.num = inode.i_links_count;
+ fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
+ fatal_error(0);
+ }
+ }
if (ino == EXT2_BAD_INO) {
struct process_block_struct pb;
pb.fragmented = 0;
pb.inode = &inode;
pb.pctx = &pctx;
- retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
- process_bad_block, &pb);
- if (retval)
- com_err(program_name, retval, "while calling e2fsc_block_interate in pass 1");
-
- ext2fs_mark_inode_bitmap(inode_used_map, ino);
+ pb.ctx = ctx;
+ pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
+ block_buf, process_bad_block, &pb);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
+ fatal_error(0);
+ }
+ ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
clear_problem_context(&pctx);
goto next;
}
* regnerated in pass #3.
*/
if (!LINUX_S_ISDIR(inode.i_mode)) {
- if (fix_problem(fs, PR_1_ROOT_NO_DIR, &pctx)) {
+ if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
inode.i_dtime = time(0);
inode.i_links_count = 0;
- ext2fs_icount_store(inode_link_info,
+ ext2fs_icount_store(ctx->inode_link_info,
ino, 0);
e2fsck_write_inode(fs, ino, &inode,
"pass1");
* as a special case.
*/
if (inode.i_dtime && inode.i_links_count) {
- if (fix_problem(fs, PR_1_ROOT_DTIME, &pctx)) {
+ if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
inode.i_dtime = 0;
e2fsck_write_inode(fs, ino, &inode,
"pass1");
}
}
if (ino == EXT2_BOOT_LOADER_INO) {
- ext2fs_mark_inode_bitmap(inode_used_map, ino);
- check_blocks(fs, &pctx, block_buf);
+ ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
+ check_blocks(ctx, &pctx, block_buf);
goto next;
}
if ((ino != EXT2_ROOT_INO) &&
(ino < EXT2_FIRST_INODE(fs->super))) {
- ext2fs_mark_inode_bitmap(inode_used_map, ino);
+ ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
if (inode.i_mode != 0) {
- if (fix_problem(fs,
+ if (fix_problem(ctx,
PR_1_RESERVED_BAD_MODE, &pctx)) {
inode.i_mode = 0;
e2fsck_write_inode(fs, ino, &inode,
"pass1");
}
}
- check_blocks(fs, &pctx, block_buf);
+ check_blocks(ctx, &pctx, block_buf);
goto next;
}
/*
*/
if (!inode.i_links_count) {
if (!inode.i_dtime && inode.i_mode) {
- if (fix_problem(fs,
+ if (fix_problem(ctx,
PR_1_ZERO_DTIME, &pctx)) {
inode.i_dtime = time(0);
e2fsck_write_inode(fs, ino, &inode,
*
*/
if (inode.i_dtime) {
- if (fix_problem(fs, PR_1_SET_DTIME, &pctx)) {
+ if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
inode.i_dtime = 0;
e2fsck_write_inode(fs, ino, &inode, "pass1");
}
}
- ext2fs_mark_inode_bitmap(inode_used_map, ino);
+ ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
switch (fs->super->s_creator_os) {
case EXT2_OS_LINUX:
frag = inode.osd2.linux2.l_i_frag;
if (inode.i_faddr || frag || fsize
|| inode.i_file_acl || inode.i_dir_acl) {
- if (!inode_bad_map)
- alloc_bad_map(fs);
- ext2fs_mark_inode_bitmap(inode_bad_map, ino);
+ if (!ctx->inode_bad_map)
+ alloc_bad_map(ctx);
+ ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
}
if (LINUX_S_ISDIR(inode.i_mode)) {
- ext2fs_mark_inode_bitmap(inode_dir_map, ino);
+ ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
add_dir_info(fs, ino, 0);
- fs_directory_count++;
+ ctx->fs_directory_count++;
} else if (LINUX_S_ISREG (inode.i_mode))
- fs_regular_count++;
+ ctx->fs_regular_count++;
else if (LINUX_S_ISCHR (inode.i_mode) &&
e2fsck_pass1_check_device_inode(&inode))
- fs_chardev_count++;
+ ctx->fs_chardev_count++;
else if (LINUX_S_ISBLK (inode.i_mode) &&
e2fsck_pass1_check_device_inode(&inode))
- fs_blockdev_count++;
+ ctx->fs_blockdev_count++;
else if (LINUX_S_ISLNK (inode.i_mode)) {
- fs_symlinks_count++;
+ ctx->fs_symlinks_count++;
if (!inode.i_blocks) {
- fs_fast_symlinks_count++;
+ ctx->fs_fast_symlinks_count++;
goto next;
}
}
else if (LINUX_S_ISFIFO (inode.i_mode))
- fs_fifo_count++;
+ ctx->fs_fifo_count++;
else if (LINUX_S_ISSOCK (inode.i_mode))
- fs_sockets_count++;
+ ctx->fs_sockets_count++;
else {
- if (!inode_bad_map)
- alloc_bad_map(fs);
- ext2fs_mark_inode_bitmap(inode_bad_map, ino);
+ if (!ctx->inode_bad_map)
+ alloc_bad_map(ctx);
+ ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
}
if (inode.i_block[EXT2_IND_BLOCK])
- fs_ind_count++;
+ ctx->fs_ind_count++;
if (inode.i_block[EXT2_DIND_BLOCK])
- fs_dind_count++;
+ ctx->fs_dind_count++;
if (inode.i_block[EXT2_TIND_BLOCK])
- fs_tind_count++;
+ ctx->fs_tind_count++;
if (inode.i_block[EXT2_IND_BLOCK] ||
inode.i_block[EXT2_DIND_BLOCK] ||
inode.i_block[EXT2_TIND_BLOCK]) {
inodes_to_process[process_inode_count].inode = inode;
process_inode_count++;
} else
- check_blocks(fs, &pctx, block_buf);
+ check_blocks(ctx, &pctx, block_buf);
- if (process_inode_count >= process_inode_size)
- process_inodes(fs, block_buf);
+ if (process_inode_count >= ctx->process_inode_size)
+ process_inodes(ctx, block_buf);
next:
- retval = ext2fs_get_next_inode(scan, &ino, &inode);
- if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
- if (!inode_bb_map)
- alloc_bb_map(fs);
- ext2fs_mark_inode_bitmap(inode_bb_map, ino);
- ext2fs_mark_inode_bitmap(inode_used_map, ino);
+ pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
+ if (!ctx->inode_bb_map)
+ alloc_bb_map(ctx);
+ ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
+ ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
goto next;
}
- if (retval) {
- com_err(program_name, retval,
- "while doing inode scan");
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
fatal_error(0);
}
}
- process_inodes(fs, block_buf);
+ process_inodes(ctx, block_buf);
ext2fs_close_inode_scan(scan);
ehandler_operation(0);
- if (invalid_bitmaps)
- handle_fs_bad_blocks(fs);
+ if (ctx->invalid_bitmaps)
+ handle_fs_bad_blocks(ctx);
if (restart_e2fsck) {
unwind_pass1(fs);
goto endit;
}
- if (block_dup_map) {
- if (preen) {
- printf("Duplicate or bad blocks in use!\n");
- preenhalt(fs);
+ if (ctx->block_dup_map) {
+ if (ctx->options & E2F_OPT_PREEN) {
+ clear_problem_context(&pctx);
+ fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
}
- pass1_dupblocks(fs, block_buf);
+ pass1_dupblocks(ctx, block_buf);
}
free(inodes_to_process);
endit:
fs->write_inode = 0;
free(block_buf);
- ext2fs_free_block_bitmap(block_illegal_map);
- block_illegal_map = 0;
+ ext2fs_free_block_bitmap(ctx->block_illegal_map);
+ ctx->block_illegal_map = 0;
- if (tflag > 1) {
- printf("Pass 1: ");
- print_resource_track(&rtrack);
- }
+ if (ctx->options & E2F_OPT_TIME2)
+ print_resource_track("Pass 1", &rtrack);
}
/*
static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
dgrp_t group, void * private)
{
- process_inodes(fs, (char *) private);
+ process_inodes((e2fsck_t) fs->private, (char *) private);
return 0;
}
/*
* Process the inodes in the "inodes to process" list.
*/
-static void process_inodes(ext2_filsys fs, char *block_buf)
+static void process_inodes(e2fsck_t ctx, char *block_buf)
{
int i;
struct ext2_inode *old_stashed_inode;
printf("begin process_inodes: ");
#endif
old_operation = ehandler_operation(0);
- old_stashed_inode = stashed_inode;
- old_stashed_ino = stashed_ino;
+ old_stashed_inode = ctx->stashed_inode;
+ old_stashed_ino = ctx->stashed_ino;
qsort(inodes_to_process, process_inode_count,
sizeof(struct process_inode_block), process_inode_cmp);
clear_problem_context(&pctx);
for (i=0; i < process_inode_count; i++) {
- pctx.inode = stashed_inode = &inodes_to_process[i].inode;
- pctx.ino = stashed_ino = inodes_to_process[i].ino;
+ pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
+ pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
#if 0
printf("%u ", pctx.ino);
#endif
sprintf(buf, "reading indirect blocks of inode %lu", pctx.ino);
ehandler_operation(buf);
- check_blocks(fs, &pctx, block_buf);
+ check_blocks(ctx, &pctx, block_buf);
}
- stashed_inode = old_stashed_inode;
- stashed_ino = old_stashed_ino;
+ ctx->stashed_inode = old_stashed_inode;
+ ctx->stashed_ino = old_stashed_ino;
process_inode_count = 0;
#if 0
printf("end process inodes\n");
/*
* This procedure will allocate the inode bad map table
*/
-static void alloc_bad_map(ext2_filsys fs)
+static void alloc_bad_map(e2fsck_t ctx)
{
- errcode_t retval;
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
- retval = ext2fs_allocate_inode_bitmap(fs, "bad inode map",
- &inode_bad_map);
- if (retval) {
- com_err("ext2fs_allocate_inode_bitmap", retval,
- "while allocating inode_bad_map");
+ pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, "bad inode map",
+ &ctx->inode_bad_map);
+ if (pctx.errcode) {
+ pctx.num = 3;
+ fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
}
/*
* This procedure will allocate the inode "bb" (badblock) map table
*/
-static void alloc_bb_map(ext2_filsys fs)
+static void alloc_bb_map(e2fsck_t ctx)
{
- errcode_t retval;
+ struct problem_context pctx;
- retval = ext2fs_allocate_inode_bitmap(fs, "inode in bad block map",
- &inode_bb_map);
- if (retval) {
- com_err("ext2fs_allocate_inode_bitmap", retval,
- "while allocating inode in bad block map");
+ clear_problem_context(&pctx);
+ pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
+ "inode in bad block map",
+ &ctx->inode_bb_map);
+ if (pctx.errcode) {
+ pctx.num = 4;
+ fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
}
* WARNING: Assumes checks have already been done to make sure block
* is valid. This is true in both process_block and process_bad_block.
*/
-static _INLINE_ void mark_block_used(ext2_filsys fs, blk_t block)
+static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
{
- errcode_t retval;
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
- if (ext2fs_fast_test_block_bitmap(block_found_map, block)) {
- if (!block_dup_map) {
- retval = ext2fs_allocate_block_bitmap(fs,
- "multiply claimed block map", &block_dup_map);
- if (retval) {
- com_err("ext2fs_allocate_block_bitmap", retval,
- "while allocating block_dup_map");
+ if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
+ if (!ctx->block_dup_map) {
+ pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
+ "multiply claimed block map",
+ &ctx->block_dup_map);
+ if (pctx.errcode) {
+ pctx.num = 3;
+ fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
+ &pctx);
fatal_error(0);
}
}
- ext2fs_fast_mark_block_bitmap(block_dup_map, block);
+ ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
} else {
- ext2fs_fast_mark_block_bitmap(block_found_map, block);
+ ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
}
}
* This subroutine is called on each inode to account for all of the
* blocks used by that inode.
*/
-static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
+static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
char *block_buf)
{
+ ext2_filsys fs = ctx->fs;
struct process_block_struct pb;
- errcode_t retval;
ino_t ino = pctx->ino;
struct ext2_inode *inode = pctx->inode;
pb.is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
pb.inode = inode;
pb.pctx = pctx;
- retval = ext2fs_block_iterate2(fs, ino,
+ pb.ctx = ctx;
+ pctx->ino = ino;
+ pctx->errcode = ext2fs_block_iterate2(fs, ino,
pb.is_dir ? BLOCK_FLAG_HOLE : 0,
block_buf, process_block, &pb);
- reset_problem_latch(PR_LATCH_BLOCK);
- if (retval)
- com_err(program_name, retval,
- "while calling ext2fs_block_iterate in check_blocks");
+ end_problem_latch(ctx, PR_LATCH_BLOCK);
+ if (pctx->errcode)
+ fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
- fs_fragmented++;
+ ctx->fs_fragmented++;
if (pb.clear) {
e2fsck_read_inode(fs, ino, inode, "check_blocks");
- if (retval) {
- com_err("check_blocks", retval,
- "while reading to be cleared inode %d", ino);
- fatal_error(0);
- }
inode->i_links_count = 0;
- ext2fs_icount_store(inode_link_info, ino, 0);
+ ext2fs_icount_store(ctx->inode_link_info, ino, 0);
inode->i_dtime = time(0);
e2fsck_write_inode(fs, ino, inode, "check_blocks");
- ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
- ext2fs_unmark_inode_bitmap(inode_used_map, ino);
+ ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+ ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
/*
* The inode was probably partially accounted for
* before processing was aborted, so we need to
pb.num_blocks);
#endif
if (!pb.num_blocks && pb.is_dir) {
- if (fix_problem(fs, PR_1_ZERO_LENGTH_DIR, pctx)) {
+ if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
inode->i_links_count = 0;
- ext2fs_icount_store(inode_link_info, ino, 0);
+ ext2fs_icount_store(ctx->inode_link_info, ino, 0);
inode->i_dtime = time(0);
e2fsck_write_inode(fs, ino, inode, "check_blocks");
- ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
- ext2fs_unmark_inode_bitmap(inode_used_map, ino);
- fs_directory_count--;
+ ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+ ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
+ ctx->fs_directory_count--;
pb.is_dir = 0;
}
}
(pb.last_block + 1) * fs->blocksize)) ||
(inode->i_size < pb.last_block * fs->blocksize)) {
pctx->num = (pb.last_block+1) * fs->blocksize;
- if (fix_problem(fs, PR_1_BAD_I_SIZE, pctx)) {
+ if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
inode->i_size = pctx->num;
e2fsck_write_inode(fs, ino, inode, "check_blocks");
}
}
if (pb.num_blocks != inode->i_blocks) {
pctx->num = pb.num_blocks;
- if (fix_problem(fs, PR_1_BAD_I_BLOCKS, pctx)) {
+ if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
inode->i_blocks = pb.num_blocks;
e2fsck_write_inode(fs, ino, inode, "check_blocks");
}
blk_t blk = *block_nr;
int ret_code = 0;
int problem = 0;
- errcode_t retval;
+ e2fsck_t ctx;
p = (struct process_block_struct *) private;
pctx = p->pctx;
+ ctx = p->ctx;
if (blk == 0) {
if (p->is_dir == 0) {
* Should never happen, since only directories
* get called with BLOCK_FLAG_HOLE
*/
+#if DEBUG_E2FSCK
printf("process_block() called with blk == 0, "
"blockcnt=%d, inode %lu???\n",
blockcnt, p->ino);
+#endif
return 0;
}
if (blockcnt < 0)
if (problem) {
p->num_illegal_blocks++;
if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
- if (fix_problem(fs, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
+ if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
p->clear = 1;
return BLOCK_ABORT;
}
- if (ask("Suppress messages", 0)) {
+ if (ask(ctx, "Suppress messages", 0)) {
p->suppress = 1;
- suppress_latch_group(PR_LATCH_BLOCK, 1);
+ set_latch_flags(PR_LATCH_BLOCK,
+ PRL_SUPPRESS, 0);
}
}
pctx->blk = blk;
pctx->blkcount = blockcnt;
- if (fix_problem(fs, problem, pctx)) {
+ if (fix_problem(ctx, problem, pctx)) {
blk = *block_nr = 0;
ret_code = BLOCK_CHANGED;
goto mark_dir;
pctx->blkcount = -1;
}
- mark_block_used(fs, blk);
+ mark_block_used(ctx, blk);
p->num_blocks++;
if (blockcnt >= 0)
p->last_block = blockcnt;
mark_dir:
if (p->is_dir && (blockcnt >= 0)) {
- retval = ext2fs_add_dir_block(fs->dblist, p->ino,
- blk, blockcnt);
- if (retval) {
- com_err(program_name, retval,
- "while adding to directory block list");
+ pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
+ blk, blockcnt);
+ if (pctx->errcode) {
+ pctx->blk = blk;
+ pctx->num = blockcnt;
+ fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
fatal_error(0);
}
}
return ret_code;
}
-static void bad_block_indirect(ext2_filsys fs, blk_t blk)
+static void bad_block_indirect(e2fsck_t ctx, blk_t blk)
{
- printf("Bad block %u used as bad block indirect block?!?\n", blk);
- preenhalt(fs);
- printf("\nThis inconsistency can not be fixed with "
- "e2fsck; to fix it, use\n"
- """dumpe2fs -b"" to dump out the bad block "
- "list and ""e2fsck -L filename""\n"
- "to read it back in again.\n");
- if (ask("Continue", 0))
- return;
- fatal_error(0);
-}
+ struct problem_context pctx;
-static int bad_primary_block(ext2_filsys fs, blk_t *block_nr)
-{
- printf("\nIf the block is really bad, the filesystem can not be "
- "fixed.\n");
- preenhalt(fs);
- printf("You can clear the this block from the bad block list\n");
- printf("and hope that block is really OK, but there are no "
- "guarantees.\n\n");
- if (ask("Clear (and hope for the best)", 1)) {
- *block_nr = 0;
- return 1;
- }
- ext2fs_unmark_valid(fs);
- return 0;
+ clear_problem_context(&pctx);
+ /*
+ * Prompt to see if we should continue or not.
+ */
+ if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, &pctx))
+ fatal_error(0);
}
int process_bad_block(ext2_filsys fs,
int first_block;
int i;
struct problem_context *pctx;
+ e2fsck_t ctx;
if (!blk)
return 0;
p = (struct process_block_struct *) private;
+ ctx = p->ctx;
pctx = p->pctx;
pctx->blk = blk;
pctx->blkcount = blockcnt;
-
if ((blk < fs->super->s_first_data_block) ||
(blk >= fs->super->s_blocks_count)) {
- if (fix_problem(fs, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
+ if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
*block_nr = 0;
return BLOCK_CHANGED;
} else
}
if (blockcnt < 0) {
- if (ext2fs_test_block_bitmap(block_found_map, blk))
- bad_block_indirect(fs, blk);
+ if (ext2fs_test_block_bitmap(ctx->block_found_map, blk))
+ bad_block_indirect(ctx, blk);
else
- mark_block_used(fs, blk);
+ mark_block_used(ctx, blk);
return 0;
}
#if 0
printf ("DEBUG: Marking %u as bad.\n", blk);
#endif
- fs_badblocks_count++;
+ ctx->fs_badblocks_count++;
/*
* If the block is not used, then mark it as used and return.
* If it is already marked as found, this must mean that
* there's an overlap between the filesystem table blocks
* (bitmaps and inode table) and the bad block list.
*/
- if (!ext2fs_test_block_bitmap(block_found_map, blk)) {
- ext2fs_mark_block_bitmap(block_found_map, blk);
+ if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
+ ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
return 0;
}
/*
for (i = 0; i < fs->group_desc_count; i++ ) {
pctx->group = i;
+ pctx->blk = blk;
if (blk == first_block) {
if (i == 0) {
- printf("The primary superblock (%u) is "
- "on the bad block list.\n", blk);
- if (bad_primary_block(fs, block_nr))
+ if (fix_problem(ctx,
+ PR_1_BAD_PRIMARY_SUPERBLOCK,
+ pctx)) {
+ *block_nr = 0;
return BLOCK_CHANGED;
+ }
return 0;
}
- if (!preen)
- printf("Warning: Group %d's superblock "
- "(%u) is bad.\n", i, blk);
+ fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
return 0;
}
if ((blk > first_block) &&
(blk <= first_block + fs->desc_blocks)) {
if (i == 0) {
- printf("Block %u in the primary group "
- "descriptors is on the bad block "
- "list\n", blk);
- if (bad_primary_block(fs, block_nr))
+ pctx->blk = *block_nr;
+ if (fix_problem(ctx,
+ PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
+ *block_nr = 0;
return BLOCK_CHANGED;
+ }
return 0;
}
- if (!preen)
- printf("Warning: Group %d's copy of the "
- "group descriptors has a bad "
- "block (%u).\n", i, blk);
+ fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
return 0;
}
if (blk == fs->group_desc[i].bg_block_bitmap) {
- if (fix_problem(fs, PR_1_BB_BAD_BLOCK, pctx)) {
- invalid_block_bitmap[i]++;
- invalid_bitmaps++;
+ if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
+ ctx->invalid_block_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
}
return 0;
}
if (blk == fs->group_desc[i].bg_inode_bitmap) {
- if (fix_problem(fs, PR_1_IB_BAD_BLOCK, pctx)) {
- invalid_inode_bitmap[i]++;
- invalid_bitmaps++;
+ if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
+ ctx->invalid_inode_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
}
return 0;
}
*/
if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
p->inode->i_block[EXT2_DIND_BLOCK]) {
- bad_block_indirect(fs, blk);
+ bad_block_indirect(ctx, blk);
return 0;
}
-
- printf("Programming error? block #%u claimed for no reason "
- "in process_bad_block.\n", blk);
+
+ pctx->group = -1;
+
+ /* Warn user that the block wasn't claimed */
+ fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
+
return 0;
}
-static void new_table_block(ext2_filsys fs, blk_t first_block, int group,
+static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
const char *name, int num, blk_t *new_block)
{
- errcode_t retval;
+ ext2_filsys fs = ctx->fs;
blk_t old_block = *new_block;
int i;
char *buf;
-
- retval = ext2fs_get_free_blocks(fs, first_block,
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
+
+ pctx.group = group;
+ pctx.blk = old_block;
+ pctx.str = name;
+
+ pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
first_block + fs->super->s_blocks_per_group,
- num, block_found_map, new_block);
- if (retval) {
- printf("Could not allocate %d block(s) for %s: %s\n",
- num, name, error_message(retval));
+ num, ctx->block_found_map, new_block);
+ if (pctx.errcode) {
+ pctx.num = num;
+ fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
ext2fs_unmark_valid(fs);
return;
}
buf = malloc(fs->blocksize);
if (!buf) {
- printf("Could not allocate block buffer for relocating %s\n",
- name);
+ fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
ext2fs_unmark_valid(fs);
return;
}
ext2fs_mark_super_dirty(fs);
- printf("Relocating group %d's %s ", group, name);
- if (old_block)
- printf("from %u ", old_block);
- printf("to %u...\n", *new_block);
+ pctx.blk2 = *new_block;
+ fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
+ PR_1_RELOC_TO), &pctx);
+ pctx.blk2 = 0;
for (i = 0; i < num; i++) {
- ext2fs_mark_block_bitmap(block_found_map, (*new_block)+i);
+ pctx.blk = i;
+ ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
if (old_block) {
- retval = io_channel_read_blk(fs->io, old_block + i,
- 1, buf);
- if (retval)
- printf("Warning: could not read block %u "
- "of %s: %s\n",
- old_block + i, name,
- error_message(retval));
+ pctx.errcode = io_channel_read_blk(fs->io,
+ old_block + i, 1, buf);
+ if (pctx.errcode)
+ fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
} else
memset(buf, 0, fs->blocksize);
- retval = io_channel_write_blk(fs->io, (*new_block) + i,
+ pctx.blk = (*new_block) + i;
+ pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
1, buf);
- if (retval)
- printf("Warning: could not write block %u for %s: %s\n",
- (*new_block) + i, name, error_message(retval));
+ if (pctx.errcode)
+ fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
}
free(buf);
}
* out, so we can try to allocate new block(s) to replace the bad
* blocks.
*/
-static void handle_fs_bad_blocks(ext2_filsys fs)
+static void handle_fs_bad_blocks(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
int i;
int first_block = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
- if (invalid_block_bitmap[i]) {
- new_table_block(fs, first_block, i, "block bitmap", 1,
- &fs->group_desc[i].bg_block_bitmap);
+ if (ctx->invalid_block_bitmap_flag[i]) {
+ new_table_block(ctx, first_block, i, "block bitmap",
+ 1, &fs->group_desc[i].bg_block_bitmap);
}
- if (invalid_inode_bitmap[i]) {
- new_table_block(fs, first_block, i, "inode bitmap", 1,
- &fs->group_desc[i].bg_inode_bitmap);
+ if (ctx->invalid_inode_bitmap_flag[i]) {
+ new_table_block(ctx, first_block, i, "inode bitmap",
+ 1, &fs->group_desc[i].bg_inode_bitmap);
}
- if (invalid_inode_table[i]) {
- new_table_block(fs, first_block, i, "inode table",
+ if (ctx->invalid_inode_table_flag[i]) {
+ new_table_block(ctx, first_block, i, "inode table",
fs->inode_blocks_per_group,
&fs->group_desc[i].bg_inode_table);
restart_e2fsck++;
}
first_block += fs->super->s_blocks_per_group;
}
- invalid_bitmaps = 0;
+ ctx->invalid_bitmaps = 0;
}
/*
* This routine marks all blocks which are used by the superblock,
* group descriptors, inode bitmaps, and block bitmaps.
*/
-static void mark_table_blocks(ext2_filsys fs)
+static void mark_table_blocks(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
blk_t block, b;
int i,j;
struct problem_context pctx;
/*
* Mark this group's copy of the superblock
*/
- ext2fs_mark_block_bitmap(block_found_map, block);
- ext2fs_mark_block_bitmap(block_illegal_map, block);
+ ext2fs_mark_block_bitmap(ctx->block_found_map, block);
+ ext2fs_mark_block_bitmap(ctx->block_illegal_map,
+ block);
/*
* Mark this group's copy of the descriptors
*/
for (j = 0; j < fs->desc_blocks; j++) {
- ext2fs_mark_block_bitmap(block_found_map,
+ ext2fs_mark_block_bitmap(ctx->block_found_map,
block + j + 1);
- ext2fs_mark_block_bitmap(block_illegal_map,
+ ext2fs_mark_block_bitmap(ctx->block_illegal_map,
block + j + 1);
}
}
for (j = 0, b = fs->group_desc[i].bg_inode_table;
j < fs->inode_blocks_per_group;
j++, b++) {
- if (ext2fs_test_block_bitmap(block_found_map,
+ if (ext2fs_test_block_bitmap(ctx->block_found_map,
b)) {
pctx.blk = b;
- if (fix_problem(fs,
+ if (fix_problem(ctx,
PR_1_ITABLE_CONFLICT, &pctx)) {
- invalid_inode_table[i]++;
- invalid_bitmaps++;
+ ctx->invalid_inode_table_flag[i]++;
+ ctx->invalid_bitmaps++;
}
} else {
- ext2fs_mark_block_bitmap(block_found_map,
+ ext2fs_mark_block_bitmap(ctx->block_found_map,
b);
- ext2fs_mark_block_bitmap(block_illegal_map,
+ ext2fs_mark_block_bitmap(ctx->block_illegal_map,
b);
}
}
* Mark block used for the block bitmap
*/
if (fs->group_desc[i].bg_block_bitmap) {
- if (ext2fs_test_block_bitmap(block_found_map,
+ if (ext2fs_test_block_bitmap(ctx->block_found_map,
fs->group_desc[i].bg_block_bitmap)) {
pctx.blk = fs->group_desc[i].bg_block_bitmap;
- if (fix_problem(fs, PR_1_BB_CONFLICT, &pctx)) {
- invalid_block_bitmap[i]++;
- invalid_bitmaps++;
+ if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
+ ctx->invalid_block_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
}
} else {
- ext2fs_mark_block_bitmap(block_found_map,
+ ext2fs_mark_block_bitmap(ctx->block_found_map,
fs->group_desc[i].bg_block_bitmap);
- ext2fs_mark_block_bitmap(block_illegal_map,
+ ext2fs_mark_block_bitmap(ctx->block_illegal_map,
fs->group_desc[i].bg_block_bitmap);
}
* Mark block used for the inode bitmap
*/
if (fs->group_desc[i].bg_inode_bitmap) {
- if (ext2fs_test_block_bitmap(block_found_map,
+ if (ext2fs_test_block_bitmap(ctx->block_found_map,
fs->group_desc[i].bg_inode_bitmap)) {
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
- if (fix_problem(fs, PR_1_IB_CONFLICT, &pctx)) {
- invalid_inode_bitmap[i]++;
- invalid_bitmaps++;
+ if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
+ ctx->invalid_inode_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
}
} else {
- ext2fs_mark_block_bitmap(block_found_map,
+ ext2fs_mark_block_bitmap(ctx->block_found_map,
fs->group_desc[i].bg_inode_bitmap);
- ext2fs_mark_block_bitmap(block_illegal_map,
+ ext2fs_mark_block_bitmap(ctx->block_illegal_map,
fs->group_desc[i].bg_inode_bitmap);
}
}
*/
errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks)
{
+ e2fsck_t ctx = fs->private;
int i;
- if (ino != stashed_ino)
+ if (ino != ctx->stashed_ino)
return EXT2_ET_CALLBACK_NOTHANDLED;
for (i=0; i < EXT2_N_BLOCKS; i++)
- blocks[i] = stashed_inode->i_block[i];
+ blocks[i] = ctx->stashed_inode->i_block[i];
return 0;
}
errcode_t pass1_read_inode(ext2_filsys fs, ino_t ino, struct ext2_inode *inode)
{
- if (ino != stashed_ino)
+ e2fsck_t ctx = fs->private;
+
+ if (ino != ctx->stashed_ino)
return EXT2_ET_CALLBACK_NOTHANDLED;
- *inode = *stashed_inode;
+ *inode = *ctx->stashed_inode;
return 0;
}
errcode_t pass1_write_inode(ext2_filsys fs, ino_t ino,
struct ext2_inode *inode)
{
- if (ino == stashed_ino)
- *stashed_inode = *inode;
+ e2fsck_t ctx = fs->private;
+
+ if (ino == ctx->stashed_ino)
+ *ctx->stashed_inode = *inode;
return EXT2_ET_CALLBACK_NOTHANDLED;
}
errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino)
{
- if (ino == stashed_ino) {
- if (!LINUX_S_ISDIR(stashed_inode->i_mode))
- return ENOTDIR;
- return 0;
- }
- printf("INTERNAL ERROR: pass1_check_directory: unexpected inode #%lu\n",
- ino);
- printf("\t(was expecting %lu)\n", stashed_ino);
- exit(FSCK_ERROR);
+ e2fsck_t ctx = fs->private;
+
+ if (ino != ctx->stashed_ino)
+ return EXT2_ET_CALLBACK_NOTHANDLED;
+
+ if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
+ return ENOTDIR;
+ return 0;
}
static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
int blockcnt, void *private);
-static void delete_file(ext2_filsys fs, struct dup_inode *dp,
+static void delete_file(e2fsck_t ctx, struct dup_inode *dp,
char *block_buf);
-static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf);
-static void pass1b(ext2_filsys fs, char *block_buf);
-static void pass1c(ext2_filsys fs, char *block_buf);
-static void pass1d(ext2_filsys fs, char *block_buf);
+static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf);
+static void pass1b(e2fsck_t ctx, char *block_buf);
+static void pass1c(e2fsck_t ctx, char *block_buf);
+static void pass1d(e2fsck_t ctx, char *block_buf);
static struct dup_block *dup_blk = 0;
static struct dup_inode *dup_ino = 0;
/*
* Main procedure for handling duplicate blocks
*/
-void pass1_dupblocks(ext2_filsys fs, char *block_buf)
+void pass1_dupblocks(e2fsck_t ctx, char *block_buf)
{
- errcode_t retval;
+ ext2_filsys fs = ctx->fs;
struct dup_block *p, *q, *next_p, *next_q;
struct dup_inode *r, *next_r;
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
- retval = ext2fs_allocate_inode_bitmap(fs,
+ pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
"multiply claimed inode map", &inode_dup_map);
- if (retval) {
- com_err("ext2fs_allocate_inode_bitmap", retval,
- "while allocating inode_dup_map");
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
- pass1b(fs, block_buf);
- pass1c(fs, block_buf);
- pass1d(fs, block_buf);
+ pass1b(ctx, block_buf);
+ pass1c(ctx, block_buf);
+ pass1d(ctx, block_buf);
/*
* Time to free all of the accumulated data structures that we
* don't need anymore.
*/
- ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0;
- ext2fs_free_block_bitmap(block_dup_map); block_dup_map = 0;
+ ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0;
+ ext2fs_free_block_bitmap(ctx->block_dup_map); ctx->block_dup_map = 0;
for (p = dup_blk; p; p = next_p) {
next_p = p->next_block;
for (q = p; q; q = next_q) {
struct process_block_struct {
ino_t ino;
int dup_blocks;
+ e2fsck_t ctx;
+ struct problem_context *pctx;
};
-void pass1b(ext2_filsys fs, char *block_buf)
+void pass1b(e2fsck_t ctx, char *block_buf)
{
+ ext2_filsys fs = ctx->fs;
ino_t ino;
struct ext2_inode inode;
ext2_inode_scan scan;
errcode_t retval;
struct process_block_struct pb;
struct dup_inode *dp;
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
- printf("Duplicate blocks found... invoking duplicate block passes.\n");
- printf("Pass 1B: Rescan for duplicate/bad blocks\n");
- retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan);
- if (retval) {
- com_err(program_name, retval, "while opening inode scan");
+ fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
+ pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
+ &scan);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
fatal_error(0);
}
- retval = ext2fs_get_next_inode(scan, &ino, &inode);
- if (retval) {
- com_err(program_name, retval, "while starting inode scan");
+ pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
fatal_error(0);
}
- stashed_inode = &inode;
+ ctx->stashed_inode = &inode;
+ pb.ctx = ctx;
+ pb.pctx = &pctx;
while (ino) {
- stashed_ino = ino;
+ pctx.ino = ctx->stashed_ino = ino;
if ((ino != EXT2_BAD_INO) &&
- (!ext2fs_test_inode_bitmap(inode_used_map, ino) ||
+ (!ext2fs_test_inode_bitmap(ctx->inode_used_map, ino) ||
!ext2fs_inode_has_valid_blocks(&inode)))
goto next;
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
process_pass1b_block, &pb);
if (pb.dup_blocks) {
- if (ino != EXT2_BAD_INO)
- printf("\n");
+ end_problem_latch(ctx, PR_LATCH_DBLOCK);
dp = allocate_memory(sizeof(struct dup_inode),
"duplicate inode record");
dp->ino = ino;
dup_inode_count++;
}
if (retval)
- com_err(program_name, retval,
+ com_err(ctx->program_name, retval,
"while calling ext2fs_block_iterate in pass1b");
next:
- retval = ext2fs_get_next_inode(scan, &ino, &inode);
- if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
+ pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
goto next;
- if (retval) {
- com_err(program_name, retval,
- "while doing inode scan");
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
fatal_error(0);
}
}
struct process_block_struct *p;
struct dup_block *dp, *q, *r;
int i;
+ e2fsck_t ctx;
if (!*block_nr)
return 0;
p = (struct process_block_struct *) private;
+ ctx = p->ctx;
- if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
+ if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
/* OK, this is a duplicate block */
if (p->ino != EXT2_BAD_INO) {
- if (!p->dup_blocks)
- printf("Duplicate/bad block(s) in inode %lu:",
- p->ino);
- printf(" %u", *block_nr);
+ p->pctx->blk = *block_nr;
+ fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
}
p->dup_blocks++;
- ext2fs_mark_block_bitmap(block_dup_map, *block_nr);
+ ext2fs_mark_block_bitmap(ctx->block_dup_map, *block_nr);
ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
dp = allocate_memory(sizeof(struct dup_block),
"duplicate block record");
}
-void pass1c(ext2_filsys fs, char *block_buf)
+void pass1c(e2fsck_t ctx, char *block_buf)
{
+ ext2_filsys fs = ctx->fs;
struct dup_inode *p;
int inodes_left = dup_inode_count;
struct search_dir_struct sd;
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
- printf("Pass 1C: Scan directories for inodes with dup blocks.\n");
+ fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
/*
* First check to see if any of the inodes with dup blocks is
search_dirent_proc, &sd);
}
-static void pass1d(ext2_filsys fs, char *block_buf)
+static void pass1d(e2fsck_t ctx, char *block_buf)
{
+ ext2_filsys fs = ctx->fs;
struct dup_inode *p, *s;
struct dup_block *q, *r;
ino_t *shared;
int shared_len;
int i;
- errcode_t retval;
int file_ok;
int meta_data = 0;
struct problem_context pctx;
+
+ clear_problem_context(&pctx);
- printf("Pass 1D: Reconciling duplicate blocks\n");
- read_bitmaps(fs);
+ fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
+ read_bitmaps(ctx);
- printf("(There are %d inodes containing duplicate/bad blocks.)\n\n",
- dup_inode_count);
+ pctx.num = dup_inode_count;
+ fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
shared = allocate_memory(sizeof(ino_t) * dup_inode_count,
"Shared inode list");
for (p = dup_ino; p; p = p->next) {
continue;
if (q->num_bad > 1)
file_ok = 0;
- if (ext2fs_test_block_bitmap(block_illegal_map,
+ if (ext2fs_test_block_bitmap(ctx->block_illegal_map,
q->block)) {
file_ok = 0;
meta_data = 1;
/*
* Report the inode that we are working on
*/
- clear_problem_context(&pctx);
pctx.inode = &p->inode;
pctx.ino = p->ino;
pctx.dir = p->dir;
pctx.blkcount = p->num_dupblocks;
pctx.num = meta_data ? shared_len+1 : shared_len;
- fix_problem(fs, PR_1B_DUP_FILE, &pctx);
+ fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
pctx.blkcount = 0;
pctx.num = 0;
if (meta_data)
- fix_problem(fs, PR_1B_SHARE_METADATA, &pctx);
+ fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
for (i = 0; i < shared_len; i++) {
for (s = dup_ino; s; s = s->next)
pctx.inode = &s->inode;
pctx.ino = s->ino;
pctx.dir = s->dir;
- fix_problem(fs, PR_1B_DUP_FILE_LIST, &pctx);
+ fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
}
if (file_ok) {
- printf("Duplicated blocks already reassigned or cloned.\n\n");
+ fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
continue;
}
-
- if (ask("Clone duplicate/bad blocks", 1)) {
- retval = clone_file(fs, p, block_buf);
- if (retval)
- printf("Couldn't clone file: %s\n",
- error_message(retval));
- else {
- printf("\n");
+ if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
+ pctx.errcode = clone_file(ctx, p, block_buf);
+ if (pctx.errcode)
+ fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
+ else
continue;
- }
}
- if (ask("Delete file", 1))
- delete_file(fs, p, block_buf);
+ if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
+ delete_file(ctx, p, block_buf);
else
ext2fs_unmark_valid(fs);
- printf("\n");
}
free(shared);
}
int blockcnt,
void *private)
{
+ struct process_block_struct *pb = private;
struct dup_block *p;
+ e2fsck_t ctx;
+
+ ctx = pb->ctx;
if (!*block_nr)
return 0;
- if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
+ if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
for (p = dup_blk; p; p = p->next_block)
if (p->block == *block_nr)
break;
if (p) {
p->num_bad--;
if (p->num_bad == 1)
- ext2fs_unmark_block_bitmap(block_dup_map,
+ ext2fs_unmark_block_bitmap(ctx->block_dup_map,
*block_nr);
} else
com_err("delete_file_block", 0,
"internal error; can't find dup_blk for %d\n",
*block_nr);
} else {
- ext2fs_unmark_block_bitmap(block_found_map, *block_nr);
+ ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
}
return 0;
}
-static void delete_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
+static void delete_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
struct process_block_struct pb;
struct ext2_inode inode;
pb.ino = dp->ino;
pb.dup_blocks = dp->num_dupblocks;
+ pb.ctx = ctx;
retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
delete_file_block, &pb);
com_err("delete_file", retval,
"while calling ext2fs_block_iterate for inode %d",
dp->ino);
- ext2fs_unmark_inode_bitmap(inode_used_map, dp->ino);
- ext2fs_unmark_inode_bitmap(inode_dir_map, dp->ino);
- if (inode_bad_map)
- ext2fs_unmark_inode_bitmap(inode_bad_map, dp->ino);
+ ext2fs_unmark_inode_bitmap(ctx->inode_used_map, dp->ino);
+ ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, dp->ino);
+ if (ctx->inode_bad_map)
+ ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, dp->ino);
ext2fs_unmark_inode_bitmap(fs->inode_map, dp->ino);
ext2fs_mark_ib_dirty(fs);
ext2fs_mark_bb_dirty(fs);
errcode_t errcode;
ino_t dir;
char *buf;
+ e2fsck_t ctx;
};
static int clone_file_block(ext2_filsys fs,
blk_t new_block;
errcode_t retval;
struct clone_struct *cs = (struct clone_struct *) private;
+ e2fsck_t ctx;
+ ctx = cs->ctx;
+
if (!*block_nr)
return 0;
- if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
+ if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
for (p = dup_blk; p; p = p->next_block)
if (p->block == *block_nr)
break;
if (p) {
- retval = ext2fs_new_block(fs, 0, block_found_map,
+ retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
&new_block);
if (retval) {
cs->errcode = retval;
}
p->num_bad--;
if (p->num_bad == 1)
- ext2fs_unmark_block_bitmap(block_dup_map,
+ ext2fs_unmark_block_bitmap(ctx->block_dup_map,
*block_nr);
*block_nr = new_block;
- ext2fs_mark_block_bitmap(block_found_map,
+ ext2fs_mark_block_bitmap(ctx->block_found_map,
new_block);
ext2fs_mark_block_bitmap(fs->block_map, new_block);
return BLOCK_CHANGED;
return 0;
}
-static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
+static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
struct clone_struct cs;
cs.errcode = 0;
- cs.buf = malloc(fs->blocksize);
cs.dir = 0;
+ cs.ctx = ctx;
+ cs.buf = malloc(fs->blocksize);
if (!cs.buf)
return ENOMEM;
- if (ext2fs_test_inode_bitmap(inode_dir_map, dp->ino))
+ if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dp->ino))
cs.dir = dp->ino;
retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
}
return 0;
}
-
-
-
-
-
* - The inode_bad_map bitmap
*/
-#include "et/com_err.h"
-
#include "e2fsck.h"
#include "problem.h"
/*
* Keeps track of how many times an inode is referenced.
*/
-ext2_icount_t inode_count = 0;
-
-static void deallocate_inode(ext2_filsys fs, ino_t ino,
+static void deallocate_inode(e2fsck_t ctx, ino_t ino,
char* block_buf);
-static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino);
+static int process_bad_inode(e2fsck_t ctx, ino_t dir, ino_t ino);
static int check_dir_block(ext2_filsys fs,
struct ext2_db_entry *dir_blocks_info,
void *private);
-static int allocate_dir_block(ext2_filsys fs,
+static int allocate_dir_block(e2fsck_t ctx,
struct ext2_db_entry *dir_blocks_info,
char *buf, struct problem_context *pctx);
static int update_dir_block(ext2_filsys fs,
struct check_dir_struct {
char *buf;
struct problem_context pctx;
+ e2fsck_t ctx;
};
-void pass2(ext2_filsys fs)
+void pass2(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
char *buf;
struct resource_track rtrack;
struct dir_info *dir;
- errcode_t retval;
- ino_t size;
struct check_dir_struct cd;
init_resource_track(&rtrack);
+ clear_problem_context(&cd.pctx);
+
#ifdef MTRACE
mtrace_print("Pass 2");
#endif
- if (!preen)
- printf("Pass 2: Checking directory structure\n");
- retval = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
- 0, inode_link_info, &inode_count);
- if (retval) {
- com_err("ext2fs_create_icount", retval,
- "while creating inode_count");
+ if (!(ctx->options & E2F_OPT_PREEN))
+ fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
+
+ cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
+ 0, ctx->inode_link_info,
+ &ctx->inode_count);
+ if (cd.pctx.errcode) {
+ fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
fatal_error(0);
}
buf = allocate_memory(fs->blocksize, "directory scan buffer");
dir->parent = EXT2_ROOT_INO;
cd.buf = buf;
- clear_problem_context(&cd.pctx);
+ cd.ctx = ctx;
- retval = ext2fs_dblist_iterate(fs->dblist, check_dir_block, &cd);
- if (retval) {
- com_err("ext2fs_dblist_iterate", retval,
- "while iterating through dblist");
+ cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
+ &cd);
+ if (cd.pctx.errcode) {
+ fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
fatal_error(0);
}
free(buf);
ext2fs_free_dblist(fs->dblist);
- if (inode_bad_map) {
- ext2fs_free_inode_bitmap(inode_bad_map);
- inode_bad_map = 0;
- }
- if (tflag > 1) {
- printf("Pass 2: ");
- print_resource_track(&rtrack);
+ if (ctx->inode_bad_map) {
+ ext2fs_free_inode_bitmap(ctx->inode_bad_map);
+ ctx->inode_bad_map = 0;
}
+ if (ctx->options & E2F_OPT_TIME2)
+ print_resource_track("Pass 2", &rtrack);
}
/*
* Make sure the first entry in the directory is '.', and that the
* directory entry is sane.
*/
-static int check_dot(ext2_filsys fs,
+static int check_dot(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
ino_t ino, struct problem_context *pctx)
{
problem = PR_2_DOT_NULL_TERM;
if (problem) {
- if (fix_problem(fs, problem, pctx)) {
+ if (fix_problem(ctx, problem, pctx)) {
if (dirent->rec_len < 12)
dirent->rec_len = 12;
dirent->inode = ino;
}
}
if (dirent->inode != ino) {
- if (fix_problem(fs, PR_2_BAD_INODE_DOT, pctx)) {
+ if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
dirent->inode = ino;
status = 1;
}
if (dirent->rec_len > 12) {
new_len = dirent->rec_len - 12;
if (new_len > 12) {
- preenhalt(fs);
+ preenhalt(ctx);
if (created ||
- ask("Directory entry for '.' is big. Split", 1)) {
+ ask(ctx, "Directory entry for '.' is big. Split", 1)) {
nextdir = (struct ext2_dir_entry *)
((char *) dirent + 12);
dirent->rec_len = 12;
* directory entry is sane. We do not check the inode number of '..'
* here; this gets done in pass 3.
*/
-static int check_dotdot(ext2_filsys fs,
+static int check_dotdot(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
struct dir_info *dir, struct problem_context *pctx)
{
problem = PR_2_DOT_DOT_NULL_TERM;
if (problem) {
- if (fix_problem(fs, problem, pctx)) {
+ if (fix_problem(ctx, problem, pctx)) {
if (dirent->rec_len < 12)
dirent->rec_len = 12;
/*
* Check to make sure a directory entry doesn't contain any illegal
* characters.
*/
-static int check_name(ext2_filsys fs,
+static int check_name(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
ino_t dir_ino, struct problem_context *pctx)
{
for ( i = 0; i < dirent->name_len; i++) {
if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
if (fixup < 0) {
- fixup = fix_problem(fs, PR_2_BAD_NAME, pctx);
+ fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
}
if (fixup) {
dirent->name[i] = '.';
struct ext2_dir_entry *dirent;
int offset = 0;
int dir_modified = 0;
- errcode_t retval;
int dot_state;
blk_t block_nr = db->blk;
ino_t ino = db->ino;
__u16 links;
struct check_dir_struct *cd = private;
- char *buf = cd->buf;
+ char *buf;
+ e2fsck_t ctx;
+ int problem;
+
+ buf = cd->buf;
+ ctx = cd->ctx;
/*
* Make sure the inode is still in use (could have been
* deleted in the duplicate/bad blocks pass.
*/
- if (!(ext2fs_test_inode_bitmap(inode_used_map, ino)))
+ if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
return 0;
cd->pctx.ino = ino;
cd->pctx.num = 0;
if (db->blk == 0) {
- if (allocate_dir_block(fs, db, buf, &cd->pctx))
+ if (allocate_dir_block(ctx, db, buf, &cd->pctx))
return 0;
block_nr = db->blk;
}
db->blockcnt, ino);
#endif
- retval = ext2fs_read_dir_block(fs, block_nr, buf);
- if (retval) {
- com_err(program_name, retval,
- "while reading directory block %d", block_nr);
+ cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
+ if (cd->pctx.errcode) {
+ if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx))
+ fatal_error(0);
+ memset(buf, 0, fs->blocksize);
}
do {
dot_state++;
+ problem = 0;
dirent = (struct ext2_dir_entry *) (buf + offset);
cd->pctx.dirent = dirent;
cd->pctx.num = offset;
(dirent->rec_len < 8) ||
((dirent->rec_len % 4) != 0) ||
((dirent->name_len+8) > dirent->rec_len)) {
- if (fix_problem(fs, PR_2_DIR_CORRUPTED, &cd->pctx)) {
+ if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
dirent->rec_len = fs->blocksize - offset;
dirent->name_len = 0;
dirent->inode = 0;
} else
return DIRENT_ABORT;
}
-
if (dirent->name_len > EXT2_NAME_LEN) {
- if (fix_problem(fs, PR_2_FILENAME_LONG, &cd->pctx)) {
+ if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
dirent->name_len = EXT2_NAME_LEN;
dir_modified++;
}
}
if (dot_state == 1) {
- if (check_dot(fs, dirent, ino, &cd->pctx))
+ if (check_dot(ctx, dirent, ino, &cd->pctx))
dir_modified++;
} else if (dot_state == 2) {
dir = get_dir_info(ino);
if (!dir) {
- printf("Internal error: couldn't find dir_info for %lu\n",
- ino);
+ fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
fatal_error(0);
}
- if (check_dotdot(fs, dirent, dir, &cd->pctx))
+ if (check_dotdot(ctx, dirent, dir, &cd->pctx))
dir_modified++;
} else if (dirent->inode == ino) {
- if (fix_problem(fs, PR_2_LINK_DOT, &cd->pctx)) {
+ problem = PR_2_LINK_DOT;
+ if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
if (!dirent->inode)
goto next;
- if (check_name(fs, dirent, ino, &cd->pctx))
- dir_modified++;
-
/*
* Make sure the inode listed is a legal one.
*/
if (((dirent->inode != EXT2_ROOT_INO) &&
(dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
(dirent->inode > fs->super->s_inodes_count)) {
- if (fix_problem(fs, PR_2_BAD_INO, &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
- }
-
- /*
- * If the inode is unused, offer to clear it.
- */
- if (!(ext2fs_test_inode_bitmap(inode_used_map,
+ problem = PR_2_BAD_INO;
+ } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
dirent->inode))) {
- if (fix_problem(fs, PR_2_UNUSED_INODE, &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
+ /*
+ * If the inode is unused, offer to clear it.
+ */
+ problem = PR_2_UNUSED_INODE;
+ } else if (ctx->inode_bb_map &&
+ (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
+ dirent->inode))) {
+ /*
+ * If the inode is in a bad block, offer to
+ * clear it.
+ */
+ problem = PR_2_BB_INODE;
+ } else if ((dot_state > 2) &&
+ (dirent->name_len == 1) &&
+ (dirent->name[0] == '.')) {
+ /*
+ * If there's a '.' entry in anything other
+ * than the first directory entry, it's a
+ * duplicate entry that should be removed.
+ */
+ problem = PR_2_DUP_DOT;
+ } else if ((dot_state > 2) &&
+ (dirent->name_len == 2) &&
+ (dirent->name[0] == '.') &&
+ (dirent->name[1] == '.')) {
+ /*
+ * If there's a '..' entry in anything other
+ * than the second directory entry, it's a
+ * duplicate entry that should be removed.
+ */
+ problem = PR_2_DUP_DOT_DOT;
+ } else if ((dot_state > 2) &&
+ (dirent->inode == EXT2_ROOT_INO)) {
+ /*
+ * Don't allow links to the root directory.
+ * We check this specially to make sure we
+ * catch this error case even if the root
+ * directory hasn't been created yet.
+ */
+ problem = PR_2_LINK_ROOT;
}
- /*
- * If the inode is in a bad block, offer to clear it.
- */
- if (inode_bb_map &&
- (ext2fs_test_inode_bitmap(inode_bb_map,
- dirent->inode))) {
- if (fix_problem(fs, PR_2_BB_INODE, &cd->pctx)) {
+ if (problem) {
+ if (fix_problem(ctx, problem, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
+ } else {
+ ext2fs_unmark_valid(fs);
+ if (problem == PR_2_BAD_INO)
+ goto next;
}
}
* (We wait until now so that we can display the
* pathname to the user.)
*/
- if (inode_bad_map &&
- ext2fs_test_inode_bitmap(inode_bad_map,
+ if (ctx->inode_bad_map &&
+ ext2fs_test_inode_bitmap(ctx->inode_bad_map,
dirent->inode)) {
- if (process_bad_inode(fs, ino, dirent->inode)) {
+ if (process_bad_inode(ctx, ino, dirent->inode)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
}
- /*
- * Don't allow links to the root directory. We check
- * this specially to make sure we catch this error
- * case even if the root directory hasn't been created
- * yet.
- */
- if ((dot_state > 2) && (dirent->inode == EXT2_ROOT_INO)) {
- if (fix_problem(fs, PR_2_LINK_ROOT, &cd->pctx)) {
- dirent->inode = 0;
- dir_modified++;
- goto next;
- }
- }
-
+ if (check_name(ctx, dirent, ino, &cd->pctx))
+ dir_modified++;
+
/*
* If this is a directory, then mark its parent in its
* dir_info structure. If the parent field is already
* and ask the user if he/she wants to clear this one.
*/
if ((dot_state > 2) &&
- (ext2fs_test_inode_bitmap(inode_dir_map,
+ (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
dirent->inode))) {
subdir = get_dir_info(dirent->inode);
if (!subdir) {
- printf("INTERNAL ERROR: missing dir %u\n",
- dirent->inode);
+ cd->pctx.ino = dirent->inode;
+ fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
fatal_error(0);
}
if (subdir->parent) {
cd->pctx.ino2 = subdir->parent;
- if (fix_problem(fs, PR_2_LINK_DIR,
+ if (fix_problem(ctx, PR_2_LINK_DIR,
&cd->pctx)) {
dirent->inode = 0;
dir_modified++;
subdir->parent = ino;
}
- ext2fs_icount_increment(inode_count, dirent->inode, &links);
+ ext2fs_icount_increment(ctx->inode_count, dirent->inode,
+ &links);
if (links > 1)
- fs_links_count++;
- fs_total_count++;
+ ctx->fs_links_count++;
+ ctx->fs_total_count++;
next:
offset += dirent->rec_len;
} while (offset < fs->blocksize);
printf("\n");
#endif
if (offset != fs->blocksize) {
- printf("Final rec_len is %d, should be %d\n",
- dirent->rec_len,
- dirent->rec_len - fs->blocksize + offset);
+ cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
+ if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
+ dirent->rec_len = cd->pctx.num;
+ dir_modified++;
+ }
}
if (dir_modified) {
- retval = ext2fs_write_dir_block(fs, block_nr, buf);
- if (retval) {
- com_err(program_name, retval,
- "while writing directory block %d", block_nr);
+ cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
+ if (cd->pctx.errcode) {
+ if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, &cd->pctx))
+ fatal_error(0);
}
ext2fs_mark_changed(fs);
}
int blockcnt,
void *private)
{
+ e2fsck_t ctx = (e2fsck_t) private;
+
if (!*block_nr)
return 0;
- ext2fs_unmark_block_bitmap(block_found_map, *block_nr);
+ ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
return 0;
}
/*
* This fuction deallocates an inode
*/
-static void deallocate_inode(ext2_filsys fs, ino_t ino,
+static void deallocate_inode(e2fsck_t ctx, ino_t ino,
char* block_buf)
{
- errcode_t retval;
+ ext2_filsys fs = ctx->fs;
struct ext2_inode inode;
-
- ext2fs_icount_store(inode_link_info, ino, 0);
+ struct problem_context pctx;
+
+ ext2fs_icount_store(ctx->inode_link_info, ino, 0);
e2fsck_read_inode(fs, ino, &inode, "deallocate_inode");
inode.i_links_count = 0;
inode.i_dtime = time(0);
e2fsck_write_inode(fs, ino, &inode, "deallocate_inode");
+ clear_problem_context(&pctx);
+ pctx.ino = ino;
/*
* Fix up the bitmaps...
*/
- read_bitmaps(fs);
- ext2fs_unmark_inode_bitmap(inode_used_map, ino);
- ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
- if (inode_bad_map)
- ext2fs_unmark_inode_bitmap(inode_bad_map, ino);
+ read_bitmaps(ctx);
+ ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
+ ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
+ if (ctx->inode_bad_map)
+ ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
return;
ext2fs_mark_bb_dirty(fs);
- retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
- deallocate_inode_block, 0);
- if (retval)
- com_err("deallocate_inode", retval,
- "while calling ext2fs_block_iterate for inode %d",
- ino);
+ pctx.errcode = ext2fs_block_iterate(fs, ino, 0, block_buf,
+ deallocate_inode_block, ctx);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
+ fatal_error(0);
+ }
}
-static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
+static int process_bad_inode(e2fsck_t ctx, ino_t dir, ino_t ino)
{
+ ext2_filsys fs = ctx->fs;
struct ext2_inode inode;
int inode_modified = 0;
unsigned char *frag, *fsize;
!LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
!LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
!(LINUX_S_ISSOCK(inode.i_mode))) {
- if (fix_problem(fs, PR_2_BAD_MODE, &pctx)) {
- deallocate_inode(fs, ino, 0);
+ if (fix_problem(ctx, PR_2_BAD_MODE, &pctx)) {
+ deallocate_inode(ctx, ino, 0);
return 1;
}
}
if (LINUX_S_ISCHR(inode.i_mode)
&& !e2fsck_pass1_check_device_inode(&inode)) {
- if (fix_problem(fs, PR_2_BAD_CHAR_DEV, &pctx)) {
- deallocate_inode(fs, ino, 0);
+ if (fix_problem(ctx, PR_2_BAD_CHAR_DEV, &pctx)) {
+ deallocate_inode(ctx, ino, 0);
return 1;
}
}
if (LINUX_S_ISBLK(inode.i_mode)
&& !e2fsck_pass1_check_device_inode(&inode)) {
- if (fix_problem(fs, PR_2_BAD_BLOCK_DEV, &pctx)) {
- deallocate_inode(fs, ino, 0);
+ if (fix_problem(ctx, PR_2_BAD_BLOCK_DEV, &pctx)) {
+ deallocate_inode(ctx, ino, 0);
return 1;
}
}
if (inode.i_faddr &&
- fix_problem(fs, PR_2_FADDR_ZERO, &pctx)) {
+ fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
inode.i_faddr = 0;
inode_modified++;
}
}
if (frag && *frag) {
pctx.num = *frag;
- if (fix_problem(fs, PR_2_FRAG_ZERO, &pctx)) {
+ if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
*frag = 0;
inode_modified++;
}
}
if (fsize && *fsize) {
pctx.num = *fsize;
- if (fix_problem(fs, PR_2_FSIZE_ZERO, &pctx)) {
+ if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
*fsize = 0;
inode_modified++;
}
}
if (inode.i_file_acl &&
- fix_problem(fs, PR_2_FILE_ACL_ZERO, &pctx)) {
+ fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
inode.i_file_acl = 0;
inode_modified++;
}
if (inode.i_dir_acl &&
- fix_problem(fs, PR_2_DIR_ACL_ZERO, &pctx)) {
+ fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
inode.i_dir_acl = 0;
inode_modified++;
}
* a "hole" in it, or if a directory has a illegal block number
* that was zeroed out and now needs to be replaced.
*/
-static int allocate_dir_block(ext2_filsys fs,
+static int allocate_dir_block(e2fsck_t ctx,
struct ext2_db_entry *db,
char *buf, struct problem_context *pctx)
{
+ ext2_filsys fs = ctx->fs;
blk_t blk;
char *block;
struct ext2_inode inode;
- errcode_t retval;
- if (fix_problem(fs, PR_2_DIRECTORY_HOLE, pctx) == 0)
+ if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
return 1;
/*
* Read the inode and block bitmaps in; we'll be messing with
* them.
*/
- read_bitmaps(fs);
+ read_bitmaps(ctx);
/*
* First, find a free block
*/
- retval = ext2fs_new_block(fs, 0, block_found_map, &blk);
- if (retval) {
- com_err("allocate_dir_block", retval,
- "while trying to fill a hole in a directory inode");
+ pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
+ if (pctx->errcode) {
+ pctx->str = "ext2fs_new_block";
+ fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
return 1;
}
- ext2fs_mark_block_bitmap(block_found_map, blk);
+ ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
ext2fs_mark_block_bitmap(fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
* Now let's create the actual data block for the inode
*/
if (db->blockcnt)
- retval = ext2fs_new_dir_block(fs, 0, 0, &block);
+ pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
else
- retval = ext2fs_new_dir_block(fs, db->ino, EXT2_ROOT_INO,
- &block);
+ pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
+ EXT2_ROOT_INO, &block);
- if (retval) {
- com_err("allocate_dir_block", retval,
- "while creating new directory block");
+ if (pctx->errcode) {
+ pctx->str = "ext2fs_new_dir_block";
+ fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
return 1;
}
- retval = ext2fs_write_dir_block(fs, blk, block);
+ pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
free(block);
- if (retval) {
- com_err("allocate_dir_block", retval,
- "while writing an empty directory block");
+ if (pctx->errcode) {
+ pctx->str = "ext2fs_write_dir_block";
+ fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
return 1;
}
* Finally, update the block pointers for the inode
*/
db->blk = blk;
- retval = ext2fs_block_iterate(fs, db->ino, BLOCK_FLAG_HOLE,
+ pctx->errcode = ext2fs_block_iterate(fs, db->ino, BLOCK_FLAG_HOLE,
0, update_dir_block, db);
- if (retval) {
- com_err("allocate_dir_block", retval,
- "while calling ext2fs_block_iterate");
+ if (pctx->errcode) {
+ pctx->str = "ext2fs_block_iterate";
+ fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
return 1;
}
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
-#include "et/com_err.h"
#include "e2fsck.h"
#include "problem.h"
-static void check_root(ext2_filsys fs);
-static void check_directory(ext2_filsys fs, struct dir_info *dir,
+static void check_root(e2fsck_t ctx);
+static void check_directory(e2fsck_t ctx, struct dir_info *dir,
struct problem_context *pctx);
-static ino_t get_lost_and_found(ext2_filsys fs);
-static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent);
-static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj);
-static errcode_t expand_directory(ext2_filsys fs, ino_t dir);
+static ino_t get_lost_and_found(e2fsck_t ctx);
+static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ino_t parent);
+static errcode_t adjust_inode_count(e2fsck_t ctx, ino_t ino, int adj);
+static errcode_t expand_directory(e2fsck_t ctx, ino_t dir);
static ino_t lost_and_found = 0;
static int bad_lost_and_found = 0;
static ext2fs_inode_bitmap inode_loop_detect;
static ext2fs_inode_bitmap inode_done_map;
-void pass3(ext2_filsys fs)
+void pass3(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
int i;
- errcode_t retval;
struct resource_track rtrack;
struct problem_context pctx;
struct dir_info *dir;
init_resource_track(&rtrack);
+ clear_problem_context(&pctx);
+
#ifdef MTRACE
mtrace_print("Pass 3");
#endif
- if (!preen)
- printf("Pass 3: Checking directory connectivity\n");
+ if (!(ctx->options & E2F_OPT_PREEN))
+ fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
/*
* Allocate some bitmaps to do loop detection.
*/
- retval = ext2fs_allocate_inode_bitmap(fs,
- "inode loop detection bitmap",
- &inode_loop_detect);
- if (retval) {
- com_err("ext2fs_allocate_inode_bitmap", retval,
- "while allocating inode_loop_detect");
+ pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
+ "inode loop detection bitmap", &inode_loop_detect);
+ if (pctx.errcode) {
+ pctx.num = 1;
+ fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
- retval = ext2fs_allocate_inode_bitmap(fs, "inode done bitmap",
- &inode_done_map);
- if (retval) {
- com_err("ext2fs_allocate_inode_bitmap", retval,
- "while allocating inode_done_map");
+ pctx.errcode = ext2fs_allocate_inode_bitmap(fs, "inode done bitmap",
+ &inode_done_map);
+ if (pctx.errcode) {
+ pctx.num = 2;
+ fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
fatal_error(0);
}
- if (tflag) {
- printf("Peak memory: ");
- print_resource_track(&global_rtrack);
- }
+ if (ctx->options & E2F_OPT_TIME)
+ print_resource_track("Peak memory", &ctx->global_rtrack);
- check_root(fs);
+ check_root(ctx);
ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
- clear_problem_context(&pctx);
for (i=0; (dir = dir_info_iter(&i)) != 0;) {
- if (ext2fs_test_inode_bitmap(inode_dir_map, dir->ino))
- check_directory(fs, dir, &pctx);
+ if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
+ check_directory(ctx, dir, &pctx);
}
free_dir_info(fs);
ext2fs_free_inode_bitmap(inode_loop_detect);
ext2fs_free_inode_bitmap(inode_done_map);
- if (tflag > 1) {
- printf("Pass 3: ");
- print_resource_track(&rtrack);
- }
+ if (ctx->options & E2F_OPT_TIME2)
+ print_resource_track("Pass 3", &rtrack);
}
/*
* This makes sure the root inode is present; if not, we ask if the
* user wants us to create it. Not creating it is a fatal error.
*/
-static void check_root(ext2_filsys fs)
+static void check_root(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
blk_t blk;
- errcode_t retval;
struct ext2_inode inode;
char * block;
+ struct problem_context pctx;
- if (ext2fs_test_inode_bitmap(inode_used_map, EXT2_ROOT_INO)) {
+ clear_problem_context(&pctx);
+
+ if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
/*
* If the root inode is a directory, die here. The
* user must have answered 'no' in pass1 when we
* offered to clear it.
*/
- if (!(ext2fs_test_inode_bitmap(inode_dir_map, EXT2_ROOT_INO)))
+ if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
+ EXT2_ROOT_INO)))
fatal_error("Root inode not directory");
return;
}
- if (!fix_problem(fs, PR_3_NO_ROOT_INODE, 0))
+ if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx))
fatal_error("Cannot proceed without a root inode.");
- read_bitmaps(fs);
+ read_bitmaps(ctx);
/*
* First, find a free block
*/
- retval = ext2fs_new_block(fs, 0, block_found_map, &blk);
- if (retval) {
- com_err("ext2fs_new_block", retval,
- "while trying to create root directory");
+ pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
+ if (pctx.errcode) {
+ pctx.str = "ext2fs_new_block";
+ fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
fatal_error(0);
}
- ext2fs_mark_block_bitmap(block_found_map, blk);
+ ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
ext2fs_mark_block_bitmap(fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
/*
* Now let's create the actual data block for the inode
*/
- retval = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
- &block);
- if (retval) {
- com_err("ext2fs_new_dir_block", retval,
- "while creating new root directory");
+ pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
+ &block);
+ if (pctx.errcode) {
+ pctx.str = "ext2fs_new_dir_block";
+ fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
fatal_error(0);
}
- retval = ext2fs_write_dir_block(fs, blk, block);
- if (retval) {
- com_err("ext2fs_write_dir_block", retval,
- "while writing the root directory block");
+ pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
+ if (pctx.errcode) {
+ pctx.str = "ext2fs_write_dir_block";
+ fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
fatal_error(0);
}
free(block);
/*
* Write out the inode.
*/
- retval = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode);
- if (retval) {
- com_err("ext2fs_write_inode", retval,
- "While trying to create /lost+found");
+ pctx.errcode = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode);
+ if (pctx.errcode) {
+ pctx.str = "ext2fs_write_inode";
+ fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
fatal_error(0);
}
* Miscellaneous bookkeeping...
*/
add_dir_info(fs, EXT2_ROOT_INO, EXT2_ROOT_INO);
- ext2fs_icount_store(inode_count, EXT2_ROOT_INO, 2);
- ext2fs_icount_store(inode_link_info, EXT2_ROOT_INO, 2);
+ ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
+ ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
- ext2fs_mark_inode_bitmap(inode_used_map, EXT2_ROOT_INO);
- ext2fs_mark_inode_bitmap(inode_dir_map, EXT2_ROOT_INO);
+ ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
+ ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
ext2fs_mark_ib_dirty(fs);
}
* a loop, we treat that as a disconnected directory and offer to
* reparent it to lost+found.
*/
-static void check_directory(ext2_filsys fs, struct dir_info *dir,
+static void check_directory(e2fsck_t ctx, struct dir_info *dir,
struct problem_context *pctx)
{
+ ext2_filsys fs = ctx->fs;
struct dir_info *p = dir;
ext2fs_clear_inode_bitmap(inode_loop_detect);
* inode; offer to reconnect it to lost+found.
*/
pctx->ino = p->ino;
- if (fix_problem(fs, PR_3_UNCONNECTED_DIR, pctx)) {
- if (reconnect_file(fs, p->ino))
+ if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
+ if (reconnect_file(ctx, p->ino))
ext2fs_unmark_valid(fs);
else {
p->parent = lost_and_found;
- fix_dotdot(fs, p, lost_and_found);
+ fix_dotdot(ctx, p, lost_and_found);
}
}
pctx->ino = dir->ino;
pctx->ino2 = dir->dotdot;
pctx->dir = dir->parent;
- if (fix_problem(fs, PR_3_BAD_DOT_DOT, pctx))
- fix_dotdot(fs, dir, dir->parent);
+ if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
+ fix_dotdot(ctx, dir, dir->parent);
}
}
* This routine gets the lost_and_found inode, making it a directory
* if necessary
*/
-ino_t get_lost_and_found(ext2_filsys fs)
+ino_t get_lost_and_found(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
ino_t ino;
blk_t blk;
errcode_t retval;
struct ext2_inode inode;
char * block;
const char name[] = "lost+found";
+ struct problem_context pctx;
+ clear_problem_context(&pctx);
+
retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
sizeof(name)-1, 0, &ino);
if (!retval)
return ino;
- if (retval != ENOENT)
- printf("Error while trying to find /lost+found: %s",
- error_message(retval));
- if (!fix_problem(fs, PR_3_NO_LF_DIR, 0))
+ if (retval != ENOENT) {
+ pctx.errcode = retval;
+ fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
+ }
+ if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
return 0;
/*
* Read the inode and block bitmaps in; we'll be messing with
* them.
*/
- read_bitmaps(fs);
+ read_bitmaps(ctx);
/*
* First, find a free block
*/
- retval = ext2fs_new_block(fs, 0, block_found_map, &blk);
+ retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
if (retval) {
- com_err("ext2fs_new_block", retval,
- "while trying to create /lost+found directory");
+ pctx.errcode = retval;
+ fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
return 0;
}
- ext2fs_mark_block_bitmap(block_found_map, blk);
+ ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
ext2fs_mark_block_bitmap(fs->block_map, blk);
ext2fs_mark_bb_dirty(fs);
/*
* Next find a free inode.
*/
- retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040755, inode_used_map,
- &ino);
+ retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040755,
+ ctx->inode_used_map, &ino);
if (retval) {
- com_err("ext2fs_new_inode", retval,
- "while trying to create /lost+found directory");
+ pctx.errcode = retval;
+ fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
return 0;
}
- ext2fs_mark_inode_bitmap(inode_used_map, ino);
- ext2fs_mark_inode_bitmap(inode_dir_map, ino);
+ ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
+ ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
ext2fs_mark_inode_bitmap(fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
*/
retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
if (retval) {
- com_err("ext2fs_new_dir_block", retval,
- "while creating new directory block");
+ pctx.errcode = retval;
+ fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
return 0;
}
retval = ext2fs_write_dir_block(fs, blk, block);
free(block);
if (retval) {
- com_err("ext2fs_write_dir_block", retval,
- "while writing the directory block for /lost+found");
+ pctx.errcode = retval;
+ fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
return 0;
}
/*
* Next, write out the inode.
*/
- retval = ext2fs_write_inode(fs, ino, &inode);
- if (retval) {
- com_err("ext2fs_write_inode", retval,
- "While trying to create /lost+found");
+ pctx.errcode = ext2fs_write_inode(fs, ino, &inode);
+ if (pctx.errcode) {
+ pctx.str = "ext2fs_write_inode";
+ fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
return 0;
}
/*
* Finally, create the directory link
*/
- retval = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, 0);
- if (retval) {
- com_err("ext2fs_link", retval, "While creating /lost+found");
+ pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, 0);
+ if (pctx.errcode) {
+ pctx.str = "ext2fs_link";
+ fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
return 0;
}
* Miscellaneous bookkeeping that needs to be kept straight.
*/
add_dir_info(fs, ino, EXT2_ROOT_INO);
- adjust_inode_count(fs, EXT2_ROOT_INO, +1);
- ext2fs_icount_store(inode_count, ino, 2);
- ext2fs_icount_store(inode_link_info, ino, 2);
+ adjust_inode_count(ctx, EXT2_ROOT_INO, +1);
+ ext2fs_icount_store(ctx->inode_count, ino, 2);
+ ext2fs_icount_store(ctx->inode_link_info, ino, 2);
#if 0
printf("/lost+found created; inode #%lu\n", ino);
#endif
/*
* This routine will connect a file to lost+found
*/
-int reconnect_file(ext2_filsys fs, ino_t inode)
+int reconnect_file(e2fsck_t ctx, ino_t inode)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
char name[80];
-
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
+ pctx.ino = inode;
+
+ if (!bad_lost_and_found && !lost_and_found) {
+ lost_and_found = get_lost_and_found(ctx);
+ if (!lost_and_found)
+ bad_lost_and_found++;
+ }
if (bad_lost_and_found) {
- printf("Bad or nonexistent /lost+found. Cannot reconnect.\n");
+ fix_problem(ctx, PR_3_NO_LPF, &pctx);
return 1;
}
- if (!lost_and_found) {
- lost_and_found = get_lost_and_found(fs);
- if (!lost_and_found) {
- printf("Bad or nonexistent /lost+found. Cannot reconnect.\n");
- bad_lost_and_found++;
- return 1;
- }
- }
-
+
sprintf(name, "#%lu", inode);
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
if (retval == EXT2_ET_DIR_NO_SPACE) {
- if (!fix_problem(fs, PR_3_EXPAND_LF_DIR, 0))
+ if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
return 1;
- retval = expand_directory(fs, lost_and_found);
+ retval = expand_directory(ctx, lost_and_found);
if (retval) {
- printf("Could not expand /lost+found: %s\n",
- error_message(retval));
+ pctx.errcode = retval;
+ fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
return 1;
}
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
}
if (retval) {
- printf("Could not reconnect %lu: %s\n", inode,
- error_message(retval));
+ pctx.errcode = retval;
+ fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
return 1;
}
-
- adjust_inode_count(fs, inode, +1);
+ adjust_inode_count(ctx, inode, +1);
return 0;
}
/*
* Utility routine to adjust the inode counts on an inode.
*/
-static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj)
+static errcode_t adjust_inode_count(e2fsck_t ctx, ino_t ino, int adj)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
struct ext2_inode inode;
inode.i_links_count += adj;
if (adj == 1) {
- ext2fs_icount_increment(inode_count, ino, 0);
- ext2fs_icount_increment(inode_link_info, ino, 0);
+ ext2fs_icount_increment(ctx->inode_count, ino, 0);
+ ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
} else {
- ext2fs_icount_decrement(inode_count, ino, 0);
- ext2fs_icount_decrement(inode_link_info, ino, 0);
+ ext2fs_icount_decrement(ctx->inode_count, ino, 0);
+ ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
}
ext2_filsys fs;
ino_t parent;
int done;
+ e2fsck_t ctx;
};
static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
{
struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) private;
errcode_t retval;
+ struct problem_context pctx;
if (dirent->name_len != 2)
return 0;
if (strncmp(dirent->name, "..", 2))
return 0;
-
- retval = adjust_inode_count(fp->fs, dirent->inode, -1);
- if (retval)
- printf("Error while adjusting inode count on inode %u\n",
- dirent->inode);
- retval = adjust_inode_count(fp->fs, fp->parent, 1);
- if (retval)
- printf("Error while adjusting inode count on inode %lu\n",
- fp->parent);
+ clear_problem_context(&pctx);
+
+ retval = adjust_inode_count(fp->ctx, dirent->inode, -1);
+ if (retval) {
+ pctx.errcode = retval;
+ fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
+ }
+ retval = adjust_inode_count(fp->ctx, fp->parent, 1);
+ if (retval) {
+ pctx.errcode = retval;
+ fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
+ }
dirent->inode = fp->parent;
fp->done++;
return DIRENT_ABORT | DIRENT_CHANGED;
}
-static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent)
+static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ino_t parent)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
struct fix_dotdot_struct fp;
+ struct problem_context pctx;
fp.fs = fs;
fp.parent = parent;
fp.done = 0;
+ fp.ctx = ctx;
#if 0
printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
0, fix_dotdot_proc, &fp);
if (retval || !fp.done) {
- printf("Couldn't fix parent of inode %lu: %s\n\n",
- dir->ino, retval ? error_message(retval) :
- "Couldn't find parent direntory entry");
+ clear_problem_context(&pctx);
+ pctx.ino = dir->ino;
+ pctx.errcode = retval;
+ fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
+ PR_3_FIX_PARENT_NOFIND, &pctx);
ext2fs_unmark_valid(fs);
}
dir->dotdot = parent;
struct expand_dir_struct {
int done;
errcode_t err;
+ e2fsck_t ctx;
};
static int expand_dir_proc(ext2_filsys fs,
static blk_t last_blk = 0;
char *block;
errcode_t retval;
+ e2fsck_t ctx;
+
+ ctx = es->ctx;
if (*blocknr) {
last_blk = *blocknr;
return 0;
}
- retval = ext2fs_new_block(fs, last_blk, block_found_map, &new_blk);
+ retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
+ &new_blk);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
free(block);
*blocknr = new_blk;
- ext2fs_mark_block_bitmap(block_found_map, new_blk);
+ ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
ext2fs_mark_bb_dirty(fs);
if (es->done)
return BLOCK_CHANGED;
}
-static errcode_t expand_directory(ext2_filsys fs, ino_t dir)
+static errcode_t expand_directory(e2fsck_t ctx, ino_t dir)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
struct expand_dir_struct es;
struct ext2_inode inode;
es.done = 0;
es.err = 0;
+ es.ctx = ctx;
retval = ext2fs_block_iterate(fs, dir, BLOCK_FLAG_APPEND,
0, expand_dir_proc, &es);
return 0;
}
-
-
-
* This subroutine returns 1 then the caller shouldn't bother with the
* rest of the pass 4 tests.
*/
-static int disconnect_inode(ext2_filsys fs, ino_t i)
+static int disconnect_inode(e2fsck_t ctx, ino_t i)
{
+ ext2_filsys fs = ctx->fs;
struct ext2_inode inode;
struct problem_context pctx;
/*
* This is a zero-length file; prompt to delete it...
*/
- if (fix_problem(fs, PR_4_ZERO_LEN_INODE, &pctx)) {
- ext2fs_icount_store(inode_link_info, i, 0);
+ if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
+ ext2fs_icount_store(ctx->inode_link_info, i, 0);
inode.i_links_count = 0;
inode.i_dtime = time(0);
e2fsck_write_inode(fs, i, &inode,
/*
* Fix up the bitmaps...
*/
- read_bitmaps(fs);
- ext2fs_unmark_inode_bitmap(inode_used_map, i);
- ext2fs_unmark_inode_bitmap(inode_dir_map, i);
+ read_bitmaps(ctx);
+ ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
+ ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
ext2fs_unmark_inode_bitmap(fs->inode_map, i);
ext2fs_mark_ib_dirty(fs);
return 0;
/*
* Prompt to reconnect.
*/
- if (fix_problem(fs, PR_4_UNATTACHED_INODE, &pctx)) {
- if (reconnect_file(fs, i))
+ if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
+ if (reconnect_file(ctx, i))
ext2fs_unmark_valid(fs);
} else {
/*
}
-void pass4(ext2_filsys fs)
+void pass4(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
ino_t i;
struct ext2_inode inode;
struct resource_track rtrack;
mtrace_print("Pass 4");
#endif
- if (!preen)
- printf("Pass 4: Checking reference counts\n");
clear_problem_context(&pctx);
+
+ if (!(ctx->options & E2F_OPT_PREEN))
+ fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
+
for (i=1; i <= fs->super->s_inodes_count; i++) {
if (i == EXT2_BAD_INO ||
(i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
continue;
- if (!(ext2fs_test_inode_bitmap(inode_used_map, i)) ||
- (inode_bb_map &&
- ext2fs_test_inode_bitmap(inode_bb_map, i)))
+ if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
+ (ctx->inode_bb_map &&
+ ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
continue;
- ext2fs_icount_fetch(inode_link_info, i, &link_count);
- ext2fs_icount_fetch(inode_count, i, &link_counted);
+ ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
+ ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
if (link_counted == 0) {
- if (disconnect_inode(fs, i))
+ if (disconnect_inode(ctx, i))
continue;
- ext2fs_icount_fetch(inode_link_info, i, &link_count);
- ext2fs_icount_fetch(inode_count, i, &link_counted);
+ ext2fs_icount_fetch(ctx->inode_link_info, i,
+ &link_count);
+ ext2fs_icount_fetch(ctx->inode_count, i,
+ &link_counted);
}
if (link_counted != link_count) {
e2fsck_read_inode(fs, i, &inode, "pass4");
pctx.ino = i;
pctx.inode = &inode;
if (link_count != inode.i_links_count) {
- printf("WARNING: PROGRAMMING BUG IN E2FSCK!\n");
- printf("\tOR SOME BONEHEAD (YOU) IS CHECKING "
- "A MOUNTED (LIVE) FILESYSTEM.\n");
- printf("inode_link_info[%ld] is %u, "
- "inode.i_links_count is %d. "
- "They should be the same!\n",
- i, link_count,
- inode.i_links_count);
+ pctx.num = link_count;
+ fix_problem(ctx,
+ PR_4_INCONSISTENT_COUNT, &pctx);
}
pctx.num = link_counted;
- if (fix_problem(fs, PR_4_BAD_REF_COUNT, &pctx)) {
+ if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
inode.i_links_count = link_counted;
e2fsck_write_inode(fs, i, &inode, "pass4");
}
}
}
- ext2fs_free_icount(inode_link_info); inode_link_info = 0;
- ext2fs_free_icount(inode_count); inode_count = 0;
- ext2fs_free_inode_bitmap(inode_bb_map);
- if (tflag > 1) {
- printf("Pass 4: ");
- print_resource_track(&rtrack);
- }
+ ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
+ ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
+ ext2fs_free_inode_bitmap(ctx->inode_bb_map);
+ ctx->inode_bb_map = 0;
+ if (ctx->options & E2F_OPT_TIME2)
+ print_resource_track("Pass 4", &rtrack);
}
*
*/
-#include "et/com_err.h"
-
#include "e2fsck.h"
+#include "problem.h"
-static void check_block_bitmaps(ext2_filsys fs);
-static void check_inode_bitmaps(ext2_filsys fs);
-static void check_inode_end(ext2_filsys fs);
-static void check_block_end(ext2_filsys fs);
-
-static int do_fix = -1;
-static const char *fix_question = "Fix summary information";
+static void check_block_bitmaps(e2fsck_t ctx);
+static void check_inode_bitmaps(e2fsck_t ctx);
+static void check_inode_end(e2fsck_t ctx);
+static void check_block_end(e2fsck_t ctx);
-void pass5(ext2_filsys fs)
+void pass5(e2fsck_t ctx)
{
struct resource_track rtrack;
+ struct problem_context pctx;
#ifdef MTRACE
mtrace_print("Pass 5");
init_resource_track(&rtrack);
- if (!preen)
- printf("Pass 5: Checking group summary information\n");
+ clear_problem_context(&pctx);
- read_bitmaps(fs);
+ if (!(ctx->options & E2F_OPT_PREEN))
+ fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
- check_block_bitmaps(fs);
- check_inode_bitmaps(fs);
- check_inode_end(fs);
- check_block_end(fs);
+ read_bitmaps(ctx);
- ext2fs_free_inode_bitmap(inode_used_map);
- ext2fs_free_inode_bitmap(inode_dir_map);
- ext2fs_free_block_bitmap(block_found_map);
+ check_block_bitmaps(ctx);
+ check_inode_bitmaps(ctx);
+ check_inode_end(ctx);
+ check_block_end(ctx);
- if (tflag > 1) {
- printf("Pass 5: ");
- print_resource_track(&rtrack);
- }
+ ext2fs_free_inode_bitmap(ctx->inode_used_map);
+ ctx->inode_used_map = 0;
+ ext2fs_free_inode_bitmap(ctx->inode_dir_map);
+ ctx->inode_dir_map = 0;
+ ext2fs_free_block_bitmap(ctx->block_found_map);
+ ctx->block_found_map = 0;
+
+ if (ctx->options & E2F_OPT_TIME2)
+ print_resource_track("Pass 5", &rtrack);
}
-static void check_block_bitmaps(ext2_filsys fs)
+static void check_block_bitmaps(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
blk_t i;
int *free_array;
int group = 0;
int free_blocks = 0;
int group_free = 0;
int actual, bitmap;
- const char *print_header = "Block bitmap differences:";
+ struct problem_context pctx;
+ int problem, fixit;
+ errcode_t retval;
+ clear_problem_context(&pctx);
free_array = allocate_memory(fs->group_desc_count * sizeof(int),
"free block count array");
if ((fs->super->s_first_data_block <
- ext2fs_get_block_bitmap_start(block_found_map)) ||
+ ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
(fs->super->s_blocks_count-1 >
- ext2fs_get_block_bitmap_end(block_found_map))) {
- printf("PROGRAMMING ERROR: filesystem endpoints (%d, %d)\n\t"
- "don't match block_found_map endpoints (%d, %d).\n",
- fs->super->s_first_data_block,
- fs->super->s_blocks_count -1,
- ext2fs_get_block_bitmap_start(block_found_map),
- ext2fs_get_block_bitmap_end(block_found_map));
+ ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
+ pctx.num = 1;
+ pctx.blk = fs->super->s_first_data_block;
+ pctx.blk2 = fs->super->s_blocks_count -1;
+ pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
+ pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
+ fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
+ /* fatal */
fatal_error(0);
}
ext2fs_get_block_bitmap_start(fs->block_map)) ||
(fs->super->s_blocks_count-1 >
ext2fs_get_block_bitmap_end(fs->block_map))) {
- printf("PROGRAMMING ERROR: filesystem endpoints (%d, %d)\n\t"
- "don't match fs->block_map endpoints (%d, %d).\n",
- fs->super->s_first_data_block,
- fs->super->s_blocks_count -1,
- ext2fs_get_block_bitmap_start(fs->block_map),
- ext2fs_get_block_bitmap_end(fs->block_map));
+ pctx.num = 2;
+ pctx.blk = fs->super->s_first_data_block;
+ pctx.blk2 = fs->super->s_blocks_count -1;
+ pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
+ pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
+ fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
+ /* fatal */
fatal_error(0);
}
-
+redo_counts:
for (i = fs->super->s_first_data_block;
i < fs->super->s_blocks_count;
i++) {
- actual = ext2fs_fast_test_block_bitmap(block_found_map, i);
+ actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
if (actual == bitmap)
goto do_counts;
-
- if (do_fix < 0)
- do_fix = ask(fix_question, 1);
- if (!preen && print_header) {
- printf(print_header);
- print_header = 0;
- }
+
if (!actual && bitmap) {
/*
* Block not used, but marked in use in the bitmap.
*/
- if (!preen)
- printf(" -%u", i);
- if (do_fix)
- ext2fs_unmark_block_bitmap(fs->block_map,
- i);
+ problem = PR_5_UNUSED_BLOCK;
} else {
/*
* Block used, but not marked in use in the bitmap.
*/
- if (!preen)
- printf(" +%u", i);
- if (do_fix)
- ext2fs_mark_block_bitmap(fs->block_map,
- i);
+ problem = PR_5_BLOCK_USED;
}
- if (do_fix) {
- ext2fs_mark_bb_dirty(fs);
- bitmap = actual;
- } else
- ext2fs_unmark_valid(fs);
-
+ pctx.blk = i;
+ fix_problem(ctx, problem, &pctx);
+
do_counts:
if (!bitmap) {
group_free++;
group_free = 0;
}
}
- if (!print_header)
- printf(". %s\n", fix_msg[do_fix]);
+ fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
+ if (fixit == 1) {
+ ext2fs_free_block_bitmap(fs->block_map);
+ retval = ext2fs_copy_bitmap(ctx->block_found_map,
+ &fs->block_map);
+ /* XXX check retval --- should never fail! */
+ ext2fs_set_bitmap_padding(fs->block_map);
+ ext2fs_mark_bb_dirty(fs);
+
+ /* Redo the counts */
+ blocks = 0; free_blocks = 0; group_free = 0; group = 0;
+ memset(free_array, 0, fs->group_desc_count * sizeof(int));
+ goto redo_counts;
+ } else if (fixit == 0)
+ ext2fs_unmark_valid(fs);
+
for (i = 0; i < fs->group_desc_count; i++) {
if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
- if (do_fix < 0)
- do_fix = ask(fix_question, 1);
- if (!preen)
- printf("Free blocks count wrong for "
- "group %u (%u, counted=%d). %s\n", i,
- fs->group_desc[i].bg_free_blocks_count,
- free_array[i], fix_msg[do_fix]);
- if (do_fix) {
+ pctx.group = i;
+ pctx.blk = fs->group_desc[i].bg_free_blocks_count;
+ pctx.blk2 = free_array[i];
+
+ if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
+ &pctx)) {
fs->group_desc[i].bg_free_blocks_count =
free_array[i];
ext2fs_mark_super_dirty(fs);
}
}
if (free_blocks != fs->super->s_free_blocks_count) {
- if (do_fix < 0)
- do_fix = ask(fix_question, 1);
- if (!preen)
- printf("Free blocks count wrong "
- "(%u, counted=%d). %s\n",
- fs->super->s_free_blocks_count, free_blocks,
- fix_msg[do_fix]);
- if (do_fix) {
+ pctx.group = 0;
+ pctx.blk = fs->super->s_free_blocks_count;
+ pctx.blk2 = free_blocks;
+
+ if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
fs->super->s_free_blocks_count = free_blocks;
ext2fs_mark_super_dirty(fs);
} else
free(free_array);
}
-static void check_inode_bitmaps(ext2_filsys fs)
+static void check_inode_bitmaps(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
ino_t i;
int free_inodes = 0;
int group_free = 0;
int *free_array;
int *dir_array;
int actual, bitmap;
- const char *print_header = "Inode bitmap differences:";
+ errcode_t retval;
+ struct problem_context pctx;
+ int problem, fixit;
+ clear_problem_context(&pctx);
free_array = allocate_memory(fs->group_desc_count * sizeof(int),
"free inode count array");
dir_array = allocate_memory(fs->group_desc_count * sizeof(int),
"directory count array");
- if ((1 < ext2fs_get_inode_bitmap_start(inode_used_map)) ||
+ if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
(fs->super->s_inodes_count >
- ext2fs_get_inode_bitmap_end(inode_used_map))) {
- printf("PROGRAMMING ERROR: filesystem inode endpoints (%d, %d)\n\t"
- "don't match inode_used_map endpoints (%d, %d).\n",
- 1, fs->super->s_inodes_count,
- ext2fs_get_inode_bitmap_start(inode_used_map),
- ext2fs_get_inode_bitmap_end(inode_used_map));
+ ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
+ pctx.num = 3;
+ pctx.blk = 1;
+ pctx.blk2 = fs->super->s_inodes_count;
+ pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
+ pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
+ fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
+ /* fatal */
fatal_error(0);
}
if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
(fs->super->s_inodes_count >
ext2fs_get_inode_bitmap_end(fs->inode_map))) {
- printf("PROGRAMMING ERROR: filesystem inode endpoints (%d, %d)\n\t"
- "don't match fs->inode_map endpoints (%d, %d).\n",
- 1, fs->super->s_inodes_count,
- ext2fs_get_inode_bitmap_start(fs->inode_map),
- ext2fs_get_inode_bitmap_end(fs->inode_map));
+ pctx.num = 4;
+ pctx.blk = 1;
+ pctx.blk2 = fs->super->s_inodes_count;
+ pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
+ pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
+ fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
+ /* fatal */
fatal_error(0);
}
+redo_counts:
for (i = 1; i <= fs->super->s_inodes_count; i++) {
- actual = ext2fs_fast_test_inode_bitmap(inode_used_map, i);
+ actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
if (actual == bitmap)
goto do_counts;
- if (do_fix < 0)
- do_fix = ask(fix_question, 1);
- if (!preen && print_header) {
- printf(print_header);
- print_header = 0;
- }
if (!actual && bitmap) {
/*
* Inode wasn't used, but marked in bitmap
*/
- if (!preen)
- printf(" -%lu", i);
- if (do_fix)
- ext2fs_unmark_inode_bitmap(fs->inode_map, i);
- } else if (actual && !bitmap) {
+ problem = PR_5_UNUSED_INODE;
+ } else /* if (actual && !bitmap) */ {
/*
* Inode used, but not in bitmap
*/
- if (!preen)
- printf (" +%lu", i);
- if (do_fix)
- ext2fs_mark_inode_bitmap(fs->inode_map, i);
+ problem = PR_5_INODE_USED;
}
- if (do_fix) {
- ext2fs_mark_ib_dirty(fs);
- bitmap = actual;
- } else
- ext2fs_unmark_valid(fs);
-
+ pctx.ino = i;
+ fix_problem(ctx, problem, &pctx);
+
do_counts:
if (!bitmap) {
group_free++;
free_inodes++;
} else {
- if (ext2fs_test_inode_bitmap(inode_dir_map, i))
+ if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
dirs_count++;
}
inodes++;
dirs_count = 0;
}
}
- if (!print_header)
- printf(". %s\n", fix_msg[do_fix]);
+ fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
+ if (fixit == 1) {
+ ext2fs_free_inode_bitmap(fs->inode_map);
+ retval = ext2fs_copy_bitmap(ctx->inode_used_map,
+ &fs->inode_map);
+ /* XXX check retval --- should never fail! */
+ ext2fs_set_bitmap_padding(fs->inode_map);
+ ext2fs_mark_ib_dirty(fs);
+
+ /* redo counts */
+ inodes = 0; free_inodes = 0; group_free = 0;
+ dirs_count = 0; group = 0;
+ memset(free_array, 0, fs->group_desc_count * sizeof(int));
+ memset(dir_array, 0, fs->group_desc_count * sizeof(int));
+ goto redo_counts;
+ } else if (fixit == 0)
+ ext2fs_unmark_valid(fs);
for (i = 0; i < fs->group_desc_count; i++) {
if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
- if (do_fix < 0)
- do_fix = ask(fix_question, 1);
- if (!preen)
- printf ("Free inodes count wrong for "
- "group #%lu (%u, counted=%d). %s\n", i,
- fs->group_desc[i].bg_free_inodes_count,
- free_array[i], fix_msg[do_fix]);
- if (do_fix) {
+ pctx.group = i;
+ pctx.ino = fs->group_desc[i].bg_free_inodes_count;
+ pctx.ino2 = free_array[i];
+ if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
+ &pctx)) {
fs->group_desc[i].bg_free_inodes_count =
free_array[i];
ext2fs_mark_super_dirty(fs);
ext2fs_unmark_valid(fs);
}
if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
- if (do_fix < 0)
- do_fix = ask(fix_question, 1);
- if (!preen)
- printf ("Directories count wrong for "
- "group #%lu (%u, counted=%d). %s\n", i,
- fs->group_desc[i].bg_used_dirs_count,
- dir_array[i], fix_msg[do_fix]);
- if (do_fix) {
+ pctx.group = i;
+ pctx.ino = fs->group_desc[i].bg_used_dirs_count;
+ pctx.ino2 = dir_array[i];
+
+ if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
+ &pctx)) {
fs->group_desc[i].bg_used_dirs_count =
dir_array[i];
ext2fs_mark_super_dirty(fs);
}
}
if (free_inodes != fs->super->s_free_inodes_count) {
- if (do_fix < 0)
- do_fix = ask(fix_question, 1);
- if (!preen)
- printf("Free inodes count wrong "
- "(%u, counted=%d). %s\n",
- fs->super->s_free_inodes_count, free_inodes,
- fix_msg[do_fix]);
- if (do_fix) {
+ pctx.group = -1;
+ pctx.ino = fs->super->s_free_inodes_count;
+ pctx.ino2 = free_inodes;
+
+ if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
fs->super->s_free_inodes_count = free_inodes;
ext2fs_mark_super_dirty(fs);
} else
free(dir_array);
}
-static void check_inode_end(ext2_filsys fs)
+static void check_inode_end(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
ino_t end, save_inodes_count, i;
- errcode_t retval;
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
- retval = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
- &save_inodes_count);
- if (retval) {
- com_err("check_inode_end", retval,
- "while trying to fudge end of inode bitmap");
+ pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
+ &save_inodes_count);
+ if (pctx.errcode) {
+ pctx.num = 1;
+ fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
fatal_error(0);
}
if (save_inodes_count == end)
for (i = save_inodes_count + 1; i <= end; i++) {
if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
- printf("Padding at end of inode bitmap is not set. ");
- if (ask("Fix", 1)) {
+ if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
for (i = save_inodes_count + 1; i <= end; i++)
ext2fs_mark_inode_bitmap(fs->inode_map,
i);
}
}
- retval = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
- save_inodes_count, 0);
- if (retval) {
- com_err("check_inode_end", retval,
- "while trying to fudge end of inode bitmap back");
+ pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
+ save_inodes_count, 0);
+ if (pctx.errcode) {
+ pctx.num = 2;
+ fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
fatal_error(0);
}
}
-static void check_block_end(ext2_filsys fs)
+static void check_block_end(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
blk_t end, save_blocks_count, i;
- errcode_t retval;
+ struct problem_context pctx;
+
+ clear_problem_context(&pctx);
end = fs->block_map->start +
(EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
- retval = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
- &save_blocks_count);
- if (retval) {
- com_err("check_block_end", retval,
- "while trying to fudge end of block bitmap");
+ pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
+ &save_blocks_count);
+ if (pctx.errcode) {
+ pctx.num = 3;
+ fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
fatal_error(0);
}
if (save_blocks_count == end)
for (i = save_blocks_count + 1; i <= end; i++) {
if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
- printf("Padding at end of block bitmap is not set. ");
-
- if (ask("Fix", 1)) {
+ if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
for (i = save_blocks_count + 1; i < end; i++)
ext2fs_mark_block_bitmap(fs->block_map,
i);
}
}
- retval = ext2fs_fudge_block_bitmap_end(fs->block_map,
- save_blocks_count, 0);
- if (retval) {
- com_err("check_block_end", retval,
- "while trying to fudge end of block bitmap back");
+ pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
+ save_blocks_count, 0);
+ if (pctx.errcode) {
+ pctx.num = 4;
+ fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
fatal_error(0);
}
}
+
+
#include "problem.h"
-#define PROMPT_FIX 0
-#define PROMPT_CLEAR 1
-#define PROMPT_RELOCATE 2
-#define PROMPT_ALLOCATE 3
-#define PROMPT_EXPAND 4
-#define PROMPT_CONNECT 5
-#define PROMPT_CREATE 6
-#define PROMPT_SALVAGE 7
-#define PROMPT_TRUNCATE 8
-#define PROMPT_CLEAR_INODE 9
+#define PROMPT_NONE 0
+#define PROMPT_FIX 1
+#define PROMPT_CLEAR 2
+#define PROMPT_RELOCATE 3
+#define PROMPT_ALLOCATE 4
+#define PROMPT_EXPAND 5
+#define PROMPT_CONNECT 6
+#define PROMPT_CREATE 7
+#define PROMPT_SALVAGE 8
+#define PROMPT_TRUNCATE 9
+#define PROMPT_CLEAR_INODE 10
+#define PROMPT_ABORT 11
+#define PROMPT_SPLIT 12
+#define PROMPT_CONTINUE 13
+#define PROMPT_CLONE 14
+#define PROMPT_DELETE 15
/*
* These are the prompts which are used to ask the user if they want
* to fix a problem.
*/
static const char *prompt[] = {
- "Fix", /* 0 */
- "Clear", /* 1 */
- "Relocate", /* 2 */
- "Allocate", /* 3 */
- "Expand", /* 4 */
- "Connect to /lost+found", /* 5 */
- "Create", /* 6 */
- "Salvage", /* 7 */
- "Truncate", /* 8 */
- "Clear inode" /* 9 */
- };
+ "(no prompt)", /* 0 */
+ "Fix", /* 1 */
+ "Clear", /* 2 */
+ "Relocate", /* 3 */
+ "Allocate", /* 4 */
+ "Expand", /* 5 */
+ "Connect to /lost+found", /* 6 */
+ "Create", /* 7 */
+ "Salvage", /* 8 */
+ "Truncate", /* 9 */
+ "Clear inode", /* 10 */
+ "Abort", /* 11 */
+ "Split", /* 12 */
+ "Continue", /* 13 */
+ "Clone duplicate/bad blocks", /* 14 */
+ "Delete file", /* 15 */
+};
/*
* These messages are printed when we are preen mode and we will be
* automatically fixing the problem.
*/
static const char *preen_msg[] = {
- "FIXED", /* 0 */
- "CLEARED", /* 1 */
- "RELOCATED", /* 2 */
- "ALLOCATED", /* 3 */
- "EXPANDED", /* 4 */
- "RECONNECTED", /* 5 */
- "CREATED", /* 6 */
- "SALVAGED", /* 7 */
- "TRUNCATED", /* 8 */
- "INODE CLEARED" /* 9 */
+ "(NONE)", /* 0 */
+ "FIXED", /* 1 */
+ "CLEARED", /* 2 */
+ "RELOCATED", /* 3 */
+ "ALLOCATED", /* 4 */
+ "EXPANDED", /* 5 */
+ "RECONNECTED", /* 6 */
+ "CREATED", /* 7 */
+ "SALVAGED", /* 8 */
+ "TRUNCATED", /* 9 */
+ "INODE CLEARED", /* 10 */
+ "ABORTED", /* 11 */
+ "SPLIT", /* 12 */
+ "CONTINUING", /* 13 */
+ "DUPLICATE/BAD BLOCKS CLONED", /* 14 */
+ "FILE DELETED", /* 15 */
};
-static struct e2fsck_problem problem_table[] = {
+static const struct e2fsck_problem problem_table[] = {
/* Pre-Pass 1 errors */
/* Block bitmap not in group */
{ PR_0_BB_NOT_GROUP, "@b @B for @g %g is not in @g. (@b %b)\n",
- PROMPT_RELOCATE, 0 },
+ PROMPT_RELOCATE, PR_LATCH_RELOC },
/* Inode bitmap not in group */
{ PR_0_IB_NOT_GROUP, "@i @B for @g %g is not in @g. (@b %b)\n",
- PROMPT_RELOCATE, 0 },
+ PROMPT_RELOCATE, PR_LATCH_RELOC },
/* Inode table not in group */
{ PR_0_ITABLE_NOT_GROUP,
"@i table for @g %g is not in @g. (@b %b)\n"
"WARNING: SEVERE DATA LOSS POSSIBLE.\n",
- PROMPT_RELOCATE, 0 },
+ PROMPT_RELOCATE, PR_LATCH_RELOC },
+
+ /* Superblock corrupt */
+ { PR_0_SB_CORRUPT,
+ "\nThe @S could not be read or does not describe a correct ext2\n"
+ "@f. If the device is valid and it really contains an ext2\n"
+ "@f (and not swap or ufs or something else), then the @S\n"
+ "is corrupt, and you might try running e2fsck with an alternate @S:\n"
+ " e2fsck -b %S <device>\n\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Filesystem size is wrong */
+ { PR_0_FS_SIZE_WRONG,
+ "The @f size (according to the @S) is %b @bs\n"
+ "The physical size of the device is %c @bs\n"
+ "Either the @S or the partition table is likely to be corrupt!\n",
+ PROMPT_ABORT, 0 },
+
+ /* Fragments not supported */
+ { PR_0_NO_FRAGMENTS,
+ "@S @b_size = %b, fragsize = %c.\n"
+ "This version of e2fsck does not support fragment sizes different\n"
+ "from the @b size.\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Bad blocks_per_group */
+ { PR_0_BLOCKS_PER_GROUP,
+ "@S @bs_per_group = %b, should have been %c\n",
+ PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
+
+ /* Bad first_data_block */
+ { PR_0_FIRST_DATA_BLOCK,
+ "@S first_data_@b = %b, should have been %c\n",
+ PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
+ /* Adding UUID to filesystem */
+ { PR_0_ADD_UUID,
+ "@f did not have a UUID; generating one.\n\n",
+ PROMPT_NONE, 0 },
+
+ /* Relocate hint */
+ { PR_0_RELOCATE_HINT,
+ "Note: if there is several inode or block bitmap blocks\n"
+ "which require relocation, or one part of the inode table\n"
+ "which must be moved, you may wish to try running e2fsck\n"
+ "with the '-b %S' option first. The problem may lie only\n"
+ "with the primary block group descriptor, and the backup\n"
+ "block group descriptor may be OK.\n\n",
+ PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
+
+ /* Miscellaneous superblock corruption */
+ { PR_0_MISC_CORRUPT_SUPER,
+ "Corruption found in @S. (%s = %N).\n",
+ PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
+
+ /* Error determing physical device size of filesystem */
+ { PR_0_GETSIZE_ERROR,
+ "Error determining size of the physical device: %m\n",
+ PROMPT_NONE, PR_FATAL },
+
/* Pass 1 errors */
+ /* Pass 1: Checking inodes, blocks, and sizes */
+ { PR_1_PASS_HEADER,
+ "Pass 1: Checking @is, @bs, and sizes\n",
+ PROMPT_NONE, 0 },
+
/* Root directory is not an inode */
{ PR_1_ROOT_NO_DIR, "@r is not a @d. ",
PROMPT_CLEAR, 0 },
/* Inode has incorrect i_size */
{ PR_1_BAD_I_SIZE,
"@i %i, i_size is %Is, @s %N. ",
- PROMPT_FIX, PR_PREEN_OK },
+ PROMPT_FIX, PR_PREEN_OK },
/* Inode has incorrect i_blocks */
{ PR_1_BAD_I_BLOCKS,
- "@i %i, i_blocks is %Ib, @s %N. ",
- PROMPT_FIX, PR_PREEN_OK },
+ "@i %i, i_@bs is %Ib, @s %N. ",
+ PROMPT_FIX, PR_PREEN_OK },
/* Illegal block number in inode */
{ PR_1_ILLEGAL_BLOCK_NUM,
/* Block number overlaps fs metadata */
{ PR_1_BLOCK_OVERLAPS_METADATA,
- "@b #%B (%b) overlaps filesystem metadata in @i %i. ",
+ "@b #%B (%b) overlaps @f metadata in @i %i. ",
PROMPT_CLEAR, PR_LATCH_BLOCK },
/* Inode has illegal blocks (latch question) */
"Bad @b @i has illegal @b(s). ",
PROMPT_CLEAR, 0 },
+ /* Duplicate or bad blocks in use! */
+ { PR_1_DUP_BLOCKS_PREENSTOP,
+ "Duplicate or bad @b in use!\n",
+ PROMPT_NONE, 0 },
+
+ /* Bad block used as bad block indirect block */
+ { PR_1_BBINODE_BAD_METABLOCK,
+ "Bad @b %b used as bad @b indirect @b?!?\n",
+ PROMPT_NONE, PR_AFTER_CODE, PR_1_BBINODE_BAD_METABLOCK_PROMPT },
+
+ /* Inconsistency can't be fixed prompt */
+ { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
+ "\nThis inconsistency can not be fixed with e2fsck; to fix it, use\n"
+ """dumpe2fs -b"" to dump out the bad @b "
+ "list and ""e2fsck -L filename""\n"
+ "to read it back in again.\n",
+ PROMPT_CONTINUE, PR_PREEN_NOMSG },
+
+ /* Bad primary block */
+ { PR_1_BAD_PRIMARY_BLOCK,
+ "\nIf the @b is really bad, the @f can not be fixed.\n",
+ PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
+
+ /* Bad primary block prompt */
+ { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
+ "You can clear the this @b (and hope for the best) from the\n"
+ "bad @b list and hope that @b is really OK, but there are no\n"
+ "guarantees.\n\n",
+ PROMPT_CLEAR, PR_PREEN_NOMSG },
+
+ /* Bad primary superblock */
+ { PR_1_BAD_PRIMARY_SUPERBLOCK,
+ "The primary @S (%b) is on the bad @b list.\n",
+ PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
+
+ /* Bad primary block group descriptors */
+ { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
+ "Block %b in the primary @g descriptors "
+ "is on the bad block list\n",
+ PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
+
+ /* Bad superblock in group */
+ { PR_1_BAD_SUPERBLOCK,
+ "Warning: Group %g's @S (%b) is bad.\n",
+ PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Bad block group descriptors in group */
+ { PR_1_BAD_GROUP_DESCRIPTORS,
+ "Warning: Group %d's copy of the @g descriptors has a bad "
+ "@b (%b).\n",
+ PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Block claimed for no reason */
+ { PR_1_PROGERR_CLAIMED_BLOCK,
+ "Programming error? @b #%b claimed for no reason in "
+ "process_bad_@b.\n",
+ PROMPT_NONE, PR_PREEN_OK },
+
+ /* Could not allocate blocks for relocating metadata */
+ { PR_1_RELOC_BLOCK_ALLOCATE,
+ "Could not allocate %N @b(s) for %s: %m\n",
+ PROMPT_NONE, PR_PREEN_OK },
+
+ /* Could not allocate memory during relocation process */
+ { PR_1_RELOC_MEMORY_ALLOCATE,
+ "Could not allocate @b buffer for relocating %s\n",
+ PROMPT_NONE, PR_PREEN_OK },
+
+ /* Relocating metadata group information from X to Y */
+ { PR_1_RELOC_FROM_TO,
+ "Relocating @g %g's %s from %b to %c...\n",
+ PROMPT_NONE, PR_PREEN_OK },
+
+ /* Relocating metatdata group information to X */
+ { PR_1_RELOC_TO,
+ "Relocating @g %g's %s to %c...\n",
+ PROMPT_NONE, PR_PREEN_OK },
+
+ /* Block read error during relocation process */
+ { PR_1_RELOC_READ_ERR,
+ "Warning: could not read @b %b of %s: %m\n",
+ PROMPT_NONE, PR_PREEN_OK },
+
+ /* Block write error during relocation process */
+ { PR_1_RELOC_WRITE_ERR,
+ "Warning: could not write @b %b for %s: %m\n",
+ PROMPT_NONE, PR_PREEN_OK },
+
+ /* Error allocating inode bitmap */
+ { PR_1_ALLOCATE_IBITMAP_ERROR,
+ "Error allocating @i @B (%N): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error allocating block bitmap */
+ { PR_1_ALLOCATE_BBITMAP_ERROR,
+ "Error allocating @b @B (%N): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error allocating icount structure */
+ { PR_1_ALLOCATE_ICOUNT,
+ "Error allocating icount link information: %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error allocating dbcount */
+ { PR_1_ALLOCATE_DBCOUNT,
+ "Error allocating directory @b array: %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error while scanning inodes */
+ { PR_1_ISCAN_ERROR,
+ "Error while scanning inodes (%i): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error while iterating over blocks */
+ { PR_1_BLOCK_ITERATE,
+ "Error while iterating over blocks in inode %i: %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error while storing inode count information */
+ { PR_1_ICOUNT_STORE,
+ "Error storing inode count information (inode=%i, count=%N): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error while storing directory block information */
+ { PR_1_ADD_DBLOCK,
+ "Error storing dir block information "
+ "(inode=%i, block=%b, num=%N): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error while reading inode (for clearing) */
+ { PR_1_READ_INODE,
+ "Error reading inode %i: %m\n",
+ PROMPT_NONE, PR_FATAL },
+
/* Pass 1b errors */
+ /* Pass 1B: Rescan for duplicate/bad blocks */
+ { PR_1B_PASS_HEADER,
+ "Duplicate @bs found... invoking duplicate @b passes.\n"
+ "Pass 1B: Rescan for duplicate/bad @bs\n",
+ PROMPT_NONE, 0 },
+
+ /* Duplicate/bad block(s) header */
+ { PR_1B_DUP_BLOCK_HEADER,
+ "Duplicate/bad @b(s) in @i %i:",
+ PROMPT_NONE, 0 },
+
+ /* Duplicate/bad block(s) in inode */
+ { PR_1B_DUP_BLOCK,
+ " %b",
+ PROMPT_NONE, PR_LATCH_DBLOCK },
+
+ /* Duplicate/bad block(s) end */
+ { PR_1B_DUP_BLOCK_END,
+ "\n",
+ PROMPT_NONE, 0 },
+
+ /* Error while scanning inodes */
+ { PR_1B_ISCAN_ERROR,
+ "Error while scanning inodes (%i): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error allocating inode bitmap */
+ { PR_1B_ALLOCATE_IBITMAP_ERROR,
+ "Error allocating @i @B (inode_dup_map): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+
+ /* Pass 1C: Scan directories for inodes with dup blocks. */
+ { PR_1C_PASS_HEADER,
+ "Pass 1C: Scan directories for @is with dup @bs.\n",
+ PROMPT_NONE, 0 },
+
+
+ /* Pass 1D: Reconciling duplicate blocks */
+ { PR_1D_PASS_HEADER,
+ "Pass 1D: Reconciling duplicate @bs\n",
+ PROMPT_NONE, 0 },
+
/* File has duplicate blocks */
- { PR_1B_DUP_FILE,
+ { PR_1D_DUP_FILE,
"File %Q (@i #%i, mod time %IM) \n"
" has %B duplicate @b(s), shared with %N file(s):\n",
- PROMPT_FIX, PR_MSG_ONLY },
+ PROMPT_NONE, 0 },
/* List of files sharing duplicate blocks */
- { PR_1B_DUP_FILE_LIST,
+ { PR_1D_DUP_FILE_LIST,
"\t%Q (@i #%i, mod time %IM)\n",
- PROMPT_FIX, PR_MSG_ONLY },
+ PROMPT_NONE, 0 },
/* File sharing blocks with filesystem metadata */
- { PR_1B_SHARE_METADATA,
- "\t<filesystem metadata>\n",
- PROMPT_FIX, PR_MSG_ONLY },
+ { PR_1D_SHARE_METADATA,
+ "\t<@f metadata>\n",
+ PROMPT_NONE, 0 },
+
+ /* Report of how many duplicate/bad inodes */
+ { PR_1D_NUM_DUP_INODES,
+ "(There are %N @is containing duplicate/bad @bs.)\n\n",
+ PROMPT_NONE, 0 },
+
+ /* Duplicated blocks already reassigned or cloned. */
+ { PR_1D_DUP_BLOCKS_DEALT,
+ "Duplicated @bs already reassigned or cloned.\n\n",
+ PROMPT_NONE, 0 },
+
+ /* Clone duplicate/bad blocks? */
+ { PR_1D_CLONE_QUESTION,
+ "", PROMPT_CLONE, PR_NO_OK },
+
+ /* Delete file? */
+ { PR_1D_DELETE_QUESTION,
+ "", PROMPT_DELETE, 0 },
+
+ /* Couldn't clone file (error) */
+ { PR_1D_CLONE_ERROR,
+ "Couldn't clone file: %m\n", PROMPT_NONE, 0 },
/* Pass 2 errors */
+ /* Pass 2: Checking directory structure */
+ { PR_2_PASS_HEADER,
+ "Pass 2: Checking @d structure\n",
+ PROMPT_NONE, 0 },
+
/* Bad inode number for '.' */
{ PR_2_BAD_INODE_DOT,
"Bad @i number for '.' in @d @i %i.\n",
"@i %i (%Q) is an @I @b device.\n",
PROMPT_CLEAR, 0 },
- /* Pass 3 errors */
+ /* Duplicate '.' entry */
+ { PR_2_DUP_DOT,
+ "@E is duplicate '.' @e.\n",
+ PROMPT_FIX, 0 },
+ /* Duplicate '..' entry */
+ { PR_2_DUP_DOT_DOT,
+ "@E is duplicate '..' @e.\n",
+ PROMPT_FIX, 0 },
+
+ /* Internal error: couldn't find dir_info */
+ { PR_2_NO_DIRINFO,
+ "Internal error: couldn't find dir_info for %i.\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Final rec_len is wrong */
+ { PR_2_FINAL_RECLEN,
+ "@E has rec_len of %dr, should be %N.\n",
+ PROMPT_FIX, 0 },
+
+ /* Error allocating icount structure */
+ { PR_2_ALLOCATE_ICOUNT,
+ "Error allocating icount structure: %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error iterating over directory blocks */
+ { PR_2_DBLIST_ITERATE,
+ "Error interating over directory blocks: %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error reading directory block */
+ { PR_2_READ_DIRBLOCK,
+ "Error reading directory block %b (inode %i): %m\n",
+ PROMPT_CONTINUE, 0 },
+
+ /* Error writing directory block */
+ { PR_2_WRITE_DIRBLOCK,
+ "Error writing directory block %b (inode %i): %m\n",
+ PROMPT_CONTINUE, 0 },
+
+ /* Error allocating new directory block */
+ { PR_2_ALLOC_DIRBOCK,
+ "Error allocating new directory block for inode %i (%s): %m\n",
+ PROMPT_NONE, 0 },
+
+ /* Error deallocating inode */
+ { PR_2_DEALLOC_INODE,
+ "Error deallocating inode %i: %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+
+ /* Pass 3 errors */
+
+ /* Pass 3: Checking directory connectivity */
+ { PR_3_PASS_HEADER,
+ "Pass 3: Checking @d connectivity\n",
+ PROMPT_NONE, 0 },
+
/* Root inode not allocated */
{ PR_3_NO_ROOT_INODE,
"@r not allocated. ",
"'..' in %Q (%i) is %P (%j), @s %q (%d).\n",
PROMPT_FIX, 0 },
+ /* Bad or non-existent /lost+found. Cannot reconnect */
+ { PR_3_NO_LPF,
+ "Bad or non-existent /@l. Cannot reconnect\n",
+ PROMPT_NONE, 0 },
+
+ /* Could not expand /lost+found */
+ { PR_3_CANT_EXPAND_LPF,
+ "Could not expand /@l: %m\n",
+ PROMPT_NONE, 0 },
+
+ /* Could not reconnect inode */
+ { PR_3_CANT_RECONNECT,
+ "Could not reconnect %i: %m\n",
+ PROMPT_NONE, 0 },
+
+ /* Error while trying to find /lost+found */
+ { PR_3_ERR_FIND_LPF,
+ "Error while trying to find /@l: %m\n",
+ PROMPT_NONE, 0 },
+
+ /* Error in ext2fs_new_block while creating /lost+found */
+ { PR_3_ERR_LPF_NEW_BLOCK,
+ "ext2fs_new_@b: %m while trying to create /@l @d\n",
+ PROMPT_NONE, 0 },
+
+ /* Error in ext2fs_new_inode while creating /lost+found */
+ { PR_3_ERR_LPF_NEW_INODE,
+ "ext2fs_new_@i: %m while trying to create /@l @d\n",
+ PROMPT_NONE, 0 },
+
+ /* Error in ext2fs_new_dir_block while creating /lost+found */
+ { PR_3_ERR_LPF_NEW_DIR_BLOCK,
+ "ext2fs_new_dir_@b: %m while creating new @d @b\n",
+ PROMPT_NONE, 0 },
+
+ /* Error while writing directory block for /lost+found */
+ { PR_3_ERR_LPF_WRITE_BLOCK,
+ "ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n",
+ PROMPT_NONE, 0 },
+
+ /* Error while adjusting inode count */
+ { PR_3_ADJUST_INODE,
+ "Error while adjusting @i count on @i %i\n",
+ PROMPT_NONE, 0 },
+
+ /* Couldn't fix parent directory -- error */
+ { PR_3_FIX_PARENT_ERR,
+ "Couldn't fix parent of @i %i: %m\n\n",
+ PROMPT_NONE, 0 },
+
+ /* Couldn't fix parent directory -- couldn't find it */
+ { PR_3_FIX_PARENT_NOFIND,
+ "Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n",
+ PROMPT_NONE, 0 },
+
+ /* Error allocating inode bitmap */
+ { PR_3_ALLOCATE_IBITMAP_ERROR,
+ "Error allocating @i @B (%N): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error creating root directory */
+ { PR_3_CREATE_ROOT_ERROR,
+ "Error creating root @d (%s): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Error creating lost and found directory */
+ { PR_3_CREATE_LPF_ERROR,
+ "Error creating /@l @d (%s): %m\n",
+ PROMPT_NONE, PR_FATAL },
+
/* Pass 4 errors */
+ /* Pass 4: Checking reference counts */
+ { PR_4_PASS_HEADER,
+ "Pass 4: Checking reference counts\n",
+ PROMPT_NONE, 0 },
+
/* Unattached zero-length inode */
{ PR_4_ZERO_LEN_INODE,
"@u @z @i %i. ",
{ PR_4_BAD_REF_COUNT,
"@i %i ref count is %Il, @s %N. ",
PROMPT_FIX, PR_PREEN_OK },
-
+
+ { PR_4_INCONSISTENT_COUNT,
+ "WARNING: PROGRAMMING BUG IN E2FSCK!\n"
+ "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
+ "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
+ "They should be the same!\n",
+ PROMPT_NONE, 0 },
+
+ /* Pass 5 errors */
+
+ /* Pass 5: Checking group summary information */
+ { PR_5_PASS_HEADER,
+ "Pass 5: Checking @g summary information\n",
+ PROMPT_NONE, 0 },
+
+ /* Padding at end of inode bitmap is not set. */
+ { PR_5_INODE_BMAP_PADDING,
+ "Padding at end of @i @B is not set. ",
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Padding at end of block bitmap is not set. */
+ { PR_5_BLOCK_BMAP_PADDING,
+ "Padding at end of @b @B is not set. ",
+ PROMPT_FIX, PR_PREEN_OK },
+
+ /* Block bitmap differences header */
+ { PR_5_BLOCK_BITMAP_HEADER,
+ "@b @B differences: ",
+ PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
+
+ /* Block not used, but marked in bitmap */
+ { PR_5_UNUSED_BLOCK,
+ " -%b",
+ PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Block used, but not marked used in bitmap */
+ { PR_5_BLOCK_USED,
+ " +%b",
+ PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Block bitmap differences end */
+ { PR_5_BLOCK_BITMAP_END,
+ "\n",
+ PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Inode bitmap differences header */
+ { PR_5_INODE_BITMAP_HEADER,
+ "@i @B differences: ",
+ PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Inode not used, but marked in bitmap */
+ { PR_5_UNUSED_INODE,
+ " -%i",
+ PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Inode used, but not marked used in bitmap */
+ { PR_5_INODE_USED,
+ " +%i",
+ PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Inode bitmap differences end */
+ { PR_5_INODE_BITMAP_END,
+ "\n",
+ PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Free inodes count for group wrong */
+ { PR_5_FREE_INODE_COUNT_GROUP,
+ "Free @is count wrong for @g #%g (%i, counted=%j).\n",
+ PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Directories count for group wrong */
+ { PR_5_FREE_DIR_COUNT_GROUP,
+ "Directories count wrong for @g #%g (%i, counted=%j).\n",
+ PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Free inodes count wrong */
+ { PR_5_FREE_INODE_COUNT,
+ "Free @is count wrong (%i, counted=%j).\n",
+ PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Free blocks count for group wrong */
+ { PR_5_FREE_BLOCK_COUNT_GROUP,
+ "Free @bs count wrong for @g #%g (%b, counted=%c).\n",
+ PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Free blocks count wrong */
+ { PR_5_FREE_BLOCK_COUNT,
+ "Free @bs count wrong (%b, counted=%c).\n",
+ PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
+
+ /* Programming error: bitmap endpoints don't match */
+ { PR_5_BMAP_ENDPOINTS,
+ "PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
+ "match calculated @B endpoints (%i, %j)\n",
+ PROMPT_NONE, PR_FATAL },
+
+ /* Internal error: fudging end of bitmap */
+ { PR_5_FUDGE_BITMAP_ERROR,
+ "Internal error: fudging end of bitmap (%N)\n",
+ PROMPT_NONE, PR_FATAL },
+
{ 0 }
};
* question for the set of problems, and all of the associated
* problems will be either fixed or not fixed.
*/
-char pr_latch[7]; /* Latch flags register */
-char pr_suppress[7]; /* Latch groups which are suppressed */
-int latch_question[7] = {
- PR_1_INODE_BLOCK_LATCH,
- PR_1_INODE_BBLOCK_LATCH
+static struct latch_descr pr_latch_info[] = {
+ { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
+ { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
+ { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
+ { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
+ { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
+ { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
+ { -1, 0, 0 },
};
-static struct e2fsck_problem *find_problem(int code)
+static const struct e2fsck_problem *find_problem(int code)
{
int i;
return 0;
}
-void reset_problem_latch(int mask)
+static struct latch_descr *find_latch(int code)
+{
+ int i;
+
+ for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
+ if (pr_latch_info[i].latch_code == code)
+ return &pr_latch_info[i];
+ }
+ return 0;
+}
+
+int end_problem_latch(e2fsck_t ctx, int mask)
+{
+ struct latch_descr *ldesc;
+ struct problem_context pctx;
+ int answer = -1;
+
+ ldesc = find_latch(mask);
+ if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
+ clear_problem_context(&pctx);
+ answer = fix_problem(ctx, ldesc->end_message, &pctx);
+ }
+ ldesc->flags &= ~(PRL_VARIABLE);
+ return answer;
+}
+
+int set_latch_flags(int mask, int setflags, int clearflags)
{
- pr_latch[PR_LATCH(mask)] = 0;
- pr_suppress[PR_LATCH(mask)] = 0;
+ struct latch_descr *ldesc;
+
+ ldesc = find_latch(mask);
+ if (!ldesc)
+ return -1;
+ ldesc->flags |= setflags;
+ ldesc->flags &= ~clearflags;
+ return 0;
}
-void suppress_latch_group(int mask, int value)
+int get_latch_flags(int mask, int *value)
{
- pr_suppress[PR_LATCH(mask)] = value;
+ struct latch_descr *ldesc;
+
+ ldesc = find_latch(mask);
+ if (!ldesc)
+ return -1;
+ *value = ldesc->flags;
+ return 0;
}
void clear_problem_context(struct problem_context *ctx)
ctx->group = -1;
}
-int fix_problem(ext2_filsys fs, int code, struct problem_context *ctx)
+int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
{
- struct e2fsck_problem *ptr;
- int def_yn, answer;
- int latch;
+ ext2_filsys fs = ctx->fs;
+ const struct e2fsck_problem *ptr;
+ struct latch_descr *ldesc = 0;
+ const char *message;
+ int def_yn, answer, ans;
int print_answer = 0;
int suppress = 0;
* latch question, if it exists
*/
if (ptr->flags & PR_LATCH_MASK) {
- latch = PR_LATCH(ptr->flags);
- if (latch_question[latch] && !pr_latch[latch])
- pr_latch[latch] = fix_problem(fs,
- latch_question[latch],
- ctx) + 1;
- if (pr_suppress[latch])
+ ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
+ if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
+ ans = fix_problem(ctx, ldesc->question, pctx);
+ if (ans == 1)
+ ldesc->flags |= PRL_YES;
+ if (ans == 0)
+ ldesc->flags |= PRL_NO;
+ ldesc->flags |= PRL_LATCHED;
+ }
+ if (ldesc->flags & PRL_SUPPRESS)
suppress++;
}
-
+ if ((ptr->flags & PR_PREEN_NOMSG) &&
+ (ctx->options & E2F_OPT_PREEN))
+ suppress++;
if (!suppress) {
- if (preen)
- printf("%s: ", device_name);
- print_e2fsck_message(fs, ptr->e2p_description, ctx, 1);
+ message = ptr->e2p_description;
+ if (ctx->options & E2F_OPT_PREEN) {
+ printf("%s: ", ctx->device_name);
+#if 0
+ if (ptr->e2p_preen_msg)
+ message = ptr->e2p_preen_msg;
+#endif
+ }
+ print_e2fsck_message(ctx, message, pctx, 1);
}
- if (!(ptr->flags & PR_PREEN_OK))
- preenhalt(fs);
+ if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
+ preenhalt(ctx);
- if (ptr->flags & PR_MSG_ONLY)
- return 1;
-
- if (preen) {
- answer = def_yn;
- print_answer = 1;
- } else if (ptr->flags & PR_LATCH_MASK) {
- latch = PR_LATCH(ptr->flags);
- if (!pr_latch[latch])
- pr_latch[latch] =
- ask(prompt[(int) ptr->prompt], def_yn) + 1;
+ if (ptr->flags & PR_FATAL)
+ fatal_error(0);
+
+ if (ptr->prompt == PROMPT_NONE) {
+ if (ptr->flags & PR_NOCOLLATE)
+ answer = -1;
else
- print_answer = 1;
- answer = pr_latch[latch] - 1;
- } else
- answer = ask(prompt[(int) ptr->prompt], def_yn);
- if (!answer && !(ptr->flags & PR_NO_OK))
- ext2fs_unmark_valid(fs);
+ answer = def_yn;
+ } else {
+ if (ctx->options & E2F_OPT_PREEN) {
+ answer = def_yn;
+ if (!(ptr->flags & PR_PREEN_NOMSG))
+ print_answer = 1;
+ } else if ((ptr->flags & PR_LATCH_MASK) &&
+ (ldesc->flags & (PRL_YES | PRL_NO))) {
+ if (!suppress)
+ print_answer = 1;
+ if (ldesc->flags & PRL_YES)
+ answer = 1;
+ else
+ answer = 0;
+ } else
+ answer = ask(ctx, prompt[(int) ptr->prompt], def_yn);
+ if (!answer && !(ptr->flags & PR_NO_OK))
+ ext2fs_unmark_valid(fs);
- if (print_answer)
- printf("%s.\n",
- answer ? preen_msg[(int) ptr->prompt] : "IGNORED");
+ if (print_answer)
+ printf("%s.\n", answer ?
+ preen_msg[(int) ptr->prompt] : "IGNORED");
+ }
+
+ if (ptr->flags & PR_AFTER_CODE)
+ (void) fix_problem(ctx, ptr->second_code, pctx);
+
+ if (ptr->prompt == PROMPT_ABORT)
+ fatal_error(0);
+
return answer;
}
* %End-Header%
*/
+typedef __u32 problem_t;
+
struct problem_context {
+ errcode_t errcode;
ino_t ino, ino2, dir;
struct ext2_inode *inode;
struct ext2_dir_entry *dirent;
- blk_t blk;
+ blk_t blk, blk2;
int blkcount, group;
__u32 num;
+ const char *str;
};
struct e2fsck_problem {
- int e2p_code;
+ problem_t e2p_code;
const char * e2p_description;
char prompt;
short flags;
+ problem_t second_code;
+};
+
+struct latch_descr {
+ int latch_code;
+ problem_t question;
+ problem_t end_message;
+ int flags;
};
#define PR_PREEN_OK 0x0001 /* Don't need to do preenhalt */
#define PR_NO_OK 0x0002 /* If user answers no, don't make fs invalid */
#define PR_NO_DEFAULT 0x0004 /* Default to no */
#define PR_MSG_ONLY 0x0008 /* Print message only */
+#define PR_FATAL 0x0080 /* Fatal error */
+#define PR_AFTER_CODE 0x0100 /* After asking the first question, */
+ /* ask another */
+#define PR_PREEN_NOMSG 0x0200 /* Don't print a message if we're preening */
+#define PR_NOCOLLATE 0x0400 /* Don't collate answers for this latch */
/*
* We define a set of "latch groups"; these are problems which are
#define PR_LATCH_MASK 0x0070 /* Latch mask */
#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
+#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */
+#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */
+#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */
+#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */
#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
+/*
+ * Latch group descriptor flags
+ */
+#define PRL_YES 0x0001 /* Answer yes */
+#define PRL_NO 0x0002 /* Answer no */
+#define PRL_LATCHED 0x0004 /* The latch group is latched */
+#define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */
+
+#define PRL_VARIABLE 0x000f /* All the flags that need to be reset */
+
/*
* Pre-Pass 1 errors
*/
/* Inode table not in group */
#define PR_0_ITABLE_NOT_GROUP 0x000003
+/* Superblock corrupt */
+#define PR_0_SB_CORRUPT 0x000004
+
+/* Filesystem size is wrong */
+#define PR_0_FS_SIZE_WRONG 0x000005
+
+/* Fragments not supported */
+#define PR_0_NO_FRAGMENTS 0x000006
+
+/* Bad blocks_per_group */
+#define PR_0_BLOCKS_PER_GROUP 0x000007
+
+/* Bad first_data_block */
+#define PR_0_FIRST_DATA_BLOCK 0x000008
+
+/* Adding UUID to filesystem */
+#define PR_0_ADD_UUID 0x000009
+
+/* Relocate hint */
+#define PR_0_RELOCATE_HINT 0x00000A
+
+/* Miscellaneous superblock corruption */
+#define PR_0_MISC_CORRUPT_SUPER 0x00000B
+
+/* Error determing physical device size of filesystem */
+#define PR_0_GETSIZE_ERROR 0x00000C
+
/*
* Pass 1 errors
*/
+/* Pass 1: Checking inodes, blocks, and sizes */
+#define PR_1_PASS_HEADER 0x010000
+
/* Root directory is not an inode */
-#define PR_1_ROOT_NO_DIR 0x010001
+#define PR_1_ROOT_NO_DIR 0x010001
/* Root directory has dtime set */
-#define PR_1_ROOT_DTIME 0x010002
+#define PR_1_ROOT_DTIME 0x010002
/* Reserved inode has bad mode */
-#define PR_1_RESERVED_BAD_MODE 0x010003
+#define PR_1_RESERVED_BAD_MODE 0x010003
/* Deleted inode has zero dtime */
-#define PR_1_ZERO_DTIME 0x010004
+#define PR_1_ZERO_DTIME 0x010004
/* Inode in use, but dtime set */
-#define PR_1_SET_DTIME 0x010005
+#define PR_1_SET_DTIME 0x010005
/* Zero-length directory */
-#define PR_1_ZERO_LENGTH_DIR 0x010006
+#define PR_1_ZERO_LENGTH_DIR 0x010006
/* Block bitmap conflicts with some other fs block */
-#define PR_1_BB_CONFLICT 0x010007
+#define PR_1_BB_CONFLICT 0x010007
/* Inode bitmap conflicts with some other fs block */
-#define PR_1_IB_CONFLICT 0x010008
+#define PR_1_IB_CONFLICT 0x010008
/* Inode table conflicts with some other fs block */
-#define PR_1_ITABLE_CONFLICT 0x010009
+#define PR_1_ITABLE_CONFLICT 0x010009
/* Block bitmap is on a bad block */
-#define PR_1_BB_BAD_BLOCK 0x01000A
+#define PR_1_BB_BAD_BLOCK 0x01000A
/* Inode bitmap is on a bad block */
-#define PR_1_IB_BAD_BLOCK 0x01000B
+#define PR_1_IB_BAD_BLOCK 0x01000B
/* Inode has incorrect i_size */
-#define PR_1_BAD_I_SIZE 0x01000C
+#define PR_1_BAD_I_SIZE 0x01000C
/* Inode has incorrect i_blocks */
-#define PR_1_BAD_I_BLOCKS 0x01000D
+#define PR_1_BAD_I_BLOCKS 0x01000D
/* Illegal block number in inode */
-#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E
+#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E
/* Block number overlaps fs metadata */
#define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F
/* Inode has illegal blocks (latch question) */
-#define PR_1_INODE_BLOCK_LATCH 0x010010
+#define PR_1_INODE_BLOCK_LATCH 0x010010
/* Too many bad blocks in inode */
-#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011
+#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011
/* Illegal block number in bad block inode */
-#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012
+#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012
/* Bad block inode has illegal blocks (latch question) */
-#define PR_1_INODE_BBLOCK_LATCH 0x010013
+#define PR_1_INODE_BBLOCK_LATCH 0x010013
+
+/* Duplicate or bad blocks in use! */
+#define PR_1_DUP_BLOCKS_PREENSTOP 0x010014
+
+/* Bad block used as bad block indirect block */
+#define PR_1_BBINODE_BAD_METABLOCK 0x010015
+
+/* Inconsistency can't be fixed prompt */
+#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
+
+/* Bad primary block */
+#define PR_1_BAD_PRIMARY_BLOCK 0x0100017
+
+/* Bad primary block prompt */
+#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x0100018
+
+/* Bad primary superblock */
+#define PR_1_BAD_PRIMARY_SUPERBLOCK 0x0100019
+
+/* Bad primary block group descriptors */
+#define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x010001A
+
+/* Bad superblock in group */
+#define PR_1_BAD_SUPERBLOCK 0x010001B
+
+/* Bad block group descriptors in group */
+#define PR_1_BAD_GROUP_DESCRIPTORS 0x010001C
+
+/* Block claimed for no reason */
+#define PR_1_PROGERR_CLAIMED_BLOCK 0x010001D
+
+/* Could not allocate blocks for relocating metadata */
+#define PR_1_RELOC_BLOCK_ALLOCATE 0x010001E
+
+/* Could not allocate memory during relocation process */
+#define PR_1_RELOC_MEMORY_ALLOCATE 0x010001F
+
+/* Relocating metadata group information from X to Y */
+#define PR_1_RELOC_FROM_TO 0x0100020
+
+/* Relocating metatdata group information to X */
+#define PR_1_RELOC_TO 0x0100021
+
+/* Block read error during relocation process */
+#define PR_1_RELOC_READ_ERR 0x0100022
+
+/* Block write error during relocation process */
+#define PR_1_RELOC_WRITE_ERR 0x0100023
+
+/* Error allocating inode bitmap */
+#define PR_1_ALLOCATE_IBITMAP_ERROR 0x0100024
+
+/* Error allocating block bitmap */
+#define PR_1_ALLOCATE_BBITMAP_ERROR 0x0100025
+
+/* Error allocating icount structure */
+#define PR_1_ALLOCATE_ICOUNT 0x0100026
+
+/* Error allocating dbcount */
+#define PR_1_ALLOCATE_DBCOUNT 0x0100027
+
+/* Error while scanning inodes */
+#define PR_1_ISCAN_ERROR 0x0100028
+
+/* Error while iterating over blocks */
+#define PR_1_BLOCK_ITERATE 0x0100029
+
+/* Error while storing inode count information */
+#define PR_1_ICOUNT_STORE 0x010002A
+
+/* Error while storing directory block information */
+#define PR_1_ADD_DBLOCK 0x010002B
+
+/* Error while reading inode (for clearing) */
+#define PR_1_READ_INODE 0x010002C
+
/*
* Pass 1b errors
*/
+/* Pass 1B: Rescan for duplicate/bad blocks */
+#define PR_1B_PASS_HEADER 0x011000
+
+/* Duplicate/bad block(s) header */
+#define PR_1B_DUP_BLOCK_HEADER 0x011001
+
+/* Duplicate/bad block(s) in inode */
+#define PR_1B_DUP_BLOCK 0x011002
+
+/* Duplicate/bad block(s) end */
+#define PR_1B_DUP_BLOCK_END 0x011003
+
+/* Error while scanning inodes */
+#define PR_1B_ISCAN_ERROR 0x011004
+
+/* Error allocating inode bitmap */
+#define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005
+
+
+/* Pass 1C: Scan directories for inodes with dup blocks. */
+#define PR_1C_PASS_HEADER 0x012000
+
+
+/* Pass 1D: Reconciling duplicate blocks */
+#define PR_1D_PASS_HEADER 0x013000
+
/* File has duplicate blocks */
-#define PR_1B_DUP_FILE 0x011001
+#define PR_1D_DUP_FILE 0x013001
/* List of files sharing duplicate blocks */
-#define PR_1B_DUP_FILE_LIST 0x011002
+#define PR_1D_DUP_FILE_LIST 0x013002
/* File sharing blocks with filesystem metadata */
-#define PR_1B_SHARE_METADATA 0x011003
+#define PR_1D_SHARE_METADATA 0x013003
+
+/* Report of how many duplicate/bad inodes */
+#define PR_1D_NUM_DUP_INODES 0x013004
+
+/* Duplicated blocks already reassigned or cloned. */
+#define PR_1D_DUP_BLOCKS_DEALT 0x013005
+
+/* Clone duplicate/bad blocks? */
+#define PR_1D_CLONE_QUESTION 0x013006
+
+/* Delete file? */
+#define PR_1D_DELETE_QUESTION 0x013007
+/* Couldn't clone file (error) */
+#define PR_1D_CLONE_ERROR 0x013008
+
/*
* Pass 2 errors
*/
+/* Pass 2: Checking directory structure */
+#define PR_2_PASS_HEADER 0x020000
+
/* Bad inode number for '.' */
#define PR_2_BAD_INODE_DOT 0x020001
/* Illegal block device in inode */
#define PR_2_BAD_BLOCK_DEV 0x020019
+/* Duplicate '.' entry */
+#define PR_2_DUP_DOT 0x02001A
+
+/* Duplicate '..' entry */
+#define PR_2_DUP_DOT_DOT 0x02001B
+
+/* Internal error: couldn't find dir_info */
+#define PR_2_NO_DIRINFO 0x02001C
+
+/* Final rec_len is wrong */
+#define PR_2_FINAL_RECLEN 0x02001D
+
+/* Error allocating icount structure */
+#define PR_2_ALLOCATE_ICOUNT 0x02001E
+
+/* Error iterating over directory blocks */
+#define PR_2_DBLIST_ITERATE 0x02001F
+
+/* Error reading directory block */
+#define PR_2_READ_DIRBLOCK 0x020020
+
+/* Error writing directory block */
+#define PR_2_WRITE_DIRBLOCK 0x020021
+
+/* Error allocating new directory block */
+#define PR_2_ALLOC_DIRBOCK 0x020022
+
+/* Error deallocating inode */
+#define PR_2_DEALLOC_INODE 0x020023
+
/*
* Pass 3 errors
*/
+/* Pass 3: Checking directory connectivity */
+#define PR_3_PASS_HEADER 0x030000
+
/* Root inode not allocated */
-#define PR_3_NO_ROOT_INODE 0x030001
+#define PR_3_NO_ROOT_INODE 0x030001
/* No room in lost+found */
-#define PR_3_EXPAND_LF_DIR 0x030002
+#define PR_3_EXPAND_LF_DIR 0x030002
/* Unconnected directory inode */
-#define PR_3_UNCONNECTED_DIR 0x030003
+#define PR_3_UNCONNECTED_DIR 0x030003
/* /lost+found not found */
-#define PR_3_NO_LF_DIR 0x030004
+#define PR_3_NO_LF_DIR 0x030004
/* .. entry is incorrect */
-#define PR_3_BAD_DOT_DOT 0x030005
+#define PR_3_BAD_DOT_DOT 0x030005
+
+/* Bad or non-existent /lost+found. Cannot reconnect */
+#define PR_3_NO_LPF 0x030006
+
+/* Could not expand /lost+found */
+#define PR_3_CANT_EXPAND_LPF 0x030007
+
+/* Could not reconnect inode */
+#define PR_3_CANT_RECONNECT 0x030008
+
+/* Error while trying to find /lost+found */
+#define PR_3_ERR_FIND_LPF 0x030009
+
+/* Error in ext2fs_new_block while creating /lost+found */
+#define PR_3_ERR_LPF_NEW_BLOCK 0x03000A
+/* Error in ext2fs_new_inode while creating /lost+found */
+#define PR_3_ERR_LPF_NEW_INODE 0x03000B
+
+/* Error in ext2fs_new_dir_block while creating /lost+found */
+#define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C
+
+/* Error while writing directory block for /lost+found */
+#define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D
+
+/* Error while adjusting inode count */
+#define PR_3_ADJUST_INODE 0x03000E
+
+/* Couldn't fix parent directory -- error */
+#define PR_3_FIX_PARENT_ERR 0x03000F
+
+/* Couldn't fix parent directory -- couldn't find it */
+#define PR_3_FIX_PARENT_NOFIND 0x030010
+
+/* Error allocating inode bitmap */
+#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011
+
+/* Error creating root directory */
+#define PR_3_CREATE_ROOT_ERROR 0x030012
+
+/* Error creating lost and found directory */
+#define PR_3_CREATE_LPF_ERROR 0x030013
/*
* Pass 4 errors
*/
+/* Pass 4: Checking reference counts */
+#define PR_4_PASS_HEADER 0x040000
+
/* Unattached zero-length inode */
#define PR_4_ZERO_LEN_INODE 0x040001
/* Inode ref count wrong */
#define PR_4_BAD_REF_COUNT 0x040003
+/* Inconsistent inode count information cached */
+#define PR_4_INCONSISTENT_COUNT 0x040004
+
/*
* Pass 5 errors
*/
+/* Pass 5: Checking group summary information */
+#define PR_5_PASS_HEADER 0x050000
+
+/* Padding at end of inode bitmap is not set. */
+#define PR_5_INODE_BMAP_PADDING 0x050001
+
+/* Padding at end of block bitmap is not set. */
+#define PR_5_BLOCK_BMAP_PADDING 0x050002
+
+/* Block bitmap differences header */
+#define PR_5_BLOCK_BITMAP_HEADER 0x050003
+
+/* Block not used, but marked in bitmap */
+#define PR_5_UNUSED_BLOCK 0x050004
+
+/* Block used, but not marked used in bitmap */
+#define PR_5_BLOCK_USED 0x050005
+
+/* Block bitmap differences end */
+#define PR_5_BLOCK_BITMAP_END 0x050006
+
+/* Inode bitmap differences header */
+#define PR_5_INODE_BITMAP_HEADER 0x050007
+
+/* Inode not used, but marked in bitmap */
+#define PR_5_UNUSED_INODE 0x050008
+
+/* Inode used, but not marked used in bitmap */
+#define PR_5_INODE_USED 0x050009
+
+/* Inode bitmap differences end */
+#define PR_5_INODE_BITMAP_END 0x05000A
+
+/* Free inodes count for group wrong */
+#define PR_5_FREE_INODE_COUNT_GROUP 0x05000B
+
+/* Directories count for group wrong */
+#define PR_5_FREE_DIR_COUNT_GROUP 0x05000C
+
+/* Free inodes count wrong */
+#define PR_5_FREE_INODE_COUNT 0x05000D
+
+/* Free blocks count for group wrong */
+#define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E
+
+/* Free blocks count wrong */
+#define PR_5_FREE_BLOCK_COUNT 0x05000F
+
+/* Programming error: bitmap endpoints don't match */
+#define PR_5_BMAP_ENDPOINTS 0x050010
+
+/* Internal error: fudging end of bitmap */
+#define PR_5_FUDGE_BITMAP_ERROR 0x050011
+
/*
* Function declarations
*/
-int fix_problem(ext2_filsys fs, int code, struct problem_context *ctx);
-void reset_problem_latch(int mask);
-void suppress_latch_group(int mask, int value);
+int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
+int end_problem_latch(e2fsck_t ctx, int mask);
+int set_latch_flags(int mask, int setflags, int clearflags);
+int get_latch_flags(int mask, int *value);
void clear_problem_context(struct problem_context *ctx);
/* message.c */
-void print_e2fsck_message(ext2_filsys fs, const char *msg,
- struct problem_context *ctx, int first);
+void print_e2fsck_message(e2fsck_t ctx, const char *msg,
+ struct problem_context *pctx, int first);
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
}
-void print_resource_track(struct resource_track *track)
+static void print_resource_track(struct resource_track *track)
{
struct rusage r;
struct timeval time_end;
--- /dev/null
+/*
+ * e2fsck.c - superblock checks
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <termios.h>
+#include <time.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#include <unistd.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#endif
+#include <sys/ioctl.h>
+#include <malloc.h>
+
+#include "uuid/uuid.h"
+#include "e2fsck.h"
+#include "problem.h"
+#include "../version.h"
+
+#define MIN_CHECK 1
+#define MAX_CHECK 2
+
+static void check_super_value(e2fsck_t ctx, const char *descr,
+ unsigned long value, int flags,
+ unsigned long min, unsigned long max)
+{
+ struct problem_context pctx;
+
+ if (((flags & MIN_CHECK) && (value < min)) ||
+ ((flags & MAX_CHECK) && (value > max))) {
+ clear_problem_context(&pctx);
+ pctx.num = value;
+ pctx.str = descr;
+ fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
+ fatal_error(0); /* never get here! */
+ }
+}
+
+void check_super_block(e2fsck_t ctx)
+{
+ ext2_filsys fs = ctx->fs;
+ blk_t first_block, last_block;
+ struct ext2fs_sb *s = (struct ext2fs_sb *) fs->super;
+ blk_t blocks_per_group = fs->super->s_blocks_per_group;
+ int i;
+ blk_t should_be;
+ struct problem_context pctx;
+
+ ctx->invalid_inode_bitmap_flag = allocate_memory(sizeof(int) *
+ fs->group_desc_count,
+ "invalid_inode_bitmap");
+ ctx->invalid_block_bitmap_flag = allocate_memory(sizeof(int) *
+ fs->group_desc_count,
+ "invalid_block_bitmap");
+ ctx->invalid_inode_table_flag = allocate_memory(sizeof(int) *
+ fs->group_desc_count,
+ "invalid_inode_table");
+
+ clear_problem_context(&pctx);
+
+ /*
+ * Verify the super block constants...
+ */
+ check_super_value(ctx, "inodes_count", s->s_inodes_count,
+ MIN_CHECK, 1, 0);
+ check_super_value(ctx, "blocks_count", s->s_blocks_count,
+ MIN_CHECK, 1, 0);
+ check_super_value(ctx, "first_data_block", s->s_first_data_block,
+ MAX_CHECK, 0, s->s_blocks_count);
+ check_super_value(ctx, "log_frag_size", s->s_log_frag_size,
+ MAX_CHECK, 0, 2);
+ check_super_value(ctx, "log_block_size", s->s_log_block_size,
+ MIN_CHECK | MAX_CHECK, s->s_log_frag_size,
+ 2);
+ check_super_value(ctx, "frags_per_group", s->s_frags_per_group,
+ MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
+ check_super_value(ctx, "blocks_per_group", s->s_blocks_per_group,
+ MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
+ check_super_value(ctx, "inodes_per_group", s->s_inodes_per_group,
+ MIN_CHECK, 1, 0);
+ check_super_value(ctx, "r_blocks_count", s->s_r_blocks_count,
+ MAX_CHECK, 0, s->s_blocks_count);
+
+ pctx.errcode = ext2fs_get_device_size(ctx->filesystem_name,
+ EXT2_BLOCK_SIZE(s),
+ &should_be);
+ if (pctx.errcode) {
+ fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
+ fatal_error(0);
+ }
+ if (should_be < s->s_blocks_count) {
+ pctx.blk = s->s_blocks_count;
+ pctx.blk2 = should_be;
+ if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx))
+ fatal_error(0);
+ }
+
+ if (s->s_log_block_size != s->s_log_frag_size) {
+ pctx.blk = EXT2_BLOCK_SIZE(s);
+ pctx.blk2 = EXT2_FRAG_SIZE(s);
+ fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
+ fatal_error(0);
+ }
+
+ should_be = s->s_frags_per_group /
+ (s->s_log_block_size - s->s_log_frag_size + 1);
+ if (s->s_blocks_per_group != should_be) {
+ pctx.blk = s->s_blocks_per_group;
+ pctx.blk2 = should_be;
+ fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
+ fatal_error(0);
+ }
+
+ should_be = (s->s_log_block_size == 0) ? 1 : 0;
+ if (s->s_first_data_block != should_be) {
+ pctx.blk = s->s_first_data_block;
+ pctx.blk2 = should_be;
+ fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
+ fatal_error(0);
+ }
+
+ /*
+ * Verify the group descriptors....
+ */
+ first_block = fs->super->s_first_data_block;
+ last_block = first_block + blocks_per_group;
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ pctx.group = i;
+
+ if (i == fs->group_desc_count - 1)
+ last_block = fs->super->s_blocks_count;
+ if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
+ (fs->group_desc[i].bg_block_bitmap >= last_block)) {
+ pctx.blk = fs->group_desc[i].bg_block_bitmap;
+ if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx)) {
+ fs->group_desc[i].bg_block_bitmap = 0;
+ ctx->invalid_block_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
+ }
+ }
+ if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
+ (fs->group_desc[i].bg_inode_bitmap >= last_block)) {
+ pctx.blk = fs->group_desc[i].bg_inode_bitmap;
+ if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx)) {
+ fs->group_desc[i].bg_inode_bitmap = 0;
+ ctx->invalid_inode_bitmap_flag[i]++;
+ ctx->invalid_bitmaps++;
+ }
+ }
+ if ((fs->group_desc[i].bg_inode_table < first_block) ||
+ ((fs->group_desc[i].bg_inode_table +
+ fs->inode_blocks_per_group - 1) >= last_block)) {
+ pctx.blk = fs->group_desc[i].bg_inode_table;
+ if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx)) {
+ fs->group_desc[i].bg_inode_table = 0;
+ ctx->invalid_inode_table_flag[i]++;
+ ctx->invalid_bitmaps++;
+ }
+ }
+ first_block += fs->super->s_blocks_per_group;
+ last_block += fs->super->s_blocks_per_group;
+ }
+ /*
+ * If we have invalid bitmaps, set the error state of the
+ * filesystem.
+ */
+ if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
+ fs->super->s_state &= ~EXT2_VALID_FS;
+ ext2fs_mark_super_dirty(fs);
+ }
+
+ /*
+ * If the UUID field isn't assigned, assign it.
+ */
+ if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(s->s_uuid)) {
+ clear_problem_context(&pctx);
+ if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
+ uuid_generate(s->s_uuid);
+ ext2fs_mark_super_dirty(fs);
+ }
+ }
+ return;
+}
+
}
}
-static void swap_inodes(ext2_filsys fs)
+static void swap_inodes(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
int i, group;
ino_t ino = 1;
char *buf, *block_buf;
inode = (struct ext2_inode *) buf;
for (i=0; i < fs->super->s_inodes_per_group;
i++, ino++, inode++) {
- stashed_ino = ino;
- stashed_inode = inode;
+ ctx->stashed_ino = ino;
+ ctx->stashed_inode = inode;
if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
ext2fs_swap_inode(fs, inode, inode, 0);
fs->get_blocks = 0;
}
-void swap_filesys(ext2_filsys fs)
+void swap_filesys(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
struct resource_track rtrack;
init_resource_track(&rtrack);
- if (!preen)
+ if (!(ctx->options & E2F_OPT_PREEN))
printf("Pass 0: Doing byte-swap of filesystem\n");
#ifdef MTRACE
fprintf(stderr, "%s: the filesystem must be freshly "
"checked using fsck\n"
"and not mounted before trying to "
- "byte-swap it.\n", device_name);
+ "byte-swap it.\n", ctx->device_name);
fatal_error(0);
}
if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
}
- swap_inodes(fs);
+ swap_inodes(ctx);
if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
fs->flags |= EXT2_FLAG_SWAP_BYTES;
fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
EXT2_FLAG_SWAP_BYTES_WRITE);
ext2fs_flush(fs);
- if (tflag > 1) {
- printf("Byte swap: ");
- print_resource_track(&rtrack);
- }
+ if (ctx->options & E2F_OPT_TIME2)
+ print_resource_track("Byte swap", &rtrack);
}
--- /dev/null
+/*
+ * unix.c - The unix-specific code for e2fsck
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <termios.h>
+#include <time.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#include <unistd.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#endif
+#include <sys/ioctl.h>
+#include <malloc.h>
+
+#include "et/com_err.h"
+#include "e2fsck.h"
+#include "problem.h"
+#include "../version.h"
+
+extern int isatty(int);
+
+/* Command line options */
+static int blocksize = 0;
+static int swapfs = 0;
+static int normalize_swapfs = 0;
+static int cflag = 0; /* check disk */
+static int show_version_only = 0;
+static int force = 0;
+static int verbose = 0;
+
+static int replace_bad_blocks = 0;
+static char *bad_blocks_file = 0;
+
+static int possible_block_sizes[] = { 1024, 2048, 4096, 8192, 0};
+
+static int root_filesystem = 0;
+static int read_only_root = 0;
+
+int restart_e2fsck = 0;
+
+static void usage(e2fsck_t ctx)
+{
+ fprintf(stderr,
+ "Usage: %s [-panyrcdfvstFSV] [-b superblock] [-B blocksize]\n"
+ "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
+ "\t\t[-l|-L bad_blocks_file] device\n", ctx->program_name);
+ exit(FSCK_USAGE);
+}
+
+static void show_stats(e2fsck_t ctx)
+{
+ ext2_filsys fs = ctx->fs;
+ int inodes, inodes_used, blocks, blocks_used;
+ int dir_links;
+ int num_files, num_links;
+ int frag_percent;
+
+ dir_links = 2 * ctx->fs_directory_count - 1;
+ num_files = ctx->fs_total_count - dir_links;
+ num_links = ctx->fs_links_count - dir_links;
+ inodes = fs->super->s_inodes_count;
+ inodes_used = (fs->super->s_inodes_count -
+ fs->super->s_free_inodes_count);
+ blocks = fs->super->s_blocks_count;
+ blocks_used = (fs->super->s_blocks_count -
+ fs->super->s_free_blocks_count);
+
+ frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
+ frag_percent = (frag_percent + 5) / 10;
+
+ if (!verbose) {
+ printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
+ ctx->device_name, inodes_used, inodes,
+ frag_percent / 10, frag_percent % 10,
+ blocks_used, blocks);
+ return;
+ }
+ printf ("\n%8d inode%s used (%d%%)\n", inodes_used,
+ (inodes_used != 1) ? "s" : "",
+ 100 * inodes_used / inodes);
+ printf ("%8d non-contiguous inodes (%0d.%d%%)\n",
+ ctx->fs_fragmented, frag_percent / 10, frag_percent % 10);
+ printf (" # of inodes with ind/dind/tind blocks: %d/%d/%d\n",
+ ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
+ printf ("%8d block%s used (%d%%)\n"
+ "%8d bad block%s\n", blocks_used,
+ (blocks_used != 1) ? "s" : "",
+ 100 * blocks_used / blocks, ctx->fs_badblocks_count,
+ ctx->fs_badblocks_count != 1 ? "s" : "");
+ printf ("\n%8d regular file%s\n"
+ "%8d director%s\n"
+ "%8d character device file%s\n"
+ "%8d block device file%s\n"
+ "%8d fifo%s\n"
+ "%8d link%s\n"
+ "%8d symbolic link%s (%d fast symbolic link%s)\n"
+ "%8d socket%s\n"
+ "--------\n"
+ "%8d file%s\n",
+ ctx->fs_regular_count,
+ (ctx->fs_regular_count != 1) ? "s" : "",
+ ctx->fs_directory_count,
+ (ctx->fs_directory_count != 1) ? "ies" : "y",
+ ctx->fs_chardev_count,
+ (ctx->fs_chardev_count != 1) ? "s" : "",
+ ctx->fs_blockdev_count,
+ (ctx->fs_blockdev_count != 1) ? "s" : "",
+ ctx->fs_fifo_count,
+ (ctx->fs_fifo_count != 1) ? "s" : "",
+ ctx->fs_links_count - dir_links,
+ ((ctx->fs_links_count - dir_links) != 1) ? "s" : "",
+ ctx->fs_symlinks_count,
+ (ctx->fs_symlinks_count != 1) ? "s" : "",
+ ctx->fs_fast_symlinks_count,
+ (ctx->fs_fast_symlinks_count != 1) ? "s" : "",
+ ctx->fs_sockets_count, (ctx->fs_sockets_count != 1) ? "s" : "",
+ ctx->fs_total_count - dir_links,
+ ((ctx->fs_total_count - dir_links) != 1) ? "s" : "");
+}
+
+static void check_mount(e2fsck_t ctx)
+{
+ errcode_t retval;
+ int mount_flags, cont, fd;
+
+ retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
+ if (retval) {
+ com_err("ext2fs_check_if_mount", retval,
+ "while determining whether %s is mounted.",
+ ctx->filesystem_name);
+ return;
+ }
+ if (!(mount_flags & EXT2_MF_MOUNTED))
+ return;
+
+#if (defined(__linux__) && defined(HAVE_MNTENT_H))
+ /*
+ * If the root is mounted read-only, then /etc/mtab is
+ * probably not correct; so we won't issue a warning based on
+ * it.
+ */
+ fd = open(MOUNTED, O_RDWR);
+ if (fd < 0) {
+ if (errno == EROFS)
+ return;
+ } else
+ close(fd);
+#endif
+
+ if (ctx->options & E2F_OPT_READONLY) {
+ printf("Warning! %s is mounted.\n", ctx->device_name);
+ return;
+ }
+
+ printf("%s is mounted.\n\n", ctx->device_name);
+ printf("\a\a\a\aWARNING!!! Running e2fsck on a mounted filesystem "
+ "may cause\nSEVERE filesystem damage.\a\a\a\n\n");
+ if (isatty (0) && isatty (1))
+ cont = ask_yn("Do you really want to continue", -1);
+ else
+ cont = 0;
+ if (!cont) {
+ printf ("check aborted.\n");
+ exit (0);
+ }
+ return;
+}
+
+static void sync_disks(NOARGS)
+{
+ sync();
+ sync();
+ sleep(1);
+ sync();
+}
+
+/*
+ * This routine checks to see if a filesystem can be skipped; if so,
+ * it will exit with E2FSCK_OK. Under some conditions it will print a
+ * message explaining why a check is being forced.
+ */
+static void check_if_skip(e2fsck_t ctx)
+{
+ ext2_filsys fs = ctx->fs;
+ const char *reason = NULL;
+
+ if (force || bad_blocks_file || cflag || swapfs)
+ return;
+
+ if (fs->super->s_state & EXT2_ERROR_FS)
+ reason = "contains a file system with errors";
+ else if (fs->super->s_mnt_count >=
+ (unsigned) fs->super->s_max_mnt_count)
+ reason = "has reached maximal mount count";
+ else if (fs->super->s_checkinterval &&
+ time(0) >= (fs->super->s_lastcheck +
+ fs->super->s_checkinterval))
+ reason = "has gone too long without being checked";
+ else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
+ reason = "was not cleanly unmounted";
+ if (reason) {
+ printf("%s %s, check forced.\n", ctx->device_name, reason);
+ return;
+ }
+ printf("%s: clean, %d/%d files, %d/%d blocks\n", 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,
+ fs->super->s_blocks_count);
+ ext2fs_close(fs);
+ exit(FSCK_OK);
+}
+
+
+#define PATH_SET "PATH=/sbin"
+
+static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
+{
+ int flush = 0;
+ char c;
+#ifdef MTRACE
+ extern void *mallwatch;
+#endif
+ char *oldpath = getenv("PATH");
+ e2fsck_t ctx;
+ errcode_t retval;
+
+ retval = e2fsck_allocate_context(&ctx);
+ if (retval)
+ return retval;
+
+ *ret_ctx = ctx;
+
+ /* Update our PATH to include /sbin */
+ if (oldpath) {
+ char *newpath;
+
+ newpath = malloc(sizeof (PATH_SET) + 1 + strlen (oldpath));
+ if (!newpath)
+ fatal_error("Couldn't malloc() newpath");
+ strcpy (newpath, PATH_SET);
+ strcat (newpath, ":");
+ strcat (newpath, oldpath);
+ putenv (newpath);
+ } else
+ putenv (PATH_SET);
+
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+ initialize_ext2_error_table();
+
+ if (argc && *argv)
+ ctx->program_name = *argv;
+ else
+ ctx->program_name = "e2fsck";
+ while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:N:Ss")) != EOF)
+ switch (c) {
+ case 'p':
+ case 'a':
+ ctx->options |= E2F_OPT_PREEN;
+ ctx->options &= ~(E2F_OPT_YES|E2F_OPT_NO);
+ break;
+ case 'n':
+ ctx->options |= E2F_OPT_NO;
+ ctx->options &= ~(E2F_OPT_YES|E2F_OPT_PREEN);
+ break;
+ case 'y':
+ ctx->options |= E2F_OPT_YES;
+ ctx->options &= ~(E2F_OPT_PREEN|E2F_OPT_NO);
+ break;
+ case 't':
+ if (ctx->options & E2F_OPT_TIME)
+ ctx->options |= E2F_OPT_TIME2;
+ else
+ ctx->options |= E2F_OPT_TIME;
+ break;
+ case 'c':
+ cflag++;
+ ctx->options |= E2F_OPT_CHECKBLOCKS;
+ break;
+ case 'r':
+ /* What we do by default, anyway! */
+ break;
+ case 'b':
+ ctx->use_superblock = atoi(optarg);
+ break;
+ case 'B':
+ blocksize = atoi(optarg);
+ break;
+ case 'I':
+ ctx->inode_buffer_blocks = atoi(optarg);
+ break;
+ case 'P':
+ ctx->process_inode_size = atoi(optarg);
+ break;
+ case 'L':
+ replace_bad_blocks++;
+ case 'l':
+ bad_blocks_file = malloc(strlen(optarg)+1);
+ if (!bad_blocks_file)
+ fatal_error("Couldn't malloc bad_blocks_file");
+ strcpy(bad_blocks_file, optarg);
+ break;
+ case 'd':
+ ctx->options |= E2F_OPT_DEBUG;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'F':
+#ifdef BLKFLSBUF
+ flush = 1;
+#else
+ fatal_error ("-F not supported");
+#endif
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'V':
+ show_version_only = 1;
+ break;
+#ifdef MTRACE
+ case 'M':
+ mallwatch = (void *) strtol(optarg, NULL, 0);
+ break;
+#endif
+ case 'N':
+ ctx->device_name = optarg;
+ break;
+ case 's':
+ normalize_swapfs = 1;
+ case 'S':
+ swapfs = 1;
+ break;
+ default:
+ usage(ctx);
+ }
+ if (show_version_only)
+ return 0;
+ if (optind != argc - 1)
+ usage(ctx);
+ if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
+ !cflag && !swapfs)
+ ctx->options |= E2F_OPT_READONLY;
+ ctx->filesystem_name = argv[optind];
+ if (ctx->device_name == 0)
+ ctx->device_name = ctx->filesystem_name;
+ if (flush) {
+#ifdef BLKFLSBUF
+ int fd = open(ctx->filesystem_name, O_RDONLY, 0);
+
+ if (fd < 0) {
+ com_err("open", errno, "while opening %s for flushing",
+ ctx->filesystem_name);
+ exit(FSCK_ERROR);
+ }
+ if (ioctl(fd, BLKFLSBUF, 0) < 0) {
+ com_err("BLKFLSBUF", errno, "while trying to flush %s",
+ ctx->filesystem_name);
+ exit(FSCK_ERROR);
+ }
+ close(fd);
+#else
+ fatal_error ("BLKFLSBUF not supported");
+#endif /* BLKFLSBUF */
+ }
+ if (swapfs) {
+ if (cflag || bad_blocks_file) {
+ fprintf(stderr, "Incompatible options not "
+ "allowed when byte-swapping.\n");
+ fatal_error(0);
+ }
+ }
+ return 0;
+}
+
+static const char *my_ver_string = E2FSPROGS_VERSION;
+static const char *my_ver_date = E2FSPROGS_DATE;
+
+int main (int argc, char *argv[])
+{
+ errcode_t retval = 0;
+ int exit_value = FSCK_OK;
+ int i;
+ ext2_filsys fs = 0;
+ io_manager io_ptr;
+ struct ext2fs_sb *s;
+ const char *lib_ver_date;
+ int my_ver, lib_ver;
+ e2fsck_t ctx;
+ struct problem_context pctx;
+ int flags;
+
+ clear_problem_context(&pctx);
+#ifdef MTRACE
+ mtrace();
+#endif
+#ifdef MCHECK
+ mcheck(0);
+#endif
+ my_ver = ext2fs_parse_version_string(my_ver_string);
+ lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
+ if (my_ver > lib_ver) {
+ fprintf( stderr, "Error: ext2fs library version "
+ "out of date!\n");
+ show_version_only++;
+ }
+
+ retval = PRS(argc, argv, &ctx);
+ if (retval) {
+ com_err("e2fsck", retval,
+ "while trying to initialize program");
+ exit(1);
+ }
+
+ init_resource_track(&ctx->global_rtrack);
+
+ if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
+ fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
+ my_ver_string, my_ver_date, EXT2FS_VERSION,
+ EXT2FS_DATE);
+
+ if (show_version_only) {
+ fprintf(stderr, "\tUsing %s, %s\n",
+ error_message(EXT2_ET_BASE), lib_ver_date);
+ exit(0);
+ }
+
+ check_mount(ctx);
+
+ if (!(ctx->options & E2F_OPT_PREEN) &&
+ !(ctx->options & E2F_OPT_NO) &&
+ !(ctx->options & E2F_OPT_YES)) {
+ if (!isatty (0) || !isatty (1))
+ die ("need terminal for interactive repairs");
+ }
+ ctx->superblock = ctx->use_superblock;
+restart:
+#if 1
+ io_ptr = unix_io_manager;
+#else
+ io_ptr = test_io_manager;
+ test_io_backing_manager = unix_io_manager;
+#endif
+ sync_disks();
+ flags = (ctx->options & E2F_OPT_READONLY) ? 0 : EXT2_FLAG_RW;
+ if (ctx->superblock && blocksize) {
+ retval = ext2fs_open(ctx->filesystem_name, flags,
+ ctx->superblock, blocksize, io_ptr, &fs);
+ } else if (ctx->superblock) {
+ for (i=0; possible_block_sizes[i]; i++) {
+ retval = ext2fs_open(ctx->filesystem_name, flags,
+ ctx->superblock,
+ possible_block_sizes[i],
+ io_ptr, &fs);
+ if (!retval)
+ break;
+ }
+ } else
+ retval = ext2fs_open(ctx->filesystem_name, flags,
+ 0, 0, io_ptr, &fs);
+ if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
+ ((retval == EXT2_ET_BAD_MAGIC) ||
+ ((retval == 0) && ext2fs_check_desc(fs)))) {
+ if (!fs || (fs->group_desc_count > 1)) {
+ printf("%s trying backup blocks...\n",
+ retval ? "Couldn't find ext2 superblock," :
+ "Group descriptors look bad...");
+ ctx->superblock = get_backup_sb(fs);
+ if (fs)
+ ext2fs_close(fs);
+ goto restart;
+ }
+ }
+ if (retval) {
+ com_err(ctx->program_name, retval, "while trying to open %s",
+ ctx->filesystem_name);
+ if (retval == EXT2_ET_REV_TOO_HIGH)
+ printf ("Get a newer version of e2fsck!\n");
+ else if (retval == EXT2_ET_SHORT_READ)
+ printf ("Could this be a zero-length partition?\n");
+ else if ((retval == EPERM) || (retval == EACCES))
+ printf("You must have %s access to the "
+ "filesystem or be root\n",
+ (ctx->options & E2F_OPT_READONLY) ?
+ "r/o" : "r/w");
+ else if (retval == ENXIO)
+ printf("Possibly non-existent or swap device?\n");
+ else
+ fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
+ fatal_error(0);
+ }
+ ctx->fs = fs;
+ fs->private = ctx;
+#ifdef EXT2_CURRENT_REV
+ if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
+ com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
+ "while trying to open %s",
+ ctx->filesystem_name);
+ goto get_newer;
+ }
+#endif
+ /*
+ * Check for compatibility with the feature sets. We need to
+ * be more stringent than ext2fs_open().
+ */
+ s = (struct ext2fs_sb *) fs->super;
+ if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
+ (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
+ com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
+ "(%s)", ctx->filesystem_name);
+ get_newer:
+ printf ("Get a newer version of e2fsck!\n");
+ fatal_error(0);
+ }
+ if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
+ com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
+ "(%s)", ctx->filesystem_name);
+ goto get_newer;
+ }
+
+ /*
+ * If the user specified a specific superblock, presumably the
+ * master superblock has been trashed. So we mark the
+ * superblock as dirty, so it can be written out.
+ */
+ if (ctx->superblock &&
+ !(ctx->options & E2F_OPT_READONLY))
+ ext2fs_mark_super_dirty(fs);
+
+ /*
+ * Don't overwrite the backup superblock and block
+ * descriptors, until we're sure the filesystem is OK....
+ */
+ fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
+
+ ehandler_init(fs->io);
+
+ if (ctx->superblock)
+ set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
+ check_super_block(ctx);
+ check_if_skip(ctx);
+ if (bad_blocks_file)
+ read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
+ else if (cflag)
+ test_disk(ctx);
+
+ if (normalize_swapfs) {
+ if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ==
+ ext2fs_native_flag()) {
+ fprintf(stderr, "%s: Filesystem byte order "
+ "already normalized.\n", ctx->device_name);
+ fatal_error(0);
+ }
+ }
+ if (swapfs)
+ swap_filesys(ctx);
+
+ /*
+ * Mark the system as valid, 'til proven otherwise
+ */
+ ext2fs_mark_valid(fs);
+
+ retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
+ if (retval) {
+ com_err(ctx->program_name, retval,
+ "while reading bad blocks inode");
+ preenhalt(ctx);
+ printf("This doesn't bode well, but we'll try to go on...\n");
+ }
+
+ pass1(ctx);
+ if (restart_e2fsck) {
+ ext2fs_close(fs);
+ printf("Restarting e2fsck from the beginning...\n");
+ restart_e2fsck = 0;
+ retval = e2fsck_reset_context(ctx);
+ if (retval) {
+ com_err(ctx->program_name, retval,
+ "while resetting context");
+ exit(1);
+ }
+ goto restart;
+ }
+ pass2(ctx);
+ pass3(ctx);
+ pass4(ctx);
+ pass5(ctx);
+
+#ifdef MTRACE
+ mtrace_print("Cleanup");
+#endif
+ if (ext2fs_test_changed(fs)) {
+ exit_value = FSCK_NONDESTRUCT;
+ if (!(ctx->options & E2F_OPT_PREEN))
+ printf("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n",
+ ctx->device_name);
+ if (root_filesystem && !read_only_root) {
+ printf("%s: ***** REBOOT LINUX *****\n",
+ ctx->device_name);
+ exit_value = FSCK_REBOOT;
+ }
+ }
+ if (ext2fs_test_valid(fs))
+ fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+ else
+ exit_value = FSCK_UNCORRECTED;
+ if (!(ctx->options & E2F_OPT_READONLY)) {
+ if (ext2fs_test_valid(fs)) {
+ if (!(fs->super->s_state & EXT2_VALID_FS))
+ exit_value = FSCK_NONDESTRUCT;
+ fs->super->s_state = EXT2_VALID_FS;
+ } else
+ fs->super->s_state &= ~EXT2_VALID_FS;
+ fs->super->s_mnt_count = 0;
+ fs->super->s_lastcheck = time(NULL);
+ ext2fs_mark_super_dirty(fs);
+ }
+ show_stats(ctx);
+
+ write_bitmaps(ctx);
+ ext2fs_close(fs);
+ sync_disks();
+
+ if (ctx->options & E2F_OPT_TIME)
+ print_resource_track(NULL, &ctx->global_rtrack);
+
+ e2fsck_free_context(ctx);
+
+ return exit_value;
+}
#include <sys/time.h>
#include <sys/resource.h>
-const char * fix_msg[2] = { "IGNORED", "FIXED" };
-
void fatal_error (const char *msg)
{
if (msg)
- fprintf (stderr, "%s: %s\n", program_name, msg);
+ fprintf (stderr, "e2fsck: %s\n", msg);
exit(FSCK_ERROR);
}
return ret;
}
-
int ask_yn(const char * string, int def)
{
int c;
return def;
}
-int ask (const char * string, int def)
+int ask (e2fsck_t ctx, const char * string, int def)
{
- if (nflag) {
+ if (ctx->options & E2F_OPT_NO) {
printf ("%s? no\n\n", string);
return 0;
}
- if (yflag) {
+ if (ctx->options & E2F_OPT_YES) {
printf ("%s? yes\n\n", string);
return 1;
}
- if (preen) {
+ if (ctx->options & E2F_OPT_PREEN) {
printf ("%s? %s\n\n", string, def ? "yes" : "no");
return def;
}
return ask_yn(string, def);
}
-void read_bitmaps(ext2_filsys fs)
+void read_bitmaps(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
- if (invalid_bitmaps) {
- com_err(program_name, 0,
+ if (ctx->invalid_bitmaps) {
+ com_err(ctx->program_name, 0,
"read_bitmaps: illegal bitmap block(s) for %s",
- device_name);
+ ctx->device_name);
fatal_error(0);
}
retval = ext2fs_read_bitmaps(fs);
ehandler_operation(0);
if (retval) {
- com_err(program_name, retval,
+ com_err(ctx->program_name, retval,
"while retrying to read bitmaps for %s",
- device_name);
+ ctx->device_name);
fatal_error(0);
}
}
-void write_bitmaps(ext2_filsys fs)
+void write_bitmaps(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
errcode_t retval;
if (ext2fs_test_bb_dirty(fs)) {
retval = ext2fs_write_block_bitmap(fs);
ehandler_operation(0);
if (retval) {
- com_err(program_name, retval,
+ com_err(ctx->program_name, retval,
"while retrying to write block bitmaps for %s",
- device_name);
+ ctx->device_name);
fatal_error(0);
}
}
retval = ext2fs_write_inode_bitmap(fs);
ehandler_operation(0);
if (retval) {
- com_err(program_name, retval,
+ com_err(ctx->program_name, retval,
"while retrying to write inode bitmaps for %s",
- device_name);
+ ctx->device_name);
fatal_error(0);
}
}
}
-void preenhalt(ext2_filsys fs)
+void preenhalt(e2fsck_t ctx)
{
- if (!preen)
+ ext2_filsys fs = ctx->fs;
+
+ if (!(ctx->options & E2F_OPT_PREEN))
return;
fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; "
"RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n",
- device_name);
+ ctx->device_name);
if (fs != NULL) {
fs->super->s_state |= EXT2_ERROR_FS;
ext2fs_mark_super_dirty(fs);
track->brk_start = sbrk(0);
gettimeofday(&track->time_start, 0);
#ifdef HAVE_GETRUSAGE
+#ifdef solaris
+ memcpy(&r, 0, sizeof(struct rusage));
+#endif
getrusage(RUSAGE_SELF, &r);
track->user_start = r.ru_utime;
track->system_start = r.ru_stime;
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
}
-void print_resource_track(struct resource_track *track)
+void print_resource_track(const char *desc, struct resource_track *track)
{
#ifdef HAVE_GETRUSAGE
struct rusage r;
struct timeval time_end;
gettimeofday(&time_end, 0);
+
+ if (desc)
+ printf("%s :", desc);
+
#ifdef HAVE_GETRUSAGE
getrusage(RUSAGE_SELF, &r);
}
#endif
+blk_t get_backup_sb(ext2_filsys fs)
+{
+ if (!fs || !fs->super)
+ return 8193;
+ return fs->super->s_blocks_per_group + 1;
+}
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Block bitmap differences: +50
+Fix? yes
+
+Free blocks count wrong for group #0 (78, counted=77).
+Fix? yes
+
+Free blocks count wrong (78, counted=77).
+Fix? yes
-Block bitmap differences: +50. FIXED
-Free blocks count wrong for group 0 (78, counted=77). FIXED
-Free blocks count wrong (78, counted=77). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 23/100 blocks
Inode 12 ref count is 1, should be 2. Fix? yes
Pass 5: Checking group summary information
-Fix summary information? yes
+Block bitmap differences: -22
+Fix? yes
+
+Free blocks count wrong (74, counted=75).
+Fix? yes
+
+Inode bitmap differences: -13
+Fix? yes
+
+Directories count wrong for group #0 (5, counted=4).
+Fix? yes
-Block bitmap differences: -22. FIXED
-Free blocks count wrong (74, counted=75). FIXED
-Inode bitmap differences: -13. FIXED
-Directories count wrong for group #0 (5, counted=4). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 14/32 files (0.0% non-contiguous), 25/100 blocks
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (70, counted=71).
+Fix? yes
+
+Free blocks count wrong (70, counted=71).
+Fix? yes
-Free blocks count wrong for group 0 (70, counted=71). FIXED
-Free blocks count wrong (70, counted=71). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 18/32 files (0.0% non-contiguous), 29/100 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Block bitmap differences: -25
+Fix? yes
+
+Free blocks count wrong for group #0 (76, counted=77).
+Fix? yes
+
+Free blocks count wrong (76, counted=77).
+Fix? yes
+
+Free inodes count wrong for group #0 (17, counted=20).
+Fix? yes
+
+Free inodes count wrong (17, counted=20).
+Fix? yes
-Block bitmap differences: -25. FIXED
-Free blocks count wrong for group 0 (76, counted=77). FIXED
-Free blocks count wrong (76, counted=77). FIXED
-Free inodes count wrong for group #0 (17, counted=20). FIXED
-Free inodes count wrong (17, counted=20). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (0.0% non-contiguous), 23/100 blocks
The primary superblock (1) is on the bad block list.
If the block is really bad, the filesystem can not be fixed.
-You can clear the this block from the bad block list
-and hope that block is really OK, but there are no guarantees.
+You can clear the this block (and hope for the best) from the
+bad block list and hope that block is really OK, but there are no
+guarantees.
-Clear (and hope for the best)? yes
+Clear? yes
Block 2 in the primary group descriptors is on the bad block list
If the block is really bad, the filesystem can not be fixed.
-You can clear the this block from the bad block list
-and hope that block is really OK, but there are no guarantees.
+You can clear the this block (and hope for the best) from the
+bad block list and hope that block is really OK, but there are no
+guarantees.
-Clear (and hope for the best)? yes
+Clear? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Inode 12 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (77, counted=76).
+Fix? yes
+
+Free blocks count wrong (77, counted=76).
+Fix? yes
+
+Free inodes count wrong for group #0 (20, counted=19).
+Fix? yes
+
+Directories count wrong for group #0 (2, counted=3).
+Fix? yes
+
+Free inodes count wrong (20, counted=19).
+Fix? yes
-Free blocks count wrong for group 0 (77, counted=76). FIXED
-Free blocks count wrong (77, counted=76). FIXED
-Free inodes count wrong for group #0 (20, counted=19). FIXED
-Directories count wrong for group #0 (2, counted=3). FIXED
-Free inodes count wrong (20, counted=19). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 13/32 files (0.0% non-contiguous), 24/100 blocks
Inode 2 ref count is 3, should be 2. Fix? yes
Pass 5: Checking group summary information
-Fix summary information? yes
-
-Block bitmap differences: -11 -12 -13 -14 -15 -16 -17 -18 -19 -20. FIXED
-Free blocks count wrong for group 0 (78, counted=88). FIXED
-Free blocks count wrong (78, counted=88). FIXED
-Inode bitmap differences: +12 +13 +14 +15 +16 +25 +26 +27 +28 +29 +30 +31 +32. FIXED
-Free inodes count wrong for group #0 (21, counted=8). FIXED
-Directories count wrong for group #0 (2, counted=1). FIXED
-Free inodes count wrong (21, counted=8). FIXED
+Block bitmap differences: -11 -12 -13 -14 -15 -16 -17 -18 -19 -20
+Fix? yes
+
+Free blocks count wrong for group #0 (78, counted=88).
+Fix? yes
+
+Free blocks count wrong (78, counted=88).
+Fix? yes
+
+Inode bitmap differences: +12 +13 +14 +15 +16 +25 +26 +27 +28 +29 +30 +31 +32
+Fix? yes
+
+Free inodes count wrong for group #0 (21, counted=8).
+Fix? yes
+
+Directories count wrong for group #0 (2, counted=1).
+Fix? yes
+
+Free inodes count wrong (21, counted=8).
+Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 24/32 files (0.0% non-contiguous), 12/100 blocks
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
-
File /lost+found (inode #11, mod time Sun Jan 2 08:28:40 1994)
has 12 duplicate block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
-
File / (inode #2, mod time Sun Jan 2 08:29:13 1994)
has 1 duplicate block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
-
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Block bitmap differences: +43
+Fix? yes
+
+Free blocks count wrong for group #0 (57, counted=41).
+Fix? yes
+
+Free blocks count wrong (57, counted=41).
+Fix? yes
-Block bitmap differences: +43. FIXED
-Free blocks count wrong for group 0 (57, counted=41). FIXED
-Free blocks count wrong (57, counted=41). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (0.0% non-contiguous), 59/100 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
-
-Block bitmap differences: -83. FIXED
-Free blocks count wrong for group 0 (1962, counted=1965). FIXED
-Free blocks count wrong (1962, counted=1965). FIXED
-Inode bitmap differences: +41 +42 +43 +44 +45 +46 +47 +48. FIXED
-Free inodes count wrong for group #0 (485, counted=477). FIXED
-Free inodes count wrong (485, counted=477). FIXED
+Block bitmap differences: -83
+Fix? yes
+
+Free blocks count wrong for group #0 (1962, counted=1965).
+Fix? yes
+
+Free blocks count wrong (1962, counted=1965).
+Fix? yes
+
+Inode bitmap differences: +41 +42 +43 +44 +45 +46 +47 +48
+Fix? yes
+
+Free inodes count wrong for group #0 (485, counted=477).
+Fix? yes
+
+Free inodes count wrong (485, counted=477).
+Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 35/512 files (0.0% non-contiguous), 83/2048 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Block bitmap differences: +12 -20 +41 -50
+Fix? yes
+
+Inode bitmap differences: +11 -15
+Fix? yes
-Block bitmap differences: +12 -20 +41 -50. FIXED
-Inode bitmap differences: +11 -15. FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (9.1% non-contiguous), 22/100 blocks
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
Clone duplicate/bad blocks? yes
-
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
has 2 duplicate block(s), shared with 1 file(s):
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (44, counted=60).
+Fix? yes
+
+Free blocks count wrong (62, counted=60).
+Fix? yes
-Free blocks count wrong for group 0 (44, counted=60). FIXED
-Free blocks count wrong (62, counted=60). FIXED
Padding at end of block bitmap is not set. Fix? yes
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
Clone duplicate/bad blocks? yes
-
File /motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
has 4 duplicate block(s), shared with 2 file(s):
/pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
Clone duplicate/bad blocks? yes
-
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
has 2 duplicate block(s), shared with 1 file(s):
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (8, counted=22).
+Fix? yes
+
+Free blocks count wrong (26, counted=22).
+Fix? yes
-Free blocks count wrong for group 0 (8, counted=22). FIXED
-Free blocks count wrong (26, counted=22). FIXED
Padding at end of block bitmap is not set. Fix? yes
<filesystem metadata>
Clone duplicate/bad blocks? yes
-
Pass 2: Checking directory structure
Directory inode 12, block 1, offset 0: directory corrupted
Salvage? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (77, counted=74).
+Fix? yes
+
+Free blocks count wrong (77, counted=74).
+Fix? yes
-Free blocks count wrong for group 0 (77, counted=74). FIXED
-Free blocks count wrong (77, counted=74). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (8.3% non-contiguous), 26/100 blocks
<filesystem metadata>
Clone duplicate/bad blocks? yes
-
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Block bitmap differences: -29 -30 -31
+Fix? yes
-Block bitmap differences: -29 -30 -31. FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 12/32 files (8.3% non-contiguous), 39/100 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (44, counted=63).
+Fix? yes
-Free blocks count wrong for group 0 (44, counted=63). FIXED
Padding at end of block bitmap is not set. Fix? yes
Inode 111 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (56, counted=55).
+Fix? yes
+
+Free blocks count wrong (56, counted=55).
+Fix? yes
+
+Free inodes count wrong for group #0 (89, counted=88).
+Fix? yes
+
+Directories count wrong for group #0 (2, counted=3).
+Fix? yes
+
+Free inodes count wrong (89, counted=88).
+Fix? yes
-Free blocks count wrong for group 0 (56, counted=55). FIXED
-Free blocks count wrong (56, counted=55). FIXED
-Free inodes count wrong for group #0 (89, counted=88). FIXED
-Directories count wrong for group #0 (2, counted=3). FIXED
-Free inodes count wrong (89, counted=88). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 112/200 files (0.0% non-contiguous), 145/200 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Block bitmap differences: +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21
+Fix? yes
-Block bitmap differences: +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21. FIXED
-Inode bitmap differences: -12 -13 -14 -15 -16 -17 -18 -19 -20 -21. FIXED
-Padding at end of block bitmap is not set. Fix? yes
+Inode bitmap differences: -12 -13 -14 -15 -16 -17 -18 -19 -20 -21
+Fix? yes
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Inode bitmap differences: +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11
+Fix? yes
-Inode bitmap differences: +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11. FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
-
-Block bitmap differences: -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21. FIXED
-Free blocks count wrong for group 0 (78, counted=90). FIXED
-Free blocks count wrong (78, counted=90). FIXED
-Inode bitmap differences: -11. FIXED
-Free inodes count wrong for group #0 (21, counted=22). FIXED
-Directories count wrong for group #0 (2, counted=1). FIXED
-Free inodes count wrong (21, counted=22). FIXED
+Block bitmap differences: -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21
+Fix? yes
+
+Free blocks count wrong for group #0 (78, counted=90).
+Fix? yes
+
+Free blocks count wrong (78, counted=90).
+Fix? yes
+
+Inode bitmap differences: -11
+Fix? yes
+
+Free inodes count wrong for group #0 (21, counted=22).
+Fix? yes
+
+Directories count wrong for group #0 (2, counted=1).
+Fix? yes
+
+Free inodes count wrong (21, counted=22).
+Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 10/32 files (0.0% non-contiguous), 10/100 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
-
-Block bitmap differences: -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -44 -45. FIXED
-Free blocks count wrong for group 0 (41, counted=58). FIXED
-Free blocks count wrong (41, counted=58). FIXED
-Inode bitmap differences: -12. FIXED
-Free inodes count wrong for group #0 (20, counted=21). FIXED
-Free inodes count wrong (20, counted=21). FIXED
+Block bitmap differences: -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -44 -45
+Fix? yes
+
+Free blocks count wrong for group #0 (41, counted=58).
+Fix? yes
+
+Free blocks count wrong (41, counted=58).
+Fix? yes
+
+Inode bitmap differences: -12
+Fix? yes
+
+Free inodes count wrong for group #0 (20, counted=21).
+Fix? yes
+
+Free inodes count wrong (20, counted=21).
+Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 42/100 blocks
Inode 15 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
-Fix summary information? yes
-
-Block bitmap differences: +22 +23 +49 +57 +58. FIXED
-Free blocks count wrong for group 0 (25, counted=33). FIXED
-Free blocks count wrong (39, counted=33). FIXED
-Inode bitmap differences: +13. FIXED
-Free inodes count wrong for group #0 (2, counted=0). FIXED
-Directories count wrong for group #0 (1, counted=2). FIXED
-Free inodes count wrong (2, counted=0). FIXED
-Padding at end of block bitmap is not set. Fix? yes
+Block bitmap differences: +22 +23 +49 +57 +58
+Fix? yes
+
+Free blocks count wrong for group #0 (25, counted=33).
+Fix? yes
+
+Free blocks count wrong (39, counted=33).
+Fix? yes
+
+Inode bitmap differences: +13
+Fix? yes
+
+Free inodes count wrong for group #0 (2, counted=0).
+Fix? yes
+
+Directories count wrong for group #0 (1, counted=2).
+Fix? yes
+
+Free inodes count wrong (2, counted=0).
+Fix? yes
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Block bitmap differences: -43 -44 -45 -46 -47 -48 -49
+Fix? yes
+
+Free blocks count wrong for group #0 (68, counted=75).
+Fix? yes
+
+Free blocks count wrong (68, counted=75).
+Fix? yes
-Block bitmap differences: -43 -44 -45 -46 -47 -48 -49. FIXED
-Free blocks count wrong for group 0 (68, counted=75). FIXED
-Free blocks count wrong (68, counted=75). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 29/32 files (3.4% non-contiguous), 25/100 blocks
Inode 2 ref count is 8, should be 4. Fix? yes
Pass 5: Checking group summary information
-Fix summary information? yes
-
-Block bitmap differences: -8385 -8386 -8387 -8388 -8389 -8390 -8391 -8392 -8393 -8394 -8395 -8396 -8397 -8398 -8399 -8400 -8401 -8402 -8403 -8404 -8405. FIXED
-Free blocks count wrong for group 0 (7987, counted=7984). FIXED
-Free blocks count wrong (11602, counted=11599). FIXED
-Inode bitmap differences: -1505 -1506 -1507 -1508 -1509 -1510 -1511 -1512 -1513 -1514 -1515 -1516. FIXED
-Free inodes count wrong for group #0 (1493, counted=1489). FIXED
-Directories count wrong for group #0 (2, counted=3). FIXED
-Free inodes count wrong (2997, counted=2993). FIXED
+Block bitmap differences: -8385 -8386 -8387 -8388 -8389 -8390 -8391 -8392 -8393 -8394 -8395 -8396 -8397 -8398 -8399 -8400 -8401 -8402 -8403 -8404 -8405
+Fix? yes
+
+Free blocks count wrong for group #0 (7987, counted=7984).
+Fix? yes
+
+Free blocks count wrong (11602, counted=11599).
+Fix? yes
+
+Inode bitmap differences: -1505 -1506 -1507 -1508 -1509 -1510 -1511 -1512 -1513 -1514 -1515 -1516
+Fix? yes
+
+Free inodes count wrong for group #0 (1493, counted=1489).
+Fix? yes
+
+Directories count wrong for group #0 (2, counted=3).
+Fix? yes
+
+Free inodes count wrong (2997, counted=2993).
+Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 15/3008 files (0.0% non-contiguous), 401/12000 blocks
Unattached zero-length inode 15. Clear? yes
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (75, counted=74).
+Fix? yes
+
+Free blocks count wrong (75, counted=74).
+Fix? yes
+
+Free inodes count wrong for group #0 (17, counted=16).
+Fix? yes
+
+Directories count wrong for group #0 (4, counted=5).
+Fix? yes
+
+Free inodes count wrong (17, counted=16).
+Fix? yes
-Free blocks count wrong for group 0 (75, counted=74). FIXED
-Free blocks count wrong (75, counted=74). FIXED
-Free inodes count wrong for group #0 (17, counted=16). FIXED
-Directories count wrong for group #0 (4, counted=5). FIXED
-Free inodes count wrong (17, counted=16). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 16/32 files (0.0% non-contiguous), 26/100 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Inode bitmap differences: -12 -13 -14 -15 -16 -17 -18 -19 -20 -21
+Fix? yes
-Inode bitmap differences: -12 -13 -14 -15 -16 -17 -18 -19 -20 -21. FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/32 files (0.0% non-contiguous), 22/100 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
-
-Free blocks count wrong for group 0 (8042, counted=7614). FIXED
-Free blocks count wrong for group 1 (170, counted=169). FIXED
-Free blocks count wrong (8212, counted=7783). FIXED
-Free inodes count wrong for group #0 (1053, counted=1052). FIXED
-Free inodes count wrong for group #1 (1064, counted=1063). FIXED
-Directories count wrong for group #1 (0, counted=1). FIXED
-Free inodes count wrong (2117, counted=2115). FIXED
+Free blocks count wrong for group #0 (8042, counted=7614).
+Fix? yes
+
+Free blocks count wrong for group #1 (170, counted=169).
+Fix? yes
+
+Free blocks count wrong (8212, counted=7783).
+Fix? yes
+
+Free inodes count wrong for group #0 (1053, counted=1052).
+Fix? yes
+
+Free inodes count wrong for group #1 (1064, counted=1063).
+Fix? yes
+
+Directories count wrong for group #1 (0, counted=1).
+Fix? yes
+
+Free inodes count wrong (2117, counted=2115).
+Fix? yes
+
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 13/2128 files (0.0% non-contiguous), 717/8500 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (7987, counted=7982).
+Fix? yes
+
+Free blocks count wrong (11602, counted=11597).
+Fix? yes
+
+Free inodes count wrong for group #0 (1493, counted=1488).
+Fix? yes
+
+Free inodes count wrong (2997, counted=2992).
+Fix? yes
-Free blocks count wrong for group 0 (7987, counted=7982). FIXED
-Free blocks count wrong (11602, counted=11597). FIXED
-Free inodes count wrong for group #0 (1493, counted=1488). FIXED
-Free inodes count wrong (2997, counted=2992). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 16/3008 files (0.0% non-contiguous), 403/12000 blocks
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-Fix summary information? yes
+Free blocks count wrong for group #0 (7987, counted=7982).
+Fix? yes
+
+Free blocks count wrong (11602, counted=11597).
+Fix? yes
+
+Free inodes count wrong for group #0 (1493, counted=1488).
+Fix? yes
+
+Free inodes count wrong (2997, counted=2992).
+Fix? yes
-Free blocks count wrong for group 0 (7987, counted=7982). FIXED
-Free blocks count wrong (11602, counted=11597). FIXED
-Free inodes count wrong for group #0 (1493, counted=1488). FIXED
-Free inodes count wrong (2997, counted=2992). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 16/3008 files (0.0% non-contiguous), 403/12000 blocks