diff --git a/Changelog b/Changelog index 98e82df5c..a0cc13aa3 100644 --- a/Changelog +++ b/Changelog @@ -8,6 +8,9 @@ fork() for running klogd. * nslookup types are now changed to u_int32_t (instead of uint32_t) changed per a patch from Pascal Bellard + * Fixed "du" so it gives the same answers as GNU "du" (busybox du used to + count hard-linked files more then once). Many thanks to + Friedrich Vedder for the fix. -Erik Andersen @@ -75,8 +78,8 @@ * Fixed a bug where init could have reference already freed memory. Found and fixed by Taketoshi Sano * Several contributions from Friedrich Vedder - * Added (and documented) "-n" option for head - Cleanup for a number of - * usage messages -- also + * Added (and documented) "-n" option for head + * Cleanup for a number of usage messages -- also contributed Friedrich Vedder * Cosmetic fix to busybox.c (Don't print a comma at the end of line if there are no more application names). @@ -87,7 +90,7 @@ * Created a tiny tail implementation, removing -c, -q, -v, and making tail -f work only with a single file. This reduced tail from 6k to 2.4k. The bigger/more featured tail can still be had by disabling - BB_FEATURE_SIMPLE_TAIL in dusybox.defs.h + BB_FEATURE_SIMPLE_TAIL in busybox.defs.h * Ping now falls back to doing the right thing if /etc/protocols turns up missing. * Fixed mount and umount. Previously they could leak loop device diff --git a/TODO b/TODO index bcba2948c..43419a09b 100644 --- a/TODO +++ b/TODO @@ -53,15 +53,6 @@ Some known bugs, todo items, etc... ----------------------- -[andersen@slag busybox]$ ./busybox du /bin -6213 /bin -[andersen@slag busybox]$ du /bin -2971 /bin -[andersen@slag busybox]$ du --block-size=512 /bin -5943 /bin - ------------------------ - -rw-r--r-- 1000/1000 4398 2000-01-06 21:55 uniq.c -rw-r--r-- 1000/1000 1568 1999-10-20 18:08 update.c -rw-r----- 0/1000 1168 2000-01-29 21:03 update.o @@ -89,13 +80,6 @@ function without this. Will you have the time to add this soon? ----------------------- - -/bin/busybox --install -s which makes all links to commands that it - can support (an optionnal -s should be used for symbolic links instead - of hard links). - ------------------------ - cd /mnt mkdir BACKUP mv * BACKUP @@ -105,3 +89,12 @@ work properly either when renaming a directory into something else (it produces a lot of disk activity when doing this). +----------------------- + + +Feature request: + +/bin/busybox --install -s which makes all links to commands that it + can support (an optionnal -s should be used for symbolic links instead + of hard links). + diff --git a/coreutils/du.c b/coreutils/du.c index 7b5acb490..02d1d9737 100644 --- a/coreutils/du.c +++ b/coreutils/du.c @@ -36,18 +36,32 @@ typedef void (Display) (long, char *); -static const char du_usage[] = +typedef struct inode_type { + struct inode_type *next; + ino_t ino; +} INODETYPE; +#define HASH_SIZE 311 /* Should be prime */ +#define hash_inode(i) ((i) % HASH_SIZE) + +static INODETYPE *inode_hash_list[HASH_SIZE]; + +static const char du_usage[] = "du [OPTION]... [FILE]...\n\n" + "Summarize disk space used for each FILE and/or directory.\n" + "Disk space is printed in units of 1024 bytes.\n\n" + "Options:\n" + "\t-l\tcount sizes many times if hard linked\n" "\t-s\tdisplay only a total for each argument\n"; static int du_depth = 0; +static int count_hardlinks = 0; static Display *print; static void print_normal(long size, char *filename) { - fprintf(stdout, "%-7ld %s\n", size, filename); + fprintf(stdout, "%ld\t%s\n", size, filename); } static void print_summary(long size, char *filename) @@ -57,6 +71,36 @@ static void print_summary(long size, char *filename) } } +/* Return 1 if inode is in inode hash list, else return 0 */ +static int is_in_list(const ino_t ino) +{ + INODETYPE *inode; + + inode = inode_hash_list[hash_inode(ino)]; + while (inode != NULL) { + if (inode->ino == ino) + return 1; + inode = inode->next; + } + + return 0; +} + +/* Add inode to inode hash list */ +static void add_inode(const ino_t ino) +{ + int i; + INODETYPE *inode; + + i = hash_inode(ino); + inode = malloc(sizeof(INODETYPE)); + if (inode == NULL) + fatalError("du: Not enough memory."); + + inode->ino = ino; + inode->next = inode_hash_list[i]; + inode_hash_list[i] = inode; +} /* tiny recursive du */ static long du(char *filename) @@ -72,7 +116,7 @@ static long du(char *filename) du_depth++; sum = (statbuf.st_blocks >> 1); - /* Don't add in stuff pointed to by links */ + /* Don't add in stuff pointed to by symbolic links */ if (S_ISLNK(statbuf.st_mode)) { return 0; } @@ -104,6 +148,12 @@ static long du(char *filename) closedir(dir); print(sum, filename); } + else if (statbuf.st_nlink > 1 && !count_hardlinks) { + /* Add files with hard links only once */ + if (is_in_list(statbuf.st_ino)) + return 0; + add_inode(statbuf.st_ino); + } du_depth--; return sum; } @@ -124,7 +174,11 @@ int du_main(int argc, char **argv) case 's': print = print_summary; break; + case 'l': + count_hardlinks = 1; + break; case 'h': + case '-': usage(du_usage); break; default: @@ -153,4 +207,4 @@ int du_main(int argc, char **argv) exit(0); } -/* $Id: du.c,v 1.13 2000/02/13 04:10:57 beppu Exp $ */ +/* $Id: du.c,v 1.14 2000/02/19 18:16:49 erik Exp $ */ diff --git a/du.c b/du.c index 7b5acb490..02d1d9737 100644 --- a/du.c +++ b/du.c @@ -36,18 +36,32 @@ typedef void (Display) (long, char *); -static const char du_usage[] = +typedef struct inode_type { + struct inode_type *next; + ino_t ino; +} INODETYPE; +#define HASH_SIZE 311 /* Should be prime */ +#define hash_inode(i) ((i) % HASH_SIZE) + +static INODETYPE *inode_hash_list[HASH_SIZE]; + +static const char du_usage[] = "du [OPTION]... [FILE]...\n\n" + "Summarize disk space used for each FILE and/or directory.\n" + "Disk space is printed in units of 1024 bytes.\n\n" + "Options:\n" + "\t-l\tcount sizes many times if hard linked\n" "\t-s\tdisplay only a total for each argument\n"; static int du_depth = 0; +static int count_hardlinks = 0; static Display *print; static void print_normal(long size, char *filename) { - fprintf(stdout, "%-7ld %s\n", size, filename); + fprintf(stdout, "%ld\t%s\n", size, filename); } static void print_summary(long size, char *filename) @@ -57,6 +71,36 @@ static void print_summary(long size, char *filename) } } +/* Return 1 if inode is in inode hash list, else return 0 */ +static int is_in_list(const ino_t ino) +{ + INODETYPE *inode; + + inode = inode_hash_list[hash_inode(ino)]; + while (inode != NULL) { + if (inode->ino == ino) + return 1; + inode = inode->next; + } + + return 0; +} + +/* Add inode to inode hash list */ +static void add_inode(const ino_t ino) +{ + int i; + INODETYPE *inode; + + i = hash_inode(ino); + inode = malloc(sizeof(INODETYPE)); + if (inode == NULL) + fatalError("du: Not enough memory."); + + inode->ino = ino; + inode->next = inode_hash_list[i]; + inode_hash_list[i] = inode; +} /* tiny recursive du */ static long du(char *filename) @@ -72,7 +116,7 @@ static long du(char *filename) du_depth++; sum = (statbuf.st_blocks >> 1); - /* Don't add in stuff pointed to by links */ + /* Don't add in stuff pointed to by symbolic links */ if (S_ISLNK(statbuf.st_mode)) { return 0; } @@ -104,6 +148,12 @@ static long du(char *filename) closedir(dir); print(sum, filename); } + else if (statbuf.st_nlink > 1 && !count_hardlinks) { + /* Add files with hard links only once */ + if (is_in_list(statbuf.st_ino)) + return 0; + add_inode(statbuf.st_ino); + } du_depth--; return sum; } @@ -124,7 +174,11 @@ int du_main(int argc, char **argv) case 's': print = print_summary; break; + case 'l': + count_hardlinks = 1; + break; case 'h': + case '-': usage(du_usage); break; default: @@ -153,4 +207,4 @@ int du_main(int argc, char **argv) exit(0); } -/* $Id: du.c,v 1.13 2000/02/13 04:10:57 beppu Exp $ */ +/* $Id: du.c,v 1.14 2000/02/19 18:16:49 erik Exp $ */