util.c 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include <err.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <stdarg.h>
  5. #include <string.h>
  6. #include "util.h"
  7. static inline int
  8. evsnprintf(char *str, size_t size, const char *fmt, va_list ap)
  9. {
  10. int ret;
  11. ret = vsnprintf(str, size, fmt, ap);
  12. if (ret < 0) {
  13. warn("vsnprintf");
  14. return -1;
  15. } else if ((size_t)ret >= size) {
  16. warnx("vsnprintf: Output truncated");
  17. return -1;
  18. }
  19. return ret;
  20. }
  21. void
  22. bprintf(char *buf, const char *fmt, ...)
  23. { /* buffer printf */
  24. va_list ap;
  25. va_start(ap, fmt);
  26. if (evsnprintf(buf, BUFF_SZ, fmt, ap) < 0) buf[0] = '\0';
  27. va_end(ap);
  28. }
  29. int
  30. pscanf(const char *path, const char *fmt, ...)
  31. { /* path scansf */
  32. int n;
  33. FILE * fp;
  34. va_list ap;
  35. if (!(fp = fopen(path, "r"))) {
  36. warn("fopen '%s'", path);
  37. return -1;
  38. }
  39. va_start(ap, fmt);
  40. n = vfscanf(fp, fmt, ap);
  41. va_end(ap);
  42. fclose(fp);
  43. return (n == EOF) ? -1 : n;
  44. }
  45. int
  46. esnprintf(char *str, size_t size, const char *fmt, ...)
  47. { /* snprintf with warn about truncating */
  48. va_list ap;
  49. int ret;
  50. va_start(ap, fmt);
  51. ret = evsnprintf(str, size, fmt, ap);
  52. va_end(ap);
  53. return ret;
  54. }
  55. void
  56. fmt_human(char *out, uintmax_t num, unsigned short int base)
  57. {
  58. double scaled;
  59. unsigned int i;
  60. const char ** prefix;
  61. const unsigned int prefixlen = 9;
  62. const char * prefix_1000[] = { "", "k", "M", "G", "T",
  63. "P", "E", "Z", "Y" };
  64. const char * prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti",
  65. "Pi", "Ei", "Zi", "Yi" };
  66. switch (base) {
  67. case 1000:
  68. prefix = prefix_1000;
  69. break;
  70. case 1024:
  71. prefix = prefix_1024;
  72. break;
  73. default:
  74. warn("fmt_human: Invalid base");
  75. ERRRET(out);
  76. }
  77. scaled = num;
  78. for (i = 0; i < prefixlen && scaled >= base; i++) {
  79. scaled /= base;
  80. }
  81. bprintf(out, "%.1f %s", scaled, prefix[i]);
  82. }