From 029011b9eeaf491d00fda1d072c4c6094df96c3a Mon Sep 17 00:00:00 2001 From: Erik Andersen Date: Sat, 4 Mar 2000 21:19:32 +0000 Subject: A few updates (including the cp fix the Craig has been looking for) -Erik --- AUTHORS | 3 +- Changelog | 14 +++ TODO | 24 +++-- applets/busybox.c | 18 +++- busybox.c | 18 +++- busybox.def.h | 3 + cat.c | 8 ++ chmod_chown_chgrp.c | 8 ++ chroot.c | 9 ++ chvt.c | 9 ++ console-tools/chvt.c | 9 ++ coreutils/cat.c | 8 ++ coreutils/chroot.c | 9 ++ coreutils/df.c | 8 ++ coreutils/du.c | 71 ++----------- coreutils/ln.c | 8 ++ coreutils/sort.c | 28 ++++-- cp_mv.c | 279 +++++++++++++++++++++++++++++++++------------------ df.c | 8 ++ du.c | 71 ++----------- init.c | 11 +- init/init.c | 11 +- init/reboot.c | 8 ++ internal.h | 11 ++ ln.c | 8 ++ miscutils/update.c | 86 ++++++++++++---- reboot.c | 8 ++ sort.c | 28 ++++-- tests/Makefile | 23 +++-- tests/cp_tests.mk | 170 ++++++++++++++++++++----------- tests/ln_tests.mk | 9 +- tests/mv_tests.mk | 41 ++++++-- update.c | 86 ++++++++++++---- utility.c | 80 ++++++++++++++- 34 files changed, 817 insertions(+), 376 deletions(-) diff --git a/AUTHORS b/AUTHORS index 7986afc94..526205b49 100644 --- a/AUTHORS +++ b/AUTHORS @@ -37,4 +37,5 @@ Charles P. Wright Enrique Zanardi tarcat (since removed), loadkmap, various fixes, Debian maintenance - +Karl M. Hegbloom + cp_mv.c, the test suite, various fixes to utility.c, &c. diff --git a/Changelog b/Changelog index 3c90ab97f..0398ce93e 100644 --- a/Changelog +++ b/Changelog @@ -18,6 +18,20 @@ free). Use of /proc (or not) is policy that should be set up in /etc/fstab (or in hardcoded scripts), not in init. * Fixed rebooting when init runs as an initrd. + * Fixes and updates from Karl M. Hegbloom + - update.c rewritten to look more like update-2.11 + - moveed the inode hash out of du.c and into utility.c to make + it a common resource that can be used by other apps. + - cp_mv.c now checks inodes to see if a source and dest are + the same, and prints an error (instead of endlessly looping). + - mv now attempts to do a rename, and will fall back to doing + a copy only if the rename fails. + * Several fixes from Pavel Roskin : + - Fixes to sort. Removed "-g", fixed and added "-r" + - Fixes to the makefile for handling "strip" + * An initial telnet implementation was added by + Randolph Chung . + -Erik Andersen diff --git a/TODO b/TODO index e05558b04..daa21cffd 100644 --- a/TODO +++ b/TODO @@ -53,12 +53,6 @@ Hmm. Needs to be carefully thought out. ----------------------- - -Some known bugs, todo items, etc... - ------------------------ - - -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 @@ -116,3 +110,21 @@ messages from the embedded box logged to a remote network syslog box, right? I can see that this would be useful. I'll add this to the TODO list, + +----------------------- + + + In utility.c:copyFile: It uses followLinks for both source and + destination files... is that right for `mv'? Will need to revisit + the GNU, freeBSD, and MINIX versions for this... Should read the + Unix98 and POSIX specs also. + +----------------------- + + I think that the add_inode &c in utility.c needs to also stow the + st_dev field, and that du.c should NOT call `reset_inode_list' + because there can be hard links from inside one argv/ to inside + another argv/. du.c probably ought to have an -x switch like GNU du + does also... + + diff --git a/applets/busybox.c b/applets/busybox.c index 13f8db909..a80a5678f 100644 --- a/applets/busybox.c +++ b/applets/busybox.c @@ -300,15 +300,17 @@ static const struct Applet applets[] = { int main(int argc, char **argv) { - char *s = argv[0]; - char *name = argv[0]; - const struct Applet *a = applets; + char *s = argv[0]; + char *name = argv[0]; + const struct Applet *a = applets; while (*s != '\0') { if (*s++ == '/') name = s; } + *argv = name; + while (a->name != 0) { if (strcmp(name, a->name) == 0) { int status; @@ -341,7 +343,7 @@ int busybox_main(int argc, char **argv) fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); fprintf(stderr, " or: [function] [arguments]...\n\n"); fprintf(stderr, - "\tMost people will create a symlink to busybox for each\n" + "\tMost people will create a link to busybox for each\n" "\tfunction name, and busybox will act like whatever you invoke it as.\n"); fprintf(stderr, "\nCurrently defined functions:\n"); @@ -362,3 +364,11 @@ int busybox_main(int argc, char **argv) return (main(argc, argv)); } } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/busybox.c b/busybox.c index 13f8db909..a80a5678f 100644 --- a/busybox.c +++ b/busybox.c @@ -300,15 +300,17 @@ static const struct Applet applets[] = { int main(int argc, char **argv) { - char *s = argv[0]; - char *name = argv[0]; - const struct Applet *a = applets; + char *s = argv[0]; + char *name = argv[0]; + const struct Applet *a = applets; while (*s != '\0') { if (*s++ == '/') name = s; } + *argv = name; + while (a->name != 0) { if (strcmp(name, a->name) == 0) { int status; @@ -341,7 +343,7 @@ int busybox_main(int argc, char **argv) fprintf(stderr, "Usage: busybox [function] [arguments]...\n"); fprintf(stderr, " or: [function] [arguments]...\n\n"); fprintf(stderr, - "\tMost people will create a symlink to busybox for each\n" + "\tMost people will create a link to busybox for each\n" "\tfunction name, and busybox will act like whatever you invoke it as.\n"); fprintf(stderr, "\nCurrently defined functions:\n"); @@ -362,3 +364,11 @@ int busybox_main(int argc, char **argv) return (main(argc, argv)); } } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/busybox.def.h b/busybox.def.h index 8ed5a9c66..d42be4422 100644 --- a/busybox.def.h +++ b/busybox.def.h @@ -150,6 +150,9 @@ // Enable support for creation of tar files. //#define BB_FEATURE_TAR_CREATE // +//// Enable reverse sort +//#define BB_FEATURE_SORT_REVERSE +// // Allow init to permenently chroot, and umount the old root fs // just like an initrd does. Requires a kernel patch by Werner Almesberger. // ftp://icaftp.epfl.ch/pub/people/almesber/misc/umount-root-*.tar.gz diff --git a/cat.c b/cat.c index 86f85fe8e..58a1b0f54 100644 --- a/cat.c +++ b/cat.c @@ -59,3 +59,11 @@ extern int cat_main(int argc, char **argv) } exit(TRUE); } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/chmod_chown_chgrp.c b/chmod_chown_chgrp.c index f037e9591..4e5e9b08e 100644 --- a/chmod_chown_chgrp.c +++ b/chmod_chown_chgrp.c @@ -181,3 +181,11 @@ int chmod_chown_chgrp_main(int argc, char **argv) bad_group: fatalError( "%s: unknown group name: %s\n", invocationName, groupName); } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/chroot.c b/chroot.c index 6a01be603..3622c26dc 100644 --- a/chroot.c +++ b/chroot.c @@ -65,3 +65,12 @@ int chroot_main(int argc, char **argv) *argv, strerror(errno)); exit(FALSE); } + + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/chvt.c b/chvt.c index a32bd3e78..635022a57 100644 --- a/chvt.c +++ b/chvt.c @@ -34,3 +34,12 @@ int chvt_main(int argc, char **argv) } exit(TRUE); } + + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/console-tools/chvt.c b/console-tools/chvt.c index a32bd3e78..635022a57 100644 --- a/console-tools/chvt.c +++ b/console-tools/chvt.c @@ -34,3 +34,12 @@ int chvt_main(int argc, char **argv) } exit(TRUE); } + + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/coreutils/cat.c b/coreutils/cat.c index 86f85fe8e..58a1b0f54 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -59,3 +59,11 @@ extern int cat_main(int argc, char **argv) } exit(TRUE); } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/coreutils/chroot.c b/coreutils/chroot.c index 6a01be603..3622c26dc 100644 --- a/coreutils/chroot.c +++ b/coreutils/chroot.c @@ -65,3 +65,12 @@ int chroot_main(int argc, char **argv) *argv, strerror(errno)); exit(FALSE); } + + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/coreutils/df.c b/coreutils/df.c index 43d5d26e7..bc843f7a2 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -108,3 +108,11 @@ extern int df_main(int argc, char **argv) exit(TRUE); } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/coreutils/du.c b/coreutils/du.c index 4dc7ea13a..b6ebaca7a 100644 --- a/coreutils/du.c +++ b/coreutils/du.c @@ -36,16 +36,6 @@ typedef void (Display) (long, char *); -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" @@ -71,52 +61,6 @@ 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; -} - -/* Clear inode hash list */ -static void reset_inode_list(void) -{ - int i; - INODETYPE *inode; - - for (i = 0; i < HASH_SIZE; i++) { - while (inode_hash_list[i] != NULL) { - inode = inode_hash_list[i]->next; - free(inode_hash_list[i]); - inode_hash_list[i] = inode; - } - } -} - /* tiny recursive du */ static long du(char *filename) { @@ -175,13 +119,13 @@ static long du(char *filename) } else if (statbuf.st_nlink > 1 && !count_hardlinks) { /* Add files with hard links only once */ - if (is_in_list(statbuf.st_ino)) { + if (is_in_ino_dev_hashtable(&statbuf, NULL)) { sum = 0L; if (du_depth == 1) print(sum, filename); } else { - add_inode(statbuf.st_ino); + add_to_ino_dev_hashtable(&statbuf, NULL); } } du_depth--; @@ -231,11 +175,18 @@ int du_main(int argc, char **argv) if (sum && isDirectory(argv[i], FALSE, NULL)) { print_normal(sum, argv[i]); } - reset_inode_list(); + reset_ino_dev_hashtable(); } } exit(0); } -/* $Id: du.c,v 1.15 2000/02/21 17:27:17 erik Exp $ */ +/* $Id: du.c,v 1.16 2000/03/04 21:19:32 erik Exp $ */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/coreutils/ln.c b/coreutils/ln.c index 0715bfaed..c54026c62 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c @@ -128,3 +128,11 @@ extern int ln_main(int argc, char **argv) } exit TRUE; } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/coreutils/sort.c b/coreutils/sort.c index 609c5e08c..e6894f6c3 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -29,7 +29,18 @@ #include #include -static const char sort_usage[] = "sort [OPTION]... [FILE]...\n\n"; +static const char sort_usage[] = "sort [-n]" +#ifdef BB_FEATURE_SORT_REVERSE +" [-r]" +#endif +" [FILE]...\n\n"; + +#ifdef BB_FEATURE_SORT_REVERSE +#define APPLY_REVERSE(x) (reverse ? -(x) : (x)) +static int reverse = 0; +#else +#define APPLY_REVERSE(x) (x) +#endif /* typedefs _______________________________________________________________ */ @@ -120,7 +131,7 @@ static int compare_ascii(const void *a, const void *b) y = *doh; // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data); - return strcmp(x->data, y->data); + return APPLY_REVERSE(strcmp(x->data, y->data)); } /* numeric order */ @@ -138,7 +149,7 @@ static int compare_numeric(const void *a, const void *b) xint = strtoul(x->data, NULL, 10); yint = strtoul(y->data, NULL, 10); - return (xint - yint); + return APPLY_REVERSE(xint - yint); } @@ -254,20 +265,19 @@ int sort_main(int argc, char **argv) if (argv[i][0] == '-') { opt = argv[i][1]; switch (opt) { - case 'g': - /* what's the diff between -g && -n? */ - compare = compare_numeric; - break; case 'h': usage(sort_usage); break; case 'n': - /* what's the diff between -g && -n? */ + /* numeric comparison */ compare = compare_numeric; break; +#ifdef BB_FEATURE_SORT_REVERSE case 'r': /* reverse */ + reverse = 1; break; +#endif default: fprintf(stderr, "sort: invalid option -- %c\n", opt); usage(sort_usage); @@ -310,4 +320,4 @@ int sort_main(int argc, char **argv) exit(0); } -/* $Id: sort.c,v 1.11 2000/02/08 19:58:47 erik Exp $ */ +/* $Id: sort.c,v 1.12 2000/03/04 21:19:32 erik Exp $ */ diff --git a/cp_mv.c b/cp_mv.c index 4c55e62d0..8dbc4e8f1 100644 --- a/cp_mv.c +++ b/cp_mv.c @@ -37,11 +37,15 @@ #include #include #include +#include /* Ok to use this since `ash' does, therefore it's in the libc subset already. */ +#include +#include +#include #define is_cp 0 #define is_mv 1 +static int dz_i; /* index into cp_mv_usage */ static const char *dz; /* dollar zero, .bss */ -static int dz_i; /* index, .bss */ static const char *cp_mv_usage[] = /* .rodata */ { "cp [OPTION]... SOURCE DEST\n" @@ -55,92 +59,131 @@ static const char *cp_mv_usage[] = /* .rodata */ "mv SOURCE DEST\n" " or: mv SOURCE... DIRECTORY\n\n" "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n" - "Warning!! This is not GNU `mv'. It does not preserve hard links.\n" }; -extern int cp_mv_main(int argc, char **argv) +static int recursiveFlag; +static int followLinks; +static int preserveFlag; + +static const char *baseSrcName; +static int srcDirFlag; +static struct stat srcStatBuf; + +static char baseDestName[PATH_MAX + 1]; +static size_t baseDestLen; +static int destDirFlag; +static struct stat destStatBuf; + +static jmp_buf catch; +static volatile int mv_Action_first_time; + +static void name_too_long__exit (void) __attribute__((noreturn)); + +static +void name_too_long__exit (void) { - __label__ name_too_long__exit; - __label__ exit_false; - - int recursiveFlag; - int followLinks; - int preserveFlag; - - const char *baseSrcName; - int srcDirFlag; - struct stat srcStatBuf; - - char baseDestName[PATH_MAX + 1]; - size_t baseDestLen; - int destDirFlag; - struct stat destStatBuf; - - void fill_baseDest_buf(char *_buf, size_t * _buflen) { - const char *srcBasename; - if ((srcBasename = strrchr(baseSrcName, '/')) == NULL) { - srcBasename = baseSrcName; - if (_buf[*_buflen - 1] != '/') { - if (++(*_buflen) > PATH_MAX) - goto name_too_long__exit; - strcat(_buf, "/"); - } + fprintf(stderr, name_too_long, dz); + exit FALSE; +} + +static void +fill_baseDest_buf(char *_buf, size_t * _buflen) { + const char *srcBasename; + if ((srcBasename = strrchr(baseSrcName, '/')) == NULL) { + srcBasename = baseSrcName; + if (_buf[*_buflen - 1] != '/') { + if (++(*_buflen) > PATH_MAX) + name_too_long__exit(); + strcat(_buf, "/"); } - if (*_buflen + strlen(srcBasename) > PATH_MAX) - goto name_too_long__exit; - strcat(_buf, srcBasename); - return; } + if (*_buflen + strlen(srcBasename) > PATH_MAX) + name_too_long__exit(); + strcat(_buf, srcBasename); + return; + +} - int fileAction(const char *fileName, struct stat *statbuf) { - char destName[PATH_MAX + 1]; - size_t destLen; - const char *srcBasename; +static int +cp_mv_Action(const char *fileName, struct stat *statbuf) +{ + char destName[PATH_MAX + 1]; + size_t destLen; + const char *srcBasename; + char *name; - strcpy(destName, baseDestName); - destLen = strlen(destName); + strcpy(destName, baseDestName); + destLen = strlen(destName); - if (srcDirFlag == TRUE) { - if (recursiveFlag == FALSE) { - fprintf(stderr, omitting_directory, "cp", baseSrcName); - return TRUE; - } - srcBasename = (strstr(fileName, baseSrcName) - + strlen(baseSrcName)); + if (srcDirFlag == TRUE) { + if (recursiveFlag == FALSE) { + fprintf(stderr, omitting_directory, dz, baseSrcName); + return TRUE; + } + srcBasename = (strstr(fileName, baseSrcName) + + strlen(baseSrcName)); - if (destLen + strlen(srcBasename) > PATH_MAX) { - fprintf(stderr, name_too_long, "cp"); + if (destLen + strlen(srcBasename) > PATH_MAX) { + fprintf(stderr, name_too_long, dz); + return FALSE; + } + strcat(destName, srcBasename); + } + else if (destDirFlag == TRUE) { + fill_baseDest_buf(&destName[0], &destLen); + } + else { + srcBasename = baseSrcName; + } + if (mv_Action_first_time && (dz_i == is_mv)) { + mv_Action_first_time = errno = 0; + if (rename(fileName, destName) < 0 && errno != EXDEV) { + fprintf(stderr, "%s: rename(%s, %s): %s\n", + dz, fileName, destName, strerror(errno)); + goto do_copyFile; /* Try anyway... */ + } + else if (errno == EXDEV) + goto do_copyFile; + else + longjmp(catch, 1); /* succeeded with rename() */ + } + do_copyFile: + if (preserveFlag == TRUE && statbuf->st_nlink > 1) { + if (is_in_ino_dev_hashtable(statbuf, &name)) { + if (link(name, destName) < 0) { + fprintf(stderr, "%s: link(%s, %s): %s\n", + dz, name, destName, strerror(errno)); return FALSE; } - strcat(destName, srcBasename); - } else if (destDirFlag == TRUE) { - fill_baseDest_buf(&destName[0], &destLen); - } else { - srcBasename = baseSrcName; + return TRUE; } - return copyFile(fileName, destName, preserveFlag, followLinks); - } - - int rmfileAction(const char *fileName, struct stat *statbuf) { - if (unlink(fileName) < 0) { - perror(fileName); - return FALSE; + else { + add_to_ino_dev_hashtable(statbuf, destName); } - return TRUE; } + return copyFile(fileName, destName, preserveFlag, followLinks); +} + +static int +rm_Action(const char *fileName, struct stat *statbuf) +{ + int status = TRUE; - int rmdirAction(const char *fileName, struct stat *statbuf) { + if (S_ISDIR(statbuf->st_mode)) { if (rmdir(fileName) < 0) { - perror(fileName); - return FALSE; + fprintf(stderr, "%s: rmdir(%s): %s\n", dz, fileName, strerror(errno)); + status = FALSE; } - return TRUE; + } else if (unlink(fileName) < 0) { + fprintf(stderr, "%s: unlink(%s): %s\n", dz, fileName, strerror(errno)); + status = FALSE; } + return status; +} - if ((dz = strrchr(*argv, '/')) == NULL) - dz = *argv; - else - dz++; +extern int cp_mv_main(int argc, char **argv) +{ + dz = *argv; /* already basename'd by busybox.c:main */ if (*dz == 'c' && *(dz + 1) == 'p') dz_i = is_cp; else @@ -199,53 +242,93 @@ extern int cp_mv_main(int argc, char **argv) while (argc-- > 1) { size_t srcLen; - int flags_memo; + volatile int flags_memo; + int status; baseSrcName = *(argv++); if ((srcLen = strlen(baseSrcName)) > PATH_MAX) - goto name_too_long__exit; + name_too_long__exit(); - if (srcLen == 0) - continue; + if (srcLen == 0) continue; /* "" */ srcDirFlag = isDirectory(baseSrcName, followLinks, &srcStatBuf); if ((flags_memo = (recursiveFlag == TRUE && srcDirFlag == TRUE && destDirFlag == TRUE))) { - if ((destStatBuf.st_ino == srcStatBuf.st_ino) && - (destStatBuf.st_rdev == srcStatBuf.st_rdev)) { - fprintf(stderr, - "%s: Cannot %s `%s' into a subdirectory of itself, `%s/%s'\n", - dz, dz, baseSrcName, baseDestName, baseSrcName); - continue; + + struct stat sb; + int state = 0; + char *pushd, *d, *p; + + if ((pushd = getcwd(NULL, PATH_MAX + 1)) == NULL) { + fprintf(stderr, "%s: getcwd(): %s\n", dz, strerror(errno)); + continue; + } + if (chdir(baseDestName) < 0) { + fprintf(stderr, "%s: chdir(%s): %s\n", dz, baseSrcName, strerror(errno)); + continue; + } + if ((d = getcwd(NULL, PATH_MAX + 1)) == NULL) { + fprintf(stderr, "%s: getcwd(): %s\n", dz, strerror(errno)); + continue; + } + while (!state && *d != '\0') { + if (stat(d, &sb) < 0) { /* stat not lstat - always dereference targets */ + fprintf(stderr, "%s: stat(%s) :%s\n", dz, d, strerror(errno)); + state = -1; + continue; + } + if ((sb.st_ino == srcStatBuf.st_ino) && + (sb.st_dev == srcStatBuf.st_dev)) { + fprintf(stderr, + "%s: Cannot %s `%s' " + "into a subdirectory of itself, `%s/%s'\n", + dz, dz, baseSrcName, baseDestName, baseSrcName); + state = -1; + continue; } + if ((p = strrchr(d, '/')) != NULL) { + *p = '\0'; + } + } + if (chdir(pushd) < 0) { + fprintf(stderr, "%s: chdir(%s): %s\n", dz, pushd, strerror(errno)); + free(pushd); + free(d); + continue; + } + free(pushd); + free(d); + if (state < 0) + continue; + else fill_baseDest_buf(baseDestName, &baseDestLen); } - if (recursiveAction(baseSrcName, - recursiveFlag, followLinks, FALSE, - fileAction, fileAction) == FALSE) - goto exit_false; - - if (dz_i == is_mv && - recursiveAction(baseSrcName, - recursiveFlag, followLinks, TRUE, - rmfileAction, rmdirAction) == FALSE) - goto exit_false; - + status = setjmp(catch); + if (status == 0) { + mv_Action_first_time = 1; + if (recursiveAction(baseSrcName, + recursiveFlag, followLinks, FALSE, + cp_mv_Action, cp_mv_Action) == FALSE) goto exit_false; + if (dz_i == is_mv && + recursiveAction(baseSrcName, + recursiveFlag, followLinks, TRUE, + rm_Action, rm_Action) == FALSE) goto exit_false; + } if (flags_memo) *(baseDestName + baseDestLen) = '\0'; } - +// exit_true: exit TRUE; - - name_too_long__exit: - fprintf(stderr, name_too_long, "cp"); - exit_false: + exit_false: exit FALSE; } -// Local Variables: -// c-file-style: "linux" -// tab-width: 4 -// End: +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/df.c b/df.c index 43d5d26e7..bc843f7a2 100644 --- a/df.c +++ b/df.c @@ -108,3 +108,11 @@ extern int df_main(int argc, char **argv) exit(TRUE); } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/du.c b/du.c index 4dc7ea13a..b6ebaca7a 100644 --- a/du.c +++ b/du.c @@ -36,16 +36,6 @@ typedef void (Display) (long, char *); -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" @@ -71,52 +61,6 @@ 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; -} - -/* Clear inode hash list */ -static void reset_inode_list(void) -{ - int i; - INODETYPE *inode; - - for (i = 0; i < HASH_SIZE; i++) { - while (inode_hash_list[i] != NULL) { - inode = inode_hash_list[i]->next; - free(inode_hash_list[i]); - inode_hash_list[i] = inode; - } - } -} - /* tiny recursive du */ static long du(char *filename) { @@ -175,13 +119,13 @@ static long du(char *filename) } else if (statbuf.st_nlink > 1 && !count_hardlinks) { /* Add files with hard links only once */ - if (is_in_list(statbuf.st_ino)) { + if (is_in_ino_dev_hashtable(&statbuf, NULL)) { sum = 0L; if (du_depth == 1) print(sum, filename); } else { - add_inode(statbuf.st_ino); + add_to_ino_dev_hashtable(&statbuf, NULL); } } du_depth--; @@ -231,11 +175,18 @@ int du_main(int argc, char **argv) if (sum && isDirectory(argv[i], FALSE, NULL)) { print_normal(sum, argv[i]); } - reset_inode_list(); + reset_ino_dev_hashtable(); } } exit(0); } -/* $Id: du.c,v 1.15 2000/02/21 17:27:17 erik Exp $ */ +/* $Id: du.c,v 1.16 2000/03/04 21:19:32 erik Exp $ */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/init.c b/init.c index 183739180..350ea62a8 100644 --- a/init.c +++ b/init.c @@ -242,6 +242,7 @@ static void console_init() int fd; int tried_devcons = 0; int tried_vtprimary = 0; + struct vt_stat vt; struct serial_struct sr; char *s; @@ -264,8 +265,6 @@ static void console_init() } #endif else { - struct vt_stat vt; - /* 2.2 kernels: identify the real console backend and try to use it */ if (ioctl(0, TIOCGSERIAL, &sr) == 0) { /* this is a serial console */ @@ -951,3 +950,11 @@ extern int init_main(int argc, char **argv) sleep(1); } } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/init/init.c b/init/init.c index 183739180..350ea62a8 100644 --- a/init/init.c +++ b/init/init.c @@ -242,6 +242,7 @@ static void console_init() int fd; int tried_devcons = 0; int tried_vtprimary = 0; + struct vt_stat vt; struct serial_struct sr; char *s; @@ -264,8 +265,6 @@ static void console_init() } #endif else { - struct vt_stat vt; - /* 2.2 kernels: identify the real console backend and try to use it */ if (ioctl(0, TIOCGSERIAL, &sr) == 0) { /* this is a serial console */ @@ -951,3 +950,11 @@ extern int init_main(int argc, char **argv) sleep(1); } } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/init/reboot.c b/init/reboot.c index ef2a848ee..f782fa1e6 100644 --- a/init/reboot.c +++ b/init/reboot.c @@ -29,3 +29,11 @@ extern int reboot_main(int argc, char **argv) /* don't assume init's pid == 1 */ exit(kill(findInitPid(), SIGINT)); } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/internal.h b/internal.h index 4d035c962..4c7bd97ed 100644 --- a/internal.h +++ b/internal.h @@ -154,6 +154,17 @@ const char *modeString(int mode); const char *timeString(time_t timeVal); int isDirectory(const char *name, const int followLinks, struct stat *statBuf); int isDevice(const char *name); + +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; +int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name); +void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name); +void reset_ino_dev_hashtable(void); + int copyFile(const char *srcName, const char *destName, int setModes, int followLinks); char *buildName(const char *dirName, const char *fileName); diff --git a/ln.c b/ln.c index 0715bfaed..c54026c62 100644 --- a/ln.c +++ b/ln.c @@ -128,3 +128,11 @@ extern int ln_main(int argc, char **argv) } exit TRUE; } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/miscutils/update.c b/miscutils/update.c index fef188bba..bb77c5f1f 100644 --- a/miscutils/update.c +++ b/miscutils/update.c @@ -1,9 +1,11 @@ /* vi: set sw=4 ts=4: */ /* - * Mini update implementation for busybox + * Mini update implementation for busybox; much pasted from update-2.11 * * * Copyright (C) 1995, 1996 by Bruce Perens . + * Copyright (c) 1996, 1997, 1999 Torsten Poulin. + * Copyright (c) 2000 by Karl M. Hegbloom * * 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 @@ -23,6 +25,8 @@ #include "internal.h" #include +#include +#include #if defined(__GLIBC__) #include @@ -30,37 +34,79 @@ _syscall2(int, bdflush, int, func, int, data); #endif /* __GLIBC__ */ +static char update_usage[] = + "update [options]\n" + " -S\tforce use of sync(2) instead of flushing\n" + " -s SECS\tcall sync this often (default 30)\n" + " -f SECS\tflush some buffers this often (default 5)\n"; + +static unsigned int sync_duration = 30; +static unsigned int flush_duration = 5; +static int use_sync = 0; + extern int update_main(int argc, char **argv) { - /* - * Update is actually two daemons, bdflush and update. - */ int pid; + while (**argv == '-') { + while (*++(*argv)) { + switch (**argv) { + case 'S': + use_sync = 1; + break; + case 's': + if (--argc < 1) usage(update_usage); + sync_duration = atoi(*(++argv)); + break; + case 'f': + if (--argc < 1) usage(update_usage); + flush_duration = atoi(*(++argv)); + break; + } + } + argc--; + argv++; + } + pid = fork(); if (pid < 0) - return pid; + exit(FALSE); else if (pid == 0) { + /* Become a proper daemon */ + setsid(); + chdir("/"); + for (pid = 0; pid < OPEN_MAX; pid++) close(pid); + /* * This is no longer necessary since 1.3.5x, but it will harmlessly * exit if that is the case. */ - strcpy(argv[0], "bdflush (update)"); - argv[1] = 0; - argv[2] = 0; - bdflush(1, 0); - _exit(0); - } - pid = fork(); - if (pid < 0) - return pid; - else if (pid == 0) { - argv[0] = "update"; + argv[0] = "bdflush (update)"; + argv[1] = NULL; + argv[2] = NULL; for (;;) { - sync(); - sleep(30); + if (use_sync) { + sleep(sync_duration); + sync(); + } else { + sleep(flush_duration); + if (bdflush(1, 0) < 0) { + openlog("update", LOG_CONS, LOG_DAEMON); + syslog(LOG_INFO, + "This kernel does not need update(8). Exiting."); + closelog(); + exit(TRUE); + } + } } } - - return 0; + return TRUE; } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/reboot.c b/reboot.c index ef2a848ee..f782fa1e6 100644 --- a/reboot.c +++ b/reboot.c @@ -29,3 +29,11 @@ extern int reboot_main(int argc, char **argv) /* don't assume init's pid == 1 */ exit(kill(findInitPid(), SIGINT)); } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/sort.c b/sort.c index 609c5e08c..e6894f6c3 100644 --- a/sort.c +++ b/sort.c @@ -29,7 +29,18 @@ #include #include -static const char sort_usage[] = "sort [OPTION]... [FILE]...\n\n"; +static const char sort_usage[] = "sort [-n]" +#ifdef BB_FEATURE_SORT_REVERSE +" [-r]" +#endif +" [FILE]...\n\n"; + +#ifdef BB_FEATURE_SORT_REVERSE +#define APPLY_REVERSE(x) (reverse ? -(x) : (x)) +static int reverse = 0; +#else +#define APPLY_REVERSE(x) (x) +#endif /* typedefs _______________________________________________________________ */ @@ -120,7 +131,7 @@ static int compare_ascii(const void *a, const void *b) y = *doh; // fprintf(stdout, "> %p: %s< %p: %s", x, x->data, y, y->data); - return strcmp(x->data, y->data); + return APPLY_REVERSE(strcmp(x->data, y->data)); } /* numeric order */ @@ -138,7 +149,7 @@ static int compare_numeric(const void *a, const void *b) xint = strtoul(x->data, NULL, 10); yint = strtoul(y->data, NULL, 10); - return (xint - yint); + return APPLY_REVERSE(xint - yint); } @@ -254,20 +265,19 @@ int sort_main(int argc, char **argv) if (argv[i][0] == '-') { opt = argv[i][1]; switch (opt) { - case 'g': - /* what's the diff between -g && -n? */ - compare = compare_numeric; - break; case 'h': usage(sort_usage); break; case 'n': - /* what's the diff between -g && -n? */ + /* numeric comparison */ compare = compare_numeric; break; +#ifdef BB_FEATURE_SORT_REVERSE case 'r': /* reverse */ + reverse = 1; break; +#endif default: fprintf(stderr, "sort: invalid option -- %c\n", opt); usage(sort_usage); @@ -310,4 +320,4 @@ int sort_main(int argc, char **argv) exit(0); } -/* $Id: sort.c,v 1.11 2000/02/08 19:58:47 erik Exp $ */ +/* $Id: sort.c,v 1.12 2000/03/04 21:19:32 erik Exp $ */ diff --git a/tests/Makefile b/tests/Makefile index 015634460..c4fb0e911 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,16 +1,21 @@ -all test_all: message_header cp_tests mv_tests ln_tests +# busybox/tests/Makefile - Run through all defined tests. +# ------------------------ +# Copyright (C) 2000 Karl M. Hegbloom GPL -clean: cp_clean mv_clean ln_clean +all:: message_header message_header: @echo - @echo If tests faile due to differences in timestamps in commands that are not set - @echo to preserve timestamps, just run the tests again. + @echo BusyBox Test Suite. @echo -include cp_tests.mk -include mv_tests.mk -include ln_tests.mk +clean:: + +distclean: clean + +.PHONY: all clean distclean message_header + +include $(wildcard *_tests.mk) BBL := $(shell pushd .. >/dev/null && \ ${MAKE} busybox.links >/dev/null && \ @@ -21,8 +26,6 @@ BBL := $(shell pushd .. >/dev/null && \ ../busybox: cd .. && ${MAKE} busybox -$(BBL): ../busybox +${BBL}: ../busybox rm -f $@ ln ../busybox $@ - -.PHONY: all test_all message_header diff --git a/tests/cp_tests.mk b/tests/cp_tests.mk index e14262ac1..e79f2b38b 100644 --- a/tests/cp_tests.mk +++ b/tests/cp_tests.mk @@ -1,18 +1,23 @@ -# This is a -*- makefile -*- +# cp_tests.mk - Set of test cases for busybox cp +# ------------- +# Copyright (C) 2000 Karl M. Hegbloom GPL +# # GNU `cp' GCP = /bin/cp # BusyBox `cp' BCP = $(shell pwd)/cp -.PHONY: cp_clean +all:: cp_tests +clean:: cp_clean + cp_clean: - rm -rf cp_tests cp_*.{gnu,bb} cp + - rm -rf cp_tests cp_*.{gnu,bb} cp -.PHONY: cp_tests cp_tests: cp_clean cp @echo; @echo "No output from diff means busybox cp is functioning properly."; + @echo "Some tests might show timestamp differences that are Ok."; @echo; ${BCP} || true; @@ -20,7 +25,8 @@ cp_tests: cp_clean cp @echo; mkdir cp_tests; - @echo; + # Copy a file to a copy of the file + @echo ------------------------------; cd cp_tests; \ echo A file > afile; \ ls -l afile > ../cp_afile_afilecopy.gnu; \ @@ -28,7 +34,7 @@ cp_tests: cp_clean cp ls -l afile afilecopy >> ../cp_afile_afilecopy.gnu; @echo; - rm -f cp_tests/afile*; + rm -rf cp_tests/*; @echo; cd cp_tests; \ @@ -38,118 +44,135 @@ cp_tests: cp_clean cp ls -l afile afilecopy >> ../cp_afile_afilecopy.bb; @echo; - diff -u cp_afile_afilecopy.gnu cp_afile_afilecopy.bb; + @echo Might show timestamp differences. + -diff -u cp_afile_afilecopy.gnu cp_afile_afilecopy.bb; @echo; - rm -f cp_tests/afile*; + rm -rf cp_tests/*; - @echo; echo; + # Copy a file pointed to by a symlink + @echo; echo ------------------------------; cd cp_tests; \ - mkdir there there1; \ - cd there; \ - ln -s ../afile .; + mkdir here there; \ + echo A file > afile; \ + cd here; \ + ln -s ../afile .; \ @echo; cd cp_tests; \ - echo A file > afile; \ - ls -l afile > ../cp_symlink.gnu; \ - ${GCP} there/afile there1/; \ - ls -l afile there/afile there1/afile >> ../cp_symlink.gnu; + ls -lR . > ../cp_symlink.gnu; \ + ${GCP} here/afile there; \ + ls -lR . >> ../cp_symlink.gnu; @echo; - rm -f cp_tests/afile cp_tests/there1/afile; + rm -rf cp_tests/there/*; + + sleep 1; @echo; cd cp_tests; \ - echo A file > afile; \ - ls -l afile > ../cp_symlink.bb; \ - ${BCP} there/afile there1/; \ - ls -l afile there/afile there1/afile >> ../cp_symlink.bb; + ls -lR . > ../cp_symlink.bb; \ + ${BCP} here/afile there; \ + ls -lR . >> ../cp_symlink.bb; @echo; - diff -u cp_symlink.gnu cp_symlink.bb; + @echo Will show timestamp difference. + -diff -u cp_symlink.gnu cp_symlink.bb; @echo; - rm -f cp_tests/afile cp_tests/there1/afile; + rm -rf cp_tests/* - @echo; echo; + # Copy a symlink, useing the -a switch. + @echo; echo ------------------------------; cd cp_tests; \ echo A file > afile; \ - ls -l afile > ../cp_a_symlink.gnu; \ - ${GCP} -a there/afile there1/; \ - ls -l afile there/afile there1/afile >> ../cp_a_symlink.gnu; + mkdir here there; \ + cd here; \ + ln -s ../afile . + + cd cp_test; \ + ls -lR . > ../cp_a_symlink.gnu; \ + ${GCP} -a here/afile there; \ + ls -lR . >> ../cp_a_symlink.gnu; @echo; - rm -f cp_tests/afile cp_tests/there1/afile; + rm -f cp_tests/there/*; + + sleep 1; @echo; cd cp_tests; \ echo A file > afile; \ - ls -l afile > ../cp_a_symlink.bb; \ - ${BCP} -a there/afile there1/; \ - ls -l afile there/afile there1/afile >> ../cp_a_symlink.bb; + ls -lR . > ../cp_a_symlink.bb; \ + ${BCP} -a here/afile there; \ + ls -lR . >> ../cp_a_symlink.bb; @echo; diff -u cp_a_symlink.gnu cp_a_symlink.bb; @echo; - rm -f cp_tests/afile - rm -rf cp_tests/there{,1}; + rm -f cp_tests/*; - @echo; echo; + # Copy a directory into another directory with the -a switch + @echo; echo ------------------------------; cd cp_tests; \ - echo A file > there/afile; \ - mkdir there/adir; \ - touch there/adir/afileinadir; \ - ln -s $(shell pwd) there/alink; + mkdir here there; \ + echo A file > here/afile; \ + mkdir here/adir; \ + touch here/adir/afileinadir; \ + ln -s $$(pwd) here/alink; @echo; cd cp_tests; \ - ${GCP} -a there/ there1/; \ - ls -lR there/ there1/ > ../cp_a_dir_dir.gnu; + ls -lR . > ../cp_a_dir_dir.gnu; \ + ${GCP} -a here/ there/; \ + ls -lR . >> ../cp_a_dir_dir.gnu; @echo; - rm -rf cp_tests/there1; + rm -rf cp_tests/there/*; + + sleep 1; @echo; cd cp_tests; \ - ${BCP} -a there/ there1/; \ - ls -lR there/ there1/ > ../cp_a_dir_dir.bb; + ls -lR . > ../cp_a_dir_dir.bb; \ + ${BCP} -a here/ there/; \ + ls -lR . >> ../cp_a_dir_dir.bb; @echo; diff -u cp_a_dir_dir.gnu cp_a_dir_dir.bb; @echo; - rm -rf cp_tests/there1/; + rm -rf cp_tests/*; - @echo; echo; + # Copy a set of files to a directory. + @echo; echo ------------------------------; cd cp_tests; \ echo A file number one > afile1; \ echo A file number two, blah. > afile2; \ ln -s afile1 symlink1; \ - mkdir there1; \ - ${GCP} afile1 afile2 symlink1 there1/; \ + mkdir there; + + cd cp_tests; \ + ${GCP} afile1 afile2 symlink1 there/; \ ls -lR > ../cp_files_dir.gnu; @echo; - rm -rf cp_tests/{afile{1,2},symlink1,there1}; + rm -rf cp_tests/there/*; @echo; cd cp_tests; \ - echo A file number one > afile1; \ - echo A file number two, blah. > afile2; \ - ln -s afile1 symlink1; \ - mkdir there1; \ - ${BCP} afile1 afile2 symlink1 there1/; \ + ${BCP} afile1 afile2 symlink1 there/; \ ls -lR > ../cp_files_dir.bb; @echo; diff -u cp_files_dir.gnu cp_files_dir.bb; @echo; - rm -rf cp_tests/{afile{1,2},symlink1,there1}; + rm -rf cp_tests/*; - @echo; echo; + # Copy a set of files to a directory with the -d switch. + @echo; echo ------------------------------; cd cp_tests; \ echo A file number one > afile1; \ echo A file number two, blah. > afile2; \ @@ -176,7 +199,8 @@ cp_tests: cp_clean cp @echo; rm -rf cp_tests/{afile{1,2},symlink1,there1}; - @echo; echo; + # Copy a set of files to a directory with the -p switch. + @echo; echo ------------------------------; cd cp_tests; \ echo A file number one > afile1; \ echo A file number two, blah. > afile2; \ @@ -205,7 +229,8 @@ cp_tests: cp_clean cp @echo; rm -rf cp_tests/{afile{1,2},symlink1,there1}; - @echo; echo; + # Copy a set of files to a directory with -p and -d switches. + @echo; echo ------------------------------; cd cp_tests; \ echo A file number one > afile1; \ echo A file number two, blah. > afile2; \ @@ -234,7 +259,8 @@ cp_tests: cp_clean cp @echo; rm -rf cp_tests/{afile{1,2},symlink1,there1}; - @echo; echo; + # Copy a directory into another directory with the -a switch. + @echo; echo ------------------------------; cd cp_tests; \ mkdir dir{a,b}; \ echo A file > dira/afile; \ @@ -246,7 +272,6 @@ cp_tests: cp_clean cp ${GCP} -a dira dirb; \ ls -lR . >> ../cp_a_dira_dirb.gnu; - # false; @echo; rm -rf cp_tests/dir{a,b}; @@ -265,6 +290,31 @@ cp_tests: cp_clean cp @echo; diff -u cp_a_dira_dirb.gnu cp_a_dira_dirb.bb; - # false; @echo; rm -rf cp_tests/dir{a,b}; + + # Copy a directory to another directory, without the -a switch. + @echo; echo ------------------------------; + @echo There should be an error message about cannot cp a dir to a subdir of itself. + cd cp_tests; \ + touch a b c; \ + mkdir adir; \ + ls -lR . > ../cp_a_star_adir.gnu; \ + ${GCP} -a * adir; \ + ls -lR . >> ../cp_a_star_adir.gnu; + + @echo + @echo There should be an error message about cannot cp a dir to a subdir of itself. + cd cp_tests; \ + rm -rf adir; \ + mkdir adir; \ + ls -lR . > ../cp_a_star_adir.bb; \ + ${BCP} -a * adir; \ + ls -lR . >> ../cp_a_star_adir.bb; + + @echo; + diff -u cp_a_star_adir.gnu cp_a_star_adir.bb; + + @echo; + rm -rf cp_tests; + @echo; echo Done. diff --git a/tests/ln_tests.mk b/tests/ln_tests.mk index 5925edd4f..3110f8199 100644 --- a/tests/ln_tests.mk +++ b/tests/ln_tests.mk @@ -1,14 +1,19 @@ +# ln_tests.mk - Set of tests for busybox ln +# ------------- +# Copyright (C) 2000 Karl M. Hegbloom GPL +# # GNU `ln' GLN = /bin/ln # BusyBox `ln' BLN = $(shell pwd)/ln -.PHONY: ln_clean +all:: ln_tests +clean:: ln_clean + ln_clean: rm -rf ln_tests ln_*.{gnu,bb} ln -.PHONY: ln_tests ln_tests: ln_clean ln @echo; @echo "No output from diff means busybox ln is functioning properly."; diff --git a/tests/mv_tests.mk b/tests/mv_tests.mk index 3a9012538..81b8ffdec 100644 --- a/tests/mv_tests.mk +++ b/tests/mv_tests.mk @@ -1,14 +1,19 @@ +# mv_tests.mk - Set of tests cases for busybox mv +# ------------- +# Copyright (C) 2000 Karl M. Hegbloom GPL +# # GNU `mv' GMV = /bin/mv # BusyBox `mv' BMV = $(shell pwd)/mv -.PHONY: mv_clean +all:: mv_tests +clean:: mv_clean + mv_clean: rm -rf mv_tests mv_*.{gnu,bb} mv -.PHONY: mv_tests mv_tests: mv_clean mv @echo; @echo "No output from diff means busybox mv is functioning properly."; @@ -45,7 +50,7 @@ mv_tests: mv_clean mv @echo; rm -f mv_tests/{afile,newname}; - @echo; echo; + @echo; echo ------------------------------; cd mv_tests; \ echo A file > afile; \ ln -s afile symlink; \ @@ -72,7 +77,7 @@ mv_tests: mv_clean mv @echo; rm -rf mv_tests/*; - @echo; echo; + @echo; echo ------------------------------; cd mv_tests; \ echo A file > afile; \ ln -s afile symlink; \ @@ -85,7 +90,7 @@ mv_tests: mv_clean mv @echo; rm -rf mv_tests/* - @echo; echo; + @echo; echo ------------------------------; cd mv_tests; \ echo A file > afile; \ ln -s afile symlink; \ @@ -101,7 +106,7 @@ mv_tests: mv_clean mv @echo; rm -rf mv_tests/*; - @echo; echo; + @echo; echo ------------------------------; cd mv_tests; \ mkdir dir{a,b}; \ echo A file > dira/afile; \ @@ -135,3 +140,27 @@ mv_tests: mv_clean mv # false; @echo; rm -rf mv_tests/dir{a,b}; + + @echo; echo ------------------------------; + @echo There should be an error message about cannot mv a dir to a subdir of itself. + cd mv_tests; \ + touch a b c; \ + mkdir adir; \ + ls -lR . > ../mv_a_star_adir.gnu; \ + ${GMV} * adir; \ + ls -lR . >> ../mv_a_star_adir.gnu; + + @echo + @echo There should be an error message about cannot mv a dir to a subdir of itself. + cd mv_tests; \ + rm -rf adir; \ + mkdir adir; \ + ls -lR . > ../mv_a_star_adir.bb; \ + ${BMV} * adir; \ + ls -lR . >> ../mv_a_star_adir.bb; + + @echo; + diff -u mv_a_star_adir.gnu mv_a_star_adir.bb; + + @echo; + rm -rf mv_test/*; diff --git a/update.c b/update.c index fef188bba..bb77c5f1f 100644 --- a/update.c +++ b/update.c @@ -1,9 +1,11 @@ /* vi: set sw=4 ts=4: */ /* - * Mini update implementation for busybox + * Mini update implementation for busybox; much pasted from update-2.11 * * * Copyright (C) 1995, 1996 by Bruce Perens . + * Copyright (c) 1996, 1997, 1999 Torsten Poulin. + * Copyright (c) 2000 by Karl M. Hegbloom * * 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 @@ -23,6 +25,8 @@ #include "internal.h" #include +#include +#include #if defined(__GLIBC__) #include @@ -30,37 +34,79 @@ _syscall2(int, bdflush, int, func, int, data); #endif /* __GLIBC__ */ +static char update_usage[] = + "update [options]\n" + " -S\tforce use of sync(2) instead of flushing\n" + " -s SECS\tcall sync this often (default 30)\n" + " -f SECS\tflush some buffers this often (default 5)\n"; + +static unsigned int sync_duration = 30; +static unsigned int flush_duration = 5; +static int use_sync = 0; + extern int update_main(int argc, char **argv) { - /* - * Update is actually two daemons, bdflush and update. - */ int pid; + while (**argv == '-') { + while (*++(*argv)) { + switch (**argv) { + case 'S': + use_sync = 1; + break; + case 's': + if (--argc < 1) usage(update_usage); + sync_duration = atoi(*(++argv)); + break; + case 'f': + if (--argc < 1) usage(update_usage); + flush_duration = atoi(*(++argv)); + break; + } + } + argc--; + argv++; + } + pid = fork(); if (pid < 0) - return pid; + exit(FALSE); else if (pid == 0) { + /* Become a proper daemon */ + setsid(); + chdir("/"); + for (pid = 0; pid < OPEN_MAX; pid++) close(pid); + /* * This is no longer necessary since 1.3.5x, but it will harmlessly * exit if that is the case. */ - strcpy(argv[0], "bdflush (update)"); - argv[1] = 0; - argv[2] = 0; - bdflush(1, 0); - _exit(0); - } - pid = fork(); - if (pid < 0) - return pid; - else if (pid == 0) { - argv[0] = "update"; + argv[0] = "bdflush (update)"; + argv[1] = NULL; + argv[2] = NULL; for (;;) { - sync(); - sleep(30); + if (use_sync) { + sleep(sync_duration); + sync(); + } else { + sleep(flush_duration); + if (bdflush(1, 0) < 0) { + openlog("update", LOG_CONS, LOG_DAEMON); + syslog(LOG_INFO, + "This kernel does not need update(8). Exiting."); + closelog(); + exit(TRUE); + } + } } } - - return 0; + return TRUE; } + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/utility.c b/utility.c index 0279cca56..c8ce3921a 100644 --- a/utility.c +++ b/utility.c @@ -122,7 +122,76 @@ int get_kernel_revision() } #endif /* BB_INIT || BB_PS */ +#if defined (BB_CP_MV) || defined (BB_DU) +#define HASH_SIZE 311 /* Should be prime */ +#define hash_inode(i) ((i) % HASH_SIZE) + +static ino_dev_hashtable_bucket_t *ino_dev_hashtable[HASH_SIZE]; + +/* + * Return 1 if statbuf->st_ino && statbuf->st_dev are recorded in + * `ino_dev_hashtable', else return 0 + * + * If NAME is a non-NULL pointer to a character pointer, and there is + * a match, then set *NAME to the value of the name slot in that + * bucket. + */ +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); + if (bucket == NULL) + fatalError("Not enough memory."); + 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; + } + } +} + +#endif /* BB_CP_MV || BB_DU */ #if defined (BB_CP_MV) || defined (BB_DU) || defined (BB_LN) /* @@ -161,7 +230,7 @@ int isDirectory(const char *fileName, const int followLinks, struct stat *statBu /* * Copy one file to another, while possibly preserving its modes, times, * and modes. Returns TRUE if successful, or FALSE on a failure with an - * error message output. (Failure is not indicted if the attributes cannot + * error message output. (Failure is not indicated if the attributes cannot * be set.) * -Erik Andersen */ @@ -1335,6 +1404,11 @@ extern void whine_if_fstab_is_missing() } #endif - - /* END CODE */ +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ -- cgit v1.2.3