+Mon Nov 3 14:35:29 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * [lots of files]: Change ext2fs_read_inode, ext2fs_write_inode
+ to take the e2fsck context as their first argument.
+ Change dir_info.c routines to take an e2fsck_context,
+ renamed them to start with e2fsck_ to avoid namespace
+ issues, and changed them to store the directory
+ information inside the e2fsck context.
+ Added e2fsck_run() which calls all of the e2fsck passes in
+ the correct order, and which handles the return of abort
+ codes. Added abort processing, both via setjmp/longjmp
+ and via flags in the e2fsck context. Use a flag in the
+ e2fsck context instead of the restart_e2fsck global
+ variable. Change uses of free and malloc to
+ ext2fs_free_mem and ext2fs_get_mem.
+
Fri Oct 31 01:12:43 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass1.c, pass3.c: Rename new error codes to _ET_ in them for
# the Makefile.in file
#
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 \
+ $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h
+super.o: $(srcdir)/super.c $(top_srcdir)/lib/uuid/uuid.h $(srcdir)/e2fsck.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.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 \
+pass1.o: $(srcdir)/pass1.c $(srcdir)/e2fsck.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.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/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.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/ext2_io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \
- $(srcdir)/problem.h
-pass3.o: $(srcdir)/pass3.c $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+pass2.o: $(srcdir)/pass2.c $(srcdir)/e2fsck.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h
+pass3.o: $(srcdir)/pass3.c $(srcdir)/e2fsck.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.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/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h
-pass5.o: $(srcdir)/pass5.c $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+pass5.o: $(srcdir)/pass5.c $(srcdir)/e2fsck.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
- $(top_srcdir)/lib/ext2fs/bitops.h
+ $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.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/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
util.o: $(srcdir)/util.c $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
- $(top_srcdir)/lib/ext2fs/bitops.h
+ $(top_srcdir)/lib/ext2fs/bitops.h
+unix.o: $(srcdir)/unix.c $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h \
+ $(srcdir)/../version.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/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.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/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
- $(top_srcdir)/lib/ext2fs/bitops.h
+ $(top_srcdir)/lib/ext2fs/bitops.h
problem.o: $(srcdir)/problem.c $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h
-
LIBNAME=E2FSCK.LIB
OBJFILE=E2FSCK.LST
-OBJS= super.obj pass1.obj pass1b.obj pass2.obj pass3.obj pass4.obj \
- pass5.obj
+OBJS= e2fsck.obj super.obj pass1.obj pass2.obj pass3.obj \
+ pass4.obj pass5.obj
!include $(TOPSRC)\powerquest\MCONFIG
#include <et/com_err.h>
#include "e2fsck.h"
-static int dir_info_count = 0;
-static int dir_info_size = 0;
-static struct dir_info *dir_info = 0;
-
-int get_num_dirs(ext2_filsys fs)
+int e2fsck_get_num_dirs(e2fsck_t ctx)
{
+ ext2_filsys fs = ctx->fs;
int i, num_dirs;
num_dirs = 0;
* entry. During pass1, the passed-in parent is 0; it will get filled
* in during pass2.
*/
-void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent)
+void e2fsck_add_dir_info(e2fsck_t ctx, ino_t ino, ino_t parent)
{
struct dir_info *dir;
- int i, j;
+ int i, j;
+ errcode_t retval;
#if 0
printf("add_dir_info for inode %lu...\n", ino);
#endif
- if (!dir_info) {
- dir_info_count = 0;
- dir_info_size = get_num_dirs(fs) + 10;
+ if (!ctx->dir_info) {
+ ctx->dir_info_count = 0;
+ ctx->dir_info_size = e2fsck_get_num_dirs(ctx) + 10;
- dir_info = allocate_memory(dir_info_size *
- sizeof (struct dir_info),
- "directory map");
+ ctx->dir_info = allocate_memory(ctx->dir_info_size *
+ sizeof (struct dir_info),
+ "directory map");
}
- if (dir_info_count >= dir_info_size) {
- dir_info_size += 10;
- dir_info = realloc(dir_info,
- dir_info_size * sizeof(struct dir_info));
+ if (ctx->dir_info_count >= ctx->dir_info_size) {
+ ctx->dir_info_size += 10;
+ retval = ext2fs_resize_mem(ctx->dir_info_size *
+ sizeof(struct dir_info),
+ (void **) &ctx->dir_info);
+ if (retval) {
+ ctx->dir_info_size -= 10;
+ return;
+ }
}
/*
* the dir_info array needs to be sorted by inode number for
* get_dir_info()'s sake.
*/
- if (dir_info_count && dir_info[dir_info_count-1].ino >= ino) {
- for (i = dir_info_count-1; i > 0; i--)
- if (dir_info[i-1].ino < ino)
+ if (ctx->dir_info_count &&
+ ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
+ for (i = ctx->dir_info_count-1; i > 0; i--)
+ if (ctx->dir_info[i-1].ino < ino)
break;
- dir = &dir_info[i];
+ dir = &ctx->dir_info[i];
if (dir->ino != ino)
- for (j = dir_info_count++; j > i; j--)
- dir_info[j] = dir_info[j-1];
+ for (j = ctx->dir_info_count++; j > i; j--)
+ ctx->dir_info[j] = ctx->dir_info[j-1];
} else
- dir = &dir_info[dir_info_count++];
+ dir = &ctx->dir_info[ctx->dir_info_count++];
dir->ino = ino;
dir->dotdot = parent;
* get_dir_info() --- given an inode number, try to find the directory
* information entry for it.
*/
-struct dir_info *get_dir_info(ino_t ino)
+struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ino_t ino)
{
int low, high, mid;
low = 0;
- high = dir_info_count-1;
- if (!dir_info)
+ high = ctx->dir_info_count-1;
+ if (!ctx->dir_info)
return 0;
- if (ino == dir_info[low].ino)
- return &dir_info[low];
- if (ino == dir_info[high].ino)
- return &dir_info[high];
+ if (ino == ctx->dir_info[low].ino)
+ return &ctx->dir_info[low];
+ if (ino == ctx->dir_info[high].ino)
+ return &ctx->dir_info[high];
while (low < high) {
mid = (low+high)/2;
if (mid == low || mid == high)
break;
- if (ino == dir_info[mid].ino)
- return &dir_info[mid];
- if (ino < dir_info[mid].ino)
+ if (ino == ctx->dir_info[mid].ino)
+ return &ctx->dir_info[mid];
+ if (ino < ctx->dir_info[mid].ino)
high = mid;
else
low = mid;
/*
* Free the dir_info structure when it isn't needed any more.
*/
-void free_dir_info(ext2_filsys fs)
+void e2fsck_free_dir_info(e2fsck_t ctx)
{
- if (dir_info) {
- free(dir_info);
- dir_info = 0;
+ if (ctx->dir_info) {
+ ext2fs_free_mem((void **) &ctx->dir_info);
+ ctx->dir_info = 0;
}
- dir_info_size = 0;
- dir_info_count = 0;
+ ctx->dir_info_size = 0;
+ ctx->dir_info_count = 0;
}
/*
* A simple interator function
*/
-struct dir_info *dir_info_iter(int *control)
+struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
{
- if (*control >= dir_info_count)
+ if (*control >= ctx->dir_info_count)
return 0;
- return(dir_info + (*control)++);
+ return(ctx->dir_info + (*control)++);
}
errcode_t e2fsck_allocate_context(e2fsck_t *ret)
{
e2fsck_t context;
+ errcode_t retval;
- context = malloc(sizeof(struct e2fsck_struct));
- if (!context)
- return ENOMEM;
-
+ retval = ext2fs_get_mem(sizeof(struct e2fsck_struct),
+ (void **) &context);
+ if (retval)
+ return retval;
+
memset(context, 0, sizeof(struct e2fsck_struct));
context->process_inode_size = 256;
*/
errcode_t e2fsck_reset_context(e2fsck_t ctx)
{
+ ctx->flags = 0;
if (ctx->inode_used_map) {
ext2fs_free_inode_bitmap(ctx->inode_used_map);
ctx->inode_used_map = 0;
ext2fs_free_dblist(ctx->fs->dblist);
ctx->fs->dblist = 0;
}
- free_dir_info(ctx->fs);
+ e2fsck_free_dir_info(ctx);
if (ctx->block_dup_map) {
ext2fs_free_block_bitmap(ctx->block_dup_map);
ctx->block_dup_map = 0;
* Clear the array of invalid meta-data flags
*/
if (ctx->invalid_inode_bitmap_flag) {
- free(ctx->invalid_inode_bitmap_flag);
+ ext2fs_free_mem((void **) &ctx->invalid_inode_bitmap_flag);
ctx->invalid_inode_bitmap_flag = 0;
}
if (ctx->invalid_block_bitmap_flag) {
- free(ctx->invalid_block_bitmap_flag);
+ ext2fs_free_mem((void **) &ctx->invalid_block_bitmap_flag);
ctx->invalid_block_bitmap_flag = 0;
}
if (ctx->invalid_inode_table_flag) {
- free(ctx->invalid_inode_table_flag);
+ ext2fs_free_mem((void **) &ctx->invalid_inode_table_flag);
ctx->invalid_inode_table_flag = 0;
}
e2fsck_reset_context(ctx);
- free(ctx);
+ ext2fs_free_mem((void **) &ctx);
}
+
+/*
+ * This function runs through the e2fsck passes and calls them all,
+ * returning restart, abort, or cancel as necessary...
+ */
+typedef void (*pass_t)(e2fsck_t ctx);
+
+pass_t e2fsck_passes[] = {
+ e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
+ e2fsck_pass5, 0 };
+
+int e2fsck_run(e2fsck_t ctx)
+{
+ int i;
+ pass_t e2fsck_pass;
+
+#ifdef HAVE_SETJMP_H
+ if (setjmp(ctx->abort_loc))
+ return (ctx->flags & E2F_FLAG_SIGNAL_MASK);
+ ctx->flags |= E2F_FLAG_SETJMP_OK;
+#endif
+
+ for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ break;
+ e2fsck_pass(ctx);
+ }
+ ctx->flags &= ~E2F_FLAG_SETJMP_OK;
+
+ if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+ return (ctx->flags & E2F_FLAG_SIGNAL_MASK);
+ return 0;
+}
+
+
+
+
+
+
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
#ifdef HAVE_LINUX_FS_H
#include <linux/fs.h>
#include "ext2fs/ext2fs.h"
-#ifdef __STDC__
+/* Everything is STDC, these days */
#define NOARGS void
-#else
-#define NOARGS
-#define const
-#endif
/*
* Exit codes used by fsck-type programs
#define E2F_OPT_DEBUG 0x0080
/*
+ * E2fsck flags
+ */
+#define E2F_FLAG_ABORT 0x0001 /* Abort signaled */
+#define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */
+#define E2F_FLAG_RESTART 0x0004 /* Restart signaled */
+#define E2F_FLAG_SIGNAL_MASK 0x000F
+
+#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
+
+/*
+ * Defines for indicating the e2fsck pass number
+ */
+#define E2F_PASS_1 1
+#define E2F_PASS_2 2
+#define E2F_PASS_3 3
+#define E2F_PASS_4 4
+#define E2F_PASS_5 5
+#define E2F_PASS_1B 6
+
+/*
* This is the global e2fsck structure.
*/
+typedef struct e2fsck_struct *e2fsck_t;
+
struct e2fsck_struct {
ext2_filsys fs;
const char *program_name;
const char *filesystem_name;
const char *device_name;
+ int flags; /* E2fsck internal flags */
int options;
blk_t use_superblock; /* sb requested by user */
blk_t superblock; /* sb used to open fs */
+#ifdef HAVE_SETJMP_H
+ jmp_buf abort_loc;
+#endif
+
+ void (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
+ unsigned long max);
+
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 */
int invalid_bitmaps; /* There are invalid bitmaps/itable */
/*
+ * Block buffer
+ */
+ char *block_buf;
+
+ /*
* For pass1_check_directory and pass1_get_blocks
*/
ino_t stashed_ino;
struct ext2_inode *stashed_inode;
/*
+ * Directory information
+ */
+ int dir_info_count;
+ int dir_info_size;
+ struct dir_info *dir_info;
+
+ /*
* Tuning parameters
*/
int process_inode_size;
int fs_fragmented;
};
-typedef struct e2fsck_struct *e2fsck_t;
-
-/*
- * Variables
- */
-extern int restart_e2fsck;
/*
* Procedure declarations
*/
-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);
+extern void e2fsck_pass1(e2fsck_t ctx);
+extern void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
+extern void e2fsck_pass2(e2fsck_t ctx);
+extern void e2fsck_pass3(e2fsck_t ctx);
+extern void e2fsck_pass4(e2fsck_t ctx);
+extern void e2fsck_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);
+extern errcode_t e2fsck_allocate_context(e2fsck_t *ret);
+extern errcode_t e2fsck_reset_context(e2fsck_t ctx);
+extern void e2fsck_free_context(e2fsck_t ctx);
+extern int e2fsck_run(e2fsck_t ctx);
+
/* pass1.c */
extern errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino);
extern void test_disk(e2fsck_t ctx);
/* dirinfo.c */
-extern void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent);
-extern struct dir_info *get_dir_info(ino_t ino);
-extern void free_dir_info(ext2_filsys fs);
-extern int get_num_dirs(ext2_filsys fs);
-extern struct dir_info *dir_info_iter(int *control);
+extern void e2fsck_add_dir_info(e2fsck_t ctx, ino_t ino, ino_t parent);
+extern struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ino_t ino);
+extern void e2fsck_free_dir_info(e2fsck_t ctx);
+extern int e2fsck_get_num_dirs(e2fsck_t ctx);
+extern struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control);
/* ehandler.c */
extern const char *ehandler_operation(const char *op);
extern void init_resource_track(struct resource_track *track);
#endif
extern int inode_has_valid_blocks(struct ext2_inode *inode);
-extern void e2fsck_read_inode(ext2_filsys fs, unsigned long ino,
+extern void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, const char * proc);
-extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino,
+extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, const char * proc);
#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(e2fsck_t ctx, ino_t inode);
+extern int e2fsck_reconnect_file(e2fsck_t ctx, ino_t inode);
fputs("???", stdout);
else {
fputs(path, stdout);
- free(path);
+ ext2fs_free_mem((void **) &path);
}
}
*/
static void unwind_pass1(ext2_filsys fs)
{
- free(inodes_to_process);inodes_to_process = 0;
+ ext2fs_free_mem((void **) &inodes_to_process);
+ inodes_to_process = 0;
}
/*
return 1;
}
-void pass1(e2fsck_t ctx)
+void e2fsck_pass1(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ino_t ino;
if (pctx.errcode) {
pctx.num = 1;
fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
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);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
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);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
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);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
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);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
inodes_to_process = allocate_memory(ctx->process_inode_size *
sizeof(struct process_inode_block),
pctx.errcode = ext2fs_init_dblist(fs, 0);
if (pctx.errcode) {
fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
mark_table_blocks(ctx);
&scan);
if (pctx.errcode) {
fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
if (pctx.errcode) {
fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
ctx->stashed_inode = &inode;
ext2fs_set_inode_callback(scan, scan_callback, block_buf);
if (pctx.errcode) {
pctx.num = inode.i_links_count;
fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
}
if (ino == EXT2_BAD_INO) {
block_buf, process_bad_block, &pb);
if (pctx.errcode) {
fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
clear_problem_context(&pctx);
inode.i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info,
ino, 0);
- e2fsck_write_inode(fs, ino, &inode,
+ e2fsck_write_inode(ctx, ino, &inode,
"pass1");
}
}
if (inode.i_dtime && inode.i_links_count) {
if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
inode.i_dtime = 0;
- e2fsck_write_inode(fs, ino, &inode,
+ e2fsck_write_inode(ctx, ino, &inode,
"pass1");
}
}
if (fix_problem(ctx,
PR_1_RESERVED_BAD_MODE, &pctx)) {
inode.i_mode = 0;
- e2fsck_write_inode(fs, ino, &inode,
+ e2fsck_write_inode(ctx, ino, &inode,
"pass1");
}
}
if (fix_problem(ctx,
PR_1_ZERO_DTIME, &pctx)) {
inode.i_dtime = time(0);
- e2fsck_write_inode(fs, ino, &inode,
+ e2fsck_write_inode(ctx, ino, &inode,
"pass1");
}
}
if (inode.i_dtime) {
if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
inode.i_dtime = 0;
- e2fsck_write_inode(fs, ino, &inode, "pass1");
+ e2fsck_write_inode(ctx, ino, &inode, "pass1");
}
}
if (LINUX_S_ISDIR(inode.i_mode)) {
ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
- add_dir_info(fs, ino, 0);
+ e2fsck_add_dir_info(ctx, ino, 0);
ctx->fs_directory_count++;
} else if (LINUX_S_ISREG (inode.i_mode))
ctx->fs_regular_count++;
} else
check_blocks(ctx, &pctx, block_buf);
- if (process_inode_count >= ctx->process_inode_size)
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
+
+ if (process_inode_count >= ctx->process_inode_size) {
process_inodes(ctx, block_buf);
+
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
+ }
next:
pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
}
if (pctx.errcode) {
fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
}
process_inodes(ctx, block_buf);
if (ctx->invalid_bitmaps)
handle_fs_bad_blocks(ctx);
- if (restart_e2fsck) {
+ if (ctx->flags & E2F_FLAG_RESTART) {
unwind_pass1(fs);
goto endit;
}
clear_problem_context(&pctx);
fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
}
- pass1_dupblocks(ctx, block_buf);
+ e2fsck_pass1_dupblocks(ctx, block_buf);
}
- free(inodes_to_process);
+ ext2fs_free_mem((void **) &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_mem((void **) &block_buf);
ext2fs_free_block_bitmap(ctx->block_illegal_map);
ctx->block_illegal_map = 0;
sprintf(buf, "reading indirect blocks of inode %lu", pctx.ino);
ehandler_operation(buf);
check_blocks(ctx, &pctx, block_buf);
+
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
}
ctx->stashed_inode = old_stashed_inode;
ctx->stashed_ino = old_stashed_ino;
if (pctx.errcode) {
pctx.num = 3;
fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- fatal_error(0);
+ /* Should never get here */
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
}
if (pctx.errcode) {
pctx.num = 4;
fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
- fatal_error(0);
+ /* Should never get here */
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
}
pctx.num = 3;
fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
&pctx);
- fatal_error(0);
+ /* Should never get here */
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
}
ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
pctx->errcode = ext2fs_block_iterate2(fs, ino,
pb.is_dir ? BLOCK_FLAG_HOLE : 0,
block_buf, process_block, &pb);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
end_problem_latch(ctx, PR_LATCH_BLOCK);
if (pctx->errcode)
fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
ctx->fs_fragmented++;
if (pb.clear) {
- e2fsck_read_inode(fs, ino, inode, "check_blocks");
+ e2fsck_read_inode(ctx, ino, inode, "check_blocks");
inode->i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
inode->i_dtime = time(0);
- e2fsck_write_inode(fs, ino, inode, "check_blocks");
+ e2fsck_write_inode(ctx, ino, inode, "check_blocks");
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
/*
* before processing was aborted, so we need to
* restart the pass 1 scan.
*/
- restart_e2fsck++;
+ ctx->flags |= E2F_FLAG_RESTART;
return;
}
inode->i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
inode->i_dtime = time(0);
- e2fsck_write_inode(fs, ino, inode, "check_blocks");
+ e2fsck_write_inode(ctx, ino, inode, "check_blocks");
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
ctx->fs_directory_count--;
pctx->num = (pb.last_block+1) * fs->blocksize;
if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
inode->i_size = pctx->num;
- e2fsck_write_inode(fs, ino, inode, "check_blocks");
+ e2fsck_write_inode(ctx, ino, inode, "check_blocks");
}
pctx->num = 0;
}
pctx->num = pb.num_blocks;
if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
inode->i_blocks = pb.num_blocks;
- e2fsck_write_inode(fs, ino, inode, "check_blocks");
+ e2fsck_write_inode(ctx, ino, inode, "check_blocks");
}
pctx->num = 0;
}
pctx->blk = blk;
pctx->num = blockcnt;
fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
- fatal_error(0);
+ /* Should never get here */
+ ctx->flags |= E2F_FLAG_ABORT;
+ return BLOCK_ABORT;
}
}
return ret_code;
* Prompt to see if we should continue or not.
*/
if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, &pctx))
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
}
int process_bad_block(ext2_filsys fs,
}
if (blockcnt < 0) {
- if (ext2fs_test_block_bitmap(ctx->block_found_map, blk))
+ if (ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
bad_block_indirect(ctx, blk);
- else
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return BLOCK_ABORT;
+ } else
mark_block_used(ctx, blk);
return 0;
}
if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
p->inode->i_block[EXT2_DIND_BLOCK]) {
bad_block_indirect(ctx, blk);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return BLOCK_ABORT;
return 0;
}
ext2fs_unmark_valid(fs);
return;
}
- buf = malloc(fs->blocksize);
- if (!buf) {
+ pctx.errcode = ext2fs_get_mem(fs->blocksize, (void **) &buf);
+ if (pctx.errcode) {
fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
ext2fs_unmark_valid(fs);
return;
if (pctx.errcode)
fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
}
- free(buf);
+ ext2fs_free_mem((void **) &buf);
}
/*
new_table_block(ctx, first_block, i, "inode table",
fs->inode_blocks_per_group,
&fs->group_desc[i].bg_inode_table);
- restart_e2fsck++;
+ ctx->flags |= E2F_FLAG_RESTART;
}
first_block += fs->super->s_blocks_per_group;
}
/*
* Main procedure for handling duplicate blocks
*/
-void pass1_dupblocks(e2fsck_t ctx, char *block_buf)
+void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
{
ext2_filsys fs = ctx->fs;
struct dup_block *p, *q, *next_p, *next_q;
next_p = p->next_block;
for (q = p; q; q = next_q) {
next_q = q->next_inode;
- free(q);
+ ext2fs_free_mem((void **) &q);
}
}
for (r = dup_ino; r; r = next_r) {
next_r = r->next;
- free(r);
+ ext2fs_free_mem((void **) &r);
}
}
struct problem_context *pctx;
};
-void pass1b(e2fsck_t ctx, char *block_buf)
+static void pass1b(e2fsck_t ctx, char *block_buf)
{
ext2_filsys fs = ctx->fs;
ino_t ino;
}
-void pass1c(e2fsck_t ctx, char *block_buf)
+static void pass1c(e2fsck_t ctx, char *block_buf)
{
ext2_filsys fs = ctx->fs;
struct dup_inode *p;
else
ext2fs_unmark_valid(fs);
}
- free(shared);
+ ext2fs_free_mem((void **) &shared);
}
static int delete_file_block(ext2_filsys fs,
ext2fs_unmark_inode_bitmap(fs->inode_map, dp->ino);
ext2fs_mark_ib_dirty(fs);
ext2fs_mark_bb_dirty(fs);
- e2fsck_read_inode(fs, dp->ino, &inode, "delete_file");
+ e2fsck_read_inode(ctx, dp->ino, &inode, "delete_file");
inode.i_links_count = 0;
inode.i_dtime = time(0);
- e2fsck_write_inode(fs, dp->ino, &inode, "delete_file");
+ e2fsck_write_inode(ctx, dp->ino, &inode, "delete_file");
}
struct clone_struct {
cs.errcode = 0;
cs.dir = 0;
cs.ctx = ctx;
- cs.buf = malloc(fs->blocksize);
- if (!cs.buf)
- return ENOMEM;
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &cs.buf);
+ if (retval)
+ return retval;
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,
clone_file_block, &cs);
ext2fs_mark_bb_dirty(fs);
- free(cs.buf);
+ ext2fs_free_mem((void **) &cs.buf);
if (retval) {
com_err("clone_file", retval,
"while calling ext2fs_block_iterate for inode %d",
e2fsck_t ctx;
};
-void pass2(e2fsck_t ctx)
+void e2fsck_pass2(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
char *buf;
&ctx->inode_count);
if (cd.pctx.errcode) {
fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
buf = allocate_memory(fs->blocksize, "directory scan buffer");
* present. (If the root directory is not present, we will
* create it in pass 3.)
*/
- dir = get_dir_info(EXT2_ROOT_INO);
+ dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
if (dir)
dir->parent = EXT2_ROOT_INO;
cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
&cd);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
if (cd.pctx.errcode) {
fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
- free(buf);
+ ext2fs_free_mem((void **) &buf);
ext2fs_free_dblist(fs->dblist);
if (ctx->inode_bad_map) {
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);
+ if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
+ ctx->flags |= E2F_FLAG_ABORT;
+ return DIRENT_ABORT;
+ }
memset(buf, 0, fs->blocksize);
}
if (check_dot(ctx, dirent, ino, &cd->pctx))
dir_modified++;
} else if (dot_state == 2) {
- dir = get_dir_info(ino);
+ dir = e2fsck_get_dir_info(ctx, ino);
if (!dir) {
fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return DIRENT_ABORT;
}
if (check_dotdot(ctx, dirent, dir, &cd->pctx))
dir_modified++;
dir_modified++;
goto next;
}
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return DIRENT_ABORT;
}
if (check_name(ctx, dirent, ino, &cd->pctx))
if ((dot_state > 2) &&
(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
dirent->inode))) {
- subdir = get_dir_info(dirent->inode);
+ subdir = e2fsck_get_dir_info(ctx, dirent->inode);
if (!subdir) {
cd->pctx.ino = dirent->inode;
fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return DIRENT_ABORT;
}
if (subdir->parent) {
cd->pctx.ino2 = subdir->parent;
if (dir_modified) {
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);
+ if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
+ &cd->pctx)) {
+ ctx->flags |= E2F_FLAG_ABORT;
+ return DIRENT_ABORT;
+ }
}
ext2fs_mark_changed(fs);
}
struct problem_context pctx;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- e2fsck_read_inode(fs, ino, &inode, "deallocate_inode");
+ e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
inode.i_links_count = 0;
inode.i_dtime = time(0);
- e2fsck_write_inode(fs, ino, &inode, "deallocate_inode");
+ e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
clear_problem_context(&pctx);
pctx.ino = ino;
deallocate_inode_block, ctx);
if (pctx.errcode) {
fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
}
int inode_modified = 0;
unsigned char *frag, *fsize;
struct problem_context pctx;
+ int problem = 0;
- e2fsck_read_inode(fs, ino, &inode, "process_bad_inode");
+ e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
clear_problem_context(&pctx);
pctx.ino = ino;
if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
!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(ctx, PR_2_BAD_MODE, &pctx)) {
- deallocate_inode(ctx, ino, 0);
- return 1;
- }
- }
+ !(LINUX_S_ISSOCK(inode.i_mode)))
+ problem = PR_2_BAD_MODE;
if (LINUX_S_ISCHR(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(&inode)) {
- if (fix_problem(ctx, PR_2_BAD_CHAR_DEV, &pctx)) {
- deallocate_inode(ctx, ino, 0);
- return 1;
- }
- }
+ && !e2fsck_pass1_check_device_inode(&inode))
+ problem = PR_2_BAD_CHAR_DEV;
if (LINUX_S_ISBLK(inode.i_mode)
- && !e2fsck_pass1_check_device_inode(&inode)) {
- if (fix_problem(ctx, PR_2_BAD_BLOCK_DEV, &pctx)) {
+ && !e2fsck_pass1_check_device_inode(&inode))
+ problem = PR_2_BAD_BLOCK_DEV;
+
+ if (problem) {
+ if (fix_problem(ctx, problem, &pctx)) {
deallocate_inode(ctx, ino, 0);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return 0;
return 1;
}
+ problem = 0;
}
-
if (inode.i_faddr &&
fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
inode_modified++;
}
if (inode_modified)
- e2fsck_write_inode(fs, ino, &inode, "process_bad_inode");
+ e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
return 0;
}
}
pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
- free(block);
+ ext2fs_free_mem((void **) &block);
if (pctx->errcode) {
pctx->str = "ext2fs_write_dir_block";
fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
/*
* Update the inode block count
*/
- e2fsck_read_inode(fs, db->ino, &inode, "allocate_dir_block");
+ e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
inode.i_blocks += fs->blocksize / 512;
if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
inode.i_size = (db->blockcnt+1) * fs->blocksize;
- e2fsck_write_inode(fs, db->ino, &inode, "allocate_dir_block");
+ e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
/*
* Finally, update the block pointers for the inode
* offer to reconnect the directory to /lost+found in to break the
* filesystem loop.
*
- * Pass 3 also contains the subroutine, reconnect_file() to reconnect
- * inodes to /lost+found; this subroutine is also used by pass 4.
- * reconnect_file() calls get_lost_and_found(), which is responsible
- * for creating /lost+found if it does not exist.
+ * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
+ * reconnect inodes to /lost+found; this subroutine is also used by
+ * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which
+ * is responsible for creating /lost+found if it does not exist.
*
* Pass 3 frees the following data structures:
* - The dirinfo directory information cache.
static ext2fs_inode_bitmap inode_loop_detect;
static ext2fs_inode_bitmap inode_done_map;
-void pass3(e2fsck_t ctx)
+void e2fsck_pass3(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
int i;
if (pctx.errcode) {
pctx.num = 1;
fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
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);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
#ifdef RESOURCE_TRACK
if (ctx->options & E2F_OPT_TIME)
#endif
check_root(ctx);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
+
ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
- for (i=0; (dir = dir_info_iter(&i)) != 0;) {
+ for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
check_directory(ctx, dir, &pctx);
}
- free_dir_info(fs);
+ e2fsck_free_dir_info(ctx);
ext2fs_free_inode_bitmap(inode_loop_detect);
ext2fs_free_inode_bitmap(inode_done_map);
#ifdef RESOURCE_TRACK
if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
/*
- * If the root inode is a directory, die here. The
+ * If the root inode is not a directory, die here. The
* user must have answered 'no' in pass1 when we
* offered to clear it.
*/
if (pctx.errcode) {
pctx.str = "ext2fs_new_block";
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
ext2fs_mark_block_bitmap(fs->block_map, blk);
if (pctx.errcode) {
pctx.str = "ext2fs_new_dir_block";
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
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);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
- free(block);
+ ext2fs_free_mem((void **) &block);
/*
* Set up the inode structure
if (pctx.errcode) {
pctx.str = "ext2fs_write_inode";
fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
/*
* Miscellaneous bookkeeping...
*/
- add_dir_info(fs, EXT2_ROOT_INO, EXT2_ROOT_INO);
+ e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
break;
ext2fs_mark_inode_bitmap(inode_loop_detect,
p->parent);
- p = get_dir_info(p->parent);
+ p = e2fsck_get_dir_info(ctx, p->parent);
}
/*
* If we've reached here, we've hit a detached directory
*/
pctx->ino = p->ino;
if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
- if (reconnect_file(ctx, p->ino))
+ if (e2fsck_reconnect_file(ctx, p->ino))
ext2fs_unmark_valid(fs);
else {
p->parent = lost_and_found;
}
retval = ext2fs_write_dir_block(fs, blk, block);
- free(block);
+ ext2fs_free_mem((void **) &block);
if (retval) {
pctx.errcode = retval;
fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
/*
* Miscellaneous bookkeeping that needs to be kept straight.
*/
- add_dir_info(fs, ino, EXT2_ROOT_INO);
+ e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
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);
/*
* This routine will connect a file to lost+found
*/
-int reconnect_file(e2fsck_t ctx, ino_t inode)
+int e2fsck_reconnect_file(e2fsck_t ctx, ino_t inode)
{
ext2_filsys fs = ctx->fs;
errcode_t retval;
}
es->done = 1;
} else {
- block = malloc(fs->blocksize);
- if (!block) {
- es->err = ENOMEM;
+ retval = ext2fs_get_mem(fs->blocksize, (void **) &block);
+ if (retval) {
+ es->err = retval;
return BLOCK_ABORT;
}
memset(block, 0, fs->blocksize);
es->err = retval;
return BLOCK_ABORT;
}
- free(block);
+ ext2fs_free_mem((void **) &block);
*blocknr = new_blk;
ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
inode.i_size += fs->blocksize;
inode.i_blocks += fs->blocksize / 512;
- e2fsck_write_inode(fs, dir, &inode, "expand_directory");
+ e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
return 0;
}
struct ext2_inode inode;
struct problem_context pctx;
- e2fsck_read_inode(fs, i, &inode, "pass4: disconnect_inode");
+ e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
clear_problem_context(&pctx);
pctx.ino = i;
pctx.inode = &inode;
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,
+ e2fsck_write_inode(ctx, i, &inode,
"disconnect_inode");
/*
* Fix up the bitmaps...
* Prompt to reconnect.
*/
if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
- if (reconnect_file(ctx, i))
+ if (e2fsck_reconnect_file(ctx, i))
ext2fs_unmark_valid(fs);
} else {
/*
}
-void pass4(e2fsck_t ctx)
+void e2fsck_pass4(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ino_t i;
&link_counted);
}
if (link_counted != link_count) {
- e2fsck_read_inode(fs, i, &inode, "pass4");
+ e2fsck_read_inode(ctx, i, &inode, "pass4");
pctx.ino = i;
pctx.inode = &inode;
if (link_count != inode.i_links_count) {
pctx.num = link_counted;
if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
inode.i_links_count = link_counted;
- e2fsck_write_inode(fs, i, &inode, "pass4");
+ e2fsck_write_inode(ctx, i, &inode, "pass4");
}
}
}
static void check_inode_end(e2fsck_t ctx);
static void check_block_end(e2fsck_t ctx);
-void pass5(e2fsck_t ctx)
+void e2fsck_pass5(e2fsck_t ctx)
{
#ifdef RESOURCE_TRACK
struct resource_track rtrack;
read_bitmaps(ctx);
check_block_bitmaps(ctx);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
check_inode_bitmaps(ctx);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
check_inode_end(ctx);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
check_block_end(ctx);
+ if (ctx->flags & E2F_FLAG_ABORT)
+ return;
ext2fs_free_inode_bitmap(ctx->inode_used_map);
ctx->inode_used_map = 0;
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);
+
+ ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+ return;
}
if ((fs->super->s_first_data_block <
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);
+
+ ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+ return;
}
redo_counts:
} else
ext2fs_unmark_valid(fs);
}
- free(free_array);
+ ext2fs_free_mem((void **) &free_array);
}
static void check_inode_bitmaps(e2fsck_t ctx)
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);
+
+ ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+ return;
}
if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
(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);
+
+ ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+ return;
}
redo_counts:
} else
ext2fs_unmark_valid(fs);
}
- free(free_array);
- free(dir_array);
+ ext2fs_free_mem((void **) &free_array);
+ ext2fs_free_mem((void **) &dir_array);
}
static void check_inode_end(e2fsck_t ctx)
if (pctx.errcode) {
pctx.num = 1;
fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+ return;
}
if (save_inodes_count == end)
return;
if (pctx.errcode) {
pctx.num = 2;
fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+ return;
}
}
if (pctx.errcode) {
pctx.num = 3;
fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+ return;
}
if (save_blocks_count == end)
return;
if (pctx.errcode) {
pctx.num = 4;
fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT; /* fatal */
+ return;
}
}
pctx.num = value;
pctx.str = descr;
fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
- fatal_error(0); /* never get here! */
+ ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
}
}
&should_be);
if (pctx.errcode) {
fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
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 (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
+ }
}
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);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
should_be = s->s_frags_per_group /
pctx.blk = s->s_blocks_per_group;
pctx.blk2 = should_be;
fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
should_be = (s->s_log_block_size == 0) ? 1 : 0;
pctx.blk = s->s_first_data_block;
pctx.blk2 = should_be;
fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
- fatal_error(0);
+ ctx->flags |= E2F_FLAG_ABORT;
+ return;
}
/*
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,
+ retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
+ (void **) &buf);
+ if (retval) {
+ com_err("swap_inodes", retval,
"while allocating inode buffer");
fatal_error(0);
}
fatal_error(0);
}
}
- free(buf);
- free(block_buf);
+ ext2fs_free_mem((void **) &buf);
+ ext2fs_free_mem((void **) &block_buf);
fs->read_inode = 0;
fs->get_blocks = 0;
}
static int root_filesystem = 0;
static int read_only_root = 0;
-int restart_e2fsck = 0;
-
static void usage(e2fsck_t ctx)
{
fprintf(stderr,
int my_ver, lib_ver;
e2fsck_t ctx;
struct problem_context pctx;
- int flags;
+ int flags, run_result;
clear_problem_context(&pctx);
#ifdef MTRACE
!(ctx->options & E2F_OPT_NO) &&
!(ctx->options & E2F_OPT_YES)) {
if (!isatty (0) || !isatty (1))
- die ("need terminal for interactive repairs");
+ fatal_error("need terminal for interactive repairs");
}
ctx->superblock = ctx->use_superblock;
restart:
preenhalt(ctx);
printf("This doesn't bode well, but we'll try to go on...\n");
}
-
- pass1(ctx);
- if (restart_e2fsck) {
+
+ run_result = e2fsck_run(ctx);
+ if (run_result == E2F_FLAG_RESTART) {
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,
}
goto restart;
}
- pass2(ctx);
- pass3(ctx);
- pass4(ctx);
- pass5(ctx);
+ if (run_result & E2F_FLAG_ABORT)
+ exit(FSCK_ERROR);
+ if (run_result & E2F_FLAG_CANCEL)
+ ext2fs_unmark_valid(fs);
#ifdef MTRACE
mtrace_print("Cleanup");
}
#endif /* RESOURCE_TRACK */
-void e2fsck_read_inode(ext2_filsys fs, unsigned long ino,
+void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, const char *proc)
{
int retval;
- retval = ext2fs_read_inode(fs, ino, inode);
+ retval = ext2fs_read_inode(ctx->fs, ino, inode);
if (retval) {
com_err("ext2fs_read_inode", retval,
"while reading inode %ld in %s", ino, proc);
}
}
-extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino,
+extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
struct ext2_inode * inode, const char *proc)
{
int retval;
- retval = ext2fs_write_inode(fs, ino, inode);
+ retval = ext2fs_write_inode(ctx->fs, ino, inode);
if (retval) {
com_err("ext2fs_write_inode", retval,
"while writing inode %ld in %s", ino, proc);