meminfo.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include <err.h>
  2. #include <errno.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include "util.h"
  6. #include "meminfo.h"
  7. #define READLINE_SIZE BUFSIZ
  8. /* clang-format off */
  9. #define MYFILE_INIT(FD) { .fd = (FD), .pos = 0 }
  10. #define MYBUF_INIT { .pos = 0, .size = 0, .last_nl = 0, .data = {0} }
  11. /* clang-format on */
  12. struct myfile {
  13. int fd;
  14. size_t pos;
  15. };
  16. struct mybuf {
  17. size_t pos;
  18. size_t size /* size of valid data */;
  19. size_t last_nl /* last '\n' char in 0..size */;
  20. char data[READLINE_SIZE];
  21. };
  22. enum read_line_status {
  23. END = EOF,
  24. ERR = 0,
  25. OK = !0,
  26. };
  27. static enum read_line_status
  28. read_line(struct myfile *file, struct mybuf *line_buf, char **line);
  29. uint8_t
  30. read_meminfo(int fd, const char *key, memory_t *val)
  31. /* read single field from meminfo */
  32. {
  33. char * line;
  34. uint8_t found = 0;
  35. size_t key_len = strlen(key);
  36. struct mybuf buf = MYBUF_INIT;
  37. struct myfile file = MYFILE_INIT(fd);
  38. while (read_line(&file, &buf, &line) == OK) {
  39. if (!strncmp(line, key, key_len)) {
  40. if (!esscanf(1,
  41. line + key_len + 1,
  42. memory_t_format,
  43. val))
  44. return 0;
  45. found = !0;
  46. break;
  47. }
  48. }
  49. return found;
  50. }
  51. uint8_t
  52. read_meminfo_keys(int fd, const struct meminfo_field *info, size_t size)
  53. {
  54. char * line;
  55. uint8_t readed = 0;
  56. struct mybuf buf = MYBUF_INIT;
  57. struct myfile file = MYFILE_INIT(fd);
  58. while (read_line(&file, &buf, &line) == OK && readed < size) {
  59. if (!strncmp(line, info[readed].key, info[readed].key_len)) {
  60. if (!esscanf(1,
  61. line + info[readed].key_len + 1,
  62. memory_t_format,
  63. info[readed].value_ptr))
  64. goto end_while;
  65. readed++;
  66. }
  67. end_while:
  68. continue;
  69. }
  70. return readed;
  71. }
  72. uint8_t
  73. get_meminfo_ram(int fd, struct meminfo_ram *info)
  74. {
  75. const struct meminfo_field fields[] =
  76. MEMINFO_INIT_RAM_FIELDS(&info->total,
  77. &info->free,
  78. &info->available,
  79. &info->buffers,
  80. &info->cached,
  81. &info->shared,
  82. &info->reclaimable);
  83. return read_meminfo_keys(fd, fields, LEN(fields)) == LEN(fields);
  84. }
  85. uint8_t
  86. get_meminfo_swap(int fd, struct meminfo_swap *info)
  87. {
  88. const struct meminfo_field fields[] =
  89. MEMINFO_INIT_SWAP_FIELDS(&info->cached, &info->total, &info->free);
  90. return read_meminfo_keys(fd, fields, LEN(fields)) == LEN(fields);
  91. }
  92. static inline enum read_line_status
  93. read_line(struct myfile *file, struct mybuf *buf, char **line)
  94. {
  95. __typeof__(buf->size) i;
  96. if (buf->pos >= buf->last_nl) {
  97. reread:
  98. buf->pos = !!buf->pos; /* if not first read, skip last '\n' */
  99. if (!!buf->last_nl)
  100. lseek(file->fd,
  101. (off_t)(file->pos -= (buf->size - buf->last_nl)),
  102. SEEK_SET);
  103. if (!eread_ret(buf->size, file->fd, WITH_LEN(buf->data)))
  104. return ERR;
  105. if (!buf->size) return END;
  106. file->pos += buf->size;
  107. for (i = 0; i < buf->size; i++)
  108. if (buf->data[i] == '\n') buf->last_nl = i;
  109. *line = buf->data + buf->pos;
  110. return OK;
  111. } else {
  112. for (; buf->pos <= buf->last_nl; buf->pos++) {
  113. if (buf->data[buf->pos] == '\n') {
  114. /* if at last '\n' try to reread next data */
  115. if (buf->pos == buf->last_nl) goto reread;
  116. *line = buf->data + ++buf->pos;
  117. return OK;
  118. }
  119. }
  120. }
  121. return ERR;
  122. }