Genext2fs autosize updates, fixed a couple bugs, and made it take into account
authorChris Larson <clarson@kergoth.com>
Thu, 14 Oct 2004 05:49:11 +0000 (05:49 +0000)
committerChris Larson <clarson@kergoth.com>
Thu, 14 Oct 2004 05:49:11 +0000 (05:49 +0000)
the inodes needed due to the device table.

BKrev: 416e1357zosXLnvmO3Y6IhPMIKGpOA

genext2fs/genext2fs-1.3/autosize.patch
genext2fs/genext2fs_1.3.oe

index e69de29..a4318a6 100644 (file)
@@ -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)
index cb59c05..fffeaf2 100644 (file)
@@ -1,7 +1,7 @@
 DESCRIPTION = "A tool to generate an ext2 filesystem \
 as a normal (non-root) user."
 SECTION = "console/utils"
-PR = "r1"
+PR = "r2"
 
 SRC_URI = "${DEBIAN_MIRROR}/main/g/genext2fs/genext2fs_${PV}.orig.tar.gz \
           file://misc.patch;patch=1 \