Updates to handle Linux 2.4.0 kernels (kludged around the "none" entries in
authorEric Andersen <andersen@codepoet.org>
Mon, 26 Jun 2000 10:45:52 +0000 (10:45 -0000)
committerEric Andersen <andersen@codepoet.org>
Mon, 26 Jun 2000 10:45:52 +0000 (10:45 -0000)
/proc/mounts, added a hack to make sysinfo work with both old and new kernels).
 -Erik

14 files changed:
Changelog
TODO
coreutils/df.c
df.c
free.c
init.c
init/init.c
internal.h
mount.c
procps/free.c
procps/uptime.c
uptime.c
util-linux/mount.c
utility.c

index 4417652bdeb78b9d944a1496570134c14e34221d..aa8b15db7940f4f9955873c06e4880be74904c02 100644 (file)
--- 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 1b456a664f4b3e5330a5b3a5fa6ed74dd0852236..a4bfa0c0087da9c70533754217a3877c25cd01c7 100644 (file)
--- 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.
 
 -----------
index ba3227f304ee771b828be0257717312ef5fe0afe..8d457ec37b118dc1db5a46b89c7d50f40eb431ee 100644 (file)
@@ -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 ba3227f304ee771b828be0257717312ef5fe0afe..8d457ec37b118dc1db5a46b89c7d50f40eb431ee 100644 (file)
--- 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 a81189be9066b9dead885304b7dc33f616a4c546..997430b39e106ad3834680ea82a5c9863e4b8ee8 100644 (file)
--- a/free.c
+++ b/free.c
 
 #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 98a58f275edc55d568663525546a78c11aeecd29..9289b86a6de7ccdc1ba1fe635738f53e4cf5addb 100644 (file)
--- 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()
index 98a58f275edc55d568663525546a78c11aeecd29..9289b86a6de7ccdc1ba1fe635738f53e4cf5addb 100644 (file)
@@ -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()
index 127460fc6f329f2a11367cb29268b4b4e82d900c..c39dfde62df91e21495c2dc8f396f012c27d6efd 100644 (file)
@@ -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 76f048b1c86c55dfb717b317f104e3d9f7b439aa..292be0c43d9888b174334185740398735849e1a6 100644 (file)
--- 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);
                                }
index a81189be9066b9dead885304b7dc33f616a4c546..997430b39e106ad3834680ea82a5c9863e4b8ee8 100644 (file)
 
 #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);
 }
+
+
index 67ca34d7556d7a72b39ec85a702873f79dd3a741..efdbccf00e87f494f02c4d6a2d50b799af3e01d6 100644 (file)
 #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;
index 67ca34d7556d7a72b39ec85a702873f79dd3a741..efdbccf00e87f494f02c4d6a2d50b799af3e01d6 100644 (file)
--- a/uptime.c
+++ b/uptime.c
 #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;
index 76f048b1c86c55dfb717b317f104e3d9f7b439aa..292be0c43d9888b174334185740398735849e1a6 100644 (file)
@@ -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);
                                }
index b9c7a76cd30c4ab65c4b040a9bf375b33cdbd195..061ba64236ef15d54593ba7594f032e0ad543ab3 100644 (file)
--- 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;