Many files:
Checkin of e2fsprogs 0.5b
diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c
index 37d202b..78fe3c9 100644
--- a/e2fsck/e2fsck.c
+++ b/e2fsck/e2fsck.c
@@ -51,6 +51,7 @@
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;
@@ -63,11 +64,17 @@
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 [-panyrdfvtFV] [-b superblock] [-B blocksize]\n"
- "\t\tdevice\n", program_name);
+ "Usage: %s [-panyrcdfvtFV] [-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);
}
@@ -182,34 +189,133 @@
sync();
}
+#define MIN_CHECK 1
+#define MAX_CHECK 2
+
+static const char *corrupt_msg = "\nThe filesystem superblock is corrupt. "
+ "Try running e2fsck with an alternate\n"
+ "superblock using the -b option. "
+ "(8193 is commonly an alternate superblock;\n"
+ "Hence, 'e2fsck -b 8193 <device>' may recover the filesystem.)\n\n";
+
+static void check_super_value(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);
+ fatal_error(0);
+ }
+}
+
static void check_super_block(ext2_filsys fs)
{
blk_t first_block, last_block;
- int blocks_per_group = fs->super->s_blocks_per_group;
+ struct ext2_super_block *s = fs->super;
+ blk_t blocks_per_group = fs->super->s_blocks_per_group;
int i;
+ blk_t should_be;
+ /*
+ * Verify the super block constants...
+ */
+ check_super_value("inodes_count", s->s_inodes_count,
+ MIN_CHECK, 1, 0);
+ check_super_value("blocks_count", s->s_blocks_count,
+ MIN_CHECK, 1, 0);
+ check_super_value("first_data_block", s->s_first_data_block,
+ MAX_CHECK, 0, s->s_blocks_count);
+ check_super_value("log_frag_size", s->s_log_frag_size,
+ MAX_CHECK, 0, 2);
+ check_super_value("log_block_size", s->s_log_block_size,
+ MIN_CHECK | MAX_CHECK, s->s_log_frag_size,
+ 2);
+ check_super_value("frags_per_group", s->s_frags_per_group,
+ MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
+ check_super_value("blocks_per_group", s->s_blocks_per_group,
+ MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
+ check_super_value("inodes_per_group", s->s_inodes_per_group,
+ MIN_CHECK, 1, 0);
+ check_super_value("r_blocks_count", s->s_r_blocks_count,
+ MAX_CHECK, 0, s->s_blocks_count);
+
+ 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 = %lu, should "
+ "have been %lu\n", s->s_blocks_per_group,
+ should_be);
+ printf(corrupt_msg);
+ }
+
+ should_be = (s->s_log_block_size == 0) ? 1 : 0;
+ if (s->s_first_data_block != should_be) {
+ printf("Superblock first_data_block = %lu, should "
+ "have been %lu\n", s->s_first_data_block,
+ should_be);
+ printf(corrupt_msg);
+ }
+
+ /*
+ * 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++) {
+ 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)) {
- printf("Block bitmap %ld for group %d not in group.\n",
+ printf("Block bitmap %lu for group %d is "
+ "not in group.\n",
fs->group_desc[i].bg_block_bitmap, i);
- fatal_error(0);
+ preenhalt();
+ if (!ask("Continue (and relocate)", 1)) {
+ fatal_error(0);
+ }
+ 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)) {
- printf("Inode bitmap %ld for group %d not in group.\n",
+ printf("Warning: Inode bitmap %lu for group %d "
+ "not in group.\n",
fs->group_desc[i].bg_inode_bitmap, i);
- fatal_error(0);
+ preenhalt();
+ if (!ask("Continue", 1)) {
+ fatal_error(0);
+ }
+ 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)) {
- printf("Inode table %ld for group %d not in group.\n",
+ printf("Warning: Inode table %lu for group %d "
+ "not in group.\n",
fs->group_desc[i].bg_inode_table, i);
- fatal_error(0);
+ printf("WARNING: SEVERE DATA LOSS POSSIBLE.\n");
+ preenhalt();
+ if (!ask("Continue", 1)) {
+ fatal_error(0);
+ }
+ 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;
@@ -250,12 +356,13 @@
static void PRS(int argc, char *argv[])
{
- int flush = 0;
- char c;
+ int flush = 0;
+ char c;
#ifdef MTRACE
- extern void *mallwatch;
+ extern void *mallwatch;
#endif
- char *oldpath, newpath[PATH_MAX];
+ char *oldpath;
+ static char newpath[PATH_MAX];
/* Update our PATH to include /sbin */
strcpy(newpath, "PATH=/sbin:");
@@ -392,6 +499,7 @@
if (!isatty (0) || !isatty (1))
die ("need terminal for interactive repairs");
}
+restart:
sync_disks();
if (superblock && blocksize) {
retval = ext2fs_open(device_name, rwflag ? EXT2_FLAG_RW : 0,
@@ -413,9 +521,21 @@
if (retval) {
com_err(program_name, retval, "while trying to open %s",
device_name);
- printf("Couldn't find valid filesystem superblock.\n");
+ if (retval == EXT2_ET_REV_TOO_HIGH)
+ printf ("Get a newer version of e2fsck!\n");
+ else
+ printf(corrupt_msg);
fatal_error(0);
}
+
+#ifdef EXT2_CURRENT_REV
+ if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
+ com_err(program_name, retval, "while trying to open %s",
+ device_name);
+ printf ("Get a newer version of e2fsck!\n");
+ fatal_error(0);
+ }
+#endif
/*
* If the user specified a specific superblock, presumably the
* master superblock has been trashed. So we mark the
@@ -426,6 +546,16 @@
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)
@@ -439,6 +569,12 @@
ext2fs_mark_valid(fs);
pass1(fs);
+ if (restart_e2fsck) {
+ ext2fs_close(fs);
+ printf("Restarting e2fsck from the beginning...\n");
+ restart_e2fsck = 0;
+ goto restart;
+ }
pass2(fs);
pass3(fs);
pass4(fs);