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