Xinqi Bao's Git

Flush the output stream instead of arbitrarily disabling buffering
[slstatus.git] / components / swap.c
1 /* See LICENSE file for copyright and license details. */
2 #include <errno.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "../util.h"
9
10 #if defined(__linux__)
11 static int
12 get_swap_info(long *s_total, long *s_free, long *s_cached)
13 {
14 FILE *fp;
15 struct {
16 const char *name;
17 const size_t len;
18 long *var;
19 } ent[] = {
20 { "SwapTotal", sizeof("SwapTotal") - 1, s_total },
21 { "SwapFree", sizeof("SwapFree") - 1, s_free },
22 { "SwapCached", sizeof("SwapCached") - 1, s_cached },
23 };
24 size_t line_len = 0, i, left;
25 char *line = NULL;
26
27 /* get number of fields we want to extract */
28 for (i = 0, left = 0; i < LEN(ent); i++) {
29 if (ent[i].var) {
30 left++;
31 }
32 }
33
34 if (!(fp = fopen("/proc/meminfo", "r"))) {
35 warn("fopen '/proc/meminfo':");
36 return 1;
37 }
38
39 /* read file line by line and extract field information */
40 while (left > 0 && getline(&line, &line_len, fp) >= 0) {
41 for (i = 0; i < LEN(ent); i++) {
42 if (ent[i].var &&
43 !strncmp(line, ent[i].name, ent[i].len)) {
44 sscanf(line + ent[i].len + 1, "%ld kB\n",
45 ent[i].var);
46 left--;
47 break;
48 }
49 }
50 }
51 free(line);
52 if (ferror(fp)) {
53 warn("getline '/proc/meminfo':");
54 return 1;
55 }
56
57 fclose(fp);
58 return 0;
59 }
60
61 const char *
62 swap_free(void)
63 {
64 long free;
65
66 if (get_swap_info(NULL, &free, NULL)) {
67 return NULL;
68 }
69
70 return fmt_human(free * 1024, 1024);
71 }
72
73 const char *
74 swap_perc(void)
75 {
76 long total, free, cached;
77
78 if (get_swap_info(&total, &free, &cached) || total == 0) {
79 return NULL;
80 }
81
82 return bprintf("%d", 100 * (total - free - cached) / total);
83 }
84
85 const char *
86 swap_total(void)
87 {
88 long total;
89
90 if (get_swap_info(&total, NULL, NULL)) {
91 return NULL;
92 }
93
94 return fmt_human(total * 1024, 1024);
95 }
96
97 const char *
98 swap_used(void)
99 {
100 long total, free, cached;
101
102 if (get_swap_info(&total, &free, &cached)) {
103 return NULL;
104 }
105
106 return fmt_human((total - free - cached) * 1024, 1024);
107 }
108 #elif defined(__OpenBSD__)
109 #include <stdlib.h>
110 #include <sys/swap.h>
111 #include <sys/types.h>
112 #include <unistd.h>
113
114 static int
115 getstats(int *total, int *used)
116 {
117 struct swapent *sep, *fsep;
118 int rnswap, nswap, i;
119
120 if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) {
121 warn("swaptctl 'SWAP_NSWAP':");
122 return 1;
123 }
124 if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) {
125 warn("calloc 'nswap':");
126 return 1;
127 }
128 if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) {
129 warn("swapctl 'SWAP_STATA':");
130 return 1;
131 }
132 if (nswap != rnswap) {
133 warn("getstats: SWAP_STATS != SWAP_NSWAP");
134 return 1;
135 }
136
137 *total = 0;
138 *used = 0;
139
140 for (i = 0; i < rnswap; i++) {
141 *total += sep->se_nblks >> 1;
142 *used += sep->se_inuse >> 1;
143 }
144
145 free(fsep);
146
147 return 0;
148 }
149
150 const char *
151 swap_free(void)
152 {
153 int total, used;
154
155 if (getstats(&total, &used)) {
156 return NULL;
157 }
158
159 return fmt_human((total - used) * 1024, 1024);
160 }
161
162 const char *
163 swap_perc(void)
164 {
165 int total, used;
166
167 if (getstats(&total, &used)) {
168 return NULL;
169 }
170
171 if (total == 0) {
172 return NULL;
173 }
174
175 return bprintf("%d", 100 * used / total);
176 }
177
178 const char *
179 swap_total(void)
180 {
181 int total, used;
182
183 if (getstats(&total, &used)) {
184 return NULL;
185 }
186
187 return fmt_human(total * 1024, 1024);
188 }
189
190 const char *
191 swap_used(void)
192 {
193 int total, used;
194
195 if (getstats(&total, &used)) {
196 return NULL;
197 }
198
199 return fmt_human(used * 1024, 1024);
200 }
201 #endif