Many files:
Checked in e2fsprogs 1.05
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 1ea0a58..fcab1e6 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,3 +1,60 @@
+Fri Aug 30 20:24:30 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * pass4.c (pass4): If the user refuses to connect an unattached
+ inode to lost+found, don't try to set i_links_count. This
+ is bad, since if the user says yes, the inode will be
+ marked as unused, which is not necessarily the right
+ thing, especially since the rest of the cleanup doesn't
+ happen here.
+
+ * pass2.c (deallocate_inode): Set inode_link_info[ino] when
+ dellocating an inode. (Not strictly necessary, but...)
+
+ * pass4.c (pass4): Add "bonehead" explanation to the "programming
+ error" message.
+
+Tue Aug 27 11:26:32 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * e2fsck.c (PRS,main): Added new options -s and -S. -s will
+ byte-swap the filesystem so that it is normalized. -S
+ will byte-swap the filesystem regardless of its current
+ byte-order.
+
+ * swapfs.c: New file, which will byte-swap a filesystem.
+
+Tue Aug 20 09:41:37 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * pass1.c (pass1): Change handling on files with non-zero dtime
+ and non-zero i_link_count; before we treated them as
+ deleted file per botched ext2 0.3c kernel behavior. We
+ now clear dtime instead.
+
+Mon Aug 19 23:33:57 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * e2fsck.c (main): If e2fsck sets the clean bit, even if
+ nothing else is changed, make sure FSCK_NONDESTRUCT is
+ set (since after all having the filesystem set to
+ invalid is an error. :-)
+
+Fri Aug 9 10:25:13 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * pass1.c (process_block): Make sure that meta data doesn't get
+ accidentally set in the dir_blocks array (which could
+ happen in some error condtions).
+
+ * pass1.c (pass1):
+ * pass2.c (process_bad_inode): Check for fragments in a
+ OS-independent fashion.
+
+Thu Aug 8 15:20:54 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * e2fsck.c (check_if_skip): Close the filesystem when skipping the
+ cleanup for the filesystem.
+
+Mon Jul 22 22:03:28 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * e2fsck.c: Improve corrupt_msg, so that it's less confusing.
+
Thu May 16 11:12:30 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.04
diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in
index 8e2e51c..f4330c3 100644
--- a/e2fsck/Makefile.in
+++ b/e2fsck/Makefile.in
@@ -6,6 +6,7 @@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
top_builddir = ..
+my_dir = e2fsck
INSTALL = @INSTALL@
LDFLAG_STATIC = @LDFLAG_STATIC@
@@ -14,14 +15,14 @@
PROGS= e2fsck extend @EXTRA_PROGS@
MANPAGES= e2fsck.8
-LIBS= $(LIBEXT2FS) $(LIBCOM_ERR)
-DEPLIBS= $(LIBEXT2FS) $(LIBCOM_ERR)
+LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBUUID)
+DEPLIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBUUID)
-STATIC_LIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
-STATIC_DEPLIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR)
+STATIC_LIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(STATIC_LIBUUID)
+STATIC_DEPLIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(STATIC_LIBUUID)
-PROFILED_LIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR)
-PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR)
+PROFILED_LIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBUUID)
+PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBUUID)
.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $@
@@ -52,12 +53,12 @@
#MCHECK= -DMCHECK
OBJS= e2fsck.o pass1.o pass1b.o pass2.o pass3.o pass4.o pass5.o \
- badblocks.o util.o dirinfo.o ehandler.o $(MTRACE_OBJ)
+ swapfs.o badblocks.o util.o dirinfo.o ehandler.o $(MTRACE_OBJ)
PROFILED_OBJS= profiled/e2fsck.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/ehandler.o profiled/swapfs.o
SRCS= $(srcdir)/e2fsck.c \
$(srcdir)/pass1.c \
@@ -72,7 +73,7 @@
$(srcdir)/ehandler.c \
$(MTRACE_SRC)
-all:: profiled $(PROGS) e2fsck.static e2fsck.shared
+all:: profiled $(PROGS) e2fsck.static e2fsck.shared $(MANPAGES)
@PROFILE_CMT@all:: e2fsck.profiled
@@ -142,39 +143,35 @@
# Makefile dependencies follow. This must be the last section in
# the Makefile.in file
#
-e2fsck.o: $(srcdir)/e2fsck.c \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
- $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \
- $(srcdir)/../version.h
+e2fsck.o: $(srcdir)/e2fsck.c $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/uuid/uuid.h $(srcdir)/e2fsck.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/../version.h
pass1.o: $(srcdir)/pass1.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
-pass1b.o: $(srcdir)/pass1b.c \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
+pass1b.o: $(srcdir)/pass1b.c $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h
+pass2.o: $(srcdir)/pass2.c $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
-pass2.o: $(srcdir)/pass2.c $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/e2fsck.h \
- $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h
-pass3.o: $(srcdir)/pass3.c \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
- $(top_srcdir)/lib/ext2fs/ext2fs.h \
- $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
- $(top_srcdir)/lib/ext2fs/bitops.h
+pass3.o: $(srcdir)/pass3.c $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/bitops.h \
+ $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
pass4.o: $(srcdir)/pass4.c $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
pass5.o: $(srcdir)/pass5.c $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
- $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h
-badblocks.o: $(srcdir)/badblocks.c \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
- $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/bitops.h \
+ $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
+badblocks.o: $(srcdir)/badblocks.c $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
util.o: $(srcdir)/util.c $(srcdir)/e2fsck.h \
@@ -182,13 +179,10 @@
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
dirinfo.o: $(srcdir)/dirinfo.c $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/e2fsck.h \
- $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h
-ehandler.o: $(srcdir)/ehandler.c \
- $(srcdir)/e2fsck.h \
+ $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h
+ehandler.o: $(srcdir)/ehandler.c $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
-
-
diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in
index bfd20f3..cb71505 100644
--- a/e2fsck/e2fsck.8.in
+++ b/e2fsck/e2fsck.8.in
@@ -8,7 +8,7 @@
.SH SYNOPSIS
.B e2fsck
[
-.B \-pacnyrdfvtFV
+.B \-pacnyrdfvstFSV
]
[
.B \-b
@@ -104,6 +104,15 @@
.I -r
This option does nothing at all; it is provided only for backwards
compatibility.
+.IP
+.I -s
+This option will byte-swap the filesystem so that it is using the normalized,
+standard byte-order (which is i386 or little endian). If the filesystem is
+already in the standard byte-order, e2fsck will take no action.
+.TP
+.I -S
+This option will byte-swap the filesystem, regardless of its current
+byte-order.
.TP
.I -t
Print timing statistics for
diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c
index 6dbfa6f..9048298 100644
--- a/e2fsck/e2fsck.c
+++ b/e2fsck/e2fsck.c
@@ -17,6 +17,10 @@
* 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>
@@ -36,6 +40,7 @@
#include <malloc.h>
#include "et/com_err.h"
+#include "uuid/uuid.h"
#include "e2fsck.h"
#include "../version.h"
@@ -52,6 +57,8 @@
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 superblock;
int blocksize = 0;
@@ -80,7 +87,7 @@
static void usage(NOARGS)
{
fprintf(stderr,
- "Usage: %s [-panyrcdfvtFV] [-b superblock] [-B blocksize]\n"
+ "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);
@@ -206,11 +213,12 @@
#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 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 8193 <device>\n\n";
static void check_super_value(const char *descr, unsigned long value,
int flags, unsigned long min, unsigned long max)
@@ -224,7 +232,7 @@
}
}
-static void relocate_hint()
+static void relocate_hint(void)
{
static hint_issued = 0;
@@ -245,7 +253,7 @@
static void check_super_block(ext2_filsys fs)
{
blk_t first_block, last_block;
- struct ext2_super_block *s = fs->super;
+ 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;
@@ -375,6 +383,20 @@
first_block += fs->super->s_blocks_per_group;
last_block += fs->super->s_blocks_per_group;
}
+
+ /*
+ * 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;
}
@@ -387,7 +409,7 @@
{
const char *reason = NULL;
- if (force || bad_blocks_file || cflag)
+ if (force || bad_blocks_file || cflag || swapfs)
return;
if (fs->super->s_state & EXT2_ERROR_FS)
@@ -409,6 +431,7 @@
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);
}
}
@@ -444,7 +467,7 @@
if (argc && *argv)
program_name = *argv;
- while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:N:")) != EOF)
+ while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:N:Ss")) != EOF)
switch (c) {
case 'p':
case 'a':
@@ -515,6 +538,11 @@
case 'N':
device_name = optarg;
break;
+ case 's':
+ normalize_swapfs = 1;
+ case 'S':
+ swapfs = 1;
+ break;
default:
usage ();
}
@@ -522,7 +550,7 @@
return;
if (optind != argc - 1)
usage ();
- if (nflag && !bad_blocks_file && !cflag)
+ if (nflag && !bad_blocks_file && !cflag && !swapfs)
rwflag = 0;
filesystem_name = argv[optind];
if (device_name == 0)
@@ -546,6 +574,13 @@
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);
+ }
+ }
}
int main (int argc, char *argv[])
@@ -604,25 +639,18 @@
if (retval) {
com_err(program_name, retval, "while trying to open %s",
filesystem_name);
- switch (retval) {
- case EXT2_ET_REV_TOO_HIGH:
+ if (retval == EXT2_ET_REV_TOO_HIGH)
printf ("Get a newer version of e2fsck!\n");
- break;
- case EXT2_ET_SHORT_READ:
+ else if (retval == EXT2_ET_SHORT_READ)
printf ("Could this be a zero-length partition?\n");
- break;
- case EPERM:
- case EACCES:
+ else if ((retval == EPERM) || (retval == EACCES))
printf("You must have %s access to the "
"filesystem or be root\n",
rwflag ? "r/w" : "r/o");
- break;
- case ENXIO:
+ else if (retval == ENXIO)
printf("Possibly non-existent or swap device?\n");
- break;
- default:
+ else
printf(corrupt_msg);
- }
fatal_error(0);
}
@@ -662,11 +690,21 @@
else if (cflag)
test_disk(fs);
+ if (normalize_swapfs) {
+ if ((fs->flags & EXT2_SWAP_BYTES) == ext2fs_native_flag()) {
+ fprintf(stderr, "%s: Filesystem byte order "
+ "already normalized.\n", device_name);
+ fatal_error(0);
+ }
+ }
+ if (swapfs)
+ swap_filesys(fs);
+
/*
* Mark the system as valid, 'til proven otherwise
*/
ext2fs_mark_valid(fs);
-
+
pass1(fs);
free(invalid_inode_bitmap);
free(invalid_block_bitmap);
@@ -698,9 +736,11 @@
if (!ext2fs_test_valid(fs))
exit_value = FSCK_UNCORRECTED;
if (rwflag) {
- if (ext2fs_test_valid(fs))
+ 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
+ } else
fs->super->s_state &= ~EXT2_VALID_FS;
fs->super->s_mnt_count = 0;
fs->super->s_lastcheck = time(NULL);
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index dea265d..2e0fa77 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -42,7 +42,7 @@
* The last ext2fs revision level that this version of e2fsck is able to
* support
*/
-#define E2FSCK_CURRENT_REV 0
+#define E2FSCK_CURRENT_REV 1
/*
* Inode count arrays
@@ -145,6 +145,12 @@
extern int invalid_bitmaps;
/*
+ * For pass1_check_directory and pass1_get_blocks
+ */
+extern ino_t stashed_ino;
+extern struct ext2_inode *stashed_inode;
+
+/*
* Procedure declarations
*/
@@ -155,6 +161,14 @@
extern void pass4(ext2_filsys fs);
extern void pass5(ext2_filsys fs);
+/* pass1.c */
+extern errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino);
+extern errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks);
+extern errcode_t pass1_read_inode(ext2_filsys fs, ino_t ino,
+ struct ext2_inode *inode);
+extern errcode_t pass1_write_inode(ext2_filsys fs, ino_t ino,
+ struct ext2_inode *inode);
+
/* badblock.c */
extern void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
int replace_bad_blocks);
@@ -171,6 +185,9 @@
extern const char *ehandler_operation(const char *op);
extern void ehandler_init(io_channel channel);
+/* swapfs.c */
+void swap_filesys(ext2_filsys fs);
+
/* util.c */
extern void *allocate_memory(int size, const char *description);
extern int ask(const char * string, int def);
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 58f3c69..27ceecd 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -69,8 +69,6 @@
ext2fs_block_bitmap block_dup_map = 0;
ext2fs_block_bitmap block_illegal_map = 0;
-static int fix_link_count = -1;
-
unsigned short * inode_link_info = NULL;
static int process_block(ext2_filsys fs, blk_t *blocknr,
@@ -80,8 +78,6 @@
static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
char *block_buf);
static void mark_table_blocks(ext2_filsys fs);
-static errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino);
-static errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks);
static void alloc_bad_map(ext2_filsys fs);
static void handle_fs_bad_blocks(ext2_filsys fs);
static void process_inodes(ext2_filsys fs, char *block_buf);
@@ -170,6 +166,7 @@
char *block_buf;
errcode_t retval;
struct resource_track rtrack;
+ unsigned char frag, fsize;
init_resource_track(&rtrack);
@@ -229,6 +226,8 @@
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) {
@@ -297,12 +296,6 @@
inode.i_dtime = 0;
e2fsck_write_inode(fs, ino, &inode,
"pass1");
- printf("Note: /lost+found will "
- "probably be deleted as well, "
- "due to the mke2fs bug.\n"
- "Be sure to run mklost+found "
- "to recreate it after e2fsck "
- "finishes.\n\n");
} else
ext2fs_unmark_valid(fs);
}
@@ -340,37 +333,44 @@
goto next;
}
/*
- * 0.3c ext2fs code didn't clear i_links_count for
+ * n.b. 0.3c ext2fs code didn't clear i_links_count for
* deleted files. Oops.
+ *
+ * Since all new ext2 implementations get this right,
+ * we now assume that the case of non-zero
+ * i_links_count and non-zero dtime means that we
+ * should keep the file, not delete it.
*
- * In the future, when the new ext2fs behavior is the
- * norm, we may want to handle the case of a non-zero
- * i_links_count and non-zero dtime by clearing dtime
- * and assuming the inode is in use, instead of
- * assuming the inode is not in use.
*/
if (inode.i_dtime) {
- if (fix_link_count == -1) {
- printf("\nDeleted inode detected with non-zero link count.\n");
- printf("This is probably due to old ext2fs kernel code. \n");
- fix_link_count = ask("Fix inode(s)", 1);
- }
- printf("Inode %lu is deleted w/ non-zero link_count. %s\n",
- ino, clear_msg[fix_link_count]);
- if (fix_link_count) {
- inode.i_links_count = 0;
- inode_link_info[ino] = 0;
+ printf("Inode %lu is in use, but has dtime set\n",
+ ino);
+ if (ask("Clear dtime", 1)) {
+ inode.i_dtime = 0;
e2fsck_write_inode(fs, ino, &inode, "pass1");
} else
ext2fs_unmark_valid(fs);
- goto next;
}
ext2fs_mark_inode_bitmap(inode_used_map, ino);
- if (inode.i_faddr
-#if HAVE_EXT2_FRAGS
- || inode.i_frag || inode.i_fsize
-#endif
+ switch (fs->super->s_creator_os) {
+ case EXT2_OS_LINUX:
+ frag = inode.osd2.linux2.l_i_frag;
+ fsize = inode.osd2.linux2.l_i_fsize;
+ break;
+ case EXT2_OS_HURD:
+ frag = inode.osd2.hurd2.h_i_frag;
+ fsize = inode.osd2.hurd2.h_i_fsize;
+ break;
+ case EXT2_OS_MASIX:
+ frag = inode.osd2.masix2.m_i_frag;
+ fsize = inode.osd2.masix2.m_i_fsize;
+ break;
+ default:
+ frag = fsize = 0;
+ }
+
+ if (inode.i_faddr || frag || fsize
|| inode.i_file_acl || inode.i_dir_acl) {
if (!inode_bad_map)
alloc_bad_map(fs);
@@ -448,10 +448,13 @@
}
pass1_dupblocks(fs, block_buf);
}
- fs->get_blocks = 0;
- fs->check_directory = 0;
free(inodes_to_process);
endit:
+ fs->get_blocks = 0;
+ fs->check_directory = 0;
+ fs->read_inode = 0;
+ fs->write_inode = 0;
+
free(block_buf);
ext2fs_free_block_bitmap(block_illegal_map);
block_illegal_map = 0;
@@ -747,6 +750,10 @@
if (blk == 0) {
if (p->is_dir == 0) {
+ /*
+ * Should never happen, since only directories
+ * get called with BLOCK_FLAG_HOLE
+ */
printf("process_block() called with blk == 0, "
"inode %lu???", p->ino);
return 0;
@@ -818,12 +825,10 @@
mark_block_used(fs, blk);
p->num_blocks++;
- if (blockcnt < 0)
- return 0;
-
- p->last_block = blockcnt;
+ if (blockcnt >= 0)
+ p->last_block = blockcnt;
mark_dir:
- if (p->is_dir) {
+ if (p->is_dir && (blockcnt >= 0)) {
if (dir_block_count >= dir_block_size) {
dir_block_size += 100;
dir_blocks = realloc(dir_blocks,
@@ -1208,7 +1213,7 @@
* structure, so there's no point in letting the ext2fs library read
* the inode again.
*/
-static errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks)
+errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks)
{
int i;
@@ -1223,7 +1228,23 @@
exit(FSCK_ERROR);
}
-static errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino)
+errcode_t pass1_read_inode(ext2_filsys fs, ino_t ino, struct ext2_inode *inode)
+{
+ if (ino != stashed_ino)
+ return EXT2_ET_CALLBACK_NOTHANDLED;
+ *inode = *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;
+ 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))
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index 287c24f..b3bc833 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -98,12 +98,6 @@
static struct dup_inode *dup_ino = 0;
static int dup_inode_count = 0;
-/*
- * For pass1_check_directory and pass1_get_blocks
- */
-extern ino_t stashed_ino;
-extern struct ext2_inode *stashed_inode;
-
static ext2fs_inode_bitmap inode_dup_map;
/*
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index f4a4d32..91bcc08 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -530,6 +530,7 @@
errcode_t retval;
struct ext2_inode inode;
+ inode_link_info[ino] = 0;
e2fsck_read_inode(fs, ino, &inode, "deallocate_inode");
inode.i_links_count = 0;
inode.i_dtime = time(0);
@@ -609,6 +610,7 @@
errcode_t retval;
int inode_modified = 0;
char *pathname;
+ unsigned char *frag, *fsize;
e2fsck_read_inode(fs, ino, &inode, "process_bad_inode");
retval = ext2fs_get_pathname(fs, dir, ino, &pathname);
@@ -634,23 +636,30 @@
}
check_for_zero_u32(fs, ino, pathname, "i_faddr", &inode.i_faddr,
&inode_modified);
-#if HAVE_EXT2_FRAGS
- check_for_zero_u8(fs, ino, pathname, "i_frag", &inode.i_frag,
- &inode_modified);
- check_for_zero_u8(fs, ino, pathname, "i_fsize", &inode.i_fsize,
- &inode_modified);
-#else
- /*
- * Even if the OS specific fields don't support i_frag and
- * i_fsize, make sure they are set to zero anyway. This may
- * cause problems if on some other OS these fields are reused
- * for something else, but that's probably a bad idea....
- */
- check_for_zero_u8(fs, ino, pathname, "i_frag",
- &inode.osd2.linux2.l_i_frag, &inode_modified);
- check_for_zero_u8(fs, ino, pathname, "i_fsize",
- &inode.osd2.linux2.l_i_fsize, &inode_modified);
-#endif
+
+ switch (fs->super->s_creator_os) {
+ case EXT2_OS_LINUX:
+ frag = &inode.osd2.linux2.l_i_frag;
+ fsize = &inode.osd2.linux2.l_i_fsize;
+ break;
+ case EXT2_OS_HURD:
+ frag = &inode.osd2.hurd2.h_i_frag;
+ fsize = &inode.osd2.hurd2.h_i_fsize;
+ break;
+ case EXT2_OS_MASIX:
+ frag = &inode.osd2.masix2.m_i_frag;
+ fsize = &inode.osd2.masix2.m_i_fsize;
+ break;
+ default:
+ frag = fsize = 0;
+ }
+ if (frag)
+ check_for_zero_u8(fs, ino, pathname, "i_frag", frag,
+ &inode_modified);
+ if (fsize)
+ check_for_zero_u8(fs, ino, pathname, "i_fsize", fsize,
+ &inode_modified);
+
check_for_zero_u32(fs, ino, pathname, "i_file_acl", &inode.i_file_acl,
&inode_modified);
check_for_zero_u32(fs, ino, pathname, "i_dir_acl", &inode.i_dir_acl,
diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c
index dde578b..f167d15 100644
--- a/e2fsck/pass4.c
+++ b/e2fsck/pass4.c
@@ -38,13 +38,23 @@
if (ask("Connect to /lost+found", 1)) {
if (reconnect_file(fs, i))
ext2fs_unmark_valid(fs);
- } else
+ } else {
+ /*
+ * If we don't attach the inode, then
+ * skip the i_links_test since there's
+ * no point in trying to force
+ * i_links_count to zero.
+ */
ext2fs_unmark_valid(fs);
+ continue;
+ }
}
if (inode_count[i] != inode_link_info[i]) {
e2fsck_read_inode(fs, i, &inode, "pass4");
if (inode_link_info[i] != 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",
diff --git a/e2fsck/swapfs.c b/e2fsck/swapfs.c
new file mode 100644
index 0000000..291fcb3
--- /dev/null
+++ b/e2fsck/swapfs.c
@@ -0,0 +1,199 @@
+/*
+ * swapfs.c --- byte-swap an ext2 filesystem
+ */
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <et/com_err.h>
+#include "e2fsck.h"
+
+struct swap_block_struct {
+ ino_t ino;
+ int isdir;
+ errcode_t errcode;
+ char *dir_buf;
+ struct ext2_inode *inode;
+};
+
+/*
+ * This is a helper function for block_iterate. We mark all of the
+ * indirect and direct blocks as changed, so that block_iterate will
+ * write them out.
+ */
+static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
+ void *private)
+{
+ errcode_t retval;
+
+ struct swap_block_struct *sb = (struct swap_block_struct *) private;
+
+ if (sb->isdir && (blockcnt >= 0) && *block_nr) {
+ retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
+ if (retval) {
+ sb->errcode = retval;
+ return BLOCK_ABORT;
+ }
+ retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
+ if (retval) {
+ sb->errcode = retval;
+ return BLOCK_ABORT;
+ }
+ }
+ if (blockcnt >= 0) {
+ if (blockcnt < EXT2_NDIR_BLOCKS)
+ return 0;
+ return BLOCK_CHANGED;
+ }
+ if (blockcnt == BLOCK_COUNT_IND) {
+ if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
+ return 0;
+ return BLOCK_CHANGED;
+ }
+ if (blockcnt == BLOCK_COUNT_DIND) {
+ if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
+ return 0;
+ return BLOCK_CHANGED;
+ }
+ if (blockcnt == BLOCK_COUNT_TIND) {
+ if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
+ return 0;
+ return BLOCK_CHANGED;
+ }
+ return BLOCK_CHANGED;
+}
+
+/*
+ * This function is responsible for byte-swapping all of the indirect,
+ * block pointers. It is also responsible for byte-swapping directories.
+ */
+static void swap_inode_blocks(ext2_filsys fs, ino_t ino, char *block_buf,
+ struct ext2_inode *inode)
+{
+ errcode_t retval;
+ struct swap_block_struct sb;
+
+ sb.ino = ino;
+ sb.inode = inode;
+ sb.dir_buf = block_buf + fs->blocksize*3;
+ sb.errcode = 0;
+ sb.isdir = 0;
+ if (LINUX_S_ISDIR(inode->i_mode))
+ sb.isdir = 1;
+
+ retval = ext2fs_block_iterate(fs, ino, 0, block_buf, swap_block, &sb);
+ if (retval) {
+ com_err("swap_inode_blocks", retval,
+ "while calling ext2fs_block_iterate");
+ fatal_error(0);
+ }
+ if (sb.errcode) {
+ com_err("swap_inode_blocks", sb.errcode,
+ "while calling iterator function");
+ fatal_error(0);
+ }
+}
+
+static void swap_inodes(ext2_filsys fs)
+{
+ int i, group;
+ ino_t ino = 1;
+ char *buf, *block_buf;
+ errcode_t retval;
+ struct ext2_inode * inode;
+
+ fs->read_inode = pass1_read_inode;
+ fs->get_blocks = pass1_get_blocks;
+
+
+ buf = malloc(fs->blocksize * fs->inode_blocks_per_group);
+ if (!buf) {
+ com_err("swap_inodes", ENOMEM,
+ "while allocating inode buffer");
+ fatal_error(0);
+ }
+ block_buf = allocate_memory(fs->blocksize * 4,
+ "block interate buffer");
+ for (group = 0; group < fs->group_desc_count; group++) {
+ retval = io_channel_read_blk(fs->io,
+ fs->group_desc[group].bg_inode_table,
+ fs->inode_blocks_per_group, buf);
+ if (retval) {
+ com_err("swap_inodes", retval,
+ "while reading inode table (group %d)",
+ group);
+ fatal_error(0);
+ }
+ inode = (struct ext2_inode *) buf;
+ for (i=0; i < fs->super->s_inodes_per_group; i++, ino++) {
+ if (fs->flags & EXT2_SWAP_BYTES_READ)
+ ext2fs_swap_inode(fs, inode, inode, 0);
+ stashed_ino = ino;
+ stashed_inode = inode;
+
+ if (inode->i_block[EXT2_IND_BLOCK] ||
+ inode->i_block[EXT2_DIND_BLOCK] ||
+ inode->i_block[EXT2_TIND_BLOCK] ||
+ LINUX_S_ISDIR(inode->i_mode))
+ swap_inode_blocks(fs, ino, block_buf, inode);
+
+ if (fs->flags & EXT2_SWAP_BYTES_WRITE)
+ ext2fs_swap_inode(fs, inode, inode, 1);
+ inode++;
+ }
+ retval = io_channel_write_blk(fs->io,
+ fs->group_desc[group].bg_inode_table,
+ fs->inode_blocks_per_group, buf);
+ if (retval) {
+ com_err("swap_inodes", retval,
+ "while writing inode table (group %d)",
+ group);
+ fatal_error(0);
+ }
+ }
+ free(buf);
+ free(block_buf);
+ fs->read_inode = 0;
+ fs->get_blocks = 0;
+}
+
+void swap_filesys(ext2_filsys fs)
+{
+ struct resource_track rtrack;
+
+ init_resource_track(&rtrack);
+
+ if (!preen)
+ printf("Pass 0: Doing byte-swap of filesystem\n");
+
+#ifdef MTRACE
+ mtrace_print("Byte swap");
+#endif
+
+ if (fs->super->s_mnt_count) {
+ fprintf(stderr, "%s: the filesystem must be freshly "
+ "checked using fsck\n"
+ "and not mounted before trying to "
+ "byte-swap it.\n", device_name);
+ fatal_error(0);
+ }
+ if (fs->flags & EXT2_SWAP_BYTES) {
+ fs->flags &= ~(EXT2_SWAP_BYTES|EXT2_SWAP_BYTES_WRITE);
+ fs->flags |= EXT2_SWAP_BYTES_READ;
+ } else {
+ fs->flags &= ~EXT2_SWAP_BYTES_READ;
+ fs->flags |= EXT2_SWAP_BYTES_WRITE;
+ }
+ swap_inodes(fs);
+ if (fs->flags & EXT2_SWAP_BYTES_WRITE)
+ fs->flags |= EXT2_SWAP_BYTES;
+ fs->flags &= ~(EXT2_SWAP_BYTES_READ|EXT2_SWAP_BYTES_WRITE);
+ ext2fs_flush(fs);
+
+ if (tflag > 1) {
+ printf("Byte swap: ");
+ print_resource_track(&rtrack);
+ }
+}
+
+