Many files:
  Checked in e2fsprogs-1.07

diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog
index d8dad46..dd6da6a 100644
--- a/lib/ext2fs/ChangeLog
+++ b/lib/ext2fs/ChangeLog
@@ -1,3 +1,154 @@
+Wed Mar 12 13:32:05 1997  Theodore Y. Ts'o  <tytso@mit.edu>
+
+	* Release of E2fsprogs version 1.07
+
+Sun Mar  2 16:46:18 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* Makefile.in (ELF_VERSION): Change version to be 2.2
+
+Tue Feb 11 14:54:02 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* alloc.c (ext2fs_get_free_blocks): Change routine to use
+	 	ext2fs_fast_test_block_bitmap_range().
+
+	* bitops.h (ext2fs_fast_test_block_bitmap_range,
+ 		ext2fs_test_block_bitmap_range: New inline functions which
+ 		test to see whether a contiguous range of blocks is
+ 		available.
+
+Thu Feb  6 10:00:13 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* badblocks.c (ext2fs_badblocks_list_create): Rename sybmols to use
+ 		use ext2fs_badblocks_* instead of badblocks_*
+
+	* bb_compat.c: New file which translates between old badblocks_*()
+		names to ext2fs_badblocks_*()
+
+	* unlink.c (ext2fs_unlink): New file, moved ext2fs_unlink() from
+	 	link.c (since e2fsck doesn't use ext2fs_unlink()).
+
+	* rs_bitmap.c (ext2fs_resize_generic_bitmap): New file, contains
+ 		bitmap resizing routine moved from bitmaps.c, since e2fsck
+ 		doesn't need to use this function.
+
+	* lookup.c (ext2fs_lookup): Moved ext2fs_lookup to its own file,
+		since e2fsck only needs ext2fs_lookup.
+
+Mon Feb  3 10:11:40 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* inode.c (ext2fs_open_inode_scan): Set fs->badblocks if it is not
+		already set; this is needed so that programs like dump
+		which use the inode scan functions will deal with
+		filesystems that have bad blocks in the inode table.
+
+Sun Feb  2 00:17:36 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* ext2fs.h (struct_badblocks_list, struct_badblocks_iterate): 
+		Moved to ext2fsP.h, since it doesn't need to be part of
+		the public interface.
+
+	* dir_iterate.c: Move ext2_dir_iterate out of namei.c.
+
+Sat Feb  1 10:14:55 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* dblist.c (ext2fs_get_num_dirs): New file, which implements a
+ 		directory block list abstraction.  (Code moved from
+ 		e2fsck).
+
+	* ext2fs.h, inode.c: Moved definition of ext2_struct_inode_scan to
+		to inode.c (since no one else should be peeking inside it!)
+
+	* valid_blk.c (ext2_inode_has_valid_blocks): New function.
+
+	* openfs.c (ext2fs_open): Check the feature set in the ext2
+		superblock, and refuse to open filesystems if they contain
+		incompatible features.  (Can be overriden with the
+		EXT2_FLAG_FORCE 
+
+Sun Jan 12 11:31:46 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* block.c (ext2fs_block_iterate2): Added new function
+	 	ext2fs_block_iterate2 which changes the function
+	 	signature of the callback function to include the
+	 	referencing block and offset.
+
+	* inode.c (ext2fs_inode_scan_goto_blockgroup): Added new function
+	 	ext2fs_inode_scan_goto_blockgroup which allows an
+	 	application to jump to a particular block group while
+	 	doing an inode scan.
+
+Wed Jan  1 23:50:12 1997  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* dirblock.c: Include string.h, since we use memcpy().
+
+Tue Dec  3 12:27:29 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* getsize.c (ext2fs_get_device_size): The ioctl BLKGETSIZE returns
+		a long not an int; this doesn't matter on i386 machines,
+		but it does on Alpha's.
+	
+Fri Nov 29 20:57:37 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* inode.c (ext2fs_write_inode, ext2fs_read_inode): If the inode
+ 		table pointer is NULL, then return an error indicating
+ 		that the inode table is missing.
+		(get_next_blockgroup, get_next_blocks,
+ 		ext2fs_get_next_inode): Don't treat a missing inode table
+ 		as permanent error.  Return MISSING_INODE_TABLE, but as an
+ 		advisory error code, much like BAD_BLOCK_IN_INODE_TABLE.
+
+	* rw_bitmaps.c (ext2fs_write_block_bitmap,
+ 	 	ext2fs_write_inode_bitmap): If the inode or block bitmap
+ 	 	block is zero, then don't write out the inode or block
+ 	 	bitmap.  The idea here is to avoid stomping on the
+ 	 	superblock.
+		(read_bitmaps): If the inode or block bitmap block is
+	 	zero, then fill in that portion of the inode or block
+	 	bitmap with all zeros.
+
+	* inode.c (ext2fs_get_next_inode): Fix bug in handling of bad
+ 		blocks in inode table when the inode table size is
+ 		non-standard (and can therefore span blocks).
+
+Tue Oct 29 20:13:14 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* alloc.c (ext2fs_new_block): Fix fencepost error in
+		ext2fs_new_block; make sure we don't try to allocate the
+		first block beyond the end of the filesystem.
+
+Mon Oct 14 11:00:48 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* inode.c (check_for_inode_bad_blocks): New function called by
+		get_next_blocks() to avoid reading in bad blocks marked in
+		fs->badblocks.  Inodes located in bad blocks are returned
+		by ext2fs_get_next_inode() returns the error code 
+		EXT2_ET_BAD_BLOCK_IN_INODE_TABLE.
+	
+	* alloc_tables.c (ext2fs_allocate_tables): New function which
+		performs the part of mke2fs's job of allocating the 
+		filesystem tables.
+
+	* test_io.c (test_close): IO manager which is used for testing
+	 	purposes.
+
+Sun Oct 13 04:31:57 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* inode.c (ext2fs_get_next_inode): Separate out the function of
+ 		setting up for a new block group to get_next_blockgroup().
+		Separate out the function of reading in blocks of the
+		inode table to get_next_blocks().
+
+	* ext2fs.h: Add the badblocks list to the ext2_filsys entry
+
+	* badblocks.c (badblocks_list_add, badblocks_list_test): Add
+ 		blocks to the badblock list in sorted order.  This allows
+ 		badblocks_list_test to be coded using a binary search for
+ 		speed.
+
+Tue Oct  8 02:02:03 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+	* Release of E2fsprogs version 1.06
+
 Mon Oct  7 00:44:17 1996  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
 	* ext2fs.h, block.c, closefs.c, dirblock.c, inode.c, native.c,
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 5319ce5..2867dce 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -9,25 +9,34 @@
 
 OBJS= ext2_err.o \
 	alloc.o \
+	alloc_tables.o \
 	badblocks.o \
+	bb_compat.o \
 	bb_inode.o \
 	bitmaps.o \
 	bitops.o \
 	block.o \
+	brel_ma.o \
 	check_desc.o \
 	closefs.o \
 	cmp_bitmaps.o \
+	dblist.o \
+	dblist_dir.o \
 	dirblock.o \
+	dir_iterate.o \
 	expanddir.o \
 	freefs.o \
 	get_pathname.o \
 	getsize.o \
+	icount.o \
 	initialize.o \
 	inline.o \
 	inode.o \
+	irel_ma.o \
 	ismounted.o \
 	link.o \
 	llseek.o \
+	lookup.o \
 	mkdir.o \
 	namei.o \
 	native.o \
@@ -35,31 +44,44 @@
 	openfs.o \
 	read_bb.o \
 	read_bb_file.o \
+	rs_bitmap.o \
 	rw_bitmaps.o \
 	swapfs.o \
-	unix_io.o 
+	test_io.o \
+	unix_io.o \
+	unlink.o \
+	valid_blk.o
 
 SRCS= ext2_err.c \
 	$(srcdir)/alloc.c \
+	$(srcdir)/alloc_tables.c \
 	$(srcdir)/badblocks.c \
+	$(srcdir)/bb_compat.c \
 	$(srcdir)/bb_inode.c \
 	$(srcdir)/bitmaps.c \
 	$(srcdir)/bitops.c \
 	$(srcdir)/block.c \
+	$(srcdir)/brel_ma.c \
 	$(srcdir)/check_desc.c \
 	$(srcdir)/closefs.c \
 	$(srcdir)/cmp_bitmaps.c \
+	$(srcdir)/dblist.c \
+	$(srcdir)/dblist_dir.c \
 	$(srcdir)/dirblock.c \
+	$(srcdir)/dir_iterate.c \
 	$(srcdir)/expanddir.c \
 	$(srcdir)/freefs.c \
 	$(srcdir)/get_pathname.c \
 	$(srcdir)/getsize.c \
+	$(srcdir)/icount.c \
 	$(srcdir)/initialize.c \
 	$(srcdir)/inline.c \
 	$(srcdir)/inode.c \
+	$(srcdir)/irel_ma.c \
 	$(srcdir)/ismounted.c \
 	$(srcdir)/link.c \
 	$(srcdir)/llseek.c \
+	$(srcdir)/lookup.c \
 	$(srcdir)/mkdir.c \
 	$(srcdir)/namei.c \
 	$(srcdir)/native.c \
@@ -67,9 +89,13 @@
 	$(srcdir)/openfs.c \
 	$(srcdir)/read_bb.c \
 	$(srcdir)/read_bb_file.c \
+	$(srcdir)/rs_bitmap.c \
 	$(srcdir)/rw_bitmaps.c \
 	$(srcdir)/swapfs.c \
-	$(srcdir)/unix_io.c 
+	$(srcdir)/test_io.c \
+	$(srcdir)/unix_io.c \
+	$(srcdir)/unlink.c \
+	$(srcdir)/valid_blk.c
 
 HFILES= bitops.h ext2fs.h io.h
 
@@ -86,11 +112,12 @@
 DLL_MYDIR = ext2fs
 DLL_INSTALL_DIR = $(libdir)
 
-ELF_VERSION = 2.1
+ELF_VERSION = 2.2
 ELF_SO_VERSION = 2
 ELF_IMAGE = libext2fs
 ELF_MYDIR = ext2fs
 ELF_INSTALL_DIR = $(libdir)
+ELF_OTHER_LIBS = -lc -L../.. -lcom_err
 
 BSDLIB_VERSION = 2.0
 BSDLIB_IMAGE = libext2fs
@@ -106,7 +133,7 @@
 
 .c.o:
 	$(CC) $(ALL_CFLAGS) -c $< -o $@
-@PROFILE_CMT@	$(CC) $(ALL_CFLAGS) -pg -o profiled/$*.o -c $<
+@PROFILE_CMT@	$(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
 @CHECKER_CMT@	$(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
 @DLL_CMT@	(export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
 @DLL_CMT@		-o jump/$*.o -c $<)
@@ -124,6 +151,17 @@
 ext2_err.c ext2_err.h: ext2_err.et
 	$(COMPILE_ET) ext2_err.et
 
+tst_badblocks: tst_badblocks.o badblocks.o
+	$(CC) -o tst_badblocks tst_badblocks.o badblocks.o $(LIBCOM_ERR)
+
+tst_iscan: tst_iscan.o inode.o $(STATIC_LIBEXT2FS)
+	$(CC) -o tst_iscan tst_iscan.o inode.o $(STATIC_LIBEXT2FS) \
+		$(LIBCOM_ERR)
+
+check:: tst_badblocks tst_iscan
+	./tst_badblocks
+	./tst_iscan
+
 installdirs::
 	$(top_srcdir)/mkinstalldirs $(DESTDIR)$(ulibdir) \
 		$(DESTDIR)$(includedir)/ext2fs
@@ -157,90 +195,205 @@
 # the Makefile.in file
 #
 ext2_err.o: ext2_err.c
-alloc.o: $(srcdir)/alloc.c $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-badblocks.o: $(srcdir)/badblocks.c $(srcdir)/ext2fs.h \
+alloc.o: $(srcdir)/alloc.c \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+alloc_tables.o: $(srcdir)/alloc_tables.c \
+ $(srcdir)/ext2fs.h \
  $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-bb_inode.o: $(srcdir)/bb_inode.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-bitmaps.o: $(srcdir)/bitmaps.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-bitops.o: $(srcdir)/bitops.c $(srcdir)/ext2fs.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+badblocks.o: $(srcdir)/badblocks.c \
+ $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+bb_compat.o: $(srcdir)/bb_compat.c \
+ $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+bb_inode.o: $(srcdir)/bb_inode.c \
+ $(srcdir)/ext2fs.h \
  $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
-block.o: $(srcdir)/block.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-check_desc.o: $(srcdir)/check_desc.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-closefs.o: $(srcdir)/closefs.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-cmp_bitmaps.o: $(srcdir)/cmp_bitmaps.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-dirblock.o: $(srcdir)/dirblock.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-expanddir.o: $(srcdir)/expanddir.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-freefs.o: $(srcdir)/freefs.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-get_pathname.o: $(srcdir)/get_pathname.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-getsize.o: $(srcdir)/getsize.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-initialize.o: $(srcdir)/initialize.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-inline.o: $(srcdir)/inline.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-inode.o: $(srcdir)/inode.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-ismounted.o: $(srcdir)/ismounted.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-link.o: $(srcdir)/link.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-llseek.o: $(srcdir)/llseek.c $(top_srcdir)/lib/et/com_err.h \
- $(srcdir)/io.h
-mkdir.o: $(srcdir)/mkdir.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-namei.o: $(srcdir)/namei.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-native.o: $(srcdir)/native.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-newdir.o: $(srcdir)/newdir.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-openfs.o: $(srcdir)/openfs.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-read_bb.o: $(srcdir)/read_bb.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-read_bb_file.o: $(srcdir)/read_bb_file.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-rw_bitmaps.o: $(srcdir)/rw_bitmaps.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-swapfs.o: $(srcdir)/swapfs.c $(srcdir)/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h  $(srcdir)/bitops.h \
- $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
-unix_io.o: $(srcdir)/unix_io.c $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+bitmaps.o: $(srcdir)/bitmaps.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+bitops.o: $(srcdir)/bitops.c \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+block.o: $(srcdir)/block.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+brel_ma.o: $(srcdir)/brel_ma.c \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h $(srcdir)/brel.h
+check_desc.o: $(srcdir)/check_desc.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+closefs.o: $(srcdir)/closefs.c \
+ $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+cmp_bitmaps.o: $(srcdir)/cmp_bitmaps.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+dblist.o: $(srcdir)/dblist.c \
+ $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+dblist_dir.o: $(srcdir)/dblist_dir.c \
+ $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+dirblock.o: $(srcdir)/dirblock.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+dir_iterate.o: $(srcdir)/dir_iterate.c \
+ $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+expanddir.o: $(srcdir)/expanddir.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+freefs.o: $(srcdir)/freefs.c \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+get_pathname.o: $(srcdir)/get_pathname.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+getsize.o: $(srcdir)/getsize.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+icount.o: $(srcdir)/icount.c $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2fs.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+initialize.o: $(srcdir)/initialize.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+inline.o: $(srcdir)/inline.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+inode.o: $(srcdir)/inode.c \
+ $(srcdir)/ext2fsP.h \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+irel_ma.o: $(srcdir)/irel_ma.c \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h $(srcdir)/irel.h
+ismounted.o: $(srcdir)/ismounted.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+link.o: $(srcdir)/link.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+llseek.o: $(srcdir)/llseek.c \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h 
+lookup.o: $(srcdir)/lookup.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+mkdir.o: $(srcdir)/mkdir.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+namei.o: $(srcdir)/namei.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+native.o: $(srcdir)/native.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+newdir.o: $(srcdir)/newdir.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+openfs.o: $(srcdir)/openfs.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+read_bb.o: $(srcdir)/read_bb.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+read_bb_file.o: $(srcdir)/read_bb_file.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+rs_bitmap.o: $(srcdir)/rs_bitmap.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+rw_bitmaps.o: $(srcdir)/rw_bitmaps.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+swapfs.o: $(srcdir)/swapfs.c \
+ $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+test_io.o: $(srcdir)/test_io.c \
+ $(top_srcdir)/lib/et/com_err.h \
  $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/io.h
+unix_io.o: $(srcdir)/unix_io.c \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/io.h
+unlink.o: $(srcdir)/unlink.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
+valid_blk.o: $(srcdir)/valid_blk.c \
+ $(srcdir)/ext2fs.h \
+ $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/bitops.h
diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c
index c048879..0bc637d 100644
--- a/lib/ext2fs/alloc.c
+++ b/lib/ext2fs/alloc.c
@@ -1,8 +1,13 @@
 /*
  * alloc.c --- allocate new inodes, blocks for ext2fs
  *
- * Copyright (C) 1993 Theodore Ts'o.  This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ * 
  */
 
 #include <stdio.h>
@@ -84,26 +89,12 @@
 			return 0;
 		}
 		i++;
-		if (i > fs->super->s_blocks_count)
+		if (i >= fs->super->s_blocks_count)
 			i = fs->super->s_first_data_block;
 	} while (i != goal);
 	return ENOSPC;
 }
 
-static int check_blocks_free(ext2_filsys fs, ext2fs_block_bitmap map,
-			     blk_t blk, int num)
-{
-	int	i;
-
-	for (i=0; i < num; i++) {
-		if ((blk+i) > fs->super->s_blocks_count)
-			return 0;
-		if (ext2fs_test_block_bitmap(map, blk+i))
-			return 0;
-	}
-	return 1;
-}
-
 errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
 				 int num, ext2fs_block_bitmap map, blk_t *ret)
 {
@@ -122,13 +113,13 @@
 	if (!num)
 		num = 1;
 	do {
-		if (check_blocks_free(fs, map, b, num)) {
+		if (b+num-1 > fs->super->s_blocks_count)
+			b = fs->super->s_first_data_block;
+		if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
 			*ret = b;
 			return 0;
 		}
 		b++;
-		if (b > fs->super->s_blocks_count)
-			b = fs->super->s_first_data_block;
 	} while (b != finish);
 	return ENOSPC;
 }
diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c
new file mode 100644
index 0000000..97bceef
--- /dev/null
+++ b/lib/ext2fs/alloc_tables.c
@@ -0,0 +1,80 @@
+/*
+ * alloc_tables.c --- Allocate tables for a newly initialized
+ * filesystem.  Used by mke2fs when initializing a filesystem
+ *
+ * Copyright (C) 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+
+errcode_t ext2fs_allocate_tables(ext2_filsys fs)
+{
+	errcode_t	retval;
+	blk_t		group_blk, last_blk, new_blk, blk;
+	int		i, j;
+
+	group_blk = fs->super->s_first_data_block;
+	for (i = 0; i < fs->group_desc_count; i++) {
+		last_blk = group_blk + fs->super->s_blocks_per_group;
+		
+		/*
+		 * Allocate the block bitmap
+		 */
+		retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
+						1, fs->block_map, &new_blk);
+		if (retval)
+			return retval;
+		ext2fs_mark_block_bitmap(fs->block_map, new_blk);
+		fs->group_desc[i].bg_block_bitmap = new_blk;
+
+		/*
+		 * ... and the inode bitmap
+		 */
+		retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
+						1, fs->block_map, &new_blk);
+		if (retval)
+			return retval;
+		ext2fs_mark_block_bitmap(fs->block_map, new_blk);
+		fs->group_desc[i].bg_inode_bitmap = new_blk;
+
+		/*
+		 * Finally, allocate the inode table
+		 */
+		retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
+						fs->inode_blocks_per_group,
+						fs->block_map, &new_blk);
+		if (retval)
+			return retval;
+		for (j=0, blk = new_blk;
+		     j < fs->inode_blocks_per_group;
+		     j++, blk++)
+			ext2fs_mark_block_bitmap(fs->block_map, blk);
+		fs->group_desc[i].bg_inode_table = new_blk;
+
+		/*
+		 * Increment the start of the block group
+		 */
+		group_blk += fs->super->s_blocks_per_group;
+	}
+	return 0;
+}
+
diff --git a/lib/ext2fs/badblocks.c b/lib/ext2fs/badblocks.c
index f286747..722af8d 100644
--- a/lib/ext2fs/badblocks.c
+++ b/lib/ext2fs/badblocks.c
@@ -1,8 +1,12 @@
 /*
  * badblocks.c --- routines to manipulate the bad block structure
  * 
- * Copyright (C) 1994 Theodore Ts'o.  This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
@@ -19,19 +23,19 @@
 
 #include <linux/ext2_fs.h>
 
-#include "ext2fs.h"
+#include "ext2fsP.h"
 
 /*
  * This procedure create an empty badblocks list.
  */
-errcode_t badblocks_list_create(badblocks_list *ret, int size)
+errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
 {
-	badblocks_list	bb;
+	ext2_badblocks_list	bb;
 
-	bb = malloc(sizeof(struct struct_badblocks_list));
+	bb = malloc(sizeof(struct ext2_struct_badblocks_list));
 	if (!bb)
 		return ENOMEM;
-	memset(bb, 0, sizeof(struct struct_badblocks_list));
+	memset(bb, 0, sizeof(struct ext2_struct_badblocks_list));
 	bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
 	bb->size = size ? size : 10;
 	bb->list = malloc(bb->size * sizeof(blk_t));
@@ -45,42 +49,42 @@
 
 /*
  * This procedure frees a badblocks list.
+ *
+ * (note: moved to closefs.c)
  */
-void badblocks_list_free(badblocks_list bb)
-{
-	if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
-		return;
 
-	if (bb->list)
-		free(bb->list);
-	bb->list = 0;
-	free(bb);
-}
 
 /*
  * This procedure adds a block to a badblocks list.
  */
-errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
+errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
 {
-	int	i;
+	int	i, j;
+	blk_t	*new_list;
 
 	EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
 
-	for (i=0; i < bb->num; i++)
-		if (bb->list[i] == blk)
-			return 0;
-
 	if (bb->num >= bb->size) {
 		bb->size += 10;
-		bb->list = realloc(bb->list, bb->size * sizeof(blk_t));
-		if (!bb->list) {
-			bb->size = 0;
-			bb->num = 0;
+		new_list = realloc(bb->list, bb->size * sizeof(blk_t));
+		if (!new_list)
 			return ENOMEM;
-		}
+		bb->list = new_list;
 	}
 
-	bb->list[bb->num++] = blk;
+	j = bb->num;
+	for (i=0; i < bb->num; i++) {
+		if (bb->list[i] == blk)
+			return 0;
+		if (bb->list[i] > blk) {
+			j = i;
+			break;
+		}
+	}
+	for (i=bb->num; i > j; i--)
+		bb->list[i] = bb->list[i-1];
+	bb->list[j] = blk;
+	bb->num++;
 	return 0;
 }
 
@@ -88,27 +92,42 @@
  * This procedure tests to see if a particular block is on a badblocks
  * list.
  */
-int badblocks_list_test(badblocks_list bb, blk_t blk)
+int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
 {
-	int	i;
+	int	low, high, mid;
 
-	EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
+	if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
+		return 0;
 
-	for (i=0; i < bb->num; i++)
-		if (bb->list[i] == blk)
+	low = 0;
+	high = bb->num-1;
+	if (blk == bb->list[low])
+		return 1;
+	if (blk == bb->list[high])
+		return 1;
+
+	while (low < high) {
+		mid = (low+high)/2;
+		if (mid == low || mid == high)
+			break;
+		if (blk == bb->list[mid])
 			return 1;
-
+		if (blk < bb->list[mid])
+			high = mid;
+		else
+			low = mid;
+	}
 	return 0;
 }
 
-errcode_t badblocks_list_iterate_begin(badblocks_list bb,
-				       badblocks_iterate *ret)
+errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
+					      ext2_badblocks_iterate *ret)
 {
-	badblocks_iterate iter;
+	ext2_badblocks_iterate iter;
 
 	EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
 
-	iter = malloc(sizeof(struct struct_badblocks_iterate));
+	iter = malloc(sizeof(struct ext2_struct_badblocks_iterate));
 	if (!iter)
 		return ENOMEM;
 
@@ -119,9 +138,9 @@
 	return 0;
 }
 
-int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
+int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
 {
-	badblocks_list	bb;
+	ext2_badblocks_list	bb;
 
 	if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
 		return 0;
@@ -139,7 +158,7 @@
 	return 0;
 }
 
-void badblocks_list_iterate_end(badblocks_iterate iter)
+void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
 {
 	if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
 		return;
diff --git a/lib/ext2fs/bb_compat.c b/lib/ext2fs/bb_compat.c
new file mode 100644
index 0000000..38aeb8a
--- /dev/null
+++ b/lib/ext2fs/bb_compat.c
@@ -0,0 +1,62 @@
+/*
+ * bb_compat.c --- compatibility badblocks routines
+ * 
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fsP.h"
+
+errcode_t badblocks_list_create(badblocks_list *ret, int size)
+{
+	return ext2fs_badblocks_list_create(ret, size);
+}
+
+void badblocks_list_free(badblocks_list bb)
+{
+	ext2fs_badblocks_list_free(bb);
+}
+
+errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
+{
+	return ext2fs_badblocks_list_add(bb, blk);
+}
+
+int badblocks_list_test(badblocks_list bb, blk_t blk)
+{
+	return ext2fs_badblocks_list_test(bb, blk);
+}
+
+errcode_t badblocks_list_iterate_begin(badblocks_list bb,
+				       badblocks_iterate *ret)
+{
+	return ext2fs_badblocks_list_iterate_begin(bb, ret);
+}
+
+int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
+{
+	return ext2fs_badblocks_list_iterate(iter, blk);
+}
+
+void badblocks_list_iterate_end(badblocks_iterate iter)
+{
+	ext2fs_badblocks_list_iterate_end(iter);
+}
diff --git a/lib/ext2fs/bb_inode.c b/lib/ext2fs/bb_inode.c
index c8dfeba..a5dd3a9 100644
--- a/lib/ext2fs/bb_inode.c
+++ b/lib/ext2fs/bb_inode.c
@@ -5,8 +5,12 @@
  * this routine returns an error, the bad block inode may be in an
  * inconsistent state.
  * 
- * Copyright (C) 1994 Theodore Ts'o.  This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ * 
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
@@ -26,7 +30,7 @@
 #include "ext2fs.h"
 
 struct set_badblock_record {
-	badblocks_iterate	bb_iter;
+	ext2_badblocks_iterate	bb_iter;
 	int		bad_block_count;
 	blk_t		*ind_blocks;
 	int		max_ind_blocks;
@@ -37,15 +41,16 @@
 };
 
 static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
-			      void *private);
+			      blk_t ref_block, int ref_offset, void *private);
 static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
-			     void *private);
+				blk_t ref_block, int ref_offset,
+				void *private);
 	
 /*
  * Given a bad blocks bitmap, update the bad blocks inode to reflect
  * the map.
  */
-errcode_t ext2fs_update_bb_inode(ext2_filsys fs, badblocks_list bb_list)
+errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
 {
 	errcode_t			retval;
 	struct set_badblock_record 	rec;
@@ -75,9 +80,9 @@
 	/*
 	 * First clear the old bad blocks (while saving the indirect blocks) 
 	 */
-	retval = ext2fs_block_iterate(fs, EXT2_BAD_INO,
-				      BLOCK_FLAG_DEPTH_TRAVERSE, 0,
-				      clear_bad_block_proc, &rec);
+	retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
+				       BLOCK_FLAG_DEPTH_TRAVERSE, 0,
+				       clear_bad_block_proc, &rec);
 	if (retval)
 		goto cleanup;
 	if (rec.err) {
@@ -93,22 +98,24 @@
 	 * block inode (!).
 	 */
 	if (bb_list) {
-		retval = badblocks_list_iterate_begin(bb_list, &rec.bb_iter);
+		retval = ext2fs_badblocks_list_iterate_begin(bb_list,
+							     &rec.bb_iter);
 		if (retval)
 			goto cleanup;
-		while (badblocks_list_iterate(rec.bb_iter, &blk)) {
+		while (ext2fs_badblocks_list_iterate(rec.bb_iter, &blk)) {
 			ext2fs_mark_block_bitmap(fs->block_map, blk); 
 		}
-		badblocks_list_iterate_end(rec.bb_iter);
+		ext2fs_badblocks_list_iterate_end(rec.bb_iter);
 		ext2fs_mark_bb_dirty(fs);
 		
-		retval = badblocks_list_iterate_begin(bb_list, &rec.bb_iter);
+		retval = ext2fs_badblocks_list_iterate_begin(bb_list,
+							     &rec.bb_iter);
 		if (retval)
 			goto cleanup;
-		retval = ext2fs_block_iterate(fs, EXT2_BAD_INO,
-					      BLOCK_FLAG_APPEND, 0,
-					      set_bad_block_proc, &rec);
-		badblocks_list_iterate_end(rec.bb_iter);
+		retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
+					       BLOCK_FLAG_APPEND, 0,
+					       set_bad_block_proc, &rec);
+		ext2fs_badblocks_list_iterate_end(rec.bb_iter);
 		if (retval) 
 			goto cleanup;
 		if (rec.err) {
@@ -148,7 +155,7 @@
  * indirect blocks.
  */
 static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
-				void *private)
+				blk_t ref_block, int ref_offset, void *private)
 {
 	struct set_badblock_record *rec = (struct set_badblock_record *)
 		private;
@@ -201,7 +208,8 @@
  * Set the block list in the bad block inode, using the supplied bitmap.
  */
 static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
-			 int blockcnt, void *private)
+			      int blockcnt, blk_t ref_block, 
+			      int ref_offset, void *private)
 {
 	struct set_badblock_record *rec = (struct set_badblock_record *)
 		private;
@@ -213,7 +221,7 @@
 		/*
 		 * Get the next bad block.
 		 */
-		if (!badblocks_list_iterate(rec->bb_iter, &blk))
+		if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
 			return BLOCK_ABORT;
 		rec->bad_block_count++;
 	} else {
diff --git a/lib/ext2fs/bitmaps.c b/lib/ext2fs/bitmaps.c
index 7250c80..3ef5666 100644
--- a/lib/ext2fs/bitmaps.c
+++ b/lib/ext2fs/bitmaps.c
@@ -2,8 +2,12 @@
  * bitmaps.c --- routines to read, write, and manipulate the inode and
  * block bitmaps.
  *
- * Copyright (C) 1993 Theodore Ts'o.  This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
@@ -166,4 +170,3 @@
 	memset(bitmap->bitmap, 0,
 	       ((bitmap->real_end - bitmap->start) / 8) + 1);
 }
-
diff --git a/lib/ext2fs/bitops.c b/lib/ext2fs/bitops.c
index 6f256e5..8ae0242 100644
--- a/lib/ext2fs/bitops.c
+++ b/lib/ext2fs/bitops.c
@@ -2,10 +2,12 @@
  * bitops.c --- Bitmap frobbing code.  See bitops.h for the inlined
  * 	routines.
  * 
- * Copyright (C) 1993, 1994 Theodore Ts'o.  This file may be
- * redistributed under the terms of the GNU Public License.
- * 
- * Taken from <asm/bitops.h>, Copyright 1992, Linus Torvalds.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h
index e967c87..24bd5a7 100644
--- a/lib/ext2fs/bitops.h
+++ b/lib/ext2fs/bitops.h
@@ -2,10 +2,15 @@
  * bitops.h --- Bitmap frobbing code.  The byte swapping routines are
  * 	also included here.
  * 
- * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.  This file may be
- * redistributed under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  * 
- * Taken from <asm/bitops.h>, Copyright 1992, Linus Torvalds.
+ * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
+ * Linus Torvalds.
  */
 
 
@@ -54,9 +59,22 @@
 extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
 					 ino_t inode);
 extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
-extern blk_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
+extern ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
 extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
-extern blk_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
+extern ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
+
+extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					   blk_t block, int num);
+extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					     blk_t block, int num);
+extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					  blk_t block, int num);
+extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						blk_t block, int num);
+extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						  blk_t block, int num);
+extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					       blk_t block, int num);
 
 /*
  * The inline routines themselves...
@@ -305,7 +323,14 @@
 #endif /* !_EXT2_HAVE_ASM_SWAB */
 
 _INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
-				       __u32 bitno)
+					 __u32 bitno);
+_INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					   blk_t bitno);
+_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					blk_t bitno);
+
+_INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
+					 __u32 bitno)
 {
 	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
 		ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
@@ -315,7 +340,7 @@
 }
 
 _INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
-					 blk_t bitno)
+					   blk_t bitno)
 {
 	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
 		ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
@@ -325,7 +350,7 @@
 }
 
 _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
-				       blk_t bitno)
+					blk_t bitno)
 {
 	if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
 		ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
@@ -455,7 +480,7 @@
 	return bitmap->start;
 }
 
-_INLINE_ blk_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
+_INLINE_ ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
 {
 	return bitmap->start;
 }
@@ -465,11 +490,107 @@
 	return bitmap->end;
 }
 
-_INLINE_ blk_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
+_INLINE_ ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
 {
 	return bitmap->end;
 }
 
+_INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					    blk_t block, int num)
+{
+	int	i;
+
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
+				   block, bitmap->description);
+		return 0;
+	}
+	for (i=0; i < num; i++) {
+		if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
+			return 0;
+	}
+	return 1;
+}
+
+_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						 blk_t block, int num)
+{
+	int	i;
+
+#ifdef EXT2FS_DEBUG_FAST_OPS
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
+				   block, bitmap->description);
+		return 0;
+	}
+#endif
+	for (i=0; i < num; i++) {
+		if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
+			return 0;
+	}
+	return 1;
+}
+
+_INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					     blk_t block, int num)
+{
+	int	i;
+	
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
+				   bitmap->description);
+		return;
+	}
+	for (i=0; i < num; i++)
+		ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						  blk_t block, int num)
+{
+	int	i;
+	
+#ifdef EXT2FS_DEBUG_FAST_OPS
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
+				   bitmap->description);
+		return;
+	}
+#endif	
+	for (i=0; i < num; i++)
+		ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+					       blk_t block, int num)
+{
+	int	i;
+	
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
+				   bitmap->description);
+		return;
+	}
+	for (i=0; i < num; i++)
+		ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
+_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
+						    blk_t block, int num)
+{
+	int	i;
+	
+#ifdef EXT2FS_DEBUG_FAST_OPS
+	if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
+		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
+				   bitmap->description);
+		return;
+	}
+#endif	
+	for (i=0; i < num; i++)
+		ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
+}
+
 #undef _INLINE_
 #endif
 
diff --git a/lib/ext2fs/block.c b/lib/ext2fs/block.c
index b7f0aa3..3552dab 100644
--- a/lib/ext2fs/block.c
+++ b/lib/ext2fs/block.c
@@ -1,8 +1,12 @@
 /*
  * block.c --- iterate over all blocks in an inode
  * 
- * Copyright (C) 1993 Theodore Ts'o.  This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
@@ -22,6 +26,8 @@
 	int (*func)(ext2_filsys	fs,
 		    blk_t	*blocknr,
 		    int		bcount,
+		    blk_t	ref_blk,
+		    int		ref_offset,
 		    void	*private);
 	int		bcount;
 	int		bsize;
@@ -33,16 +39,18 @@
 	void	*private;
 };
 
-static int block_iterate_ind(blk_t *ind_block, struct block_context *ctx)
+static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
+			     int ref_offset, struct block_context *ctx)
 {
 	int	ret = 0, changed = 0;
-	int	i, flags, limit;
+	int	i, flags, limit, offset;
 	blk_t	*block_nr;
 
 	if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
 	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
 		ret = (*ctx->func)(ctx->fs, ind_block,
-				   BLOCK_COUNT_IND, ctx->private);
+				   BLOCK_COUNT_IND, ref_block,
+				   ref_offset, ctx->private);
 	if (!*ind_block || (ret & BLOCK_ABORT))
 		return ret;
 	if (*ind_block >= ctx->fs->super->s_blocks_count ||
@@ -65,27 +73,32 @@
 			*block_nr = ext2fs_swab32(*block_nr);
 	}
 	block_nr = (blk_t *) ctx->ind_buf;
+	offset = 0;
 	if (ctx->flags & BLOCK_FLAG_APPEND) {
 		for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
 			flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
+					     *ind_block, offset, 
 					     ctx->private);
 			changed	|= flags;
 			if (flags & BLOCK_ABORT) {
 				ret |= BLOCK_ABORT;
 				break;
 			}
+			offset += sizeof(blk_t);
 		}
 	} else {
 		for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
 			if (*block_nr == 0)
 				continue;
 			flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
+					     *ind_block, offset, 
 					     ctx->private);
 			changed	|= flags;
 			if (flags & BLOCK_ABORT) {
 				ret |= BLOCK_ABORT;
 				break;
 			}
+			offset += sizeof(blk_t);
 		}
 	}
 	if (changed & BLOCK_CHANGED) {
@@ -104,20 +117,23 @@
 	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
 	    !(ret & BLOCK_ABORT))
 		ret |= (*ctx->func)(ctx->fs, ind_block,
-				    BLOCK_COUNT_IND, ctx->private);
+				    BLOCK_COUNT_IND, ref_block,
+				    ref_offset, ctx->private);
 	return ret;
 }
 	
-static int block_iterate_dind(blk_t *dind_block, struct block_context *ctx)
+static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
+			      int ref_offset, struct block_context *ctx)
 {
 	int	ret = 0, changed = 0;
-	int	i, flags, limit;
+	int	i, flags, limit, offset;
 	blk_t	*block_nr;
 
 	if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
 	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
 		ret = (*ctx->func)(ctx->fs, dind_block,
-				   BLOCK_COUNT_DIND, ctx->private);
+				   BLOCK_COUNT_DIND, ref_block,
+				   ref_offset, ctx->private);
 	if (!*dind_block || (ret & BLOCK_ABORT))
 		return ret;
 	if (*dind_block >= ctx->fs->super->s_blocks_count ||
@@ -140,25 +156,32 @@
 			*block_nr = ext2fs_swab32(*block_nr);
 	}
 	block_nr = (blk_t *) ctx->dind_buf;
+	offset = 0;
 	if (ctx->flags & BLOCK_FLAG_APPEND) {
 		for (i = 0; i < limit; i++, block_nr++) {
-			flags = block_iterate_ind(block_nr, ctx);
+			flags = block_iterate_ind(block_nr,
+						  *dind_block, offset,
+						  ctx);
 			changed |= flags;
 			if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
 				ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
 				break;
 			}
+			offset += sizeof(blk_t);
 		}
 	} else {
 		for (i = 0; i < limit; i++, block_nr++) {
 			if (*block_nr == 0)
 				continue;
-			flags = block_iterate_ind(block_nr, ctx);
+			flags = block_iterate_ind(block_nr,
+						  *dind_block, offset,
+						  ctx);
 			changed |= flags;
 			if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
 				ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
 				break;
 			}
+			offset += sizeof(blk_t);
 		}
 	}
 	if (changed & BLOCK_CHANGED) {
@@ -177,20 +200,23 @@
 	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
 	    !(ret & BLOCK_ABORT))
 		ret |= (*ctx->func)(ctx->fs, dind_block,
-				    BLOCK_COUNT_DIND, ctx->private);
+				    BLOCK_COUNT_DIND, ref_block,
+				    ref_offset, ctx->private);
 	return ret;
 }
 	
-static int block_iterate_tind(blk_t *tind_block, struct block_context *ctx)
+static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
+			      int ref_offset, struct block_context *ctx)
 {
 	int	ret = 0, changed = 0;
-	int	i, flags, limit;
+	int	i, flags, limit, offset;
 	blk_t	*block_nr;
 
 	if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
 	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY))
 		ret = (*ctx->func)(ctx->fs, tind_block,
-				   BLOCK_COUNT_TIND, ctx->private);
+				   BLOCK_COUNT_TIND, ref_block,
+				   ref_offset, ctx->private);
 	if (!*tind_block || (ret & BLOCK_ABORT))
 		return ret;
 	if (*tind_block >= ctx->fs->super->s_blocks_count ||
@@ -213,25 +239,32 @@
 			*block_nr = ext2fs_swab32(*block_nr);
 	}
 	block_nr = (blk_t *) ctx->tind_buf;
+	offset = 0;
 	if (ctx->flags & BLOCK_FLAG_APPEND) {
 		for (i = 0; i < limit; i++, block_nr++) {
-			flags = block_iterate_dind(block_nr, ctx);
+			flags = block_iterate_dind(block_nr,
+						   *tind_block,
+						   offset, ctx);
 			changed |= flags;
 			if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
 				ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
 				break;
 			}
+			offset += sizeof(blk_t);
 		}
 	} else {
 		for (i = 0; i < limit; i++, block_nr++) {
 			if (*block_nr == 0)
 				continue;
-			flags = block_iterate_dind(block_nr, ctx);
+			flags = block_iterate_dind(block_nr,
+						   *tind_block,
+						   offset, ctx);
 			changed |= flags;
 			if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
 				ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
 				break;
 			}
+			offset += sizeof(blk_t);
 		}
 	}
 	if (changed & BLOCK_CHANGED) {
@@ -250,29 +283,32 @@
 	    !(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
 	    !(ret & BLOCK_ABORT))
 		ret |= (*ctx->func)(ctx->fs, tind_block,
-				    BLOCK_COUNT_TIND, ctx->private);
+				    BLOCK_COUNT_TIND, ref_block,
+				    ref_offset, ctx->private);
 	
 	return ret;
 }
 	
-errcode_t ext2fs_block_iterate(ext2_filsys fs,
-			       ino_t	ino,
-			       int	flags,
-			       char *block_buf,
-			       int (*func)(ext2_filsys fs,
-					   blk_t	*blocknr,
-					   int	blockcnt,
-					   void	*private),
-			       void *private)
+errcode_t ext2fs_block_iterate2(ext2_filsys fs,
+				ino_t	ino,
+				int	flags,
+				char *block_buf,
+				int (*func)(ext2_filsys fs,
+					    blk_t	*blocknr,
+					    int	blockcnt,
+					    blk_t	ref_blk,
+					    int		ref_offset,
+					    void	*private),
+				void *private)
 {
 	int	i;
 	int	got_inode = 0;
 	int	ret = 0;
-	struct block_context ctx;
 	blk_t	blocks[EXT2_N_BLOCKS];	/* directory data blocks */
 	struct ext2_inode inode;
 	errcode_t	retval;
-	
+	struct block_context ctx;
+
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
 	ret = ext2fs_get_blocks(fs, ino, blocks);
@@ -282,8 +318,8 @@
 	ctx.fs = fs;
 	ctx.func = func;
 	ctx.private = private;
-	ctx.bcount = 0;
 	ctx.flags = flags;
+	ctx.bcount = 0;
 	if (block_buf) {
 		ctx.ind_buf = block_buf;
 	} else {
@@ -304,8 +340,10 @@
 			goto abort;
 		got_inode = 1;
 		if (inode.osd1.hurd1.h_i_translator) {
-			ret |= (*func)(fs, &inode.osd1.hurd1.h_i_translator,
-				       BLOCK_COUNT_TRANSLATOR, private);
+			ret |= (*ctx.func)(fs,
+					   &inode.osd1.hurd1.h_i_translator,
+					   BLOCK_COUNT_TRANSLATOR,
+					   0, 0, private);
 			if (ret & BLOCK_ABORT)
 				goto abort;
 		}
@@ -316,23 +354,27 @@
 	 */
 	for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
 		if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
-			ret |= (*func)(fs, &blocks[i], ctx.bcount, private);
+			ret |= (*ctx.func)(fs, &blocks[i],
+					    ctx.bcount, 0, 0, private);
 			if (ret & BLOCK_ABORT)
 				goto abort;
 		}
 	}
 	if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
-		ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, &ctx);
+		ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
+					 0, 0, &ctx);
 		if (ret & BLOCK_ABORT)
 			goto abort;
 	}
 	if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
-		ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK, &ctx);
+		ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
+					  0, 0, &ctx);
 		if (ret & BLOCK_ABORT)
 			goto abort;
 	}
 	if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
-		ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK, &ctx);
+		ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
+					  0, 0, &ctx);
 		if (ret & BLOCK_ABORT)
 			goto abort;
 	}
@@ -356,3 +398,40 @@
 
 	return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
 }
+
+struct xlate {
+	int (*func)(ext2_filsys	fs,
+		    blk_t	*blocknr,
+		    int		bcount,
+		    void	*private);
+	void *real_private;
+};
+
+static int xlate_func(ext2_filsys fs, blk_t *blocknr, int blockcnt,
+		      blk_t ref_block, int ref_offset, void *private)
+{
+	struct xlate *xl = private;
+
+	return (*xl->func)(fs, blocknr, blockcnt, xl->real_private);
+}
+
+errcode_t ext2fs_block_iterate(ext2_filsys fs,
+			       ino_t	ino,
+			       int	flags,
+			       char *block_buf,
+			       int (*func)(ext2_filsys fs,
+					   blk_t	*blocknr,
+					   int	blockcnt,
+					   void	*private),
+			       void *private)
+{
+	struct xlate xl;
+	
+	xl.real_private = private;
+	xl.func = func;
+
+	return ext2fs_block_iterate2(fs, ino, flags, block_buf,
+				    xlate_func, &xl);
+}
+
+
diff --git a/lib/ext2fs/brel.h b/lib/ext2fs/brel.h
new file mode 100644
index 0000000..f31b7ae
--- /dev/null
+++ b/lib/ext2fs/brel.h
@@ -0,0 +1,84 @@
+/*
+ * brel.h
+ * 
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+struct ext2_block_relocate_entry {
+	blk_t	new;
+	__s16	offset;
+	__u16	flags;
+	union {
+		blk_t	block_ref;
+		ino_t	inode_ref;
+	} owner;
+};
+
+#define RELOCATE_INODE_REF 0x0001
+
+typedef struct ext2_block_relocation_table *ext2_brel;
+
+struct ext2_block_relocation_table {
+	__u32	magic;
+	char	*name;
+	blk_t	current;
+	void	*private;
+
+	/*
+	 * Add a block relocation entry.
+	 */
+	errcode_t (*put)(ext2_brel brel, blk_t old,
+			      struct ext2_block_relocate_entry *ent);
+
+	/*
+	 * Get a block relocation entry.
+	 */
+	errcode_t (*get)(ext2_brel brel, blk_t old,
+			      struct ext2_block_relocate_entry *ent);
+
+	/*
+	 * Initialize for iterating over the block relocation entries.
+	 */
+	errcode_t (*start_iter)(ext2_brel brel);
+	
+	/*
+	 * The iterator function for the inode relocation entries.
+	 * Returns an inode number of 0 when out of entries.
+	 */
+	errcode_t (*next)(ext2_brel brel, blk_t *old,
+			  struct ext2_block_relocate_entry *ent);
+
+	/*
+	 * Move the inode relocation table from one block number to
+	 * another.
+	 */
+	errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
+
+	/*
+	 * Remove a block relocation entry.
+	 */
+	errcode_t (*delete)(ext2_brel brel, blk_t old);
+
+
+	/*
+	 * Free the block relocation table.
+	 */
+	errcode_t (*free)(ext2_brel brel);
+};
+
+errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
+				    ext2_brel *brel);
+
+#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
+#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
+#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
+#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
+#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
+#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
+#define ext2fs_brel_free(brel) ((brel)->free((brel)))
+
diff --git a/lib/ext2fs/brel_ma.c b/lib/ext2fs/brel_ma.c
new file mode 100644
index 0000000..a4258a7
--- /dev/null
+++ b/lib/ext2fs/brel_ma.c
@@ -0,0 +1,191 @@
+/*
+ * brel_ma.c
+ * 
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+#include "brel.h"
+
+static errcode_t bma_put(ext2_brel brel, blk_t old,
+			struct ext2_block_relocate_entry *ent);
+static errcode_t bma_get(ext2_brel brel, blk_t old,
+			struct ext2_block_relocate_entry *ent);
+static errcode_t bma_start_iter(ext2_brel brel);
+static errcode_t bma_next(ext2_brel brel, blk_t *old,
+			 struct ext2_block_relocate_entry *ent);
+static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
+static errcode_t bma_delete(ext2_brel brel, blk_t old);
+static errcode_t bma_free(ext2_brel brel);
+
+struct brel_ma {
+	__u32 magic;
+	blk_t max_block;
+	struct ext2_block_relocate_entry *entries;
+};
+
+errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
+				      ext2_brel *new_brel)
+{
+	ext2_brel		brel = 0;
+	errcode_t	retval;
+	struct brel_ma 	*ma = 0;
+	size_t		size;
+
+	*new_brel = 0;
+
+	/*
+	 * Allocate memory structures
+	 */
+	retval = ENOMEM;
+	brel = malloc(sizeof(struct ext2_block_relocation_table));
+	if (!brel)
+		goto errout;
+	memset(brel, 0, sizeof(struct ext2_block_relocation_table));
+	
+	brel->name = malloc(strlen(name)+1);
+	if (!brel->name)
+		goto errout;
+	strcpy(brel->name, name);
+	
+	ma = malloc(sizeof(struct brel_ma));
+	if (!ma)
+		goto errout;
+	memset(ma, 0, sizeof(struct brel_ma));
+	brel->private = ma;
+	
+	size = sizeof(struct ext2_block_relocate_entry) * (max_block+1);
+	ma->entries = malloc(size);
+	if (!ma->entries)
+		goto errout;
+	memset(ma->entries, 0, size);
+	ma->max_block = max_block;
+
+	/*
+	 * Fill in the brel data structure
+	 */
+	brel->put = bma_put;
+	brel->get = bma_get;
+	brel->start_iter = bma_start_iter;
+	brel->next = bma_next;
+	brel->move = bma_move;
+	brel->delete = bma_delete;
+	brel->free = bma_free;
+	
+	*new_brel = brel;
+	return 0;
+
+errout:
+	bma_free(brel);
+	return retval;
+}
+
+static errcode_t bma_put(ext2_brel brel, blk_t old,
+			struct ext2_block_relocate_entry *ent)
+{
+	struct brel_ma 	*ma;
+
+	ma = brel->private;
+	if (old > ma->max_block)
+		return EINVAL;
+	ma->entries[old] = *ent;
+	return 0;
+}
+
+static errcode_t bma_get(ext2_brel brel, blk_t old,
+			struct ext2_block_relocate_entry *ent)
+{
+	struct brel_ma 	*ma;
+
+	ma = brel->private;
+	if (old > ma->max_block)
+		return EINVAL;
+	if (ma->entries[old].new == 0)
+		return ENOENT;
+	*ent = ma->entries[old];
+	return 0;
+}
+
+static errcode_t bma_start_iter(ext2_brel brel)
+{
+	brel->current = 0;
+	return 0;
+}
+
+static errcode_t bma_next(ext2_brel brel, blk_t *old,
+			  struct ext2_block_relocate_entry *ent)
+{
+	struct brel_ma 	*ma;
+
+	ma = brel->private;
+	while (++brel->current < ma->max_block) {
+		if (ma->entries[brel->current].new == 0)
+			continue;
+		*old = brel->current;
+		*ent = ma->entries[brel->current];
+		return 0;
+	}
+	*old = 0;
+	return 0;
+}
+
+static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
+{
+	struct brel_ma 	*ma;
+
+	ma = brel->private;
+	if ((old > ma->max_block) || (new > ma->max_block))
+		return EINVAL;
+	if (ma->entries[old].new == 0)
+		return ENOENT;
+	ma->entries[new] = ma->entries[old];
+	ma->entries[old].new = 0;
+	return 0;
+}
+
+static errcode_t bma_delete(ext2_brel brel, blk_t old)
+{
+	struct brel_ma 	*ma;
+
+	ma = brel->private;
+	if (old > ma->max_block)
+		return EINVAL;
+	if (ma->entries[old].new == 0)
+		return ENOENT;
+	ma->entries[old].new = 0;
+	return 0;
+}
+
+static errcode_t bma_free(ext2_brel brel)
+{
+	struct brel_ma 	*ma;
+
+	if (!brel)
+		return 0;
+
+	ma = brel->private;
+
+	if (ma) {
+		if (ma->entries)
+			free (ma->entries);
+		free(ma);
+	}
+	if (brel->name)
+		free(brel->name);
+	free (brel);
+	return 0;
+}
diff --git a/lib/ext2fs/check_desc.c b/lib/ext2fs/check_desc.c
index 7d3f3d4..74b3e2d 100644
--- a/lib/ext2fs/check_desc.c
+++ b/lib/ext2fs/check_desc.c
@@ -1,8 +1,12 @@
 /*
  * check_desc.c --- Check the group descriptors of an ext2 filesystem
  * 
- * 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 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c
index 18a93db..e24b6b6 100644
--- a/lib/ext2fs/closefs.c
+++ b/lib/ext2fs/closefs.c
@@ -1,8 +1,12 @@
 /*
  * closefs.c --- close an ext2 filesystem
  * 
- * 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 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
@@ -16,7 +20,7 @@
 
 #include <linux/ext2_fs.h>
 
-#include "ext2fs.h"
+#include "ext2fsP.h"
 
 errcode_t ext2fs_flush(ext2_filsys fs)
 {
@@ -118,7 +122,6 @@
 		if (retval)
 			goto errout;
 	}
-
 	retval = 0;
 errout:
 	fs->super->s_state = fs_state;
@@ -142,6 +145,42 @@
 		if (retval)
 			return retval;
 	}
+	if (fs->write_bitmaps) {
+		retval = fs->write_bitmaps(fs);
+		if (retval)
+			return retval;
+	}
 	ext2fs_free(fs);
 	return 0;
 }
+
+/*
+ * This procedure frees a badblocks list.
+ */
+void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
+{
+	if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
+		return;
+
+	if (bb->list)
+		free(bb->list);
+	bb->list = 0;
+	free(bb);
+}
+
+/*
+ * Close a directory block list
+ */
+void ext2fs_free_dblist(ext2_dblist dblist)
+{
+	if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
+		return;
+
+	if (dblist->list)
+		free(dblist->list);
+	dblist->list = 0;
+	if (dblist->fs && dblist->fs->dblist == dblist)
+		dblist->fs->dblist = 0;
+	dblist->magic = 0;
+	free(dblist);
+}
diff --git a/lib/ext2fs/cmp_bitmaps.c b/lib/ext2fs/cmp_bitmaps.c
index cc9eb6d..3d04a97 100644
--- a/lib/ext2fs/cmp_bitmaps.c
+++ b/lib/ext2fs/cmp_bitmaps.c
@@ -1,8 +1,12 @@
 /*
  * cmp_bitmaps.c --- routines to compare inode and block bitmaps.
  *
- * Copyright (C) 1995 Theodore Ts'o.  This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
diff --git a/lib/ext2fs/dblist.c b/lib/ext2fs/dblist.c
new file mode 100644
index 0000000..72d5840
--- /dev/null
+++ b/lib/ext2fs/dblist.c
@@ -0,0 +1,175 @@
+/*
+ * dblist.c -- directory block list functions
+ * 
+ * Copyright 1997 by Theodore Ts'o
+ * 
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ * 
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fsP.h"
+
+static int dir_block_cmp(const void *a, const void *b);
+
+/*
+ * Returns the number of directories in the filesystem as reported by
+ * the group descriptors.  Of course, the group descriptors could be
+ * wrong!
+ */
+errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ino_t *ret_num_dirs)
+{
+	int	i;
+	ino_t	num_dirs;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+	
+	num_dirs = 0;
+	for (i = 0; i < fs->group_desc_count; i++)
+		num_dirs += fs->group_desc[i].bg_used_dirs_count;
+
+	*ret_num_dirs = num_dirs;
+
+	return 0;
+}
+
+/*
+ * Initialize a directory block list
+ */
+errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
+{
+	ext2_dblist	dblist;
+	errcode_t	retval;
+
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	if ((ret_dblist == 0) && fs->dblist &&
+	    (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
+		return 0;
+
+	dblist = malloc(sizeof(struct ext2_struct_dblist));
+	if (!dblist)
+		return ENOMEM;
+	memset(dblist, 0, sizeof(struct ext2_struct_dblist));
+
+	dblist->magic = EXT2_ET_MAGIC_DBLIST;
+	dblist->fs = fs;
+	retval = ext2fs_get_num_dirs(fs, &dblist->size);
+	if (retval)
+		goto cleanup;
+
+	dblist->count = 0;
+	dblist->sorted = 1;
+	dblist->list = malloc(sizeof(struct ext2_db_entry) * dblist->size);
+	if (dblist->list == NULL) {
+		retval = ENOMEM;
+		goto cleanup;
+	}
+	if (ret_dblist)
+		*ret_dblist = dblist;
+	else
+		fs->dblist = dblist;
+
+	return 0;
+cleanup:
+	if (dblist)
+		free(dblist);
+	return retval;
+}
+
+/*
+ * Close a directory block list
+ *
+ * (moved to closefs.c)
+ */
+
+
+/*
+ * Add a directory block to the directory block list
+ */
+errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
+			       int blockcnt)
+{
+	struct ext2_db_entry 	*nlist, *new;
+	
+	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+	if (dblist->count >= dblist->size) {
+		dblist->size += 100;
+		nlist = realloc(dblist->list,
+				dblist->size * sizeof(struct ext2_db_entry));
+		if (nlist == 0) {
+			dblist->size -= 100;
+			return ENOMEM;
+		}
+		dblist->list = nlist;
+	}
+	new = dblist->list + dblist->count++;
+	new->blk = blk;
+	new->ino = ino;
+	new->blockcnt = blockcnt;
+
+	dblist->sorted = 0;
+
+	return 0;
+}
+
+/*
+ * This function iterates over the directory block list
+ */
+errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
+				int (*func)(ext2_filsys fs,
+					    struct ext2_db_entry *db_info,
+					    void	*private),
+				void *private)
+{
+	ino_t	i;
+	int	ret;
+	
+	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+	if (!dblist->sorted) {
+		qsort(dblist->list, dblist->count,
+		      sizeof(struct ext2_db_entry), dir_block_cmp);
+		dblist->sorted = 1;
+	}
+	for (i=0; i < dblist->count; i++) {
+		ret = (*func)(dblist->fs, &dblist->list[i], private);
+		if (ret & DBLIST_ABORT)
+			return 0;
+	}
+	
+	return 0;
+}
+
+
+static int dir_block_cmp(const void *a, const void *b)
+{
+	const struct ext2_db_entry *db_a =
+		(const struct ext2_db_entry *) a;
+	const struct ext2_db_entry *db_b =
+		(const struct ext2_db_entry *) b;
+
+	if (db_a->blk != db_b->blk)
+		return (db_a->blk - db_b->blk);
+	
+	if (db_a->ino != db_b->ino)
+		return (db_a->ino - db_b->ino);
+
+	return (db_a->blockcnt - db_b->blockcnt);
+}
+
+			     
diff --git a/lib/ext2fs/dblist_dir.c b/lib/ext2fs/dblist_dir.c
new file mode 100644
index 0000000..10c7b58
--- /dev/null
+++ b/lib/ext2fs/dblist_dir.c
@@ -0,0 +1,79 @@
+/*
+ * dblist_dir.c --- iterate by directory entry
+ *
+ * Copyright 1997 by Theodore Ts'o
+ * 
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ * 
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fsP.h"
+
+static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
+		       void *private);
+
+extern errcode_t
+	ext2fs_dblist_dir_iterate(ext2_dblist dblist,
+				  int	flags,
+				  char	*block_buf,
+				  int (*func)(ino_t	dir,
+					      int	entry,
+					      struct ext2_dir_entry *dirent,
+					      int	offset,
+					      int	blocksize,
+					      char	*buf,
+					      void	*private),
+				  void *private)
+{
+	errcode_t		retval;
+	struct dir_context	ctx;
+
+	EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+	ctx.dir = 0;
+	ctx.flags = flags;
+	if (block_buf)
+		ctx.buf = block_buf;
+	else {
+		ctx.buf = malloc(dblist->fs->blocksize);
+		if (!ctx.buf)
+			return ENOMEM;
+	}
+	ctx.func = 0;
+	ctx.func2 = func;
+	ctx.private = private;
+	ctx.errcode = 0;
+
+	retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx);
+	
+	if (!block_buf)
+		free(ctx.buf);
+	if (retval)
+		return retval;
+	return ctx.errcode;
+}
+
+static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
+		       void *private)
+{
+	struct dir_context	*ctx = private;
+
+	ctx->dir = db_info->ino;
+	
+	return ext2fs_process_dir_block(fs, &db_info->blk,
+					db_info->blockcnt, private);
+}
diff --git a/lib/ext2fs/dir_iterate.c b/lib/ext2fs/dir_iterate.c
new file mode 100644
index 0000000..91f8ca6
--- /dev/null
+++ b/lib/ext2fs/dir_iterate.c
@@ -0,0 +1,134 @@
+/*
+ * dir_iterate.c --- ext2fs directory iteration operations
+ * 
+ * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fsP.h"
+
+errcode_t ext2fs_dir_iterate(ext2_filsys fs,
+			     ino_t dir,
+			     int flags,
+			     char *block_buf,
+			     int (*func)(struct ext2_dir_entry *dirent,
+					 int	offset,
+					 int	blocksize,
+					 char	*buf,
+					 void	*private),
+			     void *private)
+{
+	struct		dir_context	ctx;
+	errcode_t	retval;
+	
+	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+	retval = ext2fs_check_directory(fs, dir);
+	if (retval)
+		return retval;
+	
+	ctx.dir = dir;
+	ctx.flags = flags;
+	if (block_buf)
+		ctx.buf = block_buf;
+	else {
+		ctx.buf = malloc(fs->blocksize);
+		if (!ctx.buf)
+			return ENOMEM;
+	}
+	ctx.func = func;
+	ctx.func2 = 0;
+	ctx.private = private;
+	ctx.errcode = 0;
+	retval = ext2fs_block_iterate(fs, dir, 0, 0,
+				      ext2fs_process_dir_block, &ctx);
+	if (!block_buf)
+		free(ctx.buf);
+	if (retval)
+		return retval;
+	return ctx.errcode;
+}
+
+/*
+ * Helper function which is private to this module.  Used by
+ * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
+ */
+extern int ext2fs_process_dir_block(ext2_filsys  	fs,
+				    blk_t		*blocknr,
+				    int		blockcnt,
+				    void		*private)
+{
+	struct dir_context *ctx = (struct dir_context *) private;
+	int		offset = 0;
+	int		ret = 0;
+	int		changed = 0;
+	int		do_abort = 0;
+	int		entry;
+	struct ext2_dir_entry *dirent;
+
+	if (blockcnt < 0)
+		return 0;
+
+	ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
+	if (ctx->errcode)
+		return BLOCK_ABORT;
+
+	entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
+	
+	while (offset < fs->blocksize) {
+		dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
+		if (!dirent->inode &&
+		    !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
+			goto next;
+
+		if (ctx->func)
+			ret = (ctx->func)(dirent, offset, fs->blocksize,
+					  ctx->buf, ctx->private);
+		else if (ctx->func2) {
+			ret = (ctx->func2)(ctx->dir, entry, dirent, offset,
+					   fs->blocksize, ctx->buf,
+					   ctx->private);
+			if (entry < DIRENT_OTHER_FILE)
+				entry++;
+		}
+			
+		if (ret & DIRENT_CHANGED)
+			changed++;
+		if (ret & DIRENT_ABORT) {
+			do_abort++;
+			break;
+		}
+next:		
+		if (((offset + dirent->rec_len) > fs->blocksize) ||
+		    (dirent->rec_len < 8) ||
+		    ((dirent->name_len+8) > dirent->rec_len)) {
+			ctx->errcode = EXT2_ET_DIR_CORRUPTED;
+			return BLOCK_ABORT;
+		}
+		offset += dirent->rec_len;
+	}
+
+	if (changed) {
+		ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
+		if (ctx->errcode)
+			return BLOCK_ABORT;
+	}
+	if (do_abort)
+		return BLOCK_ABORT;
+	return 0;
+}
+
diff --git a/lib/ext2fs/dirblock.c b/lib/ext2fs/dirblock.c
index 0f56617..4db5b18 100644
--- a/lib/ext2fs/dirblock.c
+++ b/lib/ext2fs/dirblock.c
@@ -1,13 +1,18 @@
 /*
  * dirblock.c --- directory block routines.
  * 
- * Copyright (C) 1995 Theodore Ts'o.  This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <string.h>
 #include <time.h>
 #ifdef HAVE_ERRNO_H
 #include <errno.h>