caniadd/src/ed2k_util.c

86 lines
2.1 KiB
C
Raw Permalink Normal View History

2022-01-08 19:53:58 +01:00
#define _XOPEN_SOURCE 500
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
2022-01-09 18:45:19 +01:00
#include <assert.h>
2022-01-08 19:53:58 +01:00
2023-08-08 21:32:37 +02:00
#include "util.h"
2022-01-08 19:53:58 +01:00
#include "ed2k.h"
#include "ed2k_util.h"
#include "uio.h"
2022-01-09 18:45:19 +01:00
#include "globals.h"
2022-01-08 19:53:58 +01:00
2023-08-08 21:32:37 +02:00
static enum error ed2k_util_hash(const char *file_path, const struct stat *st, void *data)
2022-01-08 19:53:58 +01:00
{
2023-08-08 21:32:37 +02:00
off_t blksize = st->st_blksize;
2022-01-08 19:53:58 +01:00
unsigned char buf[blksize], hash[ED2K_HASH_SIZE];
2023-08-08 21:32:37 +02:00
struct ed2k_util_opts *opts = data;
2022-01-08 19:53:58 +01:00
struct ed2k_ctx ed2k;
2022-01-09 18:45:19 +01:00
enum error err;
2022-01-08 19:53:58 +01:00
FILE *f;
size_t read_len;
2022-01-09 18:45:19 +01:00
int en;
2022-01-08 19:53:58 +01:00
2023-08-08 21:32:37 +02:00
if (opts->pre_hash_fn) {
err = opts->pre_hash_fn(file_path, st, opts->data);
2022-01-08 19:53:58 +01:00
if (err == ED2KUTIL_DONTHASH)
return NOERR;
else if (err != NOERR)
return err;
}
f = fopen(file_path, "rb");
if (!f) {
2022-01-09 18:45:19 +01:00
en = errno;
uio_error("Failed to open file: %s (%s)", file_path, strerror(en));
if (en == EINTR && should_exit)
return ERR_SHOULD_EXIT;
else
2023-08-08 21:32:37 +02:00
return ERR_ITERPATH;
2022-01-08 19:53:58 +01:00
}
ed2k_init(&ed2k);
read_len = fread(buf, 1, sizeof(buf), f);
2022-01-09 18:45:19 +01:00
/* From my test, fread wont return anything special on signal interrupt */
while (read_len > 0 && !should_exit) {
2022-01-08 19:53:58 +01:00
ed2k_update(&ed2k, buf, read_len);
read_len = fread(buf, 1, sizeof(buf), f);
}
2022-01-09 18:45:19 +01:00
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");
2023-08-08 21:32:37 +02:00
err = ERR_ITERPATH;
2022-01-09 18:45:19 +01:00
goto fail;
}
assert(feof(f));
2022-01-08 19:53:58 +01:00
ed2k_final(&ed2k, hash);
2022-01-09 18:45:19 +01:00
if (fclose(f) != 0) {
en = errno;
uio_debug("Fclose failed: %s", strerror(en));
if (en == EINTR && should_exit)
return ERR_SHOULD_EXIT;
else
2023-08-08 21:32:37 +02:00
return ERR_ITERPATH;
2022-01-09 18:45:19 +01:00
}
2022-01-08 19:53:58 +01:00
2023-08-08 21:32:37 +02:00
if (opts->post_hash_fn)
return opts->post_hash_fn(file_path, hash, st, opts->data);
2022-01-08 19:53:58 +01:00
return NOERR;
2022-01-09 18:45:19 +01:00
fail:
if (f) /* We can't get a 2nd interrupt now */
fclose(f);
return err;
2022-01-08 19:53:58 +01:00
}
enum error ed2k_util_iterpath(const char *path, const struct ed2k_util_opts *opts)
{
2023-08-08 21:32:37 +02:00
return util_iterpath(path, ed2k_util_hash, (void*)opts);
2022-01-08 19:53:58 +01:00
}