summaryrefslogtreecommitdiff
path: root/genext2fs/genext2fs-1.3
diff options
context:
space:
mode:
authorChris Larson <clarson@kergoth.com>2004-10-14 05:49:11 +0000
committerChris Larson <clarson@kergoth.com>2004-10-14 05:49:11 +0000
commita517e7b6b9e5c4f14e6103c2aed672532944ca5c (patch)
tree8717dec2992360cb4836177801a2fa0cd728a33b /genext2fs/genext2fs-1.3
parent5a1bb609169fe06158068415d2e93dd01ad58f25 (diff)
Genext2fs autosize updates, fixed a couple bugs, and made it take into account
the inodes needed due to the device table. BKrev: 416e1357zosXLnvmO3Y6IhPMIKGpOA
Diffstat (limited to 'genext2fs/genext2fs-1.3')
-rw-r--r--genext2fs/genext2fs-1.3/autosize.patch339
1 files changed, 339 insertions, 0 deletions
diff --git a/genext2fs/genext2fs-1.3/autosize.patch b/genext2fs/genext2fs-1.3/autosize.patch
index e69de29bb2..a4318a6eee 100644
--- a/genext2fs/genext2fs-1.3/autosize.patch
+++ b/genext2fs/genext2fs-1.3/autosize.patch
@@ -0,0 +1,339 @@
+
+#
+# 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)