Many files:
  Checkin of e2fsprogs 0.5b

diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 9d36ee9..13f536a 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -22,8 +22,10 @@
 #include <mntent.h>
 #include <malloc.h>
 #include <sys/ioctl.h>
-#include <linux/ext2_fs.h>
+#include <sys/types.h>
+
 #include <linux/fs.h>
+#include <linux/ext2_fs.h>
 
 #include "et/com_err.h"
 #include "ext2fs/ext2fs.h"
@@ -32,6 +34,7 @@
 #define STRIDE_LENGTH 8
 
 extern int isatty(int);
+extern FILE *fpopen(const char *cmd, const char *mode);
 
 const char * program_name = "mke2fs";
 const char * device_name = NULL;
@@ -40,6 +43,7 @@
 int	cflag = 0;
 int	verbose = 0;
 int	quiet = 0;
+int	super_only = 0;
 char	*bad_blocks_filename = 0;
 
 struct ext2_super_block param;
@@ -49,8 +53,8 @@
 	fprintf(stderr,
 		"Usage: %s [-c|-t|-l filename] [-b block-size] "
 		"[-f fragment-size]\n\t[-i bytes-per-inode] "
-		"[-m reserved-blocks-percentage] [-v]\n"
-		"\tdevice [blocks-count]\n",
+		"[-m reserved-blocks-percentage] [-qvS]\n"
+		"\t[-g blocks-per-group] device [blocks-count]\n",
 		program_name);
 	exit(1);
 }
@@ -67,11 +71,11 @@
 	return l;
 }
 
-static long valid_offset (int fd, int offset)
+static long valid_offset (int fd, ext2_loff_t offset)
 {
 	char ch;
 
-	if (lseek (fd, offset, 0) < 0)
+	if (ext2_llseek (fd, offset, 0) < 0)
 		return 0;
 	if (read (fd, &ch, 1) < 1)
 		return 0;
@@ -80,14 +84,14 @@
 
 static int count_blocks (int fd)
 {
-	int high, low;
+	ext2_loff_t high, low;
 
 	low = 0;
 	for (high = 1; valid_offset (fd, high); high *= 2)
 		low = high;
 	while (low < high - 1)
 	{
-		const int mid = (low + high) / 2;
+		const ext2_loff_t mid = (low + high) / 2;
 
 		if (valid_offset (fd, mid))
 			low = mid;
@@ -192,7 +196,7 @@
 		exit(1);
 	}
 	retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
-	fclose (f);
+	pclose(f);
 	if (retval) {
 		com_err("ext2fs_read_bb_FILE", retval,
 			"while processing list of bad blocks from program");
@@ -202,11 +206,14 @@
 
 static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list)
 {
-	int			i;
+	int			i, j;
 	int			must_be_good;
 	blk_t			blk;
 	badblocks_iterate	bb_iter;
 	errcode_t		retval;
+	blk_t			group_block;
+	int			group;
+	int			group_bad;
 
 	if (!bb_list)
 		return;
@@ -227,6 +234,33 @@
 			exit(1);
 		}
 	}
+
+	/*
+	 * See if any of the bad blocks are showing up in the backup
+	 * superblocks and/or group descriptors.  If so, issue a
+	 * warning and adjust the block counts appropriately.
+	 */
+	group_block = fs->super->s_first_data_block +
+		fs->super->s_blocks_per_group;
+	group_bad = 0;
+	
+	for (i = 1; i < fs->group_desc_count; i++) {
+		for (j=0; j < fs->desc_blocks+1; j++) {
+			if (badblocks_list_test(bb_list, group_block +
+						j)) {
+				if (!group_bad) 
+					fprintf(stderr,
+"Warning: the backup superblock/group descriptors at block %ld contain\n"
+"	bad blocks.\n\n",
+						group_block);
+				group_bad++;
+				group = ext2fs_group_of_blk(fs, group_block+j);
+				fs->group_desc[group].bg_free_blocks_count++;
+				fs->super->s_free_blocks_count++;
+			}
+		}
+		group_block += fs->super->s_blocks_per_group;
+	}
 	
 	/*
 	 * Mark all the bad blocks as used...
@@ -238,13 +272,13 @@
 		exit(1);
 	}
 	while (badblocks_list_iterate(bb_iter, &blk)) 
-		ext2fs_mark_block_bitmap(fs, fs->block_map, blk);
+		ext2fs_mark_block_bitmap(fs->block_map, blk);
 	badblocks_list_iterate_end(bb_iter);
 }
 
 static void new_table_block(ext2_filsys fs, blk_t first_block,
-			    const char *name, int num, const char *buf,
-			    blk_t *new_block)
+			    const char *name, int num, int initialize,
+			    const char *buf, blk_t *new_block)
 {
 	errcode_t	retval;
 	blk_t		blk;
@@ -260,21 +294,24 @@
 		ext2fs_unmark_valid(fs);
 		return;
 	}
-	blk = *new_block;
-	for (i=0; i < num; i += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
-		if (num-i > STRIDE_LENGTH)
-			count = STRIDE_LENGTH;
-		else
-			count = num - i;
-		retval = io_channel_write_blk(fs->io, blk, count, buf);
-		if (retval)
-			printf("Warning: could not write %d blocks starting "
-			       "at %ld for %s: %s\n",
-			       count, blk, name, error_message(retval));
+	if (initialize) {
+		blk = *new_block;
+		for (i=0; i < num; i += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
+			if (num-i > STRIDE_LENGTH)
+				count = STRIDE_LENGTH;
+			else
+				count = num - i;
+			retval = io_channel_write_blk(fs->io, blk, count, buf);
+			if (retval)
+				printf("Warning: could not write %d blocks "
+				       "starting at %ld for %s: %s\n",
+				       count, blk, name,
+				       error_message(retval));
+		}
 	}
 	blk = *new_block;
 	for (i = 0; i < num; i++, blk++)
-		ext2fs_mark_block_bitmap(fs, fs->block_map, blk);
+		ext2fs_mark_block_bitmap(fs->block_map, blk);
 }	
 
 static void alloc_tables(ext2_filsys fs)
@@ -282,7 +319,6 @@
 	blk_t	group_blk;
 	int	i;
 	char	*buf;
-	int	numblocks;
 
 	buf = malloc(fs->blocksize * STRIDE_LENGTH);
 	if (!buf) {
@@ -297,28 +333,15 @@
 	for (i = 0; i < fs->group_desc_count; i++) {
 		if (!quiet)
 			printf("%4d/%4ld", i, fs->group_desc_count);
-		new_table_block(fs, group_blk, "block bitmap", 1, buf,
+		new_table_block(fs, group_blk, "block bitmap", 1, 0, buf,
 				&fs->group_desc[i].bg_block_bitmap);
-		new_table_block(fs, group_blk, "inode bitmap", 1, buf,
+		new_table_block(fs, group_blk, "inode bitmap", 1, 0, buf,
 				&fs->group_desc[i].bg_inode_bitmap);
 		new_table_block(fs, group_blk, "inode table",
-				fs->inode_blocks_per_group, buf,
+				fs->inode_blocks_per_group,
+				!super_only, buf,
 				&fs->group_desc[i].bg_inode_table);
 		
-		if (i == fs->group_desc_count-1) {
-			numblocks = (fs->super->s_blocks_count -
-				     fs->super->s_first_data_block) %
-					     fs->super->s_blocks_per_group;
-			if (!numblocks)
-				numblocks = fs->super->s_blocks_per_group;
-		} else
-			numblocks = fs->super->s_blocks_per_group;
-		numblocks -= 3 + fs->desc_blocks + fs->inode_blocks_per_group;
-		
-		fs->group_desc[i].bg_free_blocks_count = numblocks;
-		fs->group_desc[i].bg_free_inodes_count =
-			fs->super->s_inodes_per_group;
-		fs->group_desc[i].bg_used_dirs_count = 0;
 		group_blk += fs->super->s_blocks_per_group;
 		if (!quiet) 
 			printf("\b\b\b\b\b\b\b\b\b");
@@ -330,12 +353,28 @@
 static void create_root_dir(ext2_filsys fs)
 {
 	errcode_t	retval;
+	struct ext2_inode	inode;
 
 	retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
 	if (retval) {
 		com_err("ext2fs_mkdir", retval, "while creating root dir");
 		exit(1);
 	}
+	if (geteuid()) {
+		retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode);
+		if (retval) {
+			com_err("ext2fs_read_inode", retval,
+				"while reading root inode");
+			exit(1);
+		}
+		inode.i_uid = geteuid();
+		retval = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode);
+		if (retval) {
+			com_err("ext2fs_write_inode", retval,
+				"while setting root inode ownership");
+			exit(1);
+		}
+	}
 }
 
 static void create_lost_and_found(ext2_filsys fs)
@@ -371,7 +410,7 @@
 {
 	errcode_t	retval;
 	
-	ext2fs_mark_inode_bitmap(fs, fs->inode_map, EXT2_BAD_INO);
+	ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_BAD_INO);
 	fs->group_desc[0].bg_free_inodes_count--;
 	fs->super->s_free_inodes_count--;
 	retval = ext2fs_update_bb_inode(fs, bb_list);
@@ -389,7 +428,7 @@
 	int	group;
 
 	for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INO; i++) {
-		ext2fs_mark_inode_bitmap (fs, fs->inode_map, i);
+		ext2fs_mark_inode_bitmap(fs->inode_map, i);
 		group = ext2fs_group_of_ino(fs, i);
 		fs->group_desc[group].bg_free_inodes_count--;
 		fs->super->s_free_inodes_count--;
@@ -397,6 +436,20 @@
 	ext2fs_mark_ib_dirty(fs);
 }
 
+static void zap_bootblock(ext2_filsys fs)
+{
+	char buf[512];
+	int retval;
+
+	memset(buf, 0, 512);
+	
+	retval = io_channel_write_blk(fs->io, 0, -512, buf);
+	if (retval)
+		printf("Warning: could not erase block 0: %s\n", 
+		       error_message(retval));
+}
+	
+
 static void show_stats(ext2_filsys fs)
 {
 	struct ext2_super_block	*s = fs->super;
@@ -449,7 +502,8 @@
 	char	c;
 	int	size;
 	char	* tmp;
-	char *oldpath, newpath[PATH_MAX];
+	char	*oldpath;
+	static char newpath[PATH_MAX];
 	int	inode_ratio = 4096;
 	int	reserved_ratio = 5;
 
@@ -469,7 +523,7 @@
 		 EXT2FS_VERSION, EXT2FS_DATE);
 	if (argc && *argv)
 		program_name = *argv;
-	while ((c = getopt (argc, argv, "b:cf:g:i:l:m:qtv")) != EOF)
+	while ((c = getopt (argc, argv, "b:cf:g:i:l:m:qtvS")) != EOF)
 		switch (c) {
 		case 'b':
 			size = strtoul(optarg, &tmp, 0);
@@ -499,11 +553,20 @@
 			break;
 		case 'g':
 			param.s_blocks_per_group = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				com_err(program_name, 0,
+					"Illegal number for blocks per group");
+				exit(1);
+			}
 			if (param.s_blocks_per_group < 256 ||
 			    param.s_blocks_per_group > 8192 || *tmp) {
 				com_err(program_name, 0,
-					"bad blocks per group count - %s",
-					optarg);
+					"blocks per group count out of range");
+				exit(1);
+			}
+			if ((param.s_blocks_per_group % 8) != 0) {
+				com_err(program_name, 0,
+				"blocks per group must be multiple of 8");
 				exit(1);
 			}
 			break;
@@ -517,7 +580,13 @@
 			}
 			break;
 		case 'l':
-			bad_blocks_filename = strdup(optarg);
+			bad_blocks_filename = malloc(strlen(optarg)+1);
+			if (!bad_blocks_filename) {
+				com_err(program_name, ENOMEM,
+					"in malloc for bad_blocks_filename");
+				exit(1);
+			}
+			strcpy(bad_blocks_filename, optarg);
 			break;
 		case 'm':
 			reserved_ratio = strtoul(optarg, &tmp, 0);
@@ -534,6 +603,9 @@
 		case 'q':
 			quiet = 1;
 			break;
+		case 'S':
+			super_only = 1;
+			break;
 		default:
 			usage();
 		}
@@ -560,7 +632,8 @@
 	 * Calculate number of inodes based on the inode ratio
 	 */
 	param.s_inodes_count =
-		(param.s_blocks_count * EXT2_BLOCK_SIZE(&param)) / inode_ratio;
+		((long long) param.s_blocks_count * EXT2_BLOCK_SIZE(&param))
+			/ inode_ratio;
 
 	/*
 	 * Calculate number of blocks to reserve
@@ -598,10 +671,16 @@
 
 	handle_bad_blocks(fs, bb_list);
 	alloc_tables(fs);
-	create_root_dir(fs);
-	create_lost_and_found(fs);
-	reserve_inodes(fs);
-	create_bad_block_inode(fs, bb_list);
+	if (super_only) {
+		fs->super->s_state |= EXT2_ERROR_FS;
+		fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
+	} else {
+		create_root_dir(fs);
+		create_lost_and_found(fs);
+		reserve_inodes(fs);
+		create_bad_block_inode(fs, bb_list);
+		zap_bootblock(fs);
+	}
 	
 	if (!quiet)
 		printf("Writing superblocks and "