Many files:
  Checked in e2fsprogs-1.07

diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c
index b3bc833..27ca98b 100644
--- a/e2fsck/pass1b.c
+++ b/e2fsck/pass1b.c
@@ -18,8 +18,12 @@
  * (so that the file gets a fresh copy of the duplicated blocks) or
  * simply to delete the file.
  * 
- * Copyright (C) 1993, 1994 Theodore Ts'o.  This file may be
- * redistributed under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  * 
  */
 
@@ -31,6 +35,8 @@
 #include <et/com_err.h>
 #include "e2fsck.h"
 
+#include "problem.h"
+
 /*
  * This is structure is allocated for each time that a block is
  * claimed by more than one file.  So if a particular block is claimed
@@ -75,16 +81,12 @@
  * of multiply-claimed blocks.
  */
 struct dup_inode {
-	ino_t		ino;
-	time_t		mtime;
-	char		*pathname;
-	int		num_dupblocks;
-	int		flags;
+	ino_t			ino, dir;
+	int			num_dupblocks;
+	struct ext2_inode	inode;
 	struct dup_inode	*next;
 };
 
-#define DUP_INODE_DONT_FREE_PATHNAME	0x1
-
 static int process_pass1b_block(ext2_filsys fs, blk_t	*blocknr,
 				int	blockcnt, void	*private);
 static void delete_file(ext2_filsys fs, struct dup_inode *dp,
@@ -125,7 +127,7 @@
 	 * Time to free all of the accumulated data structures that we
 	 * don't need anymore.
 	 */
-	ext2fs_free_inode_bitmap(inode_dup_map);   	inode_dup_map = 0;
+	ext2fs_free_inode_bitmap(inode_dup_map);    inode_dup_map = 0;
 	ext2fs_free_block_bitmap(block_dup_map);    block_dup_map = 0;
 	for (p = dup_blk; p; p = next_p) {
 		next_p = p->next_block;
@@ -136,8 +138,6 @@
 	}
 	for (r = dup_ino; r; r = next_r) {
 		next_r = r->next;
-		if (r->pathname && !(r->flags & DUP_INODE_DONT_FREE_PATHNAME))
-			free(r->pathname);
 		free(r);
 	}
 }
@@ -176,7 +176,7 @@
 		stashed_ino = ino;
 		if ((ino != EXT2_BAD_INO) &&
 		    (!ext2fs_test_inode_bitmap(inode_used_map, ino) ||
-		     !inode_has_valid_blocks(&inode)))
+		     !ext2fs_inode_has_valid_blocks(&inode)))
 			goto next;
 
 		pb.ino = ino;
@@ -189,10 +189,9 @@
 			dp = allocate_memory(sizeof(struct dup_inode),
 					     "duplicate inode record");
 			dp->ino = ino;
-			dp->mtime = inode.i_mtime;
+			dp->dir = 0;
+			dp->inode = inode;
 			dp->num_dupblocks = pb.dup_blocks;
-			dp->pathname = 0;
-			dp->flags = 0;
 			dp->next = dup_ino;
 			dup_ino = dp;
 			if (ino != EXT2_BAD_INO)
@@ -271,112 +270,70 @@
 }
 
 /*
- * Used by pass1c to name the "special" inodes.  They are declared as
- * writeable strings to prevent const problems.
- */
-#define num_special_inodes	7
-char special_inode_name[num_special_inodes][40] =
-{
-	"<The NULL inode>",			/* 0 */
-	"<The bad blocks inode>", 		/* 1 */
-	"/",					/* 2 */
-	"<The ACL index inode>",		/* 3 */
-	"<The ACL data inode>",			/* 4 */
-	"<The boot loader inode>",		/* 5 */
-	"<The undelete directory inode>"	/* 6 */
-};
-
-/*
  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
  * is used so that we can print pathnames when prompting the user for
  * what to do.
  */
-struct process_dir_struct {
-	ext2_filsys	fs;
-	ino_t		dir_ino;
+struct search_dir_struct {
 	int		count;
+	ino_t		first_inode;
 };
 
+static int search_dirent_proc(ino_t dir, int entry,
+			      struct ext2_dir_entry *dirent,
+			      int offset, int blocksize,
+			      char *buf, void *private)
+{
+	struct search_dir_struct *sd = private;
+	struct dup_inode	*p;
+	
+	if (!dirent->inode || (entry < DIRENT_OTHER_FILE) ||
+	    !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
+		return 0;
+
+	for (p = dup_ino; p; p = p->next) {
+		if ((p->ino >= sd->first_inode) && 
+		    (p->ino == dirent->inode))
+			break;
+	}
+
+	if (!p || p->dir)
+		return 0;
+
+	p->dir = dir;
+	sd->count--;
+
+	return(sd->count ? 0 : DIRENT_ABORT);
+}
+
+
 void pass1c(ext2_filsys fs, char *block_buf)
 {
-	int	i;
 	struct dup_inode	*p;
-	errcode_t	retval;
-	char	buf[80];
 	int	inodes_left = dup_inode_count;
-	int	offset, entry;
-	struct ext2_dir_entry *dirent;
+	struct search_dir_struct sd;
 
 	printf("Pass 1C: Scan directories for inodes with dup blocks.\n");
 
 	/*
 	 * First check to see if any of the inodes with dup blocks is
-	 * the bad block inode or the root inode; handle them as
-	 * special cases.
+	 * a special inode.  (Note that the bad block inode isn't
+	 * counted.)
 	 */
 	for (p = dup_ino; p; p = p->next) {
-		if (p->ino < num_special_inodes) {
-			p->pathname = special_inode_name[p->ino];
-			p->flags |= DUP_INODE_DONT_FREE_PATHNAME;
+		if ((p->ino < EXT2_FIRST_INODE(fs->super)) &&
+		    (p->ino != EXT2_BAD_INO))
 			inodes_left--;
-		}
 	}
 
 	/*
 	 * Search through all directories to translate inodes to names
 	 * (by searching for the containing directory for that inode.)
 	 */
-	for (i=0; inodes_left && i < dir_block_count; i++) {
-		retval = ext2fs_read_dir_block(fs, dir_blocks[i].blk,
-					       block_buf);
-		entry = offset = 0;
-		while (offset < fs->blocksize) {
-			entry++;
-			dirent = (struct ext2_dir_entry *)
-				(block_buf + offset);
-			if (!dirent->inode ||
-			    ((dir_blocks[i].blockcnt == 0) && (entry <= 2)))
-				goto next;
-
-			if (!ext2fs_test_inode_bitmap(inode_dup_map,
-						      dirent->inode))
-				goto next;
-
-			for (p = dup_ino; p; p = p->next) {
-				if (p->ino == dirent->inode)
-					break;
-			}
-
-			if (!p || p->pathname)
-				goto next;
-			
-			(void) ext2fs_get_pathname(fs, dir_blocks[i].ino,
-						   p->ino, &p->pathname);
-			inodes_left--;
-			
-		next:
-			if (dirent->rec_len < 8)
-				break;
-			offset += dirent->rec_len;
-		}
-	}
-
-
-	/*
-	 * If we can't get a name, then put in a generic one.
-	 */
-	for (p = dup_ino; p; p = p->next) {
-		if (!p->pathname) {
-			sprintf(buf, "<Unknown inode #%lu>", p->ino);
-			p->pathname = malloc(strlen(buf)+1);
-			if (!p->pathname) {
-				fprintf(stderr,	"pass1c: couldn't malloc "
-					"generic pathname\n");
-				fatal_error(0);
-			}
-			strcpy(p->pathname, buf);
-		}
-	}
+	sd.count = inodes_left;
+	sd.first_inode = EXT2_FIRST_INODE(fs->super);
+	ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
+				  search_dirent_proc, &sd);
 }	
 
 static void pass1d(ext2_filsys fs, char *block_buf)
@@ -387,8 +344,8 @@
 	int	shared_len;
 	int	i;
 	errcode_t	retval;
-	char	*time_str;
 	int	file_ok;
+	struct problem_context pctx;
 	
 	printf("Pass 1D: Reconciling duplicate blocks\n");
 	read_bitmaps(fs);
@@ -436,23 +393,33 @@
 				}
 			}
 		}
-		time_str = ctime(&p->mtime);
-		time_str[24] = 0;
-		printf("File %s (inode #%lu, mod time %s) \n",
-		       p->pathname, p->ino, time_str);
-		printf("  has %d duplicate blocks, shared with %d file%s:\n",
-		       p->num_dupblocks, shared_len,
-		       (shared_len>1) ? "s" : "");
+
+		/*
+		 * Report the inode that we are working on
+		 */
+		clear_problem_context(&pctx);
+		pctx.inode = &p->inode;
+		pctx.ino = p->ino;
+		pctx.dir = p->dir;
+		pctx.blkcount = p->num_dupblocks;
+		pctx.num = shared_len;
+		fix_problem(fs, PR_1B_DUP_FILE, &pctx);
+		pctx.blkcount = 0;
+		pctx.num = 0;
+		
 		for (i = 0; i < shared_len; i++) {
 			for (s = dup_ino; s; s = s->next)
 				if (s->ino == shared[i])
 					break;
 			if (!s)
 				continue;
-			time_str = ctime(&s->mtime);
-			time_str[24] = 0;
-			printf("\t%s (inode #%lu, mod time %s)\n",
-			       s->pathname, s->ino, time_str);
+			/*
+			 * Report the inode that we are sharing with
+			 */
+			pctx.inode = &s->inode;
+			pctx.ino = s->ino;
+			pctx.dir = s->dir;
+			fix_problem(fs, PR_1B_DUP_FILE_LIST, &pctx);
 		}
 		if (file_ok) {
 			printf("Duplicated blocks already reassigned or cloned.\n\n");