mirror of
https://github.com/nextcloud/desktop.git
synced 2024-10-25 13:55:47 +03:00
Add new exported file tree traverse functions.
This commit is contained in:
parent
4a0713370e
commit
254045780a
5 changed files with 174 additions and 17 deletions
89
src/csync.c
89
src/csync.c
|
@ -491,6 +491,95 @@ int csync_propagate(CSYNC *ctx) {
|
||||||
return 0;
|
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) {
|
static void _tree_destructor(void *data) {
|
||||||
csync_file_stat_t *freedata = NULL;
|
csync_file_stat_t *freedata = NULL;
|
||||||
|
|
||||||
|
|
72
src/csync.h
72
src/csync.h
|
@ -32,11 +32,15 @@
|
||||||
#define _CSYNC_H
|
#define _CSYNC_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "std/c_rbtree.h"
|
||||||
|
|
||||||
#define CSYNC_STRINGIFY(s) CSYNC_TOSTRING(s)
|
#define CSYNC_STRINGIFY(s) CSYNC_TOSTRING(s)
|
||||||
#define CSYNC_TOSTRING(s) #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,
|
typedef int (*csync_auth_callback) (const char *prompt, char *buf, size_t len,
|
||||||
int echo, int verify, void *userdata);
|
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
|
* csync handle
|
||||||
*/
|
*/
|
||||||
|
@ -307,6 +355,30 @@ int csync_get_status(CSYNC *ctx);
|
||||||
/* Used for special modes or debugging */
|
/* Used for special modes or debugging */
|
||||||
int csync_set_status(CSYNC *ctx, int status);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -140,22 +140,6 @@ enum csync_ftw_type_e {
|
||||||
CSYNC_FTW_TYPE_DIR
|
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
|
#ifdef _MSC_VER
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
#endif
|
#endif
|
||||||
|
@ -183,6 +167,17 @@ __attribute__ ((packed))
|
||||||
|
|
||||||
typedef struct csync_file_stat_s csync_file_stat_t;
|
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* }@
|
* }@
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -141,6 +141,7 @@ out:
|
||||||
st->phash = h;
|
st->phash = h;
|
||||||
st->pathlen = len;
|
st->pathlen = len;
|
||||||
memcpy(st->path, (len ? path : ""), len + 1);
|
memcpy(st->path, (len ? path : ""), len + 1);
|
||||||
|
printf("OOOO %s (%d)\n", path, len );
|
||||||
|
|
||||||
switch (ctx->current) {
|
switch (ctx->current) {
|
||||||
case LOCAL_REPLICA:
|
case LOCAL_REPLICA:
|
||||||
|
|
|
@ -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.
|
* @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
|
* Structure that represents a red-black tree
|
||||||
|
|
Loading…
Reference in a new issue