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/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;
 }