From 254045780a6bbc5b8dcfc1ebbc461e636260eed2 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 19 Mar 2012 16:05:23 +0100 Subject: [PATCH] Add new exported file tree traverse functions. --- src/csync.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ src/csync.h | 72 ++++++++++++++++++++++++++++++++++++ src/csync_private.h | 27 ++++++-------- src/csync_update.c | 1 + src/std/c_rbtree.h | 2 +- 5 files changed, 174 insertions(+), 17 deletions(-) diff --git a/src/csync.c b/src/csync.c index 85458a2a1c..9582e4a603 100644 --- a/src/csync.c +++ b/src/csync.c @@ -491,6 +491,95 @@ int csync_propagate(CSYNC *ctx) { return 0; } +/* + * local visitor which calls the user visitor with repacked stat info. + */ +static int _csync_treewalk_visitor( void *obj, void *data ) { + csync_file_stat_t *cur = NULL; + CSYNC *ctx = NULL; + c_rbtree_visit_func *visitor = NULL; + _csync_treewalk_context *twctx = NULL; + TREE_WALK_FILE trav; + + cur = (csync_file_stat_t *) obj; + ctx = (CSYNC *) data; + if( ctx ) + twctx = (_csync_treewalk_context*) ctx->userdata; + if( twctx->instruction_filter > 0 && !(twctx->instruction_filter & cur->instruction) ) { + return 0; + } + + if(cur && twctx) { + visitor = (c_rbtree_visit_func*)(twctx->user_visitor); + if(visitor) { + trav.path = cur->path; + trav.modtime = cur->modtime; + trav.uid = cur->uid; + trav.gid = cur->gid; + trav.mode = cur->mode; + trav.type = cur->type; + trav.instruction = cur->instruction; + + return (*visitor)(&trav, twctx->userdata); + } + } + return -1; +} + +/* + * treewalk function, called from its wrappers below. + * + * it encapsulates the user visitor function, the filter and the userdata + * into a treewalk_context structure and calls the rb treewalk function, + * which calls the local _csync_treewalk_visitor in this module. + * The user visitor is called from there. + */ +static int _csync_walk_tree(CSYNC *ctx, c_rbtree_t *tree, csync_treewalk_visit_func *visitor, int filter) +{ + _csync_treewalk_context tw_ctx; + int rc = -1; + + if( !(visitor && tree && ctx)) return rc; + + tw_ctx.userdata = ctx->userdata; + tw_ctx.user_visitor = visitor; + tw_ctx.instruction_filter = filter; + + ctx->userdata = &tw_ctx; + + rc = c_rbtree_walk(tree, (void*) ctx, _csync_treewalk_visitor); + + ctx->userdata = tw_ctx.userdata; + + return rc; +} + +/* + * wrapper function for treewalk on the remote tree + */ +int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter) +{ + c_rbtree_t *tree = NULL; + + if( ctx ) { + tree = ctx->remote.tree; + } + return _csync_walk_tree(ctx, tree, visitor, filter); +} + +/* + * wrapper function for treewalk on the local tree + */ +int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter) +{ + c_rbtree_t *tree = NULL; + + if( ctx ) { + tree = ctx->local.tree; + } + return _csync_walk_tree(ctx, tree, visitor, filter); +} + static void _tree_destructor(void *data) { csync_file_stat_t *freedata = NULL; diff --git a/src/csync.h b/src/csync.h index 3aeed5f640..b0eeb18bef 100644 --- a/src/csync.h +++ b/src/csync.h @@ -32,11 +32,15 @@ #define _CSYNC_H #include +#include +#include #ifdef __cplusplus extern "C" { #endif +#include "std/c_rbtree.h" + #define CSYNC_STRINGIFY(s) CSYNC_TOSTRING(s) #define CSYNC_TOSTRING(s) #s @@ -69,6 +73,50 @@ extern "C" { typedef int (*csync_auth_callback) (const char *prompt, char *buf, size_t len, int echo, int verify, void *userdata); +/** + * Instruction enum. In the file traversal structure, it describes + * the csync state of a file. + */ +enum csync_instructions_e { + CSYNC_INSTRUCTION_NONE = 0x00000000, + CSYNC_INSTRUCTION_EVAL = 0x00000001, + CSYNC_INSTRUCTION_REMOVE = 0x00000002, + CSYNC_INSTRUCTION_RENAME = 0x00000004, + CSYNC_INSTRUCTION_NEW = 0x00000008, + CSYNC_INSTRUCTION_CONFLICT = 0x00000010, + CSYNC_INSTRUCTION_IGNORE = 0x00000020, + CSYNC_INSTRUCTION_SYNC = 0x00000040, + CSYNC_INSTRUCTION_STAT_ERROR = 0x00000080, + CSYNC_INSTRUCTION_ERROR = 0x00000100, + /* instructions for the propagator */ + CSYNC_INSTRUCTION_DELETED = 0x00000200, + CSYNC_INSTRUCTION_UPDATED = 0x00000400 +}; + +/** + * CSync File Traversal structure. + * + * This structure is passed to the visitor function for every file + * which is seen. + * Note: The file size is missing here because type off_t is depending + * on the large file support in your build. Make sure to check + * that cmake and the callback app are compiled with the same + * setting for it, such as: + * -D_LARGEFILE64_SOURCE or -D_LARGEFILE_SOURCE + * + */ +struct csync_tree_walk_file_s { + const char *path; + /* off_t size; */ + time_t modtime; + uid_t uid; + gid_t gid; + mode_t mode; + int type; + enum csync_instructions_e instruction; +}; +typedef struct csync_tree_walk_file_s TREE_WALK_FILE; + /** * csync handle */ @@ -307,6 +355,30 @@ int csync_get_status(CSYNC *ctx); /* Used for special modes or debugging */ int csync_set_status(CSYNC *ctx, int status); +typedef int csync_treewalk_visit_func(TREE_WALK_FILE* ,void*); + +/** + * @brief Walk the local file tree and call a visitor function for each file. + * + * @param ctx The csync context. + * @param visitor A callback function to handle the file info. + * @param filter A filter, built from and'ed csync_instructions_e + * + * @return 0 on success, less than 0 if an error occured. + */ +int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter); + +/** + * @brief Walk the remote file tree and call a visitor function for each file. + * + * @param ctx The csync context. + * @param visitor A callback function to handle the file info. + * @param filter A filter, built from and'ed csync_instructions_e + * + * @return 0 on success, less than 0 if an error occured. + */ +int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter); + #ifdef __cplusplus } #endif diff --git a/src/csync_private.h b/src/csync_private.h index 26cce1889f..2380aa7aab 100644 --- a/src/csync_private.h +++ b/src/csync_private.h @@ -140,22 +140,6 @@ enum csync_ftw_type_e { CSYNC_FTW_TYPE_DIR }; -enum csync_instructions_e { - CSYNC_INSTRUCTION_NONE, - CSYNC_INSTRUCTION_EVAL, - CSYNC_INSTRUCTION_REMOVE, - CSYNC_INSTRUCTION_RENAME, - CSYNC_INSTRUCTION_NEW, - CSYNC_INSTRUCTION_CONFLICT, - CSYNC_INSTRUCTION_IGNORE, - CSYNC_INSTRUCTION_SYNC, - CSYNC_INSTRUCTION_STAT_ERROR, - CSYNC_INSTRUCTION_ERROR, - /* instructions for the propagator */ - CSYNC_INSTRUCTION_DELETED, - CSYNC_INSTRUCTION_UPDATED -}; - #ifdef _MSC_VER #pragma pack(1) #endif @@ -183,6 +167,17 @@ __attribute__ ((packed)) typedef struct csync_file_stat_s csync_file_stat_t; +/* + * context for the treewalk function + */ +struct _csync_treewalk_context_s +{ + csync_treewalk_visit_func *user_visitor; + int instruction_filter; + void *userdata; +}; +typedef struct _csync_treewalk_context_s _csync_treewalk_context; + /** * }@ */ diff --git a/src/csync_update.c b/src/csync_update.c index 22190d875f..7985c09464 100644 --- a/src/csync_update.c +++ b/src/csync_update.c @@ -141,6 +141,7 @@ out: st->phash = h; st->pathlen = len; memcpy(st->path, (len ? path : ""), len + 1); + printf("OOOO %s (%d)\n", path, len ); switch (ctx->current) { case LOCAL_REPLICA: diff --git a/src/std/c_rbtree.h b/src/std/c_rbtree.h index 4416ebc84b..aca0ece632 100644 --- a/src/std/c_rbtree.h +++ b/src/std/c_rbtree.h @@ -103,7 +103,7 @@ typedef int c_rbtree_compare_func(const void *key, const void *data); * @return 0 on success, < 0 on error. You should set errno. * */ -typedef int c_rbtree_visit_func(void *obj, void *data); +typedef int c_rbtree_visit_func(void *, void *); /** * Structure that represents a red-black tree