free: implement -h
No binary (build failed)
—
(log yok)
| @@ -1065,10 +1065,10 @@ char *smart_ulltoa5(unsigned long long ul, char buf[5], const char *scale) FAST_ | |
| /* If block_size == 0, display size without fractional part, | |
| * else display (size * block_size) with one decimal digit. | |
| * If display_unit == 0, show value no bigger than 1024 with suffix (K,M,G...), | |
| - | * else divide by display_unit and do not use suffix. */ |
| + | * else divide by display_unit and do not use suffix. |
| + | * Returns "auto pointer" */ |
| #define HUMAN_READABLE_MAX_WIDTH 7 /* "1024.0G" */ | |
| #define HUMAN_READABLE_MAX_WIDTH_STR "7" | |
| - | //TODO: provide pointer to buf (avoid statics)? |
| const char *make_human_readable_str(unsigned long long size, | |
| unsigned long block_size, unsigned long display_unit) FAST_FUNC; | |
| /* Put a string of hex bytes ("1b2e66fe"...), return advanced pointer */ | |
| @@ -19,9 +19,9 @@ | |
| //kbuild:lib-$(CONFIG_FREE) += free.o | |
| //usage:#define free_trivial_usage | |
| - | //usage: "" IF_DESKTOP("[-bkmg]") |
| + | //usage: "" IF_DESKTOP("[-bkmgh]") |
| //usage:#define free_full_usage "\n\n" | |
| - | //usage: "Display the amount of free and used system memory" |
| + | //usage: "Display free and used memory" |
| //usage: | |
| //usage:#define free_example_usage | |
| //usage: "$ free\n" | |
| @@ -29,6 +29,27 @@ | |
| //usage: " Mem: 257628 248724 8904 59644 93124\n" | |
| //usage: " Swap: 128516 8404 120112\n" | |
| //usage: "Total: 386144 257128 129016\n" | |
| + | //procps-ng 3.3.15: |
| + | // -b, --bytes show output in bytes |
| + | // --kilo show output in kilobytes |
| + | // --mega show output in megabytes |
| + | // --giga show output in gigabytes |
| + | // --tera show output in terabytes |
| + | // --peta show output in petabytes |
| + | // -k, --kibi show output in kibibytes |
| + | // -m, --mebi show output in mebibytes |
| + | // -g, --gibi show output in gibibytes |
| + | // --tebi show output in tebibytes |
| + | // --pebi show output in pebibytes |
| + | // -h, --human show human-readable output |
| + | // --si use powers of 1000 not 1024 |
| + | // -l, --lohi show detailed low and high memory statistics |
| + | // -t, --total show total for RAM + swap |
| + | // -s N, --seconds N repeat printing every N seconds |
| + | // -c N, --count N repeat printing N times, then exit |
| + | // -w, --wide wide output |
| + | // |
| + | //NB: if we implement -s or -c, need to stop being NOFORK! |
| #include "libbb.h" | |
| #ifdef __linux__ | |
| @@ -38,18 +59,22 @@ | |
| struct globals { | |
| unsigned mem_unit; | |
| #if ENABLE_DESKTOP | |
| - | uint8_t unit_steps; |
| - | # define G_unit_steps g->unit_steps |
| + | unsigned unit; |
| + | # define G_unit g->unit |
| #else | |
| - | # define G_unit_steps 10 |
| + | # define G_unit (1 << 10) |
| #endif | |
| unsigned long cached_kb, available_kb, reclaimable_kb; | |
| }; | |
| /* Because of NOFORK, "globals" are not in global data */ | |
| - | static unsigned long long scale(struct globals *g, unsigned long d) |
| + | static const char *scale(struct globals *g, unsigned long d) |
| { | |
| - | return ((unsigned long long)d * g->mem_unit) >> G_unit_steps; |
| + | /* Display (size * block_size) with one decimal digit. |
| + | * If display_unit == 0, show value no bigger than 1024 with suffix (K,M,G...), |
| + | * else divide by display_unit and do not use suffix. |
| + | * Returns "auto pointer" */ |
| + | return make_human_readable_str(d, g->mem_unit, G_unit); |
| } | |
| /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ | |
| @@ -88,20 +113,27 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |
| int seen_available; | |
| #if ENABLE_DESKTOP | |
| - | G.unit_steps = 10; |
| + | G.unit = 1 << 10; |
| if (argv[1] && argv[1][0] == '-') { | |
| switch (argv[1][1]) { | |
| case 'b': | |
| - | G.unit_steps = 0; |
| + | G.unit = 1; |
| break; | |
| case 'k': /* 2^10 */ | |
| - | /* G.unit_steps = 10; - already is */ |
| + | /* G.unit = 1 << 10; - already is */ |
| break; | |
| case 'm': /* 2^20 */ | |
| - | G.unit_steps = 20; |
| + | G.unit = 1 << 20; |
| break; | |
| case 'g': /* 2^30 */ | |
| - | G.unit_steps = 30; |
| + | G.unit = 1 << 30; |
| + | break; |
| + | // case 't': |
| + | // -- WRONG, -t is not "terabytes" in procps-ng, it's --total |
| + | // G.unit = 1 << 40; |
| + | // break; |
| + | case 'h': |
| + | G.unit = 0; /* human readable */ |
| break; | |
| default: | |
| bb_show_usage(); | |
| @@ -126,23 +158,13 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |
| cached += ((unsigned long long) G.reclaimable_kb * 1024) / G.mem_unit; | |
| cached_plus_free = cached + info.freeram; | |
| - | /* In case (long long * G.mem_unit) can overflow, this can be used to reduce the chances */ |
| - | #if 0 //ENABLE_DESKTOP |
| - | while (!(G.mem_unit & 1) && G.unit_steps != 0) { |
| - | G.mem_unit >>= 1; |
| - | G.unit_steps--; |
| - | //bb_error_msg("mem_unit:%d unit_steps:%d", G.mem_unit, G.unit_steps); |
| - | } |
| - | #endif |
| - | |
| - | #define FIELDS_6 "%12llu %11llu %11llu %11llu %11llu %11llu\n" |
| - | #define FIELDS_3 (FIELDS_6 + 6 + 7 + 7) |
| - | #define FIELDS_2 (FIELDS_6 + 6 + 7 + 7 + 7) |
| - | |
| - | printf(FIELDS_6, |
| + | printf("%12s%12s%12s", |
| scale(&G, info.totalram), //total | |
| scale(&G, info.totalram - cached_plus_free), //used | |
| - | scale(&G, info.freeram), //free |
| + | scale(&G, info.freeram) //free |
| + | ); |
| + | /* using two printf's: only 4 auto strings are supported, we need 6 */ |
| + | printf("%12s%12s%12s\n", |
| scale(&G, info.sharedram), //shared | |
| scale(&G, cached), //buff/cache | |
| scale(&G, available) //available | |
| @@ -152,14 +174,14 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |
| * buffer cache as free memory. */ | |
| if (!seen_available) { | |
| printf("-/+ buffers/cache: "); | |
| - | printf(FIELDS_2, |
| + | printf("%12s%12s%12s\n" + 4, |
| scale(&G, info.totalram - cached_plus_free), //used | |
| scale(&G, cached_plus_free) //free | |
| ); | |
| } | |
| #if BB_MMU | |
| printf("Swap: "); | |
| - | printf(FIELDS_3, |
| + | printf("%12s%12s%12s\n", |
| scale(&G, info.totalswap), //total | |
| scale(&G, info.totalswap - info.freeswap), //used | |
| scale(&G, info.freeswap) //free | |