util.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #include <err.h>
  2. #include <fcntl.h>
  3. #include <stdio.h>
  4. #include <stdint.h>
  5. #include <stdarg.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. #include "util.h"
  9. #include "numfmt.h"
  10. #include "../components_config.h"
  11. #ifndef FMT_HUMAN_NUMFMT
  12. # define FMT_HUMAN_NUMFMT NUMFMT_IEC
  13. #endif
  14. static inline int
  15. evsnprintf(char *str, size_t size, const char *fmt, va_list ap)
  16. {
  17. int ret;
  18. ret = vsnprintf(str, size, fmt, ap);
  19. if (ret < 0) {
  20. warn("vsnprintf");
  21. return -1;
  22. } else if ((size_t)ret >= size) {
  23. warnx("vsnprintf: Output truncated");
  24. return -1;
  25. }
  26. return ret;
  27. }
  28. void
  29. bprintf(char *buf, const char *fmt, ...)
  30. {
  31. va_list ap;
  32. va_start(ap, fmt);
  33. if (evsnprintf(buf, BUFF_SZ, fmt, ap) < 0) *buf = '\0';
  34. va_end(ap);
  35. }
  36. void
  37. fmt_human(char *out, uintmax_t num)
  38. {
  39. uint8_t i;
  40. double scaled;
  41. const char *prefix[] =
  42. #if FMT_HUMAN_NUMFMT == NUMFMT_IEC
  43. { "",
  44. "Ki",
  45. "Mi",
  46. "Gi",
  47. "Ti",
  48. "Pi",
  49. "Ei",
  50. "Zi",
  51. "Yi" }
  52. #elif FMT_HUMAN_NUMFMT == NUMFMT_SI
  53. { "",
  54. "k",
  55. "M",
  56. "G",
  57. "T",
  58. "P",
  59. "E",
  60. "Z",
  61. "Y" }
  62. #else
  63. # error invalid FMT_HUMAN_NUMFMT
  64. #endif
  65. ;
  66. SAFE_ASSIGN(scaled, num);
  67. for (i = 0; i < LEN(prefix) && scaled >= FMT_HUMAN_NUMFMT; i++)
  68. scaled /= FMT_HUMAN_NUMFMT;
  69. bprintf(out, "%.1f %s", scaled, prefix[i]);
  70. }
  71. int
  72. _sysfs_fd(const char *func,
  73. const char *path,
  74. const char *device,
  75. const char *property)
  76. {
  77. uint8_t i;
  78. int fds[3] = { -1, -1, -1 };
  79. int *path_fd = &fds[0], *device_fd = &fds[1], *property_fd = &fds[2];
  80. if ((*path_fd = _eopen(func,
  81. path,
  82. WITH_STR(O_RDONLY | O_CLOEXEC | O_DIRECTORY)))
  83. == -1)
  84. goto end;
  85. if ((*device_fd =
  86. _eopenat(func,
  87. *path_fd,
  88. device,
  89. WITH_STR(O_RDONLY | O_CLOEXEC | O_DIRECTORY)))
  90. == -1)
  91. goto end;
  92. if (!!property) {
  93. if ((*property_fd = _eopenat(func,
  94. *device_fd,
  95. property,
  96. WITH_STR(O_RDONLY | O_CLOEXEC)))
  97. == -1)
  98. goto end;
  99. } else {
  100. *property_fd = *device_fd;
  101. *device_fd = -1;
  102. }
  103. end:
  104. for (i = 0; i < (LEN(fds) - 1 /* except last */); i++)
  105. if (fds[i] >= 0) _eclose(func, fds[i]);
  106. return *property_fd;
  107. }
  108. uint8_t
  109. _sysfs_fd_or_rewind(const char *func,
  110. int * fd,
  111. const char *path,
  112. const char *device,
  113. const char *property)
  114. {
  115. if (*fd > 0) return _fd_rewind(func, *fd);
  116. if ((*fd = _sysfs_fd(func, path, device, property)) != -1) return !0;
  117. return 0;
  118. }
  119. int
  120. _eopen(const char *func, const char *path, int flags, const char *sflags)
  121. {
  122. int fd;
  123. if ((fd = open(path, flags)) == -1)
  124. warn("%s: open(" QUOTED("%s") ", %s)", func, path, sflags);
  125. return fd;
  126. }
  127. int
  128. _eopenat(
  129. const char *func, int fd, const char *path, int flags, const char *sflags)
  130. {
  131. int new_fd;
  132. if ((new_fd = openat(fd, path, flags)) == -1)
  133. warn("%s: openat(%d, " QUOTED("%s") ", %s)",
  134. func,
  135. fd,
  136. path,
  137. sflags);
  138. return new_fd;
  139. }
  140. off_t
  141. _elseek(const char *func, int fd, off_t offset, int whence)
  142. {
  143. off_t ret;
  144. if ((ret = lseek(fd, offset, whence)) == (off_t)-1)
  145. warn("%s: lseek(%d, %ld, %d)", func, fd, offset, whence);
  146. return ret;
  147. }
  148. uint8_t
  149. _fd_rewind(const char *func, int fd)
  150. {
  151. return _elseek(func, fd, 0, SEEK_SET) != (off_t)-1;
  152. }
  153. ssize_t
  154. _eread(const char *func, int fd, void *buf, size_t size)
  155. {
  156. ssize_t ret;
  157. if ((ret = read(fd, buf, size)) == -1)
  158. warn("%s: read(%d, %p, %lu)", func, fd, buf, size);
  159. return ret;
  160. }
  161. uint8_t
  162. _eclose(const char *func, int fd)
  163. {
  164. uint8_t ret;
  165. if (!(ret = (close(fd) != -1))) warn("%s: close(%d)", func, fd);
  166. return ret;
  167. }
  168. uint8_t
  169. _esscanf(const char *func,
  170. int count,
  171. const char *restrict str,
  172. const char *restrict fmt,
  173. ...)
  174. {
  175. va_list ap;
  176. int err;
  177. __typeof__(count) match = 0;
  178. va_start(ap, fmt);
  179. errno = 0;
  180. match = vsscanf(str, fmt, ap);
  181. err = errno;
  182. va_end(ap);
  183. if (match == count)
  184. return !0;
  185. else if (err != 0)
  186. warn("%s: sscanf(%p, " QUOTED("%s") ", ...)", func, str, fmt);
  187. else
  188. warnx("%s: sscnaf(fmt: " QUOTED("%s") "): matched %d of %d",
  189. func,
  190. fmt,
  191. match,
  192. count);
  193. return 0;
  194. }
  195. void
  196. fd_cleanup(void *ptr)
  197. {
  198. int fd = *((int *)ptr);
  199. if (fd > 0) eclose(fd);
  200. }