A few updates (including the cp fix the Craig has been looking for)
authorErik Andersen <andersen@codepoet.org>
Sat, 4 Mar 2000 21:19:32 +0000 (21:19 -0000)
committerErik Andersen <andersen@codepoet.org>
Sat, 4 Mar 2000 21:19:32 +0000 (21:19 -0000)
 -Erik

34 files changed:
AUTHORS
Changelog
TODO
applets/busybox.c
busybox.c
busybox.def.h
cat.c
chmod_chown_chgrp.c
chroot.c
chvt.c
console-tools/chvt.c
coreutils/cat.c
coreutils/chroot.c
coreutils/df.c
coreutils/du.c
coreutils/ln.c
coreutils/sort.c
cp_mv.c
df.c
du.c
init.c
init/init.c
init/reboot.c
internal.h
ln.c
miscutils/update.c
reboot.c
sort.c
tests/Makefile
tests/cp_tests.mk
tests/ln_tests.mk
tests/mv_tests.mk
update.c
utility.c

diff --git a/AUTHORS b/AUTHORS
index 7986afc..526205b 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -37,4 +37,5 @@ Charles P. Wright <cpwright@villagenet.com>
 Enrique Zanardi <ezanardi@ull.es>
     tarcat (since removed), loadkmap, various fixes, Debian maintenance
 
-
+Karl M. Hegbloom <karlheg@debian.org>
+    cp_mv.c, the test suite, various fixes to utility.c, &c.
index 3c90ab9..0398ce9 100644 (file)
--- a/Changelog
+++ b/Changelog
            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  <karlheg@debian.org>
+           - 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 <pavel_roskin@geocities.com>:
+           - 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 <tausq@debian.org>.
+
 
        -Erik Andersen
 
diff --git a/TODO b/TODO
index e05558b..daa21cf 100644 (file)
--- 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...
+
+
index 13f8db9..a80a567 100644 (file)
@@ -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:
+*/
index 13f8db9..a80a567 100644 (file)
--- 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:
+*/
index 8ed5a9c..d42be44 100644 (file)
 // 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 86f85fe..58a1b0f 100644 (file)
--- 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:
+*/
index f037e95..4e5e9b0 100644 (file)
@@ -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:
+*/
index 6a01be6..3622c26 100644 (file)
--- 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 a32bd3e..635022a 100644 (file)
--- 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:
+*/
index a32bd3e..635022a 100644 (file)
@@ -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:
+*/
index 86f85fe..58a1b0f 100644 (file)
@@ -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:
+*/
index 6a01be6..3622c26 100644 (file)
@@ -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:
+*/
index 43d5d26..bc843f7 100644 (file)
@@ -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:
+*/
index 4dc7ea1..b6ebaca 100644 (file)
 
 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:
+*/
index 0715bfa..c54026c 100644 (file)
@@ -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:
+*/
index 609c5e0..e6894f6 100644 (file)
 #include <stdio.h>
 #include <errno.h>
 
-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 4c55e62..8dbc4e8 100644 (file)
--- a/cp_mv.c
+++ b/cp_mv.c
 #include <utime.h>
 #include <dirent.h>
 #include <sys/param.h>
+#include <setjmp.h>                            /* Ok to use this since `ash' does, therefore it's in the libc subset already. */
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
 
 #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 43d5d26..bc843f7 100644 (file)
--- 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 4dc7ea1..b6ebaca 100644 (file)
--- a/du.c
+++ b/du.c
 
 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 1837391..350ea62 100644 (file)
--- 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:
+*/
index 1837391..350ea62 100644 (file)
@@ -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:
+*/
index ef2a848..f782fa1 100644 (file)
@@ -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:
+*/
index 4d035c9..4c7bd97 100644 (file)
@@ -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 0715bfa..c54026c 100644 (file)
--- 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:
+*/
index fef188b..bb77c5f 100644 (file)
@@ -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 <bruce@pixar.com>.
+ * Copyright (c) 1996, 1997, 1999 Torsten Poulin.
+ * Copyright (c) 2000 by Karl M. Hegbloom <karlheg@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
@@ -23,6 +25,8 @@
 
 #include "internal.h"
 #include <linux/unistd.h>
+#include <sys/param.h>
+#include <sys/syslog.h>
 
 #if defined(__GLIBC__)
 #include <sys/kdaemon.h>
 _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:
+*/
index ef2a848..f782fa1 100644 (file)
--- 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 609c5e0..e6894f6 100644 (file)
--- a/sort.c
+++ b/sort.c
 #include <stdio.h>
 #include <errno.h>
 
-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 $ */
index 0156344..c4fb0e9 100644 (file)
@@ -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 <karlheg@debian.org>  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
index e14262a..e79f2b3 100644 (file)
@@ -1,18 +1,23 @@
-# This is a -*- makefile -*-
+# cp_tests.mk - Set of test cases for busybox cp
+# -------------
+# Copyright (C) 2000 Karl M. Hegbloom <karlheg@debian.org> 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;
+\f      # 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;
+\f      # 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;
+\f      # 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;
+\f      # 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;
+\f      # 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;
+\f      # 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;
+\f      # 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;
+\f      # 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;
+\f      # 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};
+
+\f      # 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;
+\f
+       @echo;
+       rm -rf cp_tests;
+       @echo; echo Done.
index 5925edd..3110f81 100644 (file)
@@ -1,14 +1,19 @@
+# ln_tests.mk - Set of tests for busybox ln
+# -------------
+# Copyright (C) 2000 Karl M. Hegbloom <karlheg@debian.org> 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.";
index 3a90125..81b8ffd 100644 (file)
@@ -1,14 +1,19 @@
+# mv_tests.mk - Set of tests cases for busybox mv
+# -------------
+# Copyright (C) 2000 Karl M. Hegbloom <karlheg@debian.org> 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/*;
index fef188b..bb77c5f 100644 (file)
--- 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 <bruce@pixar.com>.
+ * Copyright (c) 1996, 1997, 1999 Torsten Poulin.
+ * Copyright (c) 2000 by Karl M. Hegbloom <karlheg@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
@@ -23,6 +25,8 @@
 
 #include "internal.h"
 #include <linux/unistd.h>
+#include <sys/param.h>
+#include <sys/syslog.h>
 
 #if defined(__GLIBC__)
 #include <sys/kdaemon.h>
 _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:
+*/
index 0279cca..c8ce392 100644 (file)
--- 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:
+*/