From 10dc9d4d17e6880bfdfd253716ce72ec1243227f Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Mon, 26 Jun 2000 10:45:52 +0000 Subject: [PATCH] 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). -Erik --- Changelog | 10 ++++++++++ TODO | 23 +++-------------------- coreutils/df.c | 3 +++ df.c | 3 +++ free.c | 36 +++++++++++++++++++++++++++--------- init.c | 20 +++++++++++++++++--- init/init.c | 20 +++++++++++++++++--- internal.h | 21 ++++++++++++++++++++- mount.c | 8 ++++++++ procps/free.c | 36 +++++++++++++++++++++++++++--------- procps/uptime.c | 3 ++- uptime.c | 3 ++- util-linux/mount.c | 8 ++++++++ utility.c | 12 ++++++++++++ 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 -#include +#include + -#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 #include #include -#include /* For check_free_memory() */ #include #include #include @@ -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 #include #include -#include /* For check_free_memory() */ #include #include #include @@ -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 #include #include +#include #include #include #include @@ -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 -#include +#include + -#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 #include -#include +#include #define FSHIFT 16 /* nr of bits of precision */ #define FIXED_1 (1<> 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 #include -#include +#include #define FSHIFT 16 /* nr of bits of precision */ #define FIXED_1 (1<> 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 +_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;