diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-10-01 21:57:59 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-10-01 21:57:59 +0200 |
commit | 5542934d65016e5eb29ed56f5cdea090e137b321 (patch) | |
tree | 92227b5e26964674e94027c4fa6a6a6537c771d3 /procps/free.c | |
parent | ee5ab8f321f7060c5720b50b1834f273e00f5859 (diff) | |
download | busybox-5542934d65016e5eb29ed56f5cdea090e137b321.tar.gz |
free: add -b/k/m/g options; remove 4 TB limitation. +100 bytes
Based on patch by Stefan Tomanek (stefan@pico.ruhr.de)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'procps/free.c')
-rw-r--r-- | procps/free.c | 98 |
1 files changed, 56 insertions, 42 deletions
diff --git a/procps/free.c b/procps/free.c index be65f46f1..efbac5ba6 100644 --- a/procps/free.c +++ b/procps/free.c @@ -11,47 +11,58 @@ #include "libbb.h" +struct globals { + unsigned mem_unit; +#if ENABLE_DESKTOP + unsigned unit_steps; +# define G_unit_steps G.unit_steps +#else +# define G_unit_steps 10 +#endif +}; +#define G (*(struct globals*)&bb_common_bufsiz1) +#define INIT_G() do { } while (0) + + +static unsigned long long scale(unsigned long d) +{ + return ((unsigned long long)d * G.mem_unit) >> G_unit_steps; +} + + int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) { struct sysinfo info; - unsigned mem_unit; + + INIT_G(); #if ENABLE_DESKTOP - if (argv[1] && argv[1][0] == '-') - bb_show_usage(); + G.unit_steps = 10; + if (argv[1] && argv[1][0] == '-') { + switch (argv[1][1]) { + case 'b': + G.unit_steps = 0; + break; + case 'k': /* 2^10 */ + /* G.unit_steps = 10; - already is */ + break; + case 'm': /* 2^(2*10) */ + G.unit_steps = 20; + break; + case 'g': /* 2^(3*10) */ + G.unit_steps = 30; + break; + default: + bb_show_usage(); + } + } #endif sysinfo(&info); /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ - mem_unit = 1; - if (info.mem_unit != 0) { - mem_unit = info.mem_unit; - } - - /* Convert values to kbytes */ - if (mem_unit == 1) { - info.totalram >>= 10; - info.freeram >>= 10; -#if BB_MMU - info.totalswap >>= 10; - info.freeswap >>= 10; -#endif - info.sharedram >>= 10; - info.bufferram >>= 10; - } else { - mem_unit >>= 10; - /* TODO: Make all this stuff not overflow when mem >= 4 Tb */ - info.totalram *= mem_unit; - info.freeram *= mem_unit; -#if BB_MMU - info.totalswap *= mem_unit; - info.freeswap *= mem_unit; -#endif - info.sharedram *= mem_unit; - info.bufferram *= mem_unit; - } + G.mem_unit = (info.mem_unit ? info.mem_unit : 1); printf(" %13s%13s%13s%13s%13s\n", "total", @@ -63,30 +74,33 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) * /proc/meminfo instead and get "Cached: NNN kB" from there. */ ); -#define FIELDS_5 "%13lu%13lu%13lu%13lu%13lu\n" -#define FIELDS_3 (FIELDS_5 + 2*5) -#define FIELDS_2 (FIELDS_5 + 3*5) + +#define FIELDS_5 "%13llu%13llu%13llu%13llu%13llu\n" +#define FIELDS_3 (FIELDS_5 + 2*6) +#define FIELDS_2 (FIELDS_5 + 3*6) + printf("Mem: "); printf(FIELDS_5, - info.totalram, - info.totalram - info.freeram, - info.freeram, - info.sharedram, info.bufferram + scale(info.totalram), + scale(info.totalram - info.freeram), + scale(info.freeram), + scale(info.sharedram), + scale(info.bufferram) ); /* Show alternate, more meaningful busy/free numbers by counting * buffer cache as free memory (make it "-/+ buffers/cache" * if/when we add support for "cached" column): */ printf("-/+ buffers: "); printf(FIELDS_2, - info.totalram - info.freeram - info.bufferram, - info.freeram + info.bufferram + scale(info.totalram - info.freeram - info.bufferram), + scale(info.freeram + info.bufferram) ); #if BB_MMU printf("Swap:"); printf(FIELDS_3, - info.totalswap, - info.totalswap - info.freeswap, - info.freeswap + scale(info.totalswap), + scale(info.totalswap - info.freeswap), + scale(info.freeswap) ); #endif return EXIT_SUCCESS; |