Xinqi Bao's Git

Refactor swap.c to use getline() instead of buf-filling
[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/param.h> /* dbtob */
111 #include <sys/swap.h>
112 #include <sys/types.h>
113 #include <unistd.h>
114
115 static int
116 getstats(int *total, int *used)
117 {
118 struct swapent *sep, *fsep;
119 int rnswap, nswap, i;
120
121 if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) {
122 warn("swaptctl 'SWAP_NSWAP':");
123 return 1;
124 }
125 if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) {
126 warn("calloc 'nswap':");
127 return 1;
128 }
129 if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) {
130 warn("swapctl 'SWAP_STATA':");
131 return 1;
132 }
133 if (nswap != rnswap) {
134 warn("getstats: SWAP_STATS != SWAP_NSWAP");
135 return 1;
136 }
137
138 *total = 0;
139 *used = 0;
140
141 for (i = 0; i < rnswap; i++) {
142 *total += sep->se_nblks >> 1;
143 *used += sep->se_inuse >> 1;
144 }
145
146 free(fsep);
147
148 return 0;
149 }
150
151 const char *
152 swap_free(void)
153 {
154 int total, used;
155
156 if (getstats(&total, &used)) {
157 return NULL;
158 }
159
160 return fmt_human((total - used) * 1024, 1024);
161 }
162
163 const char *
164 swap_perc(void)
165 {
166 int total, used;
167
168 if (getstats(&total, &used)) {
169 return NULL;
170 }
171
172 if (total == 0) {
173 return NULL;
174 }
175
176 return bprintf("%d", 100 * used / total);
177 }
178
179 const char *
180 swap_total(void)
181 {
182 int total, used;
183
184 if (getstats(&total, &used)) {
185 return NULL;
186 }
187
188 return fmt_human(total * 1024, 1024);
189 }
190
191 const char *
192 swap_used(void)
193 {
194 int total, used;
195
196 if (getstats(&total, &used)) {
197 return NULL;
198 }
199
200 return fmt_human(used * 1024, 1024);
201 }
202 #endif