slstatus-diskio-1.0.patch - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
slstatus-diskio-1.0.patch (5892B) | |
--- | |
1 From 42d644b1e4ba7d10654574c4225700c8a6a2507b Mon Sep 17 00:00:00 2001 | |
2 From: Gene Carlson <[email protected]> | |
3 Date: Sun, 27 Aug 2023 14:06:10 +0900 | |
4 Subject: [PATCH] Add disk IO reporting for Linux systems (read, write, | |
5 percentage). | |
6 | |
7 --- | |
8 Makefile | 1 + | |
9 README | 1 + | |
10 components/iocheck.c | 177 +++++++++++++++++++++++++++++++++++++++++++ | |
11 config.def.h | 3 + | |
12 slstatus.h | 5 ++ | |
13 5 files changed, 187 insertions(+) | |
14 create mode 100644 components/iocheck.c | |
15 | |
16 diff --git a/Makefile b/Makefile | |
17 index 7a18274..75a94cb 100644 | |
18 --- a/Makefile | |
19 +++ b/Makefile | |
20 @@ -13,6 +13,7 @@ COM =\ | |
21 components/disk\ | |
22 components/entropy\ | |
23 components/hostname\ | |
24 + components/iocheck\ | |
25 components/ip\ | |
26 components/kernel_release\ | |
27 components/keyboard_indicators\ | |
28 diff --git a/README b/README | |
29 index 12d38bf..1be92c2 100644 | |
30 --- a/README | |
31 +++ b/README | |
32 @@ -18,6 +18,7 @@ Features | |
33 - Available entropy | |
34 - Username/GID/UID | |
35 - Hostname | |
36 +- Disk IO (read, write and percentage) (Linux only) | |
37 - IP address (IPv4 and IPv6) | |
38 - Kernel version | |
39 - Keyboard indicators | |
40 diff --git a/components/iocheck.c b/components/iocheck.c | |
41 new file mode 100644 | |
42 index 0000000..1bf027e | |
43 --- /dev/null | |
44 +++ b/components/iocheck.c | |
45 @@ -0,0 +1,177 @@ | |
46 +/* See LICENSE file for copyright and license details. */ | |
47 +#include <stdio.h> | |
48 +#include <string.h> | |
49 +#include <stdint.h> | |
50 +#include <stdlib.h> | |
51 +#include <dirent.h> | |
52 +#include <unistd.h> | |
53 + | |
54 +#include "../util.h" | |
55 + | |
56 +#if defined(__linux__) | |
57 + static int | |
58 + get_io(uintmax_t *s_in, uintmax_t *s_out) | |
59 + { | |
60 + FILE *fp; | |
61 + struct { | |
62 + const char *name; | |
63 + const size_t len; | |
64 + uintmax_t *var; | |
65 + } ent[] = { | |
66 + { "pgpgin", sizeof("pgpgin") - 1, s_in }, | |
67 + { "pgpgout", sizeof("pgpgout") - 1, s_out }, | |
68 + }; | |
69 + size_t line_len = 0, i, left; | |
70 + char *line = NULL; | |
71 + | |
72 + /* get number of fields we want to extract */ | |
73 + for (i = 0, left = 0; i < LEN(ent); i++) { | |
74 + if (ent[i].var) { | |
75 + left++; | |
76 + } | |
77 + } | |
78 + | |
79 + if (!(fp = fopen("/proc/vmstat", "r"))) { | |
80 + warn("fopen '/proc/vmstat':"); | |
81 + return 1; | |
82 + } | |
83 + | |
84 + /* read file line by line and extract field information… | |
85 + while (left > 0 && getline(&line, &line_len, fp) >= 0) { | |
86 + for (i = 0; i < LEN(ent); i++) { | |
87 + if (ent[i].var && | |
88 + !strncmp(line,ent[i].name, ent[i].len))… | |
89 + sscanf(line + ent[i].len + 1, | |
90 + "%ju\n", ent[i].var); | |
91 + left--; | |
92 + break; | |
93 + } | |
94 + } | |
95 + } | |
96 + free(line); | |
97 + if(ferror(fp)) { | |
98 + warn("getline '/proc/vmstat':"); | |
99 + return 1; | |
100 + } | |
101 + | |
102 + fclose(fp); | |
103 + return 0; | |
104 + } | |
105 + | |
106 + const char * | |
107 + io_in(void) | |
108 + { | |
109 + uintmax_t oldin; | |
110 + static uintmax_t newin; | |
111 + | |
112 + oldin = newin; | |
113 + | |
114 + if (get_io(&newin, NULL)) { | |
115 + return NULL; | |
116 + } | |
117 + if (oldin == 0) { | |
118 + return NULL; | |
119 + } | |
120 + | |
121 + return fmt_human((newin - oldin) * 1024, 1024); | |
122 + } | |
123 + | |
124 + const char * | |
125 + io_out(void) | |
126 + { | |
127 + uintmax_t oldout; | |
128 + static uintmax_t newout; | |
129 + | |
130 + oldout = newout; | |
131 + | |
132 + if (get_io(NULL, &newout)) { | |
133 + return NULL; | |
134 + } | |
135 + if (oldout == 0) { | |
136 + return NULL; | |
137 + } | |
138 + | |
139 + return fmt_human((newout - oldout) * 1024, 1024); | |
140 + } | |
141 + | |
142 + const char * | |
143 + io_perc(void) | |
144 + { | |
145 + struct dirent *dp; | |
146 + DIR *bd; | |
147 + uintmax_t oldwait; | |
148 + static uintmax_t newwait; | |
149 + extern const unsigned int interval; | |
150 + | |
151 + oldwait = newwait; | |
152 + | |
153 + if (!(bd = opendir("/sys/block"))) { | |
154 + warn("opendir '%s':", "/sys/block"); | |
155 + return NULL; | |
156 + } | |
157 + | |
158 + newwait = 0; | |
159 + /* get IO wait stats from the /sys/block directories */ | |
160 + while ((dp = readdir(bd))) { | |
161 + int devlen, chklen, statlen; | |
162 + devlen = strlen(dp->d_name); | |
163 + char devname[devlen]; | |
164 + strcpy(devname, dp->d_name); | |
165 + if (strstr(devname, "loop") || | |
166 + strstr(devname, "ram")) { | |
167 + continue; | |
168 + } | |
169 + if (!strcmp(devname, ".") || | |
170 + !strcmp(devname, "..")) { | |
171 + continue; | |
172 + } | |
173 + | |
174 + statlen = 16 + devlen; | |
175 + chklen = 18 + devlen; | |
176 + char statpath[statlen], chkpath[chklen]; | |
177 + strcpy(statpath, "/sys/block/"); | |
178 + strcat(statpath, devname); | |
179 + /* non-virtual devices only */ | |
180 + strcpy(chkpath, statpath); | |
181 + strcat(chkpath, "/device"); | |
182 + if (access(chkpath, F_OK) != 0) { | |
183 + continue; | |
184 + } | |
185 + | |
186 + strcat(statpath, "/stat"); | |
187 + uintmax_t partwait; | |
188 + if (pscanf(statpath, | |
189 + "%*d %*d %*d %*d %*d %*d %*d %*d %*d %j… | |
190 + &partwait) != 1) { | |
191 + continue; | |
192 + } | |
193 + newwait += partwait; | |
194 + } | |
195 + closedir(bd); | |
196 + if (oldwait == 0 || newwait < oldwait) { | |
197 + return NULL; | |
198 + } | |
199 + | |
200 + return bprintf("%0.1f", 100 * | |
201 + (newwait - oldwait) / (float)interval); | |
202 + } | |
203 + | |
204 +#else | |
205 + const char * | |
206 + io_in(void) | |
207 + { | |
208 + return NULL; | |
209 + } | |
210 + | |
211 + const char * | |
212 + io_out(void) | |
213 + { | |
214 + return NULL; | |
215 + } | |
216 + | |
217 + const char * | |
218 + io_perc(void) | |
219 + { | |
220 + return NULL; | |
221 + } | |
222 +#endif | |
223 diff --git a/config.def.h b/config.def.h | |
224 index d805331..b4e7b26 100644 | |
225 --- a/config.def.h | |
226 +++ b/config.def.h | |
227 @@ -29,6 +29,9 @@ static const char unknown_str[] = "n/a"; | |
228 * entropy available entropy NULL | |
229 * gid GID of current user NULL | |
230 * hostname hostname NULL | |
231 + * io_in disk IO (read) NULL | |
232 + * io_out disk IO (write) NULL | |
233 + * io_perc disk IO (percentage) NULL | |
234 * ipv4 IPv4 address interface name (… | |
235 * ipv6 IPv6 address interface name (… | |
236 * kernel_release `uname -r` NULL | |
237 diff --git a/slstatus.h b/slstatus.h | |
238 index 8ef5874..7c09fb4 100644 | |
239 --- a/slstatus.h | |
240 +++ b/slstatus.h | |
241 @@ -27,6 +27,11 @@ const char *entropy(const char *unused); | |
242 /* hostname */ | |
243 const char *hostname(const char *unused); | |
244 | |
245 +/* iocheck */ | |
246 +const char *io_in(const char *unused); | |
247 +const char *io_out(const char *unused); | |
248 +const char *io_perc(const char *unused); | |
249 + | |
250 /* ip */ | |
251 const char *ipv4(const char *interface); | |
252 const char *ipv6(const char *interface); | |
253 -- | |
254 2.42.0 | |
255 |