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