slstatus-diskio-1.0.patch - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
slstatus-diskio-1.0.patch (5892B)
---
1 From 42d644b1e4ba7d10654574c4225700c8a6a2507b Mon Sep 17 00:00:00 2001
2 From: Gene Carlson <kvngncrlsn@gmail.com>
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 %ju %*d",
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 (eth0)
235 * ipv6 IPv6 address interface name (eth0)
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