summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen2000-03-04 21:19:32 +0000
committerErik Andersen2000-03-04 21:19:32 +0000
commit029011b9eeaf491d00fda1d072c4c6094df96c3a (patch)
tree7c49f1fc1547a2f9cee812472f422a5c1a5c448b
parent7c4b2f3fe5cb6b9a5c6bd089c18279c5ce29dc21 (diff)
downloadbusybox-029011b9eeaf491d00fda1d072c4c6094df96c3a.zip
busybox-029011b9eeaf491d00fda1d072c4c6094df96c3a.tar.gz
A few updates (including the cp fix the Craig has been looking for)
-Erik
-rw-r--r--AUTHORS3
-rw-r--r--Changelog14
-rw-r--r--TODO24
-rw-r--r--applets/busybox.c18
-rw-r--r--busybox.c18
-rw-r--r--busybox.def.h3
-rw-r--r--cat.c8
-rw-r--r--chmod_chown_chgrp.c8
-rw-r--r--chroot.c9
-rw-r--r--chvt.c9
-rw-r--r--console-tools/chvt.c9
-rw-r--r--coreutils/cat.c8
-rw-r--r--coreutils/chroot.c9
-rw-r--r--coreutils/df.c8
-rw-r--r--coreutils/du.c71
-rw-r--r--coreutils/ln.c8
-rw-r--r--coreutils/sort.c28
-rw-r--r--cp_mv.c279
-rw-r--r--df.c8
-rw-r--r--du.c71
-rw-r--r--init.c11
-rw-r--r--init/init.c11
-rw-r--r--init/reboot.c8
-rw-r--r--internal.h11
-rw-r--r--ln.c8
-rw-r--r--miscutils/update.c86
-rw-r--r--reboot.c8
-rw-r--r--sort.c28
-rw-r--r--tests/Makefile23
-rw-r--r--tests/cp_tests.mk170
-rw-r--r--tests/ln_tests.mk9
-rw-r--r--tests/mv_tests.mk41
-rw-r--r--update.c86
-rw-r--r--utility.c80
34 files changed, 817 insertions, 376 deletions
diff --git a/AUTHORS b/AUTHORS
index 7986afc..526205b 100644
--- 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.
diff --git a/Changelog b/Changelog
index 3c90ab9..0398ce9 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 <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
--- 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 13f8db9..a80a567 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 13f8db9..a80a567 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 8ed5a9c..d42be44 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 86f85fe..58a1b0f 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 f037e95..4e5e9b0 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 6a01be6..3622c26 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 a32bd3e..635022a 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 a32bd3e..635022a 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 86f85fe..58a1b0f 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 6a01be6..3622c26 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 43d5d26..bc843f7 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 4dc7ea1..b6ebaca 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 0715bfa..c54026c 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 609c5e0..e6894f6 100644
--- a/coreutils/sort.c
+++ b/coreutils/sort.c
@@ -29,7 +29,18 @@
#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
--- a/cp_mv.c
+++ b/cp_mv.c
@@ -37,11 +37,15 @@
#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
--- 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
--- 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 1837391..350ea62 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 1837391..350ea62 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 ef2a848..f782fa1 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 4d035c9..4c7bd97 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 0715bfa..c54026c 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 fef188b..bb77c5f 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 <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>
@@ -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 ef2a848..f782fa1 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 609c5e0..e6894f6 100644
--- a/sort.c
+++ b/sort.c
@@ -29,7 +29,18 @@
#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/tests/Makefile b/tests/Makefile
index 0156344..c4fb0e9 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 <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
diff --git a/tests/cp_tests.mk b/tests/cp_tests.mk
index e14262a..e79f2b3 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 <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;
+ # 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 5925edd..3110f81 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 <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.";
diff --git a/tests/mv_tests.mk b/tests/mv_tests.mk
index 3a90125..81b8ffd 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 <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/*;
diff --git a/update.c b/update.c
index fef188b..bb77c5f 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 <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>
@@ -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 0279cca..c8ce392 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:
+*/