blob: 47f2fc3b2597eb3f23b4cda2e899cf41a3802afd
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Mini free implementation for busybox |
4 | * |
5 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> |
6 | * |
7 | * Licensed under GPLv2, see file LICENSE in this source tree. |
8 | */ |
9 | |
10 | /* getopt not needed */ |
11 | |
12 | //usage:#define free_trivial_usage |
13 | //usage: "" IF_DESKTOP("[-b/k/m/g]") |
14 | //usage:#define free_full_usage "\n\n" |
15 | //usage: "Display the amount of free and used system memory" |
16 | //usage: |
17 | //usage:#define free_example_usage |
18 | //usage: "$ free\n" |
19 | //usage: " total used free shared buffers\n" |
20 | //usage: " Mem: 257628 248724 8904 59644 93124\n" |
21 | //usage: " Swap: 128516 8404 120112\n" |
22 | //usage: "Total: 386144 257128 129016\n" |
23 | |
24 | #include "libbb.h" |
25 | #ifdef __linux__ |
26 | # include <sys/sysinfo.h> |
27 | #endif |
28 | |
29 | struct globals { |
30 | unsigned mem_unit; |
31 | #if ENABLE_DESKTOP |
32 | unsigned unit_steps; |
33 | # define G_unit_steps G.unit_steps |
34 | #else |
35 | # define G_unit_steps 10 |
36 | #endif |
37 | } FIX_ALIASING; |
38 | #define G (*(struct globals*)&bb_common_bufsiz1) |
39 | #define INIT_G() do { } while (0) |
40 | |
41 | |
42 | static unsigned long long scale(unsigned long d) |
43 | { |
44 | return ((unsigned long long)d * G.mem_unit) >> G_unit_steps; |
45 | } |
46 | |
47 | |
48 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
49 | int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) |
50 | { |
51 | struct sysinfo info; |
52 | |
53 | INIT_G(); |
54 | |
55 | #if ENABLE_DESKTOP |
56 | G.unit_steps = 10; |
57 | if (argv[1] && argv[1][0] == '-') { |
58 | switch (argv[1][1]) { |
59 | case 'b': |
60 | G.unit_steps = 0; |
61 | break; |
62 | case 'k': /* 2^10 */ |
63 | /* G.unit_steps = 10; - already is */ |
64 | break; |
65 | case 'm': /* 2^(2*10) */ |
66 | G.unit_steps = 20; |
67 | break; |
68 | case 'g': /* 2^(3*10) */ |
69 | G.unit_steps = 30; |
70 | break; |
71 | default: |
72 | bb_show_usage(); |
73 | } |
74 | } |
75 | #endif |
76 | |
77 | sysinfo(&info); |
78 | |
79 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ |
80 | G.mem_unit = (info.mem_unit ? info.mem_unit : 1); |
81 | |
82 | printf(" %13s%13s%13s%13s%13s\n", |
83 | "total", |
84 | "used", |
85 | "free", |
86 | "shared", "buffers" /* swap and total don't have these columns */ |
87 | /* procps version 3.2.8 also shows "cached" column, but |
88 | * sysinfo() does not provide this value, need to parse |
89 | * /proc/meminfo instead and get "Cached: NNN kB" from there. |
90 | */ |
91 | ); |
92 | |
93 | #define FIELDS_5 "%13llu%13llu%13llu%13llu%13llu\n" |
94 | #define FIELDS_3 (FIELDS_5 + 2*6) |
95 | #define FIELDS_2 (FIELDS_5 + 3*6) |
96 | |
97 | printf("Mem: "); |
98 | printf(FIELDS_5, |
99 | scale(info.totalram), |
100 | scale(info.totalram - info.freeram), |
101 | scale(info.freeram), |
102 | scale(info.sharedram), |
103 | scale(info.bufferram) |
104 | ); |
105 | /* Show alternate, more meaningful busy/free numbers by counting |
106 | * buffer cache as free memory (make it "-/+ buffers/cache" |
107 | * if/when we add support for "cached" column): */ |
108 | printf("-/+ buffers: "); |
109 | printf(FIELDS_2, |
110 | scale(info.totalram - info.freeram - info.bufferram), |
111 | scale(info.freeram + info.bufferram) |
112 | ); |
113 | #if BB_MMU |
114 | printf("Swap:"); |
115 | printf(FIELDS_3, |
116 | scale(info.totalswap), |
117 | scale(info.totalswap - info.freeswap), |
118 | scale(info.freeswap) |
119 | ); |
120 | #endif |
121 | return EXIT_SUCCESS; |
122 | } |
123 |