Many files:
  Checkin of e2fsprogs 1.03.

diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
index ae69bc2..04c5e4d 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -35,6 +35,8 @@
 
 	scan->magic = EXT2_ET_MAGIC_INODE_SCAN;
 	scan->fs = fs;
+	scan->inode_size = EXT2_INODE_SIZE(fs->super);
+	scan->bytes_left = 0;
 	scan->current_group = -1;
 	scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
 	scan->groups_left = fs->group_desc_count;
@@ -45,6 +47,12 @@
 		free(scan);
 		return ENOMEM;
 	}
+	scan->temp_buffer = malloc(scan->inode_size);
+	if (!scan->temp_buffer) {
+		free(scan->inode_buffer);
+		free(scan);
+		return ENOMEM;
+	}
 	*ret_scan = scan;
 	return 0;
 }
@@ -56,6 +64,8 @@
 	
 	free(scan->inode_buffer);
 	scan->inode_buffer = NULL;
+	free(scan->temp_buffer);
+	scan->temp_buffer = NULL;
 	free(scan);
 	return;
 }
@@ -79,53 +89,82 @@
 {
 	errcode_t	retval;
 	int		num_blocks;
+	int		extra_bytes = 0;
 	
 	EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
 
+	/*
+	 * Do we need to start reading a new block group?
+	 */
 	if (scan->inodes_left <= 0) {
-		if (scan->blocks_left <= 0) {
-			if (scan->done_group) {
-				retval = (scan->done_group)
-					(scan->fs, scan,
-					 scan->current_group,
-					 scan->done_group_data);
-				if (retval)
-					return retval;
-			}
-			do {
-				if (scan->groups_left <= 0) {
-					*ino = 0;
-					return 0;
-				}
-				scan->current_group++;
-				scan->groups_left--;
-			
-				scan->current_block =
-		scan->fs->group_desc[scan->current_group].bg_inode_table;
-				scan->blocks_left = (EXT2_INODES_PER_GROUP(scan->fs->super) /
-						     EXT2_INODES_PER_BLOCK(scan->fs->super));
-			} while (scan->current_block == 0);
-		} else {
-			scan->current_block += scan->inode_buffer_blocks;
+		if (scan->done_group) {
+			retval = (scan->done_group)
+				(scan->fs, scan,
+				 scan->current_group,
+				 scan->done_group_data);
+			if (retval)
+				return retval;
 		}
+		if (scan->groups_left <= 0) {
+			*ino = 0;
+			return 0;
+		}
+		scan->current_group++;
+		scan->groups_left--;
+			
+		scan->current_block = scan->fs->
+			group_desc[scan->current_group].bg_inode_table;
+
+		if (scan->current_block == 0)
+			return EXT2_ET_MISSING_INODE_TABLE;
+		scan->bytes_left = 0;
+		scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
+		scan->blocks_left = scan->fs->inode_blocks_per_group;
+	}
+
+	/*
+	 * Have we run out of space in the inode buffer?  If so, we
+	 * need to read in more blocks.
+	 */
+	if (scan->bytes_left < scan->inode_size) {
+		memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
+		extra_bytes = scan->bytes_left;
+		
 		scan->blocks_left -= scan->inode_buffer_blocks;
 		num_blocks = scan->inode_buffer_blocks;
 		if (scan->blocks_left < 0)
 			num_blocks += scan->blocks_left;
 		
-		scan->inodes_left = EXT2_INODES_PER_BLOCK(scan->fs->super) *
-			num_blocks;
-
 		retval = io_channel_read_blk(scan->fs->io, scan->current_block,
 					     num_blocks, scan->inode_buffer);
 		if (retval)
 			return EXT2_ET_NEXT_INODE_READ;
-		scan->inode_scan_ptr = (struct ext2_inode *) scan->inode_buffer;
+		scan->ptr = scan->inode_buffer;
+		scan->bytes_left = num_blocks * scan->fs->blocksize;
+	
+		scan->current_block += scan->inode_buffer_blocks;
 	}
-	if (scan->fs->flags & EXT2_SWAP_BYTES)
-		inocpy_with_swap(inode, scan->inode_scan_ptr++);
-	else
-		*inode = *scan->inode_scan_ptr++;
+
+	if (extra_bytes) {
+		memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
+		       scan->inode_size - extra_bytes);
+		scan->ptr += scan->inode_size - extra_bytes;
+		scan->bytes_left -= scan->inode_size - extra_bytes;
+
+		if (scan->fs->flags & EXT2_SWAP_BYTES)
+			inocpy_with_swap(inode, (struct ext2_inode *)
+					 scan->temp_buffer);
+		else
+			*inode = *((struct ext2_inode *) scan->temp_buffer);
+	} else {
+		if (scan->fs->flags & EXT2_SWAP_BYTES)
+			inocpy_with_swap(inode, (struct ext2_inode *)
+					 scan->ptr);
+		else
+			*inode = *((struct ext2_inode *) scan->ptr);
+		scan->ptr += scan->inode_size;
+		scan->bytes_left -= scan->inode_size;
+	}
 
 	scan->inodes_left--;
 	scan->current_inode++;
@@ -137,17 +176,16 @@
  * Functions to read and write a single inode.
  */
 static char *inode_buffer = 0;
-static blk_t inode_buffer_block;
+static blk_t inode_buffer_block = 0;
 static int inode_buffer_size = 0;
 
 errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
 			     struct ext2_inode * inode)
 {
-	unsigned long group;
-	unsigned long block;
-	unsigned long block_nr;
+	unsigned long 	group, block, block_nr, offset;
+	char 		*ptr;
 	errcode_t	retval;
-	int i;
+	int 		clen, length;
 
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -165,10 +203,9 @@
 	}
 		
 	group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
-	block = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) /
-		EXT2_INODES_PER_BLOCK(fs->super);
-	i = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) %
-		EXT2_INODES_PER_BLOCK(fs->super);
+	offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+		EXT2_INODE_SIZE(fs->super);
+	block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
 	block_nr = fs->group_desc[group].bg_inode_table + block;
 	if (block_nr != inode_buffer_block) {
 		retval = io_channel_read_blk(fs->io, block_nr, 1,
@@ -177,23 +214,44 @@
 			return retval;
 		inode_buffer_block = block_nr;
 	}
+	offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
+	ptr = ((char *) inode_buffer) + offset;
+
+	memset(inode, 0, sizeof(struct ext2_inode));
+	length = EXT2_INODE_SIZE(fs->super);
+	if (length > sizeof(struct ext2_inode))
+		length = sizeof(struct ext2_inode);
+	
+	if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) {
+		clen = EXT2_BLOCK_SIZE(fs->super) - offset;
+		memcpy((char *) inode, ptr, clen);
+		length -= clen;
+		
+		retval = io_channel_read_blk(fs->io, block_nr+1, 1,
+					     inode_buffer);
+		if (retval)
+			return retval;
+		inode_buffer_block = block_nr+1;
+		
+		memcpy(((char *) inode) + clen,
+		       inode_buffer, length);
+	} else
+		memcpy((char *) inode, ptr, length);
+	
 	if (fs->flags & EXT2_SWAP_BYTES)
-		inocpy_with_swap(inode,
-				 (struct ext2_inode *) inode_buffer + i);
-	else
-		memcpy (inode, (struct ext2_inode *) inode_buffer + i,
-			sizeof (struct ext2_inode));
+		inocpy_with_swap(inode, inode);
+
 	return 0;
 }
 
 errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
 		     struct ext2_inode * inode)
 {
-	unsigned long group;
-	unsigned long block;
-	unsigned long block_nr;
+	unsigned long group, block, block_nr, offset;
 	errcode_t	retval;
-	int i;
+	struct ext2_inode temp_inode;
+	char *ptr;
+	int i, clen, length;
 
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -213,13 +271,23 @@
 		inode_buffer_size = fs->blocksize;
 		inode_buffer_block = 0;
 	}
-		
+	if (fs->flags & EXT2_SWAP_BYTES)
+		inocpy_with_swap(&temp_inode, inode);
+	else
+		memcpy(&temp_inode, inode, sizeof(struct ext2_inode));
+	
 	group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
-	block = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) /
-		EXT2_INODES_PER_BLOCK(fs->super);
-	i = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) %
-		EXT2_INODES_PER_BLOCK(fs->super);
+	offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
+		EXT2_INODE_SIZE(fs->super);
+	block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
 	block_nr = fs->group_desc[group].bg_inode_table + block;
+	offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
+	ptr = (char *) inode_buffer + offset;
+
+	length = EXT2_INODE_SIZE(fs->super);
+	if (length > sizeof(struct ext2_inode))
+		length = sizeof(struct ext2_inode);
+	
 	if (inode_buffer_block != block_nr) {
 		retval = io_channel_read_blk(fs->io, block_nr, 1,
 					     inode_buffer);
@@ -227,15 +295,35 @@
 			return retval;
 		inode_buffer_block = block_nr;
 	}
-	if (fs->flags & EXT2_SWAP_BYTES)
-		inocpy_with_swap((struct ext2_inode *) inode_buffer + i,
-				 inode);
-	else
-		memcpy ((struct ext2_inode *) inode_buffer + i, inode,
-			sizeof (struct ext2_inode));
+	
+	if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) {
+		clen = EXT2_BLOCK_SIZE(fs->super) - offset;
+		memcpy(ptr, &temp_inode, clen);
+		length -= clen;
+	} else {
+		memcpy(ptr, &temp_inode, length);
+		length = 0;
+	}
 	retval = io_channel_write_blk(fs->io, block_nr, 1, inode_buffer);
 	if (retval)
 		return retval;
+
+	if (length) {
+		retval = io_channel_read_blk(fs->io, ++block_nr, 1,
+					     inode_buffer);
+		if (retval) {
+			inode_buffer_block = 0;
+			return retval;
+		}
+		inode_buffer_block = block_nr;
+		memcpy(inode_buffer, ((char *) &temp_inode) + clen, length);
+
+		retval = io_channel_write_blk(fs->io, block_nr, 1,
+					      inode_buffer);
+		if (retval)
+			return retval;
+	}
+	
 	fs->flags |= EXT2_FLAG_CHANGED;
 	return 0;
 }