slstatus

status monitor
git clone git://git.suckless.org/slstatus
Log | Files | Refs | README | LICENSE

swap.c (5044B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <stdint.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include "../slstatus.h"
      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 		if (!(fp = fopen("/proc/meminfo", "r"))) {
     33 			warn("fopen '/proc/meminfo':");
     34 			return 1;
     35 		}
     36 
     37 		/* read file line by line and extract field information */
     38 		while (left > 0 && getline(&line, &line_len, fp) >= 0) {
     39 			for (i = 0; i < LEN(ent); i++) {
     40 				if (ent[i].var &&
     41 				    !strncmp(line, ent[i].name, ent[i].len)) {
     42 					sscanf(line + ent[i].len + 1,
     43 					       "%ld kB\n", ent[i].var);
     44 					left--;
     45 					break;
     46 				}
     47 			}
     48 		}
     49 		free(line);
     50 		if (ferror(fp)) {
     51 			warn("getline '/proc/meminfo':");
     52 			return 1;
     53 		}
     54 
     55 		fclose(fp);
     56 		return 0;
     57 	}
     58 
     59 	const char *
     60 	swap_free(const char *unused)
     61 	{
     62 		long free;
     63 
     64 		if (get_swap_info(NULL, &free, NULL))
     65 			return NULL;
     66 
     67 		return fmt_human(free * 1024, 1024);
     68 	}
     69 
     70 	const char *
     71 	swap_perc(const char *unused)
     72 	{
     73 		long total, free, cached;
     74 
     75 		if (get_swap_info(&total, &free, &cached) || total == 0)
     76 			return NULL;
     77 
     78 		return bprintf("%d", 100 * (total - free - cached) / total);
     79 	}
     80 
     81 	const char *
     82 	swap_total(const char *unused)
     83 	{
     84 		long total;
     85 
     86 		if (get_swap_info(&total, NULL, NULL))
     87 			return NULL;
     88 
     89 		return fmt_human(total * 1024, 1024);
     90 	}
     91 
     92 	const char *
     93 	swap_used(const char *unused)
     94 	{
     95 		long total, free, cached;
     96 
     97 		if (get_swap_info(&total, &free, &cached))
     98 			return NULL;
     99 
    100 		return fmt_human((total - free - cached) * 1024, 1024);
    101 	}
    102 #elif defined(__OpenBSD__)
    103 	#include <stdlib.h>
    104 	#include <sys/swap.h>
    105 	#include <sys/types.h>
    106 	#include <unistd.h>
    107 
    108 	static int
    109 	getstats(int *total, int *used)
    110 	{
    111 		struct swapent *sep, *fsep;
    112 		int rnswap, nswap, i;
    113 
    114 		if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) {
    115 			warn("swaptctl 'SWAP_NSWAP':");
    116 			return 1;
    117 		}
    118 		if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) {
    119 			warn("calloc 'nswap':");
    120 			return 1;
    121 		}
    122 		if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) {
    123 			warn("swapctl 'SWAP_STATA':");
    124 			return 1;
    125 		}
    126 		if (nswap != rnswap) {
    127 			warn("getstats: SWAP_STATS != SWAP_NSWAP");
    128 			return 1;
    129 		}
    130 
    131 		*total = 0;
    132 		*used = 0;
    133 
    134 		for (i = 0; i < rnswap; i++) {
    135 			*total += sep->se_nblks >> 1;
    136 			*used += sep->se_inuse >> 1;
    137 		}
    138 
    139 		free(fsep);
    140 
    141 		return 0;
    142 	}
    143 
    144 	const char *
    145 	swap_free(const char *unused)
    146 	{
    147 		int total, used;
    148 
    149 		if (getstats(&total, &used))
    150 			return NULL;
    151 
    152 		return fmt_human((total - used) * 1024, 1024);
    153 	}
    154 
    155 	const char *
    156 	swap_perc(const char *unused)
    157 	{
    158 		int total, used;
    159 
    160 		if (getstats(&total, &used))
    161 			return NULL;
    162 
    163 		if (total == 0)
    164 			return NULL;
    165 
    166 		return bprintf("%d", 100 * used / total);
    167 	}
    168 
    169 	const char *
    170 	swap_total(const char *unused)
    171 	{
    172 		int total, used;
    173 
    174 		if (getstats(&total, &used))
    175 			return NULL;
    176 
    177 		return fmt_human(total * 1024, 1024);
    178 	}
    179 
    180 	const char *
    181 	swap_used(const char *unused)
    182 	{
    183 		int total, used;
    184 
    185 		if (getstats(&total, &used))
    186 			return NULL;
    187 
    188 		return fmt_human(used * 1024, 1024);
    189 	}
    190 #elif defined(__FreeBSD__)
    191 	#include <fcntl.h>
    192 	#include <kvm.h>
    193 	#include <stdlib.h>
    194 	#include <sys/types.h>
    195 	#include <unistd.h>
    196 
    197 	static int getswapinfo(struct kvm_swap *swap_info, size_t size)
    198 	{
    199 		kvm_t *kd;
    200 
    201 		kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, NULL);
    202 		if (kd == NULL) {
    203 			warn("kvm_openfiles '/dev/null':");
    204 			return 0;
    205 		}
    206 
    207 		if (kvm_getswapinfo(kd, swap_info, size, 0 /* Unused flags */) < 0) {
    208 			warn("kvm_getswapinfo:");
    209 			kvm_close(kd);
    210 			return 0;
    211 		}
    212 
    213 		kvm_close(kd);
    214 		return 1;
    215 	}
    216 
    217 	const char *
    218 	swap_free(const char *unused)
    219 	{
    220 		struct kvm_swap swap_info[1];
    221 		long used, total;
    222 
    223 		if (!getswapinfo(swap_info, 1))
    224 			return NULL;
    225 
    226 		total = swap_info[0].ksw_total;
    227 		used = swap_info[0].ksw_used;
    228 
    229 		return fmt_human((total - used) * getpagesize(), 1024);
    230 	}
    231 
    232 	const char *
    233 	swap_perc(const char *unused)
    234 	{
    235 		struct kvm_swap swap_info[1];
    236 		long used, total;
    237 
    238 		if (!getswapinfo(swap_info, 1))
    239 			return NULL;
    240 
    241 		total = swap_info[0].ksw_total;
    242 		used = swap_info[0].ksw_used;
    243 
    244 		return bprintf("%d", used * 100 / total);
    245 	}
    246 
    247 	const char *
    248 	swap_total(const char *unused)
    249 	{
    250 		struct kvm_swap swap_info[1];
    251 		long total;
    252 
    253 		if (!getswapinfo(swap_info, 1))
    254 			return NULL;
    255 
    256 		total = swap_info[0].ksw_total;
    257 
    258 		return fmt_human(total * getpagesize(), 1024);
    259 	}
    260 
    261 	const char *
    262 	swap_used(const char *unused)
    263 	{
    264 		struct kvm_swap swap_info[1];
    265 		long used;
    266 
    267 		if (!getswapinfo(swap_info, 1))
    268 			return NULL;
    269 
    270 		used = swap_info[0].ksw_used;
    271 
    272 		return fmt_human(used * getpagesize(), 1024);
    273 	}
    274 #endif