aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog10
-rw-r--r--TODO23
-rw-r--r--coreutils/df.c3
-rw-r--r--df.c3
-rw-r--r--free.c36
-rw-r--r--init.c20
-rw-r--r--init/init.c20
-rw-r--r--internal.h21
-rw-r--r--mount.c8
-rw-r--r--procps/free.c36
-rw-r--r--procps/uptime.c3
-rw-r--r--uptime.c3
-rw-r--r--util-linux/mount.c8
-rw-r--r--utility.c12
14 files changed, 159 insertions, 47 deletions
diff --git a/Changelog b/Changelog
index 4417652bd..aa8b15db7 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,13 @@
+0.46
+
+ * Updates to handle Linux 2.4.0 kernels (kludged around the
+ "none" entries in /proc/mounts, added a hack to make sysinfo
+ work with both old and new kernels).
+ * Fixed a nasty bug in tar when could mess up saved symlinks.
+
+ -Erik Andersen
+
+
0.45
* Now compiles vs libc5 (which can save lots of space for
embedded systems).
diff --git a/TODO b/TODO
index 1b456a664..a4bfa0c00 100644
--- a/TODO
+++ b/TODO
@@ -39,31 +39,14 @@ list discussion):
Linux 2.4.x kernels
-BusyBox 0.45 currently will not work with the Linux 2.4.x kernels.
+BusyBox 0.46 currently will not work with the Linux 2.4.x kernels.
I know of the following problems:
-1) The sysinfo syscall has changed what it does (binary incompatable), breaking
- init and free.
-2) BusyBox NFS support is broken with 2.4.x (needs to be adjusted for NFSv3 and
+1) BusyBox NFS support is broken with 2.4.x (needs to be adjusted for NFSv3 and
kernel header changes).
-3) mount,umount,and df are all broken by the "none" entries for fake filesystems
- such as the shared mem one. Al Viro claims these will be disappearing soon...
-
-I made a kernel patch that reverts the sysinfo changes
- http://kernelnotes.org/lnxlists/linux-kernel/lk_0006_01/msg00619.html
-
-and I have been fighting with Alan Cox to get these changes fixed in a binary
-compatable way, but Alan has so far not been very receptive. I am planning on
-appealing to Linus (when he gets back from vacation) and then going with
-whatever he decides...
-
-So my thought is, 2.4.x just isn't ready for BusyBox to target it, and even if
-it was, BusyBox isn't ready yet either. Seems to me like this will not be
-ready for a while, and we should just not worry about it yet.
As long as I have BB_FEATURE_NFSMOUNT turned off, everything compiles cleanly
-for me with linux2.4.0test1-ac22-riel (i.e. I don't see the freeramdisk.c
-problem you reported). I use Debian potato (gcc 2.95.2, GNU libc 2.1.3).
+for me with linux2.4.0test2. I use Debian potato (gcc 2.95.2, GNU libc 2.1.3).
Of course, as noted above, compiling != working.
-----------
diff --git a/coreutils/df.c b/coreutils/df.c
index ba3227f30..8d457ec37 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -103,6 +103,9 @@ extern int df_main(int argc, char **argv)
}
while ((mountEntry = getmntent(mountTable))) {
+ if (strcmp(mountEntry->mnt_fsname, "none") == 0) {
+ continue;
+ }
df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
}
endmntent(mountTable);
diff --git a/df.c b/df.c
index ba3227f30..8d457ec37 100644
--- a/df.c
+++ b/df.c
@@ -103,6 +103,9 @@ extern int df_main(int argc, char **argv)
}
while ((mountEntry = getmntent(mountTable))) {
+ if (strcmp(mountEntry->mnt_fsname, "none") == 0) {
+ continue;
+ }
df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
}
endmntent(mountTable);
diff --git a/free.c b/free.c
index a81189be9..997430b39 100644
--- a/free.c
+++ b/free.c
@@ -23,20 +23,36 @@
#include "internal.h"
#include <stdio.h>
-#include <sys/sysinfo.h>
+#include <errno.h>
+
-#define DIVISOR 1024
extern int free_main(int argc, char **argv)
{
struct sysinfo info;
sysinfo(&info);
- info.totalram/=DIVISOR;
- info.freeram/=DIVISOR;
- info.totalswap/=DIVISOR;
- info.freeswap/=DIVISOR;
- info.sharedram/=DIVISOR;
- info.bufferram/=DIVISOR;
-
+ /* Kernels prior to 2.4.x will return info.mem_unit==0. Kernels after
+ * 2.4.x actually fill this value in */
+ if (info.mem_unit==0) {
+ /* Looks like we have a kernel prior to Linux 2.4.x */
+ info.mem_unit=1024;
+ info.totalram/=info.mem_unit;
+ info.freeram/=info.mem_unit;
+ info.totalswap/=info.mem_unit;
+ info.freeswap/=info.mem_unit;
+ info.sharedram/=info.mem_unit;
+ info.bufferram/=info.mem_unit;
+ } else {
+ /* Bah. Linux 2.4.x completely changed sysinfo. This can in theory
+ overflow a 32 bit unsigned long, but who puts more then 4GiB ram+swap
+ on an embedded system? */
+ info.mem_unit/=1024;
+ info.totalram*=info.mem_unit;
+ info.freeram*=info.mem_unit;
+ info.totalswap*=info.mem_unit;
+ info.freeswap*=info.mem_unit;
+ info.sharedram*=info.mem_unit;
+ info.bufferram*=info.mem_unit;
+ }
if (argc > 1 && **(argv + 1) == '-') {
usage("free\n"
#ifndef BB_FEATURE_TRIVIAL_HELP
@@ -61,3 +77,5 @@ extern int free_main(int argc, char **argv)
info.freeram+info.freeswap);
return(TRUE);
}
+
+
diff --git a/init.c b/init.c
index 98a58f275..9289b86a6 100644
--- a/init.c
+++ b/init.c
@@ -42,7 +42,6 @@
#include <linux/version.h>
#include <linux/reboot.h>
#include <linux/unistd.h>
-#include <sys/sysinfo.h> /* For check_free_memory() */
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
@@ -270,13 +269,28 @@ static int check_free_memory()
{
struct sysinfo info;
+ /* Pre initialize mem_unit in case this kernel is something prior to
+ * the linux 2.4 kernel (which will actually fill in mem_unit... */
sysinfo(&info);
if (sysinfo(&info) != 0) {
- message(LOG, "Error checking free memory: %s\n", strerror(errno));
+ printf("Error checking free memory: %s\n", strerror(errno));
return -1;
}
+ if (info.mem_unit==0) {
+ /* Looks like we have a kernel prior to Linux 2.4.x */
+ info.mem_unit=1024;
+ info.totalram/=info.mem_unit;
+ info.totalswap/=info.mem_unit;
+ } else {
+ /* Bah. Linux 2.4.x completely changed sysinfo. This can in theory
+ overflow a 32 bit unsigned long, but who puts more then 4GiB ram+swap
+ on an embedded system? */
+ info.mem_unit/=1024;
+ info.totalram*=info.mem_unit;
+ info.totalswap*=info.mem_unit;
+ }
- return((info.totalram+info.totalswap)/1024);
+ return(info.totalram+info.totalswap);
}
static void console_init()
diff --git a/init/init.c b/init/init.c
index 98a58f275..9289b86a6 100644
--- a/init/init.c
+++ b/init/init.c
@@ -42,7 +42,6 @@
#include <linux/version.h>
#include <linux/reboot.h>
#include <linux/unistd.h>
-#include <sys/sysinfo.h> /* For check_free_memory() */
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
@@ -270,13 +269,28 @@ static int check_free_memory()
{
struct sysinfo info;
+ /* Pre initialize mem_unit in case this kernel is something prior to
+ * the linux 2.4 kernel (which will actually fill in mem_unit... */
sysinfo(&info);
if (sysinfo(&info) != 0) {
- message(LOG, "Error checking free memory: %s\n", strerror(errno));
+ printf("Error checking free memory: %s\n", strerror(errno));
return -1;
}
+ if (info.mem_unit==0) {
+ /* Looks like we have a kernel prior to Linux 2.4.x */
+ info.mem_unit=1024;
+ info.totalram/=info.mem_unit;
+ info.totalswap/=info.mem_unit;
+ } else {
+ /* Bah. Linux 2.4.x completely changed sysinfo. This can in theory
+ overflow a 32 bit unsigned long, but who puts more then 4GiB ram+swap
+ on an embedded system? */
+ info.mem_unit/=1024;
+ info.totalram*=info.mem_unit;
+ info.totalswap*=info.mem_unit;
+ }
- return((info.totalram+info.totalswap)/1024);
+ return(info.totalram+info.totalswap);
}
static void console_init()
diff --git a/internal.h b/internal.h
index 127460fc6..c39dfde62 100644
--- a/internal.h
+++ b/internal.h
@@ -30,6 +30,7 @@
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <mntent.h>
@@ -296,9 +297,27 @@ int nfsmount(const char *spec, const char *node, unsigned long *flags,
#define RB_POWER_OFF 0x4321fedc
#endif
+/* Include our own copy of struct sysinfo to avoid binary compatability
+ * problems with Linux 2.4, which changed things. Grumble, grumble. */
+struct sysinfo {
+ long uptime; /* Seconds since boot */
+ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
+ unsigned long totalram; /* Total usable main memory size */
+ unsigned long freeram; /* Available memory size */
+ unsigned long sharedram; /* Amount of shared memory */
+ unsigned long bufferram; /* Memory used by buffers */
+ unsigned long totalswap; /* Total swap space size */
+ unsigned long freeswap; /* swap space still available */
+ unsigned short procs; /* Number of current processes */
+ unsigned long totalhigh; /* Total high memory size */
+ unsigned long freehigh; /* Available high memory size */
+ unsigned int mem_unit; /* Memory unit size in bytes */
+ char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */
+};
+extern int sysinfo (struct sysinfo* info);
-#ifndef setbit
/* Bit map related macros -- libc5 doens't provide these... sigh. */
+#ifndef setbit
#define NBBY CHAR_BIT
#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
diff --git a/mount.c b/mount.c
index 76f048b1c..292be0c43 100644
--- a/mount.c
+++ b/mount.c
@@ -358,6 +358,10 @@ extern int mount_main(int argc, char **argv)
fatalError( "\nDEVMTAB_GET_MOUNTS: %s\n", strerror (errno));
for( i = 0 ; i < numfilesystems ; i++) {
+ /* klude around Linux 2.4.x stupidity */
+ if (strcmp(mntentlist[i].mnt_fsname, "none") == 0) {
+ continue;
+ }
fprintf( stdout, "%s %s %s %s %d %d\n", mntentlist[i].mnt_fsname,
mntentlist[i].mnt_dir, mntentlist[i].mnt_type,
mntentlist[i].mnt_opts, mntentlist[i].mnt_freq,
@@ -380,6 +384,10 @@ extern int mount_main(int argc, char **argv)
while ((m = getmntent(mountTable)) != 0) {
char *blockDevice = m->mnt_fsname;
+ /* klude around Linux 2.4.x stupidity */
+ if (strcmp(blockDevice, "none") == 0) {
+ continue;
+ }
if (strcmp(blockDevice, "/dev/root") == 0) {
find_real_root_device_name( blockDevice);
}
diff --git a/procps/free.c b/procps/free.c
index a81189be9..997430b39 100644
--- a/procps/free.c
+++ b/procps/free.c
@@ -23,20 +23,36 @@
#include "internal.h"
#include <stdio.h>
-#include <sys/sysinfo.h>
+#include <errno.h>
+
-#define DIVISOR 1024
extern int free_main(int argc, char **argv)
{
struct sysinfo info;
sysinfo(&info);
- info.totalram/=DIVISOR;
- info.freeram/=DIVISOR;
- info.totalswap/=DIVISOR;
- info.freeswap/=DIVISOR;
- info.sharedram/=DIVISOR;
- info.bufferram/=DIVISOR;
-
+ /* Kernels prior to 2.4.x will return info.mem_unit==0. Kernels after
+ * 2.4.x actually fill this value in */
+ if (info.mem_unit==0) {
+ /* Looks like we have a kernel prior to Linux 2.4.x */
+ info.mem_unit=1024;
+ info.totalram/=info.mem_unit;
+ info.freeram/=info.mem_unit;
+ info.totalswap/=info.mem_unit;
+ info.freeswap/=info.mem_unit;
+ info.sharedram/=info.mem_unit;
+ info.bufferram/=info.mem_unit;
+ } else {
+ /* Bah. Linux 2.4.x completely changed sysinfo. This can in theory
+ overflow a 32 bit unsigned long, but who puts more then 4GiB ram+swap
+ on an embedded system? */
+ info.mem_unit/=1024;
+ info.totalram*=info.mem_unit;
+ info.freeram*=info.mem_unit;
+ info.totalswap*=info.mem_unit;
+ info.freeswap*=info.mem_unit;
+ info.sharedram*=info.mem_unit;
+ info.bufferram*=info.mem_unit;
+ }
if (argc > 1 && **(argv + 1) == '-') {
usage("free\n"
#ifndef BB_FEATURE_TRIVIAL_HELP
@@ -61,3 +77,5 @@ extern int free_main(int argc, char **argv)
info.freeram+info.freeswap);
return(TRUE);
}
+
+
diff --git a/procps/uptime.c b/procps/uptime.c
index 67ca34d75..efdbccf00 100644
--- a/procps/uptime.c
+++ b/procps/uptime.c
@@ -31,13 +31,14 @@
#include "internal.h"
#include <stdio.h>
#include <time.h>
-#include <sys/sysinfo.h>
+#include <errno.h>
#define FSHIFT 16 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
extern int uptime_main(int argc, char **argv)
{
int updays, uphours, upminutes;
diff --git a/uptime.c b/uptime.c
index 67ca34d75..efdbccf00 100644
--- a/uptime.c
+++ b/uptime.c
@@ -31,13 +31,14 @@
#include "internal.h"
#include <stdio.h>
#include <time.h>
-#include <sys/sysinfo.h>
+#include <errno.h>
#define FSHIFT 16 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
extern int uptime_main(int argc, char **argv)
{
int updays, uphours, upminutes;
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 76f048b1c..292be0c43 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -358,6 +358,10 @@ extern int mount_main(int argc, char **argv)
fatalError( "\nDEVMTAB_GET_MOUNTS: %s\n", strerror (errno));
for( i = 0 ; i < numfilesystems ; i++) {
+ /* klude around Linux 2.4.x stupidity */
+ if (strcmp(mntentlist[i].mnt_fsname, "none") == 0) {
+ continue;
+ }
fprintf( stdout, "%s %s %s %s %d %d\n", mntentlist[i].mnt_fsname,
mntentlist[i].mnt_dir, mntentlist[i].mnt_type,
mntentlist[i].mnt_opts, mntentlist[i].mnt_freq,
@@ -380,6 +384,10 @@ extern int mount_main(int argc, char **argv)
while ((m = getmntent(mountTable)) != 0) {
char *blockDevice = m->mnt_fsname;
+ /* klude around Linux 2.4.x stupidity */
+ if (strcmp(blockDevice, "none") == 0) {
+ continue;
+ }
if (strcmp(blockDevice, "/dev/root") == 0) {
find_real_root_device_name( blockDevice);
}
diff --git a/utility.c b/utility.c
index b9c7a76cd..061ba6423 100644
--- a/utility.c
+++ b/utility.c
@@ -131,6 +131,15 @@ extern int get_kernel_revision(void)
}
#endif /* BB_INIT */
+
+
+#if defined BB_FREE || defined BB_INIT || defined BB_UNAME || defined BB_UPTIME
+#include <sys/syscall.h>
+_syscall1(int, sysinfo, struct sysinfo *, info);
+#endif /* BB_INIT */
+
+
+
#if defined (BB_CP_MV) || defined (BB_DU)
#define HASH_SIZE 311 /* Should be prime */
@@ -1189,6 +1198,9 @@ extern struct mntent *findMountPoint(const char *name, const char *table)
return 0;
while ((mountEntry = getmntent(mountTable)) != 0) {
+ if (strcmp(mountEntry->mnt_fsname, "none") == 0) {
+ continue;
+ }
if (strcmp(name, mountEntry->mnt_dir) == 0
|| strcmp(name, mountEntry->mnt_fsname) == 0) /* String match. */
break;