Browse Source

Move iterpath into util from ed2k_util

dev
x3 8 months ago
parent
commit
f1ed4b0944
Signed by: x3 <sugarpanning@cock.li> GPG Key ID: 7E9961E8AD0E240E
5 changed files with 94 additions and 58 deletions
  1. +2
    -3
      src/cmd_ed2k.c
  2. +12
    -52
      src/ed2k_util.c
  3. +1
    -2
      src/error.h
  4. +66
    -1
      src/util.c
  5. +13
    -0
      src/util.h

+ 2
- 3
src/cmd_ed2k.c View File

@@ -53,9 +53,8 @@ enum error cmd_ed2k(void *data)
opts.link = *link;

for (int i = 0; i < fcount; i++) {
err = ed2k_util_iterpath(config_get_nonopt(i), &ed2k_opts);
if (err != NOERR)
break;
ed2k_util_iterpath(config_get_nonopt(i), &ed2k_opts);
/* Above may fail if the path doesn't exists or smth, but still continue */
}
return err;
}


+ 12
- 52
src/ed2k_util.c View File

@@ -2,28 +2,27 @@
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <ftw.h>
#include <assert.h>

#include "util.h"
#include "ed2k.h"
#include "ed2k_util.h"
#include "uio.h"
#include "globals.h"

static struct ed2k_util_opts l_opts;

static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
const struct stat *st)
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 (l_opts.pre_hash_fn) {
err = l_opts.pre_hash_fn(file_path, st, l_opts.data);
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)
@@ -38,7 +37,7 @@ static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
if (en == EINTR && should_exit)
return ERR_SHOULD_EXIT;
else
return ERR_ED2KUTIL_FS;
return ERR_ITERPATH;
}

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 */
uio_error("Failure while reading file");
err = ERR_ED2KUTIL_FS;
err = ERR_ITERPATH;
goto fail;
}
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)
return ERR_SHOULD_EXIT;
else
return ERR_ED2KUTIL_FS;
return ERR_ITERPATH;
}

if (l_opts.post_hash_fn)
return l_opts.post_hash_fn(file_path, hash, st, l_opts.data);
if (opts->post_hash_fn)
return opts->post_hash_fn(file_path, hash, st, opts->data);
return NOERR;

fail:
@@ -80,46 +79,7 @@ fail:
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)
{
struct stat ts;

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;
return util_iterpath(path, ed2k_util_hash, (void*)opts);
}

+ 1
- 2
src/error.h View File

@@ -25,8 +25,7 @@
E(ERR_CMD_NONE) /* No command was run */ \
E(ERR_CMD_ARG) /* Some problem with the command arguments */ \
\
E(ERR_ED2KUTIL_FS) /* Some filesystem problem */ \
E(ERR_ED2KUTIL_UNSUP) /* Operation or file type is unsupported */ \
E(ERR_ITERPATH) /* Couldn't start iterating over the given path */ \
E(ED2KUTIL_DONTHASH) /* Skip the hashing part. pre_hash_fn can return this */ \
\
E(ERR_API_ENCRYPTFAIL) /* Cannot start encryption with the api */ \


+ 66
- 1
src/util.c View File

@@ -1,9 +1,15 @@
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE 500
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <sys/stat.h>
#include <ftw.h>

#include "util.h"
#include "error.h"
#include "uio.h"

void util_byte2hex(const uint8_t* bytes, size_t bytes_len,
bool uppercase, char* out)
@@ -86,3 +92,62 @@ uint64_t util_iso2unix(const char *isotime)

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
- 0
src/util.h View File

@@ -1,9 +1,13 @@
#ifndef _UTIL_H
#define _UTIL_H
#include <sys/stat.h>
#include <time.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#include "error.h"

#define MS_TO_TIMESPEC(ts, ms) { \
ts->tv_sec = ms / 1000; \
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);

/*
* 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 */

Loading…
Cancel
Save