Many 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.

diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index aaa3ec4..083d7ac 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,3 +1,19 @@
+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
diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in
index 40595e6..82acdb9 100644
--- a/e2fsck/Makefile.in
+++ b/e2fsck/Makefile.in
@@ -151,35 +151,39 @@
 # 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 \
@@ -187,7 +191,12 @@
 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 \
@@ -195,9 +204,8 @@
 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
-
diff --git a/e2fsck/Makefile.pq b/e2fsck/Makefile.pq
index a5e5b49..6388e6c 100644
--- a/e2fsck/Makefile.pq
+++ b/e2fsck/Makefile.pq
@@ -2,8 +2,8 @@
 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
 
diff --git a/e2fsck/dirinfo.c b/e2fsck/dirinfo.c
index 5218234..8d37544 100644
--- a/e2fsck/dirinfo.c
+++ b/e2fsck/dirinfo.c
@@ -8,12 +8,9 @@
 #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;
@@ -28,27 +25,33 @@
  * 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;
+		}
 	}
 
 	/*
@@ -60,16 +63,17 @@
 	 * 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;
@@ -80,26 +84,26 @@
  * 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;
@@ -110,23 +114,23 @@
 /*
  * 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)++);
 }
diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c
index 592541b..c80036e 100644
--- a/e2fsck/e2fsck.c
+++ b/e2fsck/e2fsck.c
@@ -22,11 +22,13 @@
 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;
@@ -41,6 +43,7 @@
  */
 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;
@@ -61,7 +64,7 @@
 		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;
@@ -79,15 +82,15 @@
 	 * 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;
 	}
 
@@ -121,5 +124,44 @@
 	
 	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;
+}
+
+
+	
+
+	
+
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 83c5d61..a497fb2 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -16,6 +16,9 @@
 #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>
@@ -24,12 +27,8 @@
 
 #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
@@ -85,17 +84,47 @@
 #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 */
@@ -121,12 +150,24 @@
 	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;
@@ -157,28 +198,24 @@
 	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);
@@ -195,11 +232,11 @@
 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);
@@ -225,18 +262,16 @@
 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);
diff --git a/e2fsck/message.c b/e2fsck/message.c
index 673c463..e7bdd51 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -147,7 +147,7 @@
 		fputs("???", stdout);
 	else {
 		fputs(path, stdout);
-		free(path);
+		ext2fs_free_mem((void **) &path);
 	}
 }
 
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 6a2681a..ea443b8 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -96,7 +96,8 @@
  */
 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;
 }
 
 /*
@@ -113,7 +114,7 @@
 	return 1;
 }
 
-void pass1(e2fsck_t ctx)
+void e2fsck_pass1(e2fsck_t ctx)
 {
 	ext2_filsys fs = ctx->fs;
 	ino_t	ino;
@@ -146,34 +147,39 @@
 	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),
@@ -183,7 +189,8 @@
 	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);
@@ -197,13 +204,15 @@
 					      &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);
@@ -217,7 +226,8 @@
 			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) {
@@ -235,7 +245,8 @@
 				     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);
@@ -253,7 +264,7 @@
 					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");
 				}
 			}
@@ -269,7 +280,7 @@
 			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");
 				}
 			}
@@ -286,7 +297,7 @@
 				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");
 				}
 			}
@@ -302,7 +313,7 @@
 				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");
 				}
 			}
@@ -321,7 +332,7 @@
 		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");
 			}
 		}
 		
@@ -352,7 +363,7 @@
 		
 		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++;
@@ -393,8 +404,15 @@
 		} 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) {
@@ -406,7 +424,8 @@
 		}
 		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);
@@ -416,7 +435,7 @@
 	if (ctx->invalid_bitmaps)
 		handle_fs_bad_blocks(ctx);
 
-	if (restart_e2fsck) {
+	if (ctx->flags & E2F_FLAG_RESTART) {
 		unwind_pass1(fs);
 		goto endit;
 	}
@@ -426,16 +445,16 @@
 			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;
 
@@ -487,6 +506,9 @@
 		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;
@@ -522,7 +544,9 @@
 	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;
 	}
 }
 
@@ -540,7 +564,9 @@
 	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;
 	}
 }
 
@@ -566,7 +592,9 @@
 				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);
@@ -604,6 +632,8 @@
 	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);
@@ -612,11 +642,11 @@
 		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);
 		/*
@@ -624,7 +654,7 @@
 		 * before processing was aborted, so we need to
 		 * restart the pass 1 scan.
 		 */
-		restart_e2fsck++;
+		ctx->flags |= E2F_FLAG_RESTART;
 		return;
 	}
 
@@ -639,7 +669,7 @@
 			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--;
@@ -652,7 +682,7 @@
 		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;
 	}
@@ -660,7 +690,7 @@
 		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;
 	}
@@ -826,7 +856,9 @@
 			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;
@@ -841,7 +873,7 @@
 	 * 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,
@@ -878,9 +910,11 @@
 	}
 
 	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;
 	}
@@ -966,6 +1000,8 @@
 	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;
 	}
 
@@ -1001,8 +1037,8 @@
 		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;
@@ -1029,7 +1065,7 @@
 		if (pctx.errcode)
 			fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
 	}
-	free(buf);
+	ext2fs_free_mem((void **) &buf);
 }
 
 /*
@@ -1058,7 +1094,7 @@
 			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;
 	}
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index e965217..1aa586b 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -105,7 +105,7 @@
 /*
  * 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;
@@ -135,12 +135,12 @@
 		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);
 	}
 }
 
@@ -154,7 +154,7 @@
 	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;
@@ -322,7 +322,7 @@
 }
 
 
-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;
@@ -468,7 +468,7 @@
 		else
 			ext2fs_unmark_valid(fs);
 	}
-	free(shared);
+	ext2fs_free_mem((void **) &shared);
 }
 
 static int delete_file_block(ext2_filsys fs,
@@ -530,10 +530,10 @@
 	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 {
@@ -616,9 +616,9 @@
 	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;
@@ -626,7 +626,7 @@
 	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",
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index edb2482..4facc60 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -66,7 +66,7 @@
 	e2fsck_t ctx;
 };	
 
-void pass2(e2fsck_t ctx)
+void e2fsck_pass2(e2fsck_t ctx)
 {
 	ext2_filsys 	fs = ctx->fs;
 	char	*buf;
@@ -94,7 +94,8 @@
 						&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");
 
@@ -103,7 +104,7 @@
 	 * 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;
 
@@ -112,12 +113,15 @@
 	
 	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) {
@@ -309,8 +313,10 @@
 	
 	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);
 	}
 
@@ -343,10 +349,11 @@
 			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++;
@@ -438,6 +445,8 @@
 				dir_modified++;
 				goto next;
 			}
+			if (ctx->flags & E2F_FLAG_ABORT)
+				return DIRENT_ABORT;
 		}
 
 		if (check_name(ctx, dirent, ino, &cd->pctx))
@@ -453,11 +462,12 @@
 		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;
@@ -493,8 +503,11 @@
 	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);
 	}
@@ -530,10 +543,10 @@
 	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;
 
@@ -556,7 +569,8 @@
 					    deallocate_inode_block, ctx);
 	if (pctx.errcode) {
 		fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
-		fatal_error(0);
+		ctx->flags |= E2F_FLAG_ABORT;
+		return;
 	}
 }
 
@@ -567,8 +581,9 @@
 	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;
@@ -578,29 +593,26 @@
 	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)) {
@@ -652,7 +664,7 @@
 		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;
 }
 
@@ -710,7 +722,7 @@
 	}
 
 	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);
@@ -720,11 +732,11 @@
 	/*
 	 * 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
diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index 48d3c7c..f85d9bd 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -25,10 +25,10 @@
  * 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.
@@ -55,7 +55,7 @@
 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;
@@ -86,14 +86,16 @@
 	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)
@@ -101,15 +103,18 @@
 #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
@@ -134,7 +139,7 @@
 	
 	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.
 		 */
@@ -156,7 +161,8 @@
 	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);
@@ -170,16 +176,18 @@
 	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
@@ -199,13 +207,14 @@
 	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);
 
@@ -259,7 +268,7 @@
 			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
@@ -267,7 +276,7 @@
 	 */
 	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;
@@ -362,7 +371,7 @@
 	}
 
 	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);
@@ -402,7 +411,7 @@
 	/*
 	 * 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);
@@ -415,7 +424,7 @@
 /*
  * 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;
@@ -613,9 +622,9 @@
 		}
 		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);
@@ -625,7 +634,7 @@
 		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);
@@ -672,7 +681,7 @@
 	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;
 }
diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c
index 9b814b4..6aca7d4 100644
--- a/e2fsck/pass4.c
+++ b/e2fsck/pass4.c
@@ -28,7 +28,7 @@
 	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;
@@ -42,7 +42,7 @@
 			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...
@@ -60,7 +60,7 @@
 	 * 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 {
 		/*
@@ -75,7 +75,7 @@
 }
 
 
-void pass4(e2fsck_t ctx)
+void e2fsck_pass4(e2fsck_t ctx)
 {
 	ext2_filsys fs = ctx->fs;
 	ino_t	i;
@@ -118,7 +118,7 @@
 					    &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) {
@@ -129,7 +129,7 @@
 			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");
 			}
 		}
 	}
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index be2edd9..9dcb7fd 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -18,7 +18,7 @@
 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;
@@ -41,9 +41,17 @@
 	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;
@@ -86,8 +94,9 @@
 		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 <
@@ -100,8 +109,9 @@
 		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:		       
@@ -184,7 +194,7 @@
 		} else
 			ext2fs_unmark_valid(fs);
 	}
-	free(free_array);
+	ext2fs_free_mem((void **) &free_array);
 }
 			
 static void check_inode_bitmaps(e2fsck_t ctx)
@@ -219,8 +229,9 @@
 		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 > 
@@ -231,8 +242,9 @@
 		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:
@@ -332,8 +344,8 @@
 		} 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)
@@ -350,7 +362,8 @@
 	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;
@@ -373,7 +386,8 @@
 	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;
 	}
 }
 
@@ -392,7 +406,8 @@
 	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;
@@ -415,7 +430,8 @@
 	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;
 	}
 }
 
diff --git a/e2fsck/super.c b/e2fsck/super.c
index 40a272c..1b6fb04 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -46,7 +46,7 @@
 		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! */
 	}
 }
 
@@ -100,20 +100,24 @@
 					      &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 /
@@ -122,7 +126,8 @@
 		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;
@@ -130,7 +135,8 @@
 		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;
 	}
 
 	/*
diff --git a/e2fsck/swapfs.c b/e2fsck/swapfs.c
index f6d3d70..ab012c7 100644
--- a/e2fsck/swapfs.c
+++ b/e2fsck/swapfs.c
@@ -114,10 +114,10 @@
 	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);
 	}
@@ -168,8 +168,8 @@
 			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;
 }
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index 9868e36..97bb33d 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -55,8 +55,6 @@
 static int root_filesystem = 0;
 static int read_only_root = 0;
 
-int restart_e2fsck = 0;
-
 static void usage(e2fsck_t ctx)
 {
 	fprintf(stderr,
@@ -414,7 +412,7 @@
 	int		my_ver, lib_ver;
 	e2fsck_t	ctx;
 	struct problem_context pctx;
-	int flags;
+	int flags, run_result;
 	
 	clear_problem_context(&pctx);
 #ifdef MTRACE
@@ -459,7 +457,7 @@
 	    !(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:
@@ -595,12 +593,11 @@
 		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,
@@ -609,10 +606,10 @@
 		}
 		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");
diff --git a/e2fsck/util.c b/e2fsck/util.c
index f676b26..46ceaa9 100644
--- a/e2fsck/util.c
+++ b/e2fsck/util.c
@@ -238,12 +238,12 @@
 }
 #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);
@@ -251,12 +251,12 @@
 	}
 }
 
-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);