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.

94 lines
2.3KB

  1. #define _XOPEN_SOURCE 500
  2. #include <sys/stat.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <ftw.h>
  6. #include "ed2k.h"
  7. #include "ed2k_util.h"
  8. #include "uio.h"
  9. static struct ed2k_util_opts l_opts;
  10. static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
  11. const struct stat *st)
  12. {
  13. unsigned char buf[blksize], hash[ED2K_HASH_SIZE];
  14. struct ed2k_ctx ed2k;
  15. FILE *f;
  16. size_t read_len;
  17. if (l_opts.pre_hash_fn) {
  18. enum error err = l_opts.pre_hash_fn(file_path, st, l_opts.data);
  19. if (err == ED2KUTIL_DONTHASH)
  20. return NOERR;
  21. else if (err != NOERR)
  22. return err;
  23. }
  24. f = fopen(file_path, "rb");
  25. if (!f) {
  26. uio_error("Failed to open file: %s (%s)", file_path, strerror(errno));
  27. return ERR_ED2KUTIL_FS;
  28. }
  29. ed2k_init(&ed2k);
  30. read_len = fread(buf, 1, sizeof(buf), f);
  31. while (read_len > 0) {
  32. ed2k_update(&ed2k, buf, read_len);
  33. read_len = fread(buf, 1, sizeof(buf), f);
  34. }
  35. // TODO check if eof or error
  36. ed2k_final(&ed2k, hash);
  37. fclose(f);
  38. if (l_opts.post_hash_fn)
  39. return l_opts.post_hash_fn(file_path, hash, st, l_opts.data);
  40. return NOERR;
  41. }
  42. static int ed2k_util_walk(const char *fpath, const struct stat *sb,
  43. int typeflag, struct FTW *ftwbuf)
  44. {
  45. if (typeflag == FTW_DNR) {
  46. uio_error("Cannot read directory '%s'. Skipping", fpath);
  47. return NOERR;
  48. }
  49. if (typeflag == FTW_D)
  50. return NOERR;
  51. if (typeflag != FTW_F) {
  52. uio_error("Unhandled error '%d'", typeflag);
  53. return ERR_ED2KUTIL_UNSUP;
  54. }
  55. return ed2k_util_hash(fpath, sb->st_blksize, sb);
  56. }
  57. enum error ed2k_util_iterpath(const char *path, const struct ed2k_util_opts *opts)
  58. {
  59. struct stat ts;
  60. if (stat(path, &ts) != 0) {
  61. uio_error("Stat failed for path: '%s' (%s)",
  62. path, strerror(errno));
  63. return ERR_ED2KUTIL_FS;
  64. }
  65. l_opts = *opts;
  66. if (S_ISREG(ts.st_mode)) {
  67. return ed2k_util_hash(path, ts.st_blksize, &ts);
  68. } else if (S_ISDIR(ts.st_mode)) {
  69. int ftwret = nftw(path, ed2k_util_walk, 20, 0);
  70. if (ftwret == -1) {
  71. uio_error("nftw failure");
  72. return ERR_ED2KUTIL_FS;
  73. }
  74. return ftwret;
  75. }
  76. uio_error("Unsupported file type: %d", ts.st_mode & S_IFMT);
  77. return ERR_ED2KUTIL_UNSUP;
  78. }