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.

86 lines
2.1KB

  1. #define _XOPEN_SOURCE 500
  2. #include <sys/stat.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <assert.h>
  6. #include "util.h"
  7. #include "ed2k.h"
  8. #include "ed2k_util.h"
  9. #include "uio.h"
  10. #include "globals.h"
  11. static enum error ed2k_util_hash(const char *file_path, const struct stat *st, void *data)
  12. {
  13. off_t blksize = st->st_blksize;
  14. unsigned char buf[blksize], hash[ED2K_HASH_SIZE];
  15. struct ed2k_util_opts *opts = data;
  16. struct ed2k_ctx ed2k;
  17. enum error err;
  18. FILE *f;
  19. size_t read_len;
  20. int en;
  21. if (opts->pre_hash_fn) {
  22. err = opts->pre_hash_fn(file_path, st, opts->data);
  23. if (err == ED2KUTIL_DONTHASH)
  24. return NOERR;
  25. else if (err != NOERR)
  26. return err;
  27. }
  28. f = fopen(file_path, "rb");
  29. if (!f) {
  30. en = errno;
  31. uio_error("Failed to open file: %s (%s)", file_path, strerror(en));
  32. if (en == EINTR && should_exit)
  33. return ERR_SHOULD_EXIT;
  34. else
  35. return ERR_ITERPATH;
  36. }
  37. ed2k_init(&ed2k);
  38. read_len = fread(buf, 1, sizeof(buf), f);
  39. /* From my test, fread wont return anything special on signal interrupt */
  40. while (read_len > 0 && !should_exit) {
  41. ed2k_update(&ed2k, buf, read_len);
  42. read_len = fread(buf, 1, sizeof(buf), f);
  43. }
  44. if (should_exit) {
  45. err = ERR_SHOULD_EXIT;
  46. goto fail;
  47. }
  48. if (ferror(f)) { /* Loop stopped bcuz of error, not EOF */
  49. uio_error("Failure while reading file");
  50. err = ERR_ITERPATH;
  51. goto fail;
  52. }
  53. assert(feof(f));
  54. ed2k_final(&ed2k, hash);
  55. if (fclose(f) != 0) {
  56. en = errno;
  57. uio_debug("Fclose failed: %s", strerror(en));
  58. if (en == EINTR && should_exit)
  59. return ERR_SHOULD_EXIT;
  60. else
  61. return ERR_ITERPATH;
  62. }
  63. if (opts->post_hash_fn)
  64. return opts->post_hash_fn(file_path, hash, st, opts->data);
  65. return NOERR;
  66. fail:
  67. if (f) /* We can't get a 2nd interrupt now */
  68. fclose(f);
  69. return err;
  70. }
  71. enum error ed2k_util_iterpath(const char *path, const struct ed2k_util_opts *opts)
  72. {
  73. return util_iterpath(path, ed2k_util_hash, (void*)opts);
  74. }