]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
Many files:
authorTheodore Ts'o <tytso@mit.edu>
Fri, 3 Oct 1997 17:48:10 +0000 (17:48 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 3 Oct 1997 17:48:10 +0000 (17:48 +0000)
  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.
  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.
  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.
  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
expect.1, expect.2:
  Updated tests to align with e2fsck problem.c changes.

49 files changed:
e2fsck/ChangeLog
e2fsck/Makefile.in
e2fsck/badblocks.c
e2fsck/e2fsck.c
e2fsck/e2fsck.h
e2fsck/ehandler.c
e2fsck/iscan.c
e2fsck/message.c
e2fsck/pass1.c
e2fsck/pass1b.c
e2fsck/pass2.c
e2fsck/pass3.c
e2fsck/pass4.c
e2fsck/pass5.c
e2fsck/problem.c
e2fsck/problem.h
e2fsck/scantest.c
e2fsck/super.c [new file with mode: 0644]
e2fsck/swapfs.c
e2fsck/unix.c [new file with mode: 0644]
e2fsck/util.c
tests/f_badbblocks/expect.1
tests/f_baddir/expect.1
tests/f_baddotdir/expect.1
tests/f_badinode/expect.1
tests/f_badprimary/expect.1
tests/f_badroot/expect.1
tests/f_badtable/expect.1
tests/f_bbfile/expect.1
tests/f_bbinode/expect.1
tests/f_bitmaps/expect.1
tests/f_dup/expect.1
tests/f_dup2/expect.1
tests/f_dupfsblks/expect.1
tests/f_dupsuper/expect.1
tests/f_end-bitmap/expect.1
tests/f_expand/expect.1
tests/f_illbbitmap/expect.1
tests/f_illibitmap/expect.1
tests/f_illitable/expect.1
tests/f_lotsbad/expect.1
tests/f_lpf/expect.1
tests/f_messy_inode/expect.1
tests/f_misstable/expect.1
tests/f_noroot/expect.1
tests/f_overfsblks/expect.1
tests/f_preen/expect.2
tests/f_zero_group/expect.1
tests/f_zero_super/expect.1

index 9fceacde7bfd95141cf3e7aadf7c3d3c9f4f36c7..efa67c358f765a1b093ccfcdc16ea0b7e78f4447 100644 (file)
@@ -1,3 +1,43 @@
+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"
index 24a9efb62090df4dfeb495dc7ba682e3c9f978a0..e16c12f35f16970ef2a69ce9a2251264bacb7491 100644 (file)
@@ -52,17 +52,19 @@ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBUUI
 #
 #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 \
@@ -71,6 +73,7 @@ SRCS= $(srcdir)/e2fsck.c \
        $(srcdir)/pass5.c \
        $(srcdir)/badblocks.c \
        $(srcdir)/util.c \
+       $(srcdir)/unix.c \
        $(srcdir)/dirinfo.c \
        $(srcdir)/ehandler.c \
        $(srcdir)/problem.c \
index e6ab4bcc9b32884176bc9a8a49d079f635e942d6..a9addf750e6a5203440666aa6bc3da2d94f4a916 100644 (file)
@@ -23,15 +23,16 @@ static void invalid_block(ext2_filsys fs, blk_t blk)
        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
@@ -72,8 +73,8 @@ void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
                }
        } 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,
@@ -106,9 +107,9 @@ void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
        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,
index 57390eee72a6a4bfd1085f1070f62f1a078ee75a..592541b0ff2e7e373d00b1a5ef03e19d02299d68 100644 (file)
  * %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);
 }
index c6dbd57dca588876bba6f8048aa2bf869e4fcdd5..27d703a02af5fb9c27580e1b3bf5d367d77bbfd6 100644 (file)
  */
 #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
@@ -73,85 +67,110 @@ struct resource_track {
 };
 
 /*
- * 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);
@@ -163,9 +182,9 @@ extern errcode_t pass1_write_inode(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);
@@ -178,18 +197,22 @@ extern struct dir_info *dir_info_iter(int *control);
 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,
@@ -199,10 +222,11 @@ extern void e2fsck_write_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);
index 131a0abb8415c6c1ce8d01d6085c65c6038eacb2..b370756433e2f41dbae1f994e55b37a7718425a5 100644 (file)
@@ -29,6 +29,10 @@ static errcode_t e2fsck_handle_read_error(io_channel channel,
 {
        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
@@ -51,8 +55,8 @@ static errcode_t e2fsck_handle_read_error(io_channel channel,
        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;
@@ -68,7 +72,11 @@ static errcode_t e2fsck_handle_write_error(io_channel channel,
 {
        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
@@ -91,8 +99,8 @@ static errcode_t e2fsck_handle_write_error(io_channel channel,
        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;
index d964b344b23195b7d8957b145aaafe7f091c649d..5a67b945a58e172e9d703f38c363c0ac15f68bc1 100644 (file)
@@ -139,7 +139,7 @@ int main (int argc, char *argv[])
                num_inodes++;
        }
        
-       print_resource_track(&global_rtrack);
+       print_resource_track(NULL, &global_rtrack);
        printf("%d inodes scanned.\n", num_inodes);
        
        exit(0);
index b9f9dea126bc6e502c681264088717abc9ebb5ef..673c4638d64f57d3eb3b27580d55557053a4a310 100644 (file)
  *
  *     %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
@@ -29,6 +32,7 @@
  *     %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
@@ -37,6 +41,8 @@
  *     %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
  */
 
@@ -90,6 +99,7 @@ static const char *abbrevs[] = {
        "ddirectory",
        "eentry",
        "E@e '%Dn' in %p (%i)",
+       "ffilesystem",
        "Ffor @i %i (%Q) is",
        "ggroup",
        "llost+found",
@@ -97,6 +107,7 @@ static const char *abbrevs[] = {
        "uunattached",
        "rroot @i",
        "sshould be",
+       "Ssuper@b",
        "zzero-length",
        "@@",
        0
@@ -145,8 +156,8 @@ static void print_pathname(ext2_filsys fs, ino_t dir, ino_t ino)
  * 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;
@@ -162,7 +173,7 @@ static _INLINE_ void expand_at_expression(ext2_filsys fs, char ch,
                        *first = 0;
                        fputc(toupper(*str++), stdout);
                }
-               print_e2fsck_message(fs, str, ctx, *first);
+               print_e2fsck_message(ctx, str, pctx, *first);
        } else
                printf("@%c", ch);
 }
@@ -242,6 +253,12 @@ static _INLINE_ void expand_dirent_expression(char 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);
@@ -265,6 +282,9 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
        case 'B':
                printf("%d", ctx->blkcount);
                break;
+       case 'c':
+               printf("%u", ctx->blk2);
+               break;
        case 'd':
                printf("%lu", ctx->dir);
                break;
@@ -277,6 +297,9 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
        case 'j':
                printf("%lu", ctx->ino2);
                break;
+       case 'm':
+               printf("%s", error_message(ctx->errcode));
+               break;
        case 'N':
                printf("%u", ctx->num);
                break;
@@ -293,6 +316,12 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
        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);
@@ -300,25 +329,26 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char 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] == '%')
index 2f1d67e79159eb8f6fa38f041b952411e90ead34..bd046d21e2174c09394830d355137e185fd30dad 100644 (file)
@@ -40,7 +40,6 @@
 #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);
@@ -105,6 +76,7 @@ struct process_block_struct {
        blk_t   previous_block;
        struct ext2_inode *inode;
        struct problem_context *pctx;
+       e2fsck_t        ctx;
 };
 
 struct process_inode_block {
@@ -112,18 +84,11 @@ 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
@@ -131,39 +96,7 @@ int process_inode_size = 256;
  */
 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;
 }
 
 /*
@@ -180,21 +113,22 @@ int e2fsck_pass1_check_device_inode(struct ext2_inode *inode)
        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");
@@ -203,85 +137,85 @@ void pass1(ext2_filsys fs)
        /*
         * 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;
                        
@@ -292,12 +226,14 @@ void pass1(ext2_filsys fs)
                        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;
                }
@@ -308,10 +244,10 @@ void pass1(ext2_filsys fs)
                         * 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");
@@ -327,7 +263,7 @@ void pass1(ext2_filsys fs)
                         * 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");
@@ -335,22 +271,22 @@ void pass1(ext2_filsys fs)
                        }
                }
                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;
                }
                /*
@@ -359,7 +295,7 @@ void pass1(ext2_filsys fs)
                 */
                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,
@@ -379,13 +315,13 @@ void pass1(ext2_filsys fs)
                 * 
                 */
                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;
@@ -405,45 +341,45 @@ void pass1(ext2_filsys fs)
                
                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]) {
@@ -451,43 +387,42 @@ void pass1(ext2_filsys fs)
                        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:
@@ -497,13 +432,11 @@ 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);
 }
 
 /*
@@ -513,14 +446,14 @@ endit:
 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;
@@ -533,24 +466,24 @@ static void process_inodes(ext2_filsys fs, char *block_buf)
        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");
@@ -572,15 +505,17 @@ static int process_inode_cmp(const void *a, const void *b)
 /*
  * 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);
        }
 }
@@ -588,15 +523,17 @@ static void alloc_bad_map(ext2_filsys fs)
 /*
  * 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);
        }
 }
@@ -608,23 +545,27 @@ static void alloc_bb_map(ext2_filsys fs)
  * 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);
        }
 }
 
@@ -632,11 +573,11 @@ static _INLINE_ void mark_block_used(ext2_filsys fs, blk_t 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;
        
@@ -652,30 +593,26 @@ static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
        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
@@ -692,14 +629,14 @@ static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
               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;
                }
        }
@@ -707,7 +644,7 @@ static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
                           (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");
                }
@@ -715,7 +652,7 @@ static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
        }
        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");
                }
@@ -790,10 +727,11 @@ int process_block(ext2_filsys fs,
        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) {
@@ -801,9 +739,11 @@ int process_block(ext2_filsys fs,
                         * 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)
@@ -846,18 +786,19 @@ int process_block(ext2_filsys fs,
        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;
@@ -867,51 +808,34 @@ int process_block(ext2_filsys fs,
                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,
@@ -926,20 +850,21 @@ 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
@@ -947,24 +872,24 @@ int process_bad_block(ext2_filsys fs,
        }
 
        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;
        }
        /*
@@ -974,46 +899,45 @@ int process_bad_block(ext2_filsys fs,
        
        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;
                }
@@ -1035,62 +959,69 @@ int process_bad_block(ext2_filsys fs,
         */
        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);
 }
@@ -1102,37 +1033,39 @@ static void new_table_block(ext2_filsys fs, blk_t first_block, int group,
  * 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;
@@ -1147,16 +1080,17 @@ static void mark_table_blocks(ext2_filsys fs)
                        /*
                         * 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);
                        }
                }
@@ -1168,18 +1102,18 @@ static void mark_table_blocks(ext2_filsys fs)
                        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);
                                }
                        }
@@ -1189,17 +1123,17 @@ static void mark_table_blocks(ext2_filsys fs)
                 * 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);
                    }
                        
@@ -1208,17 +1142,17 @@ static void mark_table_blocks(ext2_filsys fs)
                 * 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);
                        }
                }
@@ -1234,41 +1168,45 @@ static void mark_table_blocks(ext2_filsys fs)
  */
 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;
 }
index 0edefdea9bc0dbd5c7d16a85c5a3017e8cf86370..30c592459c81629e1dc56c37ff42fb4fcc946cf6 100644 (file)
@@ -89,12 +89,12 @@ struct dup_inode {
 
 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;
@@ -105,30 +105,32 @@ static ext2fs_inode_bitmap inode_dup_map;
 /*
  * 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) {
@@ -148,34 +150,42 @@ void pass1_dupblocks(ext2_filsys fs, char *block_buf)
 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;
 
@@ -184,8 +194,7 @@ void pass1b(ext2_filsys fs, char *block_buf)
                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;
@@ -198,16 +207,15 @@ void pass1b(ext2_filsys fs, char *block_buf)
                                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);
                }
        }
@@ -224,21 +232,21 @@ int process_pass1b_block(ext2_filsys fs,
        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");
@@ -314,13 +322,17 @@ static int search_dirent_proc(ino_t dir, int entry,
 }
 
 
-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
@@ -344,23 +356,25 @@ void pass1c(ext2_filsys fs, char *block_buf)
                                  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) {
@@ -385,7 +399,7 @@ static void pass1d(ext2_filsys fs, char *block_buf)
                                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;
@@ -412,18 +426,17 @@ static void pass1d(ext2_filsys fs, char *block_buf)
                /*
                 * 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)
@@ -437,28 +450,23 @@ static void pass1d(ext2_filsys fs, char *block_buf)
                        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);
 }
@@ -468,40 +476,46 @@ static int delete_file_block(ext2_filsys fs,
                             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);
@@ -509,10 +523,10 @@ static void delete_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
                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);
@@ -526,6 +540,7 @@ struct clone_struct {
        errcode_t       errcode;
        ino_t           dir;
        char    *buf;
+       e2fsck_t ctx;
 };
 
 static int clone_file_block(ext2_filsys fs,
@@ -537,16 +552,19 @@ 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;
@@ -574,10 +592,10 @@ static int clone_file_block(ext2_filsys fs,
                        }
                        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;
@@ -589,18 +607,20 @@ static int clone_file_block(ext2_filsys fs,
        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,
@@ -620,8 +640,3 @@ static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
        }
        return 0;
 }
-
-
-       
-
-       
index 2c52944a78ba5ac6a04ad419fdb67963f7ff6c8e..bcd8aa2fba9aebea4f90ecddf4e70aff7b8535ab 100644 (file)
  *     - 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,
@@ -67,30 +63,33 @@ 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");
@@ -105,33 +104,31 @@ void pass2(ext2_filsys fs)
                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)
 {
@@ -150,7 +147,7 @@ static int check_dot(ext2_filsys fs,
                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;
@@ -162,7 +159,7 @@ static int check_dot(ext2_filsys fs,
                }
        }
        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;
                }
@@ -170,9 +167,9 @@ static int check_dot(ext2_filsys fs,
        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;
@@ -191,7 +188,7 @@ static int check_dot(ext2_filsys fs,
  * 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)
 {
@@ -207,7 +204,7 @@ static int check_dotdot(ext2_filsys fs,
                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;
                        /*
@@ -232,7 +229,7 @@ static int check_dotdot(ext2_filsys fs,
  * 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)
 {
@@ -243,7 +240,7 @@ static int check_name(ext2_filsys fs,
        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] = '.';
@@ -262,19 +259,23 @@ static int check_dir_block(ext2_filsys fs,
        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;
@@ -285,7 +286,7 @@ static int check_dir_block(ext2_filsys fs,
        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;
        }
@@ -300,14 +301,16 @@ static int check_dir_block(ext2_filsys fs,
               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;
@@ -315,7 +318,7 @@ static int check_dir_block(ext2_filsys fs,
                    (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;
@@ -323,28 +326,27 @@ static int check_dir_block(ext2_filsys fs,
                        } 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;
@@ -353,44 +355,66 @@ static int check_dir_block(ext2_filsys fs,
                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;
                        }
                }
 
@@ -400,30 +424,19 @@ static int check_dir_block(ext2_filsys fs,
                 * (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
@@ -432,17 +445,17 @@ static int check_dir_block(ext2_filsys fs,
                 * 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++;
@@ -453,10 +466,11 @@ static int check_dir_block(ext2_filsys fs,
                                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);
@@ -464,15 +478,17 @@ static int check_dir_block(ext2_filsys fs,
        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);
        }
@@ -488,9 +504,11 @@ static int deallocate_inode_block(ext2_filsys 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;
 }
@@ -498,26 +516,29 @@ static int deallocate_inode_block(ext2_filsys fs,
 /*
  * 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);
 
@@ -525,16 +546,17 @@ static void deallocate_inode(ext2_filsys fs, ino_t ino,
                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;
@@ -551,31 +573,31 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
            !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++;
        }
@@ -598,7 +620,7 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
        }
        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++;
                }
@@ -606,7 +628,7 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
        }
        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++;
                }
@@ -614,12 +636,12 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
        }
 
        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++;
        }
@@ -635,34 +657,34 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
  *     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);
 
@@ -670,22 +692,22 @@ static int allocate_dir_block(ext2_filsys 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;
        }
 
@@ -702,11 +724,11 @@ static int allocate_dir_block(ext2_filsys fs,
         * 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;
        }
 
index 2f97aa4cb1bcc0f5446372788c37ba625578a133..7d7c6495d2ff2129183384021446a274c214977b 100644 (file)
 #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;
@@ -56,120 +55,120 @@ 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);
@@ -188,10 +187,10 @@ static void check_root(ext2_filsys fs)
        /*
         * 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);
        }
        
@@ -199,11 +198,11 @@ static void check_root(ext2_filsys fs)
         * 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);
 }
@@ -216,9 +215,10 @@ static void check_root(ext2_filsys 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);
@@ -258,12 +258,12 @@ static void check_directory(ext2_filsys fs, struct dir_info *dir,
         * 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);
                }
        }
 
@@ -276,8 +276,8 @@ check_dot_dot:
                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);
        }
 }      
 
@@ -285,56 +285,61 @@ check_dot_dot:
  * 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);
 
@@ -343,16 +348,16 @@ ino_t get_lost_and_found(ext2_filsys 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;
        }
 
@@ -370,18 +375,19 @@ ino_t get_lost_and_found(ext2_filsys fs)
        /*
         * 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;
        }
 
@@ -389,9 +395,9 @@ ino_t get_lost_and_found(ext2_filsys fs)
         * 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
@@ -401,44 +407,45 @@ ino_t get_lost_and_found(ext2_filsys fs)
 /*
  * 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;
 }
@@ -446,8 +453,9 @@ int reconnect_file(ext2_filsys fs, ino_t inode)
 /*
  * 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;
        
@@ -465,11 +473,11 @@ static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj)
 
        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);
        }
        
 
@@ -487,6 +495,7 @@ struct fix_dotdot_struct {
        ext2_filsys     fs;
        ino_t           parent;
        int             done;
+       e2fsck_t        ctx;
 };
 
 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
@@ -497,35 +506,42 @@ 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);
@@ -534,9 +550,11 @@ static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t 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;
@@ -552,6 +570,7 @@ static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent)
 struct expand_dir_struct {
        int     done;
        errcode_t       err;
+       e2fsck_t        ctx;
 };
 
 static int expand_dir_proc(ext2_filsys fs,
@@ -564,12 +583,16 @@ 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;
@@ -596,7 +619,7 @@ static int expand_dir_proc(ext2_filsys fs,
        }
        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)
@@ -605,8 +628,9 @@ static int expand_dir_proc(ext2_filsys fs,
                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;
@@ -620,6 +644,7 @@ static errcode_t expand_directory(ext2_filsys fs, ino_t dir)
        
        es.done = 0;
        es.err = 0;
+       es.ctx = ctx;
        
        retval = ext2fs_block_iterate(fs, dir, BLOCK_FLAG_APPEND,
                                      0, expand_dir_proc, &es);
@@ -643,6 +668,3 @@ static errcode_t expand_directory(ext2_filsys fs, ino_t dir)
 
        return 0;
 }
-
-
-               
index 627b55488bfa77e215caf50b7cd2b2bbb555a867..f5784cfd2eba5235e0d3f9270c57c43cedd8d3cc 100644 (file)
@@ -22,8 +22,9 @@
  * 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;
 
@@ -37,8 +38,8 @@ static int disconnect_inode(ext2_filsys fs, ino_t i)
                /*
                 * 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,
@@ -46,9 +47,9 @@ static int disconnect_inode(ext2_filsys fs, ino_t i)
                        /*
                         * 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;
@@ -58,8 +59,8 @@ static int disconnect_inode(ext2_filsys fs, ino_t i)
        /*
         * 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 {
                /*
@@ -74,8 +75,9 @@ static int disconnect_inode(ext2_filsys fs, ino_t i)
 }
 
 
-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;
@@ -88,52 +90,50 @@ void pass4(ext2_filsys fs)
        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);
 }
 
index def492a9fd66a9b679d36bf3f08385772914ce0c..499c92ce0e90bf56244b536d8312218b57b1081c 100644 (file)
  * 
  */
 
-#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");
@@ -32,28 +29,32 @@ void pass5(ext2_filsys fs)
 
        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;
@@ -61,21 +62,25 @@ static void check_block_bitmaps(ext2_filsys fs)
        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);
        }
                       
@@ -83,56 +88,40 @@ static void check_block_bitmaps(ext2_filsys fs)
             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++;
@@ -147,18 +136,30 @@ static void check_block_bitmaps(ext2_filsys fs)
                        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);
@@ -167,14 +168,11 @@ static void check_block_bitmaps(ext2_filsys 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
@@ -183,8 +181,9 @@ static void check_block_bitmaps(ext2_filsys fs)
        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;
@@ -194,77 +193,70 @@ static void check_inode_bitmaps(ext2_filsys fs)
        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++;
@@ -278,19 +270,31 @@ do_counts:
                        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);
@@ -298,14 +302,12 @@ do_counts:
                                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);
@@ -314,14 +316,11 @@ do_counts:
                }
        }
        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
@@ -331,17 +330,20 @@ do_counts:
        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)
@@ -349,8 +351,7 @@ static void check_inode_end(ext2_filsys fs)
        
        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);
@@ -361,27 +362,30 @@ static void check_inode_end(ext2_filsys fs)
                }
        }
 
-       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)
@@ -389,9 +393,7 @@ static void check_block_end(ext2_filsys fs)
        
        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);
@@ -402,12 +404,14 @@ static void check_block_end(ext2_filsys fs)
                }
        }
 
-       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);
        }
 }
 
+
+
index 512e2c69a99eaa80b75f7009b2f782ab97bc71c8..eae98b1167a192107b8e8ea483bbe5b348116e07 100644 (file)
 
 #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 }, 
@@ -141,12 +222,12 @@ static struct e2fsck_problem problem_table[] = {
        /* 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,
@@ -155,7 +236,7 @@ static struct e2fsck_problem problem_table[] = {
 
        /* 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) */
@@ -178,26 +259,230 @@ static struct e2fsck_problem problem_table[] = {
          "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",
@@ -323,8 +608,64 @@ static struct e2fsck_problem problem_table[] = {
          "@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.  ",
@@ -350,8 +691,83 @@ static struct e2fsck_problem problem_table[] = {
          "'..' 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.  ",
@@ -366,7 +782,107 @@ static struct e2fsck_problem problem_table[] = {
        { 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 }
 };
 
@@ -376,14 +892,17 @@ static struct e2fsck_problem problem_table[] = {
  * 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;
 
@@ -394,15 +913,53 @@ static struct e2fsck_problem *find_problem(int code)
        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)
@@ -412,11 +969,13 @@ 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;
 
@@ -432,45 +991,72 @@ int fix_problem(ext2_filsys fs, int code, struct problem_context *ctx)
         * 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;
 }
index 5e1fd9ba048318220e0f5166c44f3046cc2be3c4..3fbbb2ad65a48c6572f41f32f6f767e8057fb2d7 100644 (file)
@@ -9,26 +9,43 @@
  * %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
@@ -38,9 +55,23 @@ struct e2fsck_problem {
 #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
  */
@@ -54,84 +85,234 @@ struct e2fsck_problem {
 /* 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
 
@@ -207,30 +388,107 @@ struct e2fsck_problem {
 /* 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
 
@@ -240,19 +498,77 @@ struct e2fsck_problem {
 /* 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);
 
index 29d1e888537933f06121f2ee5299697204144602..f82e67f9cdf909a85f19cb3fdd8f1d24100cc29a 100644 (file)
@@ -72,7 +72,7 @@ static __inline__ float timeval_subtract(struct timeval *tv1,
                ((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;
diff --git a/e2fsck/super.c b/e2fsck/super.c
new file mode 100644 (file)
index 0000000..d6a0c98
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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;
+}
+
index a317cc789f7fd024fadf333a8fc8a58ac71bfc41..64d4775a086b45455a4c9ca11eaf92d3d4c45252 100644 (file)
@@ -102,8 +102,9 @@ static void swap_inode_blocks(ext2_filsys fs, ino_t ino, char *block_buf,
        }
 }
 
-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;
@@ -135,8 +136,8 @@ static void swap_inodes(ext2_filsys fs)
                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);
@@ -173,13 +174,14 @@ static void swap_inodes(ext2_filsys fs)
        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
@@ -190,7 +192,7 @@ void swap_filesys(ext2_filsys fs)
                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) {
@@ -201,17 +203,15 @@ void swap_filesys(ext2_filsys fs)
                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);
 }
 
 
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
new file mode 100644 (file)
index 0000000..7bc0963
--- /dev/null
@@ -0,0 +1,651 @@
+/*
+ * 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;
+}
index 24f77d268151d5ac3d40f3cd9cae3da59d4b3335..879e7baafd67368bde17f004c9863d6affd95893 100644 (file)
 #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);
 }
 
@@ -46,7 +44,6 @@ void *allocate_memory(int size, const char *description)
        return ret;
 }
 
-
 int ask_yn(const char * string, int def)
 {
        int             c;
@@ -91,31 +88,32 @@ int ask_yn(const char * string, int def)
        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);
        }
 
@@ -123,15 +121,16 @@ void read_bitmaps(ext2_filsys fs)
        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)) {
@@ -139,9 +138,9 @@ void write_bitmaps(ext2_filsys 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);
                }
        }
@@ -151,21 +150,23 @@ void write_bitmaps(ext2_filsys fs)
                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);
@@ -183,6 +184,9 @@ void init_resource_track(struct resource_track *track)
        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;
@@ -205,7 +209,7 @@ static _INLINE_ float timeval_subtract(struct timeval *tv1,
                ((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;
@@ -213,6 +217,10 @@ void print_resource_track(struct resource_track *track)
        struct timeval time_end;
 
        gettimeofday(&time_end, 0);
+
+       if (desc)
+               printf("%s :", desc);
+       
 #ifdef HAVE_GETRUSAGE
        getrusage(RUSAGE_SELF, &r);
 
@@ -265,4 +273,10 @@ void mtrace_print(char *mesg)
 }
 #endif
 
+blk_t get_backup_sb(ext2_filsys fs)
+{
+       if (!fs || !fs->super)
+               return 8193;
+       return fs->super->s_blocks_per_group + 1;
+}
 
index 208543fa5d17f9ea12c12da81b6eed18d2fe6721..d64e745fdcba3d6d7ce129462716066529e82b7e 100644 (file)
@@ -13,11 +13,15 @@ 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:  +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
index f8f025586dd7a44a78ec4bc46906f93a74649a45..375a2bf9c0696be9f3d331da6c61129397c5be2c 100644 (file)
@@ -36,12 +36,18 @@ Pass 4: Checking reference counts
 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
index 77b8f8cf86ab64afb14a82c337337f966225cb97..e24aa94ff9f442a718d2cce0091cb49fb3e43966 100644 (file)
@@ -47,10 +47,12 @@ Fix? yes
 
 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
index 67120d09ce0f147c7aaa15b53ec9456d1f3b13f7..29af17bafa154482a0f79d08990bff43fc2dec54 100644 (file)
@@ -20,13 +20,21 @@ Clear? yes
 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
index bca07d2bf87cc5f3338c7c9f3bb1fb6c80b8d348..eb498ff5c23980008260a7f6e2724e9946df5e5f 100644 (file)
@@ -4,18 +4,20 @@ Pass 1: Checking inodes, blocks, and sizes
 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
index cd73a334e7a88fcb737a7ffca17d3081b180a16a..187c49a49fbad4f32a9cde6a030123bf25d97178 100644 (file)
@@ -23,13 +23,21 @@ Connect to /lost+found? yes
 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
index 11bbc970a6d7e4a3f0877210fe5b47d3ec50c435..5cb96176d516b834088d8da9523da32a572aa69a 100644 (file)
@@ -16,15 +16,27 @@ Pass 4: Checking reference counts
 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
index 8dcbc4f5e01b788ee0ffbe2efe8283fddc04236f..6ffed26403b0aa59d65b1e9efc1ef64625868d87 100644 (file)
@@ -18,28 +18,29 @@ File /termcap (inode #12, mod time Sun Jan  2 08:29:13 1994)
        <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
index 91de7461e477189e50a3c7521758e0c02c09faf2..0a3ab1075559b78281a760b537b1e5a92088769e 100644 (file)
@@ -27,14 +27,24 @@ Clear? yes
 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
index 9b15ea2b704cfd0ecc7df900802454e1bba3f0dc..715984d4dc74665ea24d72f1ce94e4dfa204512d 100644 (file)
@@ -5,10 +5,12 @@ 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:  +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
index 082c5454b9a466fbb395d799ae5e57aa6f8038e3..8375b4ed5c6d9019fdf05db6f4272080198db36b 100644 (file)
@@ -14,7 +14,6 @@ File /motd (inode #13, mod time Tue Sep 21 03:19:20 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)
@@ -24,10 +23,12 @@ 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
+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
 
 
index f9962952ad56555a23f8ff7cf151efcaf6648f94..ff5d30ac41a96e739f6cfe3d3c58b024f029637a 100644 (file)
@@ -15,14 +15,12 @@ File /pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
        /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)
@@ -32,10 +30,12 @@ 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
+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
 
 
index 1adda3b38ded0aec8b23b2665ce45f5dba93a629..1249f395fa1ea9d797dc5b4100ffcde3677e5bc3 100644 (file)
@@ -13,7 +13,6 @@ File /foo (inode #12, mod time Thu Apr 28 17:57:53 1994)
        <filesystem metadata>
 Clone duplicate/bad blocks? yes
 
-
 Pass 2: Checking directory structure
 Directory inode 12, block 1, offset 0: directory corrupted
 Salvage? yes
@@ -27,10 +26,12 @@ 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
index 61603bffc501f5faf89ae2412a50579e36758fa0..6fff1c054b827858949fb7dd1458af584b3849da 100644 (file)
@@ -13,14 +13,13 @@ File /termcap (inode #12, mod time Sun Jan  2 08:29:13 1994)
        <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
index f2beea6221c7e615ed29882ee2c754337155fe11..87e2fd647bbbd37e0e369f942c1ed2b97f349129 100644 (file)
@@ -5,9 +5,9 @@ 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
+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
 
 
index 86aba903225f2e880185c3ffbf6356396f5cb4ec..e8fffdb3dca79fab982099e4a24b15123b3f1cd6 100644 (file)
@@ -518,13 +518,21 @@ Connect to /lost+found? 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
index d22dbf2a21effd0b4f4d46049b60a8d3b5ae0419..0d20dec604d5fea66916a78e482058d965d8f281 100644 (file)
@@ -16,11 +16,11 @@ 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:  +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 *****
index 4e4d996cba069531331e0fd09706ada6209f4fd4..b2ffc3600f42415d10440c1c43c96bd541976215 100644 (file)
@@ -16,9 +16,9 @@ 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
+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
index e0af316ef3527dcc37618213dc77a15202c0d17a..aef002c4a7812ab33da135d71d312587f15e39da 100644 (file)
@@ -23,15 +23,27 @@ Root inode not allocated.  Allocate? yes
 
 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
index fd491d50bed64d3abd8b6a59a7dbda8163982a1a..8a0f06a3053ae15e05fc6a8bc4449f1df854fcd9 100644 (file)
@@ -25,14 +25,24 @@ Entry 'termcap' in / (2) has deleted/unused inode 12.  Clear? yes
 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
index 3803029a12c018e0fd8f036ac50eaa139fb18fd1..83261fcda5423e430d51a655eee444a7cb89366d 100644 (file)
@@ -24,16 +24,26 @@ Connect to /lost+found? yes
 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 *****
index 32b2a15c8553ae95e422d9b5b653c85561f67989..ae5f52ac786160e770a12e8cdff69ded62f3865f 100644 (file)
@@ -24,11 +24,15 @@ Clear? yes
 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
index 83514548bf957a62d06f2b1c39795b9473a4294c..5e7746136f85fd3a095f8f820f4763d6b616a970 100644 (file)
@@ -21,15 +21,27 @@ Pass 4: Checking reference counts
 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
index cef02279d9ff0c4227d3c2813de04f30db998d69..cc90d93a6bfbdf8090880e5e243bd31f8f8be839 100644 (file)
@@ -27,13 +27,21 @@ Inode 12 ref count is 4, should be 3.  Fix? yes
 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
index d0f47ebd40bd7dcfb4a467bd0ea6528747279de4..a38b914273a76895cc3e54ec90b59db632814c3d 100644 (file)
@@ -9,9 +9,9 @@ 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
+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
index 9d30709d7fef9c1acbbda4cda734e52fa9d16935..a7f6ce10d20579e4fdbc24f5d47113b61675c58e 100644 (file)
@@ -3,15 +3,27 @@ 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
-
-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
index c066e8c4847a8a8b626d271fcb4eab8819c2e5b7..20796198dabce6d7c0fbd0a512beeae8b23f8c80 100644 (file)
@@ -4,12 +4,18 @@ 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
+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
index ff9e1b3b311b3af5cda5451aac907779f4291dd2..a7a6b480dc32c9e2ef52e022138afbfaaf8d51b7 100644 (file)
@@ -4,12 +4,18 @@ 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
+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