mirror of https://git.lain.church/x3/caniadd.git
Move iterpath into util from ed2k_util
This commit is contained in:
parent
b7619f4404
commit
f1ed4b0944
|
@ -53,9 +53,8 @@ enum error cmd_ed2k(void *data)
|
||||||
opts.link = *link;
|
opts.link = *link;
|
||||||
|
|
||||||
for (int i = 0; i < fcount; i++) {
|
for (int i = 0; i < fcount; i++) {
|
||||||
err = ed2k_util_iterpath(config_get_nonopt(i), &ed2k_opts);
|
ed2k_util_iterpath(config_get_nonopt(i), &ed2k_opts);
|
||||||
if (err != NOERR)
|
/* Above may fail if the path doesn't exists or smth, but still continue */
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,27 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ftw.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
#include "ed2k.h"
|
#include "ed2k.h"
|
||||||
#include "ed2k_util.h"
|
#include "ed2k_util.h"
|
||||||
#include "uio.h"
|
#include "uio.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
static struct ed2k_util_opts l_opts;
|
static enum error ed2k_util_hash(const char *file_path, const struct stat *st, void *data)
|
||||||
|
|
||||||
static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
|
|
||||||
const struct stat *st)
|
|
||||||
{
|
{
|
||||||
|
off_t blksize = st->st_blksize;
|
||||||
unsigned char buf[blksize], hash[ED2K_HASH_SIZE];
|
unsigned char buf[blksize], hash[ED2K_HASH_SIZE];
|
||||||
|
struct ed2k_util_opts *opts = data;
|
||||||
struct ed2k_ctx ed2k;
|
struct ed2k_ctx ed2k;
|
||||||
enum error err;
|
enum error err;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
size_t read_len;
|
size_t read_len;
|
||||||
int en;
|
int en;
|
||||||
|
|
||||||
if (l_opts.pre_hash_fn) {
|
if (opts->pre_hash_fn) {
|
||||||
err = l_opts.pre_hash_fn(file_path, st, l_opts.data);
|
err = opts->pre_hash_fn(file_path, st, opts->data);
|
||||||
if (err == ED2KUTIL_DONTHASH)
|
if (err == ED2KUTIL_DONTHASH)
|
||||||
return NOERR;
|
return NOERR;
|
||||||
else if (err != NOERR)
|
else if (err != NOERR)
|
||||||
|
@ -38,7 +37,7 @@ static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
|
||||||
if (en == EINTR && should_exit)
|
if (en == EINTR && should_exit)
|
||||||
return ERR_SHOULD_EXIT;
|
return ERR_SHOULD_EXIT;
|
||||||
else
|
else
|
||||||
return ERR_ED2KUTIL_FS;
|
return ERR_ITERPATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
ed2k_init(&ed2k);
|
ed2k_init(&ed2k);
|
||||||
|
@ -54,7 +53,7 @@ static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
|
||||||
}
|
}
|
||||||
if (ferror(f)) { /* Loop stopped bcuz of error, not EOF */
|
if (ferror(f)) { /* Loop stopped bcuz of error, not EOF */
|
||||||
uio_error("Failure while reading file");
|
uio_error("Failure while reading file");
|
||||||
err = ERR_ED2KUTIL_FS;
|
err = ERR_ITERPATH;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
assert(feof(f));
|
assert(feof(f));
|
||||||
|
@ -67,11 +66,11 @@ static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
|
||||||
if (en == EINTR && should_exit)
|
if (en == EINTR && should_exit)
|
||||||
return ERR_SHOULD_EXIT;
|
return ERR_SHOULD_EXIT;
|
||||||
else
|
else
|
||||||
return ERR_ED2KUTIL_FS;
|
return ERR_ITERPATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l_opts.post_hash_fn)
|
if (opts->post_hash_fn)
|
||||||
return l_opts.post_hash_fn(file_path, hash, st, l_opts.data);
|
return opts->post_hash_fn(file_path, hash, st, opts->data);
|
||||||
return NOERR;
|
return NOERR;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -80,46 +79,7 @@ fail:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ed2k_util_walk(const char *fpath, const struct stat *sb,
|
|
||||||
int typeflag, struct FTW *ftwbuf)
|
|
||||||
{
|
|
||||||
if (typeflag == FTW_DNR) {
|
|
||||||
uio_error("Cannot read directory '%s'. Skipping", fpath);
|
|
||||||
return NOERR;
|
|
||||||
}
|
|
||||||
if (typeflag == FTW_D)
|
|
||||||
return NOERR;
|
|
||||||
if (typeflag != FTW_F) {
|
|
||||||
uio_error("Unhandled error '%d'", typeflag);
|
|
||||||
return ERR_ED2KUTIL_UNSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ed2k_util_hash(fpath, sb->st_blksize, sb);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum error ed2k_util_iterpath(const char *path, const struct ed2k_util_opts *opts)
|
enum error ed2k_util_iterpath(const char *path, const struct ed2k_util_opts *opts)
|
||||||
{
|
{
|
||||||
struct stat ts;
|
return util_iterpath(path, ed2k_util_hash, (void*)opts);
|
||||||
|
|
||||||
if (stat(path, &ts) != 0) {
|
|
||||||
uio_error("Stat failed for path: '%s' (%s)",
|
|
||||||
path, strerror(errno));
|
|
||||||
return ERR_ED2KUTIL_FS;
|
|
||||||
}
|
|
||||||
|
|
||||||
l_opts = *opts;
|
|
||||||
|
|
||||||
if (S_ISREG(ts.st_mode)) {
|
|
||||||
return ed2k_util_hash(path, ts.st_blksize, &ts);
|
|
||||||
} else if (S_ISDIR(ts.st_mode)) {
|
|
||||||
int ftwret = nftw(path, ed2k_util_walk, 20, 0);
|
|
||||||
if (ftwret == -1) {
|
|
||||||
uio_error("nftw failure");
|
|
||||||
return ERR_ED2KUTIL_FS;
|
|
||||||
}
|
|
||||||
return ftwret;
|
|
||||||
}
|
|
||||||
|
|
||||||
uio_error("Unsupported file type: %d", ts.st_mode & S_IFMT);
|
|
||||||
return ERR_ED2KUTIL_UNSUP;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,7 @@
|
||||||
E(ERR_CMD_NONE) /* No command was run */ \
|
E(ERR_CMD_NONE) /* No command was run */ \
|
||||||
E(ERR_CMD_ARG) /* Some problem with the command arguments */ \
|
E(ERR_CMD_ARG) /* Some problem with the command arguments */ \
|
||||||
\
|
\
|
||||||
E(ERR_ED2KUTIL_FS) /* Some filesystem problem */ \
|
E(ERR_ITERPATH) /* Couldn't start iterating over the given path */ \
|
||||||
E(ERR_ED2KUTIL_UNSUP) /* Operation or file type is unsupported */ \
|
|
||||||
E(ED2KUTIL_DONTHASH) /* Skip the hashing part. pre_hash_fn can return this */ \
|
E(ED2KUTIL_DONTHASH) /* Skip the hashing part. pre_hash_fn can return this */ \
|
||||||
\
|
\
|
||||||
E(ERR_API_ENCRYPTFAIL) /* Cannot start encryption with the api */ \
|
E(ERR_API_ENCRYPTFAIL) /* Cannot start encryption with the api */ \
|
||||||
|
|
67
src/util.c
67
src/util.c
|
@ -1,9 +1,15 @@
|
||||||
#define _XOPEN_SOURCE
|
#define _XOPEN_SOURCE 500
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <ftw.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "uio.h"
|
||||||
|
|
||||||
void util_byte2hex(const uint8_t* bytes, size_t bytes_len,
|
void util_byte2hex(const uint8_t* bytes, size_t bytes_len,
|
||||||
bool uppercase, char* out)
|
bool uppercase, char* out)
|
||||||
|
@ -86,3 +92,62 @@ uint64_t util_iso2unix(const char *isotime)
|
||||||
|
|
||||||
return mktime(&tm);
|
return mktime(&tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* nftw doesn't support passing in user data to the callback function :/ */
|
||||||
|
static util_itercb global_iterpath_cb = NULL;
|
||||||
|
static void *global_iterpath_data = NULL;
|
||||||
|
|
||||||
|
static int util_iterpath_walk(const char *fpath, const struct stat *sb,
|
||||||
|
int typeflag, struct FTW *ftwbuf)
|
||||||
|
{
|
||||||
|
if (typeflag == FTW_DNR) {
|
||||||
|
uio_error("Cannot read directory '%s'. Skipping", fpath);
|
||||||
|
return NOERR;
|
||||||
|
}
|
||||||
|
if (typeflag == FTW_D)
|
||||||
|
return NOERR;
|
||||||
|
if (typeflag != FTW_F) {
|
||||||
|
uio_error("Unhandled error '%d'", typeflag);
|
||||||
|
return ERR_ITERPATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_iterpath_cb(fpath, sb, global_iterpath_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum error util_iterpath(const char *path, util_itercb cb, void *data)
|
||||||
|
{
|
||||||
|
assert(global_iterpath_cb == NULL);
|
||||||
|
enum error ret = ERR_ITERPATH;
|
||||||
|
struct stat ts;
|
||||||
|
|
||||||
|
if (stat(path, &ts) != 0) {
|
||||||
|
uio_error("Stat failed for path: '%s' (%s)",
|
||||||
|
path, strerror(errno));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISREG(ts.st_mode)) {
|
||||||
|
/* If the path is a regular file, call the cb once */
|
||||||
|
ret = cb(path, &ts, data);
|
||||||
|
goto end;
|
||||||
|
} else if (S_ISDIR(ts.st_mode)) {
|
||||||
|
global_iterpath_cb = cb;
|
||||||
|
global_iterpath_data = data;
|
||||||
|
|
||||||
|
/* If a directory, walk over it */
|
||||||
|
ret = nftw(path, util_iterpath_walk, 20, 0);
|
||||||
|
if (ret == -1) {
|
||||||
|
uio_error("nftw failure");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
uio_error("Unsupported file type: %d", ts.st_mode & S_IFMT);
|
||||||
|
end:
|
||||||
|
global_iterpath_cb = global_iterpath_data = NULL;
|
||||||
|
return ret;
|
||||||
|
error:
|
||||||
|
ret = ERR_ITERPATH;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
13
src/util.h
13
src/util.h
|
@ -1,9 +1,13 @@
|
||||||
#ifndef _UTIL_H
|
#ifndef _UTIL_H
|
||||||
#define _UTIL_H
|
#define _UTIL_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <time.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
#define MS_TO_TIMESPEC(ts, ms) { \
|
#define MS_TO_TIMESPEC(ts, ms) { \
|
||||||
ts->tv_sec = ms / 1000; \
|
ts->tv_sec = ms / 1000; \
|
||||||
ts->tv_nsec = (ms % 1000) * 1000000; \
|
ts->tv_nsec = (ms % 1000) * 1000000; \
|
||||||
|
@ -50,4 +54,13 @@ uint64_t util_timespec_diff(const struct timespec *past,
|
||||||
*/
|
*/
|
||||||
uint64_t util_iso2unix(const char *isotime);
|
uint64_t util_iso2unix(const char *isotime);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Iterate over a given path and call the 'cb' function for each file
|
||||||
|
* If 'cb' returns anything other than NOERR, the iteration will stop and
|
||||||
|
* that error will be returned.
|
||||||
|
* !! THIS FUNCTION IS NOT THREAD SAFE !!
|
||||||
|
*/
|
||||||
|
typedef enum error (*util_itercb)(const char *path, const struct stat *fstat, void *data);
|
||||||
|
enum error util_iterpath(const char *path, util_itercb cb, void *data);
|
||||||
|
|
||||||
#endif /* _UTIL_H */
|
#endif /* _UTIL_H */
|
||||||
|
|
Loading…
Reference in New Issue