
#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- genext2fs-1.3.orig/genext2fs.c~autosize.patch
+++ genext2fs-1.3.orig/genext2fs.c
@@ -4,6 +4,11 @@
 // ext2 filesystem generator for embedded systems
 // Copyright (C) 2000 Xavier Bestel <xavier.bestel@free.fr>
 //
+// 'du' portions taken from coreutils/du.c in busybox:
+//	Copyright (C) 1999,2000 by Lineo, inc. and John Beppu
+//	Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
+//	Copyright (C) 2002  Edward Betts <edward@debian.org>
+//
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License
 // as published by the Free Software Foundation; version
@@ -79,9 +84,93 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <sys/types.h>
+#include <getopt.h>
+
+#define HASH_SIZE	311		/* Should be prime */
+#define hash_inode(i)	((i) % HASH_SIZE)
+
+typedef struct ino_dev_hash_bucket_struct {
+	struct ino_dev_hash_bucket_struct *next;
+	ino_t ino;
+	dev_t dev;
+	char name[1];
+} ino_dev_hashtable_bucket_t;
+
+static ino_dev_hashtable_bucket_t *ino_dev_hashtable[HASH_SIZE];
+
+struct stats {
+	unsigned long nblocks;
+	unsigned long ninodes;
+};
+
+int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name)
+{
+	ino_dev_hashtable_bucket_t *bucket;
+
+	bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)];
+	while (bucket != NULL) {
+		if ((bucket->ino == statbuf->st_ino) &&
+		    (bucket->dev == statbuf->st_dev))
+		{
+			if (name) *name = bucket->name;
+			return 1;
+		}
+		bucket = bucket->next;
+	}
+	return 0;
+}
+
+/* Add statbuf to statbuf hash table */
+void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name)
+{
+	int i;
+	size_t s;
+	ino_dev_hashtable_bucket_t *bucket;
+    
+	i = hash_inode(statbuf->st_ino);
+	s = name ? strlen(name) : 0;
+	bucket = malloc(sizeof(ino_dev_hashtable_bucket_t) + s);
+	bucket->ino = statbuf->st_ino;
+	bucket->dev = statbuf->st_dev;
+	if (name)
+		strcpy(bucket->name, name);
+	else
+		bucket->name[0] = '\0';
+	bucket->next = ino_dev_hashtable[i];
+	ino_dev_hashtable[i] = bucket;
+}
+
+/* Clear statbuf hash table */
+void reset_ino_dev_hashtable(void)
+{
+	int i;
+	ino_dev_hashtable_bucket_t *bucket;
+
+	for (i = 0; i < HASH_SIZE; i++) {
+		while (ino_dev_hashtable[i] != NULL) {
+			bucket = ino_dev_hashtable[i]->next;
+			free(ino_dev_hashtable[i]);
+			ino_dev_hashtable[i] = bucket;
+		}
+	}
+}
 
+static int count_ino_in_hashtable(void)
+{
+	long count = 0;
+	int i;
 
+	for (i = 0; i < HASH_SIZE; i++) {
+		ino_dev_hashtable_bucket_t *bucket = ino_dev_hashtable[i];
+		while (bucket != NULL) {
+			count++;
+			bucket = bucket->next;
+		}
+	}
 
+	return count;
+}
 
 // block size
 
@@ -1178,6 +1267,38 @@
 	return n;
 }
 
+void stats_from_dir(struct stats *stats)
+{
+	DIR *dh;
+	struct dirent *dent;
+	struct stat st;
+	if(!(dh = opendir(".")))
+		perror_msg_and_die(".");
+	while((dent = readdir(dh)))
+	{
+		if((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, "..")))
+			continue;
+		lstat(dent->d_name, &st);
+		if (S_ISLNK(st.st_mode)) {
+			stats->ninodes++;
+		} else if (S_ISDIR(st.st_mode)) {
+			if(chdir(dent->d_name) < 0)
+				perror_msg_and_die(dent->d_name);
+			stats->ninodes++;
+			stats_from_dir(stats);
+			chdir("..");
+		} else {
+			if (!is_in_ino_dev_hashtable(&st, NULL)) {
+				add_to_ino_dev_hashtable(&st, NULL);
+				stats->nblocks += (st.st_blocks >> 1);
+				stats->ninodes++;
+			}
+		}
+	}
+	closedir(dh);
+	reset_ino_dev_hashtable();
+}
+
 // adds a tree of entries to the filesystem from current dir
 void add2fs_from_dir(filesystem *fs, uint32 this_nod)
 {
@@ -1436,7 +1557,6 @@
 		free_blocks_per_group = nbblocks_per_group - overhead_per_group;
 	}
 	nbblocks = nbblocks_per_group * nbgroups + 1;
-	
 
 	if(!(fs = (filesystem*)calloc(nbblocks, BLOCKSIZE)))
 		error_msg_and_die("not enough memory for filesystem");
@@ -1891,6 +2011,7 @@
     Regular files must exist in the target root directory.  If a char,
     block, fifo, or directory does not exist, it will be created.
 */
+
 static int interpret_table_entry(filesystem *fs, char *line)
 {
 	char type, *name = NULL, *tmp, *dir, *bname;
@@ -2026,6 +2147,52 @@
 	return 0;
 }
 
+static int stats_from_table_entry(char *line, struct stats *stats)
+{
+	char type, *name = NULL, *tmp, *dir, *bname;
+	unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
+	unsigned long start = 0, increment = 1, count = 0;
+	inode *entry;
+
+	if (sscanf (line, "%" SCANF_PREFIX "s %c %lo %lu %lu %lu %lu %lu %lu %lu",
+				SCANF_STRING(name), &type, &mode, &uid, &gid, &major, &minor,
+				&start, &increment, &count) < 0) 
+	{
+		return 1;
+	}
+
+	if (!strcmp(name, "/")) {
+		error_msg_and_die("Device table entries require absolute paths");
+	}
+
+	tmp = xstrdup(name);
+	bname = xstrdup(basename(tmp));
+	free(tmp);
+	switch (type) {
+		case 'd':
+			stats->ninodes++;
+			break;
+		case 'c':
+		case 'b':
+			if (count > 0) {
+				dev_t rdev;
+				char *dname;
+				unsigned long i;
+				for (i = start; i < count; i++) {
+					asprintf(&dname, "%s%lu", bname, i);
+					stats->ninodes++;
+					free(dname);
+				}
+			} else {
+				stats->ninodes++;
+			}
+			break;
+	}
+	free(bname);
+	free(name);
+	return 0;
+}
+
 static int parse_device_table(filesystem *root, FILE * file)
 {
 	char *line;
@@ -2070,6 +2237,45 @@
 	return status;
 }
 
+static int stats_from_dev_table(FILE *file, struct stats *stats)
+{
+	char *line;
+	int status = 0;
+	size_t length = 0;
+
+	/* Looks ok so far.  The general plan now is to read in one
+	 * line at a time, check for leading comment delimiters ('#'),
+	 * then try and parse the line as a device table.  If we fail
+	 * to parse things, try and help the poor fool to fix their
+	 * device table with a useful error msg... */
+	line = NULL;
+	while (getline(&line, &length, file) != -1) {
+		/* First trim off any whitespace */
+		int len = strlen(line);
+
+		/* trim trailing whitespace */
+		while (len > 0 && isspace(line[len - 1]))
+			line[--len] = '\0';
+		/* trim leading whitespace */
+		memmove(line, &line[strspn(line, " \n\r\t\v")], len);
+
+		/* How long are we after trimming? */
+		len = strlen(line);
+
+		/* If this is NOT a comment line, try to interpret it */
+		if (len && *line != '#') {
+			if (stats_from_table_entry(line, stats))
+				status = 1;
+		}
+
+		free(line);
+		line = NULL;
+	}
+	fclose(file);
+
+	return status;
+}
+
 /*
 Local Variables:
 c-file-style: "linux"
@@ -2112,6 +2318,8 @@
 	int nbblocks = -1;
 	int nbinodes = -1;
 	int nbresrvd = -1;
+	int tmp_nbblocks = -1;
+	int tmp_nbinodes = -1;
 	char * fsout = "-";
 	char * fsin = 0;
 	char * dopt[MAX_DOPT];
@@ -2128,6 +2336,7 @@
 	int c;
 	struct stat sb;
 	FILE *devtable = NULL;
+	struct stats stats;
 
 	app_name = argv[0];
 	while((c = getopt(argc, argv, "x:d:b:i:r:g:e:zvhD:f:qUP")) != EOF)
@@ -2184,6 +2393,7 @@
 			default:
 				exit(1);
 		}
+
 	if(optind < (argc - 1))
 		error_msg_and_die("too many arguments");
 	if(optind == (argc - 1))
@@ -2201,6 +2411,46 @@
 	}
 	else
 	{
+		stats.ninodes = 0;
+		stats.nblocks = 0;
+		for(i = 0; i < didx; i++)
+		{
+			struct stat st;
+			char *pdir;
+			stat(dopt[i], &st);
+			switch(st.st_mode & S_IFMT)
+			{
+				case S_IFDIR:
+					if(!(pdir = getcwd(0, GETCWD_SIZE)))
+						perror_msg_and_die(dopt[i]);
+					if(chdir(dopt[i]) < 0)
+						perror_msg_and_die(dopt[i]);
+					stats_from_dir(&stats);
+					if(chdir(pdir) < 0)
+						perror_msg_and_die(pdir);
+					free(pdir);
+					break;
+				default:
+					error_msg_and_die("%s is neither a file nor a directory", dopt[i]);
+			}
+		}
+	
+		if(devtable)
+			stats_from_dev_table(devtable, &stats);
+	
+		tmp_nbinodes = stats.ninodes + EXT2_FIRST_INO + 1;
+		tmp_nbblocks = stats.nblocks;
+	
+		if(tmp_nbblocks > nbblocks)
+		{
+			printf("Number of blocks too low, increasing to %d\n",tmp_nbblocks);
+			nbblocks = tmp_nbblocks;
+		}
+		if(tmp_nbinodes > nbinodes)
+		{
+			printf("Number of inodes too low, increasing to %d\n",tmp_nbinodes);
+			nbinodes = tmp_nbinodes;
+		}
 		if(nbblocks == -1)
 			error_msg_and_die("filesystem size unspecified");
 		if(nbinodes == -1)
