/proc/mounts, added a hack to make sysinfo work with both old and new kernels).
-Erik
+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).
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.
-----------
}
while ((mountEntry = getmntent(mountTable))) {
+ if (strcmp(mountEntry->mnt_fsname, "none") == 0) {
+ continue;
+ }
df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
}
endmntent(mountTable);
}
while ((mountEntry = getmntent(mountTable))) {
+ if (strcmp(mountEntry->mnt_fsname, "none") == 0) {
+ continue;
+ }
df(mountEntry->mnt_fsname, mountEntry->mnt_dir);
}
endmntent(mountTable);
#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
info.freeram+info.freeswap);
return(TRUE);
}
+
+
#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>
{
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()
#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>
{
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()
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <mntent.h>
#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)))
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,
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);
}
#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
info.freeram+info.freeswap);
return(TRUE);
}
+
+
#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;
#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;
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,
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);
}
}
#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 */
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;