swap.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. #include "../slstatus.h"
  7. #include "../util.h"
  8. #if defined(__linux__)
  9. static int
  10. get_swap_info(long *s_total, long *s_free, long *s_cached)
  11. {
  12. FILE *fp;
  13. struct {
  14. const char *name;
  15. const size_t len;
  16. long *var;
  17. } ent[] = {
  18. { "SwapTotal", sizeof("SwapTotal") - 1, s_total },
  19. { "SwapFree", sizeof("SwapFree") - 1, s_free },
  20. { "SwapCached", sizeof("SwapCached") - 1, s_cached },
  21. };
  22. size_t line_len = 0, i, left;
  23. char *line = NULL;
  24. /* get number of fields we want to extract */
  25. for (i = 0, left = 0; i < LEN(ent); i++)
  26. if (ent[i].var)
  27. left++;
  28. if (!(fp = fopen("/proc/meminfo", "r"))) {
  29. warn("fopen '/proc/meminfo':");
  30. return 1;
  31. }
  32. /* read file line by line and extract field information */
  33. while (left > 0 && getline(&line, &line_len, fp) >= 0) {
  34. for (i = 0; i < LEN(ent); i++) {
  35. if (ent[i].var &&
  36. !strncmp(line, ent[i].name, ent[i].len)) {
  37. sscanf(line + ent[i].len + 1,
  38. "%ld kB\n", ent[i].var);
  39. left--;
  40. break;
  41. }
  42. }
  43. }
  44. free(line);
  45. if (ferror(fp)) {
  46. warn("getline '/proc/meminfo':");
  47. return 1;
  48. }
  49. fclose(fp);
  50. return 0;
  51. }
  52. const char *
  53. swap_free(const char *unused)
  54. {
  55. long free;
  56. if (get_swap_info(NULL, &free, NULL))
  57. return NULL;
  58. return fmt_human(free * 1024, 1024);
  59. }
  60. const char *
  61. swap_perc(const char *unused)
  62. {
  63. long total, free, cached;
  64. if (get_swap_info(&total, &free, &cached) || total == 0)
  65. return NULL;
  66. return bprintf("%d", 100 * (total - free - cached) / total);
  67. }
  68. const char *
  69. swap_total(const char *unused)
  70. {
  71. long total;
  72. if (get_swap_info(&total, NULL, NULL))
  73. return NULL;
  74. return fmt_human(total * 1024, 1024);
  75. }
  76. const char *
  77. swap_used(const char *unused)
  78. {
  79. long total, free, cached;
  80. if (get_swap_info(&total, &free, &cached))
  81. return NULL;
  82. return fmt_human((total - free - cached) * 1024, 1024);
  83. }
  84. #elif defined(__OpenBSD__)
  85. #include <stdlib.h>
  86. #include <sys/swap.h>
  87. #include <sys/types.h>
  88. #include <unistd.h>
  89. static int
  90. getstats(int *total, int *used)
  91. {
  92. struct swapent *sep, *fsep;
  93. int rnswap, nswap, i;
  94. if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) < 1) {
  95. warn("swaptctl 'SWAP_NSWAP':");
  96. return 1;
  97. }
  98. if (!(fsep = sep = calloc(nswap, sizeof(*sep)))) {
  99. warn("calloc 'nswap':");
  100. return 1;
  101. }
  102. if ((rnswap = swapctl(SWAP_STATS, (void *)sep, nswap)) < 0) {
  103. warn("swapctl 'SWAP_STATA':");
  104. return 1;
  105. }
  106. if (nswap != rnswap) {
  107. warn("getstats: SWAP_STATS != SWAP_NSWAP");
  108. return 1;
  109. }
  110. *total = 0;
  111. *used = 0;
  112. for (i = 0; i < rnswap; i++) {
  113. *total += sep->se_nblks >> 1;
  114. *used += sep->se_inuse >> 1;
  115. }
  116. free(fsep);
  117. return 0;
  118. }
  119. const char *
  120. swap_free(const char *unused)
  121. {
  122. int total, used;
  123. if (getstats(&total, &used))
  124. return NULL;
  125. return fmt_human((total - used) * 1024, 1024);
  126. }
  127. const char *
  128. swap_perc(const char *unused)
  129. {
  130. int total, used;
  131. if (getstats(&total, &used))
  132. return NULL;
  133. if (total == 0)
  134. return NULL;
  135. return bprintf("%d", 100 * used / total);
  136. }
  137. const char *
  138. swap_total(const char *unused)
  139. {
  140. int total, used;
  141. if (getstats(&total, &used))
  142. return NULL;
  143. return fmt_human(total * 1024, 1024);
  144. }
  145. const char *
  146. swap_used(const char *unused)
  147. {
  148. int total, used;
  149. if (getstats(&total, &used))
  150. return NULL;
  151. return fmt_human(used * 1024, 1024);
  152. }
  153. #elif defined(__FreeBSD__)
  154. #include <fcntl.h>
  155. #include <kvm.h>
  156. #include <stdlib.h>
  157. #include <sys/types.h>
  158. #include <unistd.h>
  159. static int getswapinfo(struct kvm_swap *swap_info, size_t size)
  160. {
  161. kvm_t *kd;
  162. kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, NULL);
  163. if (kd == NULL) {
  164. warn("kvm_openfiles '/dev/null':");
  165. return 0;
  166. }
  167. if (kvm_getswapinfo(kd, swap_info, size, 0 /* Unused flags */) < 0) {
  168. warn("kvm_getswapinfo:");
  169. kvm_close(kd);
  170. return 0;
  171. }
  172. kvm_close(kd);
  173. return 1;
  174. }
  175. const char *
  176. swap_free(const char *unused)
  177. {
  178. struct kvm_swap swap_info[1];
  179. long used, total;
  180. if (!getswapinfo(swap_info, 1))
  181. return NULL;
  182. total = swap_info[0].ksw_total;
  183. used = swap_info[0].ksw_used;
  184. return fmt_human((total - used) * getpagesize(), 1024);
  185. }
  186. const char *
  187. swap_perc(const char *unused)
  188. {
  189. struct kvm_swap swap_info[1];
  190. long used, total;
  191. if (!getswapinfo(swap_info, 1))
  192. return NULL;
  193. total = swap_info[0].ksw_total;
  194. used = swap_info[0].ksw_used;
  195. return bprintf("%d", used * 100 / total);
  196. }
  197. const char *
  198. swap_total(const char *unused)
  199. {
  200. struct kvm_swap swap_info[1];
  201. long total;
  202. if (!getswapinfo(swap_info, 1))
  203. return NULL;
  204. total = swap_info[0].ksw_total;
  205. return fmt_human(total * getpagesize(), 1024);
  206. }
  207. const char *
  208. swap_used(const char *unused)
  209. {
  210. struct kvm_swap swap_info[1];
  211. long used;
  212. if (!getswapinfo(swap_info, 1))
  213. return NULL;
  214. used = swap_info[0].ksw_used;
  215. return fmt_human(used * getpagesize(), 1024);
  216. }
  217. #endif