util.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /* See LICENSE file for copyright and license details. */
  2. #include <errno.h>
  3. #include <stdarg.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "util.h"
  9. char *argv0;
  10. static void
  11. verr(const char *fmt, va_list ap)
  12. {
  13. if (argv0 && strncmp(fmt, "usage", sizeof("usage") - 1)) {
  14. fprintf(stderr, "%s: ", argv0);
  15. }
  16. vfprintf(stderr, fmt, ap);
  17. if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
  18. fputc(' ', stderr);
  19. perror(NULL);
  20. } else {
  21. fputc('\n', stderr);
  22. }
  23. }
  24. void
  25. warn(const char *fmt, ...)
  26. {
  27. va_list ap;
  28. va_start(ap, fmt);
  29. verr(fmt, ap);
  30. va_end(ap);
  31. }
  32. void
  33. die(const char *fmt, ...)
  34. {
  35. va_list ap;
  36. va_start(ap, fmt);
  37. verr(fmt, ap);
  38. va_end(ap);
  39. exit(1);
  40. }
  41. static int
  42. evsnprintf(char *str, size_t size, const char *fmt, va_list ap)
  43. {
  44. int ret;
  45. ret = vsnprintf(str, size, fmt, ap);
  46. if (ret < 0) {
  47. warn("vsnprintf:");
  48. return -1;
  49. } else if ((size_t)ret >= size) {
  50. warn("vsnprintf: Output truncated");
  51. return -1;
  52. }
  53. return ret;
  54. }
  55. int
  56. esnprintf(char *str, size_t size, const char *fmt, ...)
  57. {
  58. va_list ap;
  59. int ret;
  60. va_start(ap, fmt);
  61. ret = evsnprintf(str, size, fmt, ap);
  62. va_end(ap);
  63. return ret;
  64. }
  65. const char *
  66. bprintf(const char *fmt, ...)
  67. {
  68. va_list ap;
  69. int ret;
  70. va_start(ap, fmt);
  71. ret = evsnprintf(buf, sizeof(buf), fmt, ap);
  72. va_end(ap);
  73. return (ret < 0) ? NULL : buf;
  74. }
  75. const char *
  76. fmt_human(uintmax_t num, int base)
  77. {
  78. double scaled;
  79. size_t i, prefixlen;
  80. const char **prefix;
  81. const char *prefix_1000[] = { "", "k", "M", "G", "T", "P", "E", "Z",
  82. "Y" };
  83. const char *prefix_1024[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei",
  84. "Zi", "Yi" };
  85. switch (base) {
  86. case 1000:
  87. prefix = prefix_1000;
  88. prefixlen = LEN(prefix_1000);
  89. break;
  90. case 1024:
  91. prefix = prefix_1024;
  92. prefixlen = LEN(prefix_1024);
  93. break;
  94. default:
  95. warn("fmt_human: Invalid base");
  96. return NULL;
  97. }
  98. scaled = num;
  99. for (i = 0; i < prefixlen && scaled >= base; i++) {
  100. scaled /= base;
  101. }
  102. return bprintf("%.1f %s", scaled, prefix[i]);
  103. }
  104. int
  105. pscanf(const char *path, const char *fmt, ...)
  106. {
  107. FILE *fp;
  108. va_list ap;
  109. int n;
  110. if (!(fp = fopen(path, "r"))) {
  111. warn("fopen '%s':", path);
  112. return -1;
  113. }
  114. va_start(ap, fmt);
  115. n = vfscanf(fp, fmt, ap);
  116. va_end(ap);
  117. fclose(fp);
  118. return (n == EOF) ? -1 : n;
  119. }