diff options
author | Chris Larson <clarson@kergoth.com> | 2004-10-14 05:49:11 +0000 |
---|---|---|
committer | Chris Larson <clarson@kergoth.com> | 2004-10-14 05:49:11 +0000 |
commit | a517e7b6b9e5c4f14e6103c2aed672532944ca5c (patch) | |
tree | 8717dec2992360cb4836177801a2fa0cd728a33b /genext2fs/genext2fs-1.3 | |
parent | 5a1bb609169fe06158068415d2e93dd01ad58f25 (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.patch | 339 |
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) |