A tool for adding anime to your anidb list.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
3.8KB

  1. #define _XOPEN_SOURCE 500
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <assert.h>
  6. #include <errno.h>
  7. #include <sys/stat.h>
  8. #include <ftw.h>
  9. #include "util.h"
  10. #include "error.h"
  11. #include "uio.h"
  12. void util_byte2hex(const uint8_t* bytes, size_t bytes_len,
  13. bool uppercase, char* out)
  14. {
  15. const char* hex = (uppercase) ? "0123456789ABCDEF" : "0123456789abcdef";
  16. for (size_t i = 0; i < bytes_len; i++) {
  17. *out++ = hex[bytes[i] >> 4];
  18. *out++ = hex[bytes[i] & 0xF];
  19. }
  20. *out = '\0';
  21. }
  22. void util_hex2byte(const char *str, uint8_t* out_bytes)
  23. {
  24. while (*str) {
  25. if (*str >= '0' && *str <= '9')
  26. *out_bytes = (*str - '0') << 4;
  27. if (*str >= 'A' && *str <= 'F')
  28. *out_bytes = (*str - ('A' - 10)) << 4;
  29. else
  30. *out_bytes = (*str - ('a' - 10)) << 4;
  31. str++;
  32. if (*str >= '0' && *str <= '9')
  33. *out_bytes |= (*str - '0');
  34. if (*str >= 'A' && *str <= 'F')
  35. *out_bytes |= (*str - ('A' - 10));
  36. else
  37. *out_bytes |= (*str - ('a' - 10));
  38. out_bytes++;
  39. str++;
  40. }
  41. }
  42. const char *util_get_home()
  43. {
  44. const char *home_env = getenv("HOME");
  45. return home_env; /* TODO this can be null, use other methods as fallback */
  46. }
  47. char *util_basename(const char *fullpath)
  48. {
  49. char *name_part = strrchr(fullpath, '/');
  50. if (name_part)
  51. name_part++;
  52. else
  53. name_part = (char*)fullpath;
  54. return name_part;
  55. }
  56. uint64_t util_timespec_diff(const struct timespec *past,
  57. const struct timespec *future)
  58. {
  59. int64_t sdiff = future->tv_sec - past->tv_sec;
  60. int64_t nsdiff = future->tv_nsec - past->tv_nsec;
  61. return sdiff * 1000 + (nsdiff / 1000000);
  62. }
  63. uint64_t util_iso2unix(const char *isotime)
  64. {
  65. struct tm tm = {0};
  66. char *ms = strptime(isotime, "%Y-%m-%d", &tm);
  67. if (!ms || (*ms != '\0' && *ms != ' ' && *ms != 'T'))
  68. return 0;
  69. if (*ms == '\0')
  70. ms = "T00:00:00";
  71. ms = strptime(ms + 1, "%H:%M", &tm);
  72. if (!ms || (*ms != '\0' && *ms != ':'))
  73. return 0;
  74. if (*ms == '\0')
  75. ms = ":00";
  76. ms = strptime(ms + 1, "%S", &tm);
  77. if (!ms)
  78. return 0;
  79. return mktime(&tm);
  80. }
  81. /* nftw doesn't support passing in user data to the callback function :/ */
  82. static util_itercb global_iterpath_cb = NULL;
  83. static void *global_iterpath_data = NULL;
  84. static int util_iterpath_walk(const char *fpath, const struct stat *sb,
  85. int typeflag, struct FTW *ftwbuf)
  86. {
  87. if (typeflag == FTW_DNR) {
  88. uio_error("Cannot read directory '%s'. Skipping", fpath);
  89. return NOERR;
  90. }
  91. if (typeflag == FTW_D)
  92. return NOERR;
  93. if (typeflag != FTW_F) {
  94. uio_error("Unhandled error '%d'", typeflag);
  95. return ERR_ITERPATH;
  96. }
  97. return global_iterpath_cb(fpath, sb, global_iterpath_data);
  98. }
  99. enum error util_iterpath(const char *path, util_itercb cb, void *data)
  100. {
  101. assert(global_iterpath_cb == NULL);
  102. enum error ret = ERR_ITERPATH;
  103. struct stat ts;
  104. if (stat(path, &ts) != 0) {
  105. uio_error("Stat failed for path: '%s' (%s)",
  106. path, strerror(errno));
  107. goto error;
  108. }
  109. if (S_ISREG(ts.st_mode)) {
  110. /* If the path is a regular file, call the cb once */
  111. ret = cb(path, &ts, data);
  112. goto end;
  113. } else if (S_ISDIR(ts.st_mode)) {
  114. global_iterpath_cb = cb;
  115. global_iterpath_data = data;
  116. /* If a directory, walk over it */
  117. ret = nftw(path, util_iterpath_walk, 20, 0);
  118. if (ret == -1) {
  119. uio_error("nftw failure");
  120. goto error;
  121. }
  122. goto end;
  123. }
  124. uio_error("Unsupported file type: %d", ts.st_mode & S_IFMT);
  125. end:
  126. global_iterpath_cb = global_iterpath_data = NULL;
  127. return ret;
  128. error:
  129. ret = ERR_ITERPATH;
  130. goto end;
  131. }