#define _XOPEN_SOURCE 500 #include #include #include #include #include "util.h" #include "ed2k.h" #include "ed2k_util.h" #include "uio.h" #include "globals.h" static enum error ed2k_util_hash(const char *file_path, const struct stat *st, void *data) { off_t blksize = st->st_blksize; unsigned char buf[blksize], hash[ED2K_HASH_SIZE]; struct ed2k_util_opts *opts = data; struct ed2k_ctx ed2k; enum error err; FILE *f; size_t read_len; int en; if (opts->pre_hash_fn) { err = opts->pre_hash_fn(file_path, st, opts->data); if (err == ED2KUTIL_DONTHASH) return NOERR; else if (err != NOERR) return err; } f = fopen(file_path, "rb"); if (!f) { en = errno; uio_error("Failed to open file: %s (%s)", file_path, strerror(en)); if (en == EINTR && should_exit) return ERR_SHOULD_EXIT; else return ERR_ITERPATH; } ed2k_init(&ed2k); read_len = fread(buf, 1, sizeof(buf), f); /* From my test, fread wont return anything special on signal interrupt */ while (read_len > 0 && !should_exit) { ed2k_update(&ed2k, buf, read_len); read_len = fread(buf, 1, sizeof(buf), f); } if (should_exit) { err = ERR_SHOULD_EXIT; goto fail; } if (ferror(f)) { /* Loop stopped bcuz of error, not EOF */ uio_error("Failure while reading file"); err = ERR_ITERPATH; goto fail; } assert(feof(f)); ed2k_final(&ed2k, hash); if (fclose(f) != 0) { en = errno; uio_debug("Fclose failed: %s", strerror(en)); if (en == EINTR && should_exit) return ERR_SHOULD_EXIT; else return ERR_ITERPATH; } if (opts->post_hash_fn) return opts->post_hash_fn(file_path, hash, st, opts->data); return NOERR; fail: if (f) /* We can't get a 2nd interrupt now */ fclose(f); return err; } enum error ed2k_util_iterpath(const char *path, const struct ed2k_util_opts *opts) { return util_iterpath(path, ed2k_util_hash, (void*)opts); }