Added a csync_errno function to provide more info for clients.

This commit is contained in:
Klaas Freitag 2012-03-30 15:33:13 +02:00
parent 55c3b0862c
commit b0f6602681
4 changed files with 147 additions and 20 deletions

View file

@ -93,12 +93,15 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
/* remove trailing slashes */
len = strlen(local);
while(len > 0 && local[len - 1] == '/') --len;
ctx->local.uri = c_strndup(local, len);
if (ctx->local.uri == NULL) {
ctx->error_code = CSYNC_ERR_MEM;
return -1;
}
@ -109,6 +112,7 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
ctx->remote.uri = c_strndup(remote, len);
if (ctx->remote.uri == NULL) {
SAFE_FREE(ctx->remote.uri);
ctx->error_code = CSYNC_ERR_MEM;
return -1;
}
@ -127,6 +131,7 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
SAFE_FREE(ctx->remote.uri);
SAFE_FREE(ctx);
errno = ENOMEM;
ctx->error_code = CSYNC_ERR_MEM;
return -1;
}
@ -137,6 +142,7 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) {
SAFE_FREE(ctx->remote.uri);
SAFE_FREE(ctx);
errno = ENOMEM;
ctx->error_code = CSYNC_ERR_MEM;
return -1;
}
@ -154,10 +160,12 @@ int csync_init(CSYNC *ctx) {
#ifndef _WIN32
char errbuf[256] = {0};
#endif
if (ctx == NULL) {
errno = EBADF;
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
/* Do not initialize twice */
if (ctx->status & CSYNC_STATUS_INIT) {
@ -166,6 +174,7 @@ int csync_init(CSYNC *ctx) {
/* load log file */
if (csync_log_init() < 0) {
ctx->error_code = CSYNC_ERR_LOG;
fprintf(stderr, "csync_init: logger init failed\n");
return -1;
}
@ -176,6 +185,7 @@ int csync_init(CSYNC *ctx) {
}
if (asprintf(&log, "%s/%s", ctx->options.config_dir, CSYNC_LOG_FILE) < 0) {
ctx->error_code = CSYNC_ERR_UNSPEC;
rc = -1;
goto out;
}
@ -193,12 +203,14 @@ int csync_init(CSYNC *ctx) {
/* create lock file */
if (asprintf(&lock, "%s/%s", ctx->options.config_dir, CSYNC_LOCK_FILE) < 0) {
ctx->error_code = CSYNC_ERR_UNSPEC;
rc = -1;
goto out;
}
#ifndef _WIN32
if (csync_lock(lock) < 0) {
ctx->error_code = CSYNC_ERR_LOCK;
rc = -1;
goto out;
}
@ -217,6 +229,7 @@ int csync_init(CSYNC *ctx) {
#ifndef _WIN32
/* load global exclude list */
if (asprintf(&exclude, "%s/csync/%s", SYSCONFDIR, CSYNC_EXCLUDE_FILE) < 0) {
ctx->error_code = CSYNC_ERR_UNSPEC;
rc = -1;
goto out;
}
@ -229,8 +242,8 @@ int csync_init(CSYNC *ctx) {
SAFE_FREE(exclude);
/* load exclude list */
if (asprintf(&exclude, "%s/%s", ctx->options.config_dir,
CSYNC_EXCLUDE_FILE) < 0) {
if (asprintf(&exclude, "%s/%s", ctx->options.config_dir, CSYNC_EXCLUDE_FILE) < 0) {
ctx->error_code = CSYNC_ERR_UNSPEC;
rc = -1;
goto out;
}
@ -247,6 +260,7 @@ int csync_init(CSYNC *ctx) {
uint64_t h = csync_create_statedb_hash(ctx);
if (asprintf(&ctx->statedb.file, "%s/csync_statedb_%llu.db",
ctx->options.config_dir, (long long unsigned int) h) < 0) {
ctx->error_code = CSYNC_ERR_UNSPEC;
rc = -1;
goto out;
}
@ -254,6 +268,7 @@ int csync_init(CSYNC *ctx) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Statedb: %s", ctx->statedb.file);
if (csync_statedb_load(ctx, ctx->statedb.file) < 0) {
ctx->error_code = CSYNC_ERR_STATEDB_LOAD;
rc = -1;
goto out;
}
@ -271,6 +286,7 @@ int csync_init(CSYNC *ctx) {
/* module name */
module = c_strndup(ctx->remote.uri, len);
if (module == NULL) {
ctx->error_code = CSYNC_ERR_MODULE;
rc = -1;
goto out;
}
@ -284,7 +300,8 @@ retry_vio_init:
module[len-1] = '\0';
goto retry_vio_init;
}
/* Now vio init finally failed which means a module could not be found. */
ctx->error_code = CSYNC_ERR_MODULE;
SAFE_FREE(module);
goto out;
}
@ -301,27 +318,33 @@ retry_vio_init:
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL,
"Clock skew detected. The time difference is greater than %d seconds!",
ctx->options.max_time_difference);
ctx->error_code = CSYNC_ERR_TIMESKEW;
rc = -1;
goto out;
} else if (timediff < 0) {
/* error code was set in csync_timediff() */
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Synchronisation is not possible!");
ctx->error_code = CSYNC_ERR_TIMESKEW;
rc = -1;
goto out;
}
if (csync_unix_extensions(ctx) < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Could not detect filesystem type.");
ctx->error_code = CSYNC_ERR_FILESYSTEM;
rc = -1;
goto out;
}
}
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
ctx->error_code = CSYNC_ERR_TREE;
rc = -1;
goto out;
}
if (c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp) < 0) {
ctx->error_code = CSYNC_ERR_TREE;
rc = -1;
goto out;
}
@ -341,11 +364,12 @@ out:
int csync_update(CSYNC *ctx) {
int rc = -1;
struct timespec start, finish;
if (ctx == NULL) {
errno = EBADF;
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
csync_memstat_check();
@ -364,6 +388,7 @@ int csync_update(CSYNC *ctx) {
csync_memstat_check();
if (rc < 0) {
ctx->error_code = CSYNC_ERR_TREE;
return -1;
}
@ -384,6 +409,7 @@ int csync_update(CSYNC *ctx) {
csync_memstat_check();
if (rc < 0) {
ctx->error_code = CSYNC_ERR_TREE;
return -1;
}
}
@ -400,6 +426,7 @@ int csync_reconcile(CSYNC *ctx) {
errno = EBADF;
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
/* Reconciliation for local replica */
csync_gettime(&start);
@ -416,6 +443,7 @@ int csync_reconcile(CSYNC *ctx) {
c_secdiff(finish, start), c_rbtree_size(ctx->local.tree));
if (rc < 0) {
ctx->error_code = CSYNC_ERR_RECONCILE;
return -1;
}
@ -434,6 +462,7 @@ int csync_reconcile(CSYNC *ctx) {
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
if (rc < 0) {
ctx->error_code = CSYNC_ERR_RECONCILE;
return -1;
}
@ -450,6 +479,7 @@ int csync_propagate(CSYNC *ctx) {
errno = EBADF;
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
/* Reconciliation for local replica */
csync_gettime(&start);
@ -466,6 +496,7 @@ int csync_propagate(CSYNC *ctx) {
c_secdiff(finish, start), c_rbtree_size(ctx->local.tree));
if (rc < 0) {
ctx->error_code = CSYNC_ERR_PROPAGATE;
return -1;
}
@ -484,6 +515,7 @@ int csync_propagate(CSYNC *ctx) {
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
if (rc < 0) {
ctx->error_code = CSYNC_ERR_PROPAGATE;
return -1;
}
@ -495,18 +527,25 @@ int csync_propagate(CSYNC *ctx) {
/*
* 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;
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) ) {
if (ctx == NULL) {
errno = EBADF;
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
twctx = (_csync_treewalk_context*) ctx->userdata;
if(cur && twctx && twctx->instruction_filter > 0 && !(twctx->instruction_filter & cur->instruction)) {
return 0;
}
@ -524,6 +563,7 @@ static int _csync_treewalk_visitor( void *obj, void *data ) {
return (*visitor)(&trav, twctx->userdata);
}
}
ctx->error_code = CSYNC_ERR_TREE;
return -1;
}
@ -540,8 +580,17 @@ static int _csync_walk_tree(CSYNC *ctx, c_rbtree_t *tree, csync_treewalk_visit_f
_csync_treewalk_context tw_ctx;
int rc = -1;
if( !(visitor && tree && ctx)) return rc;
if (ctx == NULL) {
errno = EBADF;
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
if(!(visitor && tree)) {
ctx->error_code = CSYNC_ERR_PARAM;
return rc;
}
tw_ctx.userdata = ctx->userdata;
tw_ctx.user_visitor = visitor;
tw_ctx.instruction_filter = filter;
@ -549,7 +598,9 @@ static int _csync_walk_tree(CSYNC *ctx, c_rbtree_t *tree, csync_treewalk_visit_f
ctx->userdata = &tw_ctx;
rc = c_rbtree_walk(tree, (void*) ctx, _csync_treewalk_visitor);
if( rc < 0 )
ctx->error_code = CSYNC_ERR_TREE;
ctx->userdata = tw_ctx.userdata;
return rc;
@ -561,11 +612,15 @@ static int _csync_walk_tree(CSYNC *ctx, c_rbtree_t *tree, csync_treewalk_visit_f
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter)
{
c_rbtree_t *tree = NULL;
if( ctx ) {
int rc = -1;
if(ctx) {
tree = ctx->remote.tree;
}
return _csync_walk_tree(ctx, tree, visitor, filter);
/* all error handling in the called function */
rc = _csync_walk_tree(ctx, tree, visitor, filter);
return rc;
}
/*
@ -574,11 +629,15 @@ int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int
int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter)
{
c_rbtree_t *tree = NULL;
int rc = -1;
if( ctx ) {
if(ctx) {
tree = ctx->local.tree;
}
return _csync_walk_tree(ctx, tree, visitor, filter);
/* all error handling in the called function */
rc = _csync_walk_tree(ctx, tree, visitor, filter);
return rc;
}
static void _tree_destructor(void *data) {
@ -598,6 +657,7 @@ int csync_destroy(CSYNC *ctx) {
errno = EBADF;
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
csync_vio_shutdown(ctx);
@ -681,6 +741,7 @@ int csync_add_exclude_list(CSYNC *ctx, const char *path) {
if (ctx == NULL || path == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
return csync_exclude_load(ctx, path);
}
@ -689,6 +750,7 @@ const char *csync_get_config_dir(CSYNC *ctx) {
if (ctx == NULL) {
return NULL;
}
ctx->error_code = CSYNC_ERR_NONE;
return ctx->options.config_dir;
}
@ -697,10 +759,12 @@ int csync_set_config_dir(CSYNC *ctx, const char *path) {
if (ctx == NULL || path == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
SAFE_FREE(ctx->options.config_dir);
ctx->options.config_dir = c_strdup(path);
if (ctx->options.config_dir == NULL) {
ctx->error_code = CSYNC_ERR_MEM;
return -1;
}
@ -711,8 +775,10 @@ int csync_enable_statedb(CSYNC *ctx) {
if (ctx == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
if (ctx->status & CSYNC_STATUS_INIT) {
ctx->error_code = CSYNC_ERR_UNSPEC;
fprintf(stderr, "This function must be called before initialization.");
return -1;
}
@ -726,8 +792,10 @@ int csync_disable_statedb(CSYNC *ctx) {
if (ctx == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
if (ctx->status & CSYNC_STATUS_INIT) {
ctx->error_code = CSYNC_ERR_UNSPEC;
fprintf(stderr, "This function must be called before initialization.");
return -1;
}
@ -741,6 +809,7 @@ int csync_is_statedb_disabled(CSYNC *ctx) {
if (ctx == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
return ctx->statedb.disabled;
}
@ -749,9 +818,11 @@ int csync_set_auth_callback(CSYNC *ctx, csync_auth_callback cb) {
if (ctx == NULL || cb == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
if (ctx->status & CSYNC_STATUS_INIT) {
fprintf(stderr, "This function must be called before initialization.");
ctx->error_code = CSYNC_ERR_UNSPEC;
return -1;
}
@ -764,6 +835,7 @@ const char *csync_get_statedb_file(CSYNC *ctx) {
if (ctx == NULL) {
return NULL;
}
ctx->error_code = CSYNC_ERR_NONE;
return c_strdup(ctx->statedb.file);
}
@ -772,6 +844,7 @@ void *csync_get_userdata(CSYNC *ctx) {
if (ctx == NULL) {
return NULL;
}
ctx->error_code = CSYNC_ERR_NONE;
return ctx->userdata;
}
@ -780,6 +853,7 @@ int csync_set_userdata(CSYNC *ctx, void *userdata) {
if (ctx == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
ctx->userdata = userdata;
@ -790,6 +864,7 @@ csync_auth_callback csync_get_auth_callback(CSYNC *ctx) {
if (ctx == NULL) {
return NULL;
}
ctx->error_code = CSYNC_ERR_NONE;
return ctx->auth_callback;
}
@ -798,6 +873,7 @@ int csync_set_status(CSYNC *ctx, int status) {
if (ctx == NULL || status < 0) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
ctx->status = status;
@ -808,6 +884,7 @@ int csync_get_status(CSYNC *ctx) {
if (ctx == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
return ctx->status;
}
@ -816,9 +893,11 @@ int csync_enable_conflictcopys(CSYNC* ctx){
if (ctx == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
if (ctx->status & CSYNC_STATUS_INIT) {
fprintf(stderr, "This function must be called before initialization.");
ctx->error_code = CSYNC_ERR_UNSPEC;
return -1;
}
@ -827,13 +906,15 @@ int csync_enable_conflictcopys(CSYNC* ctx){
return 0;
}
int csync_set_local_only( CSYNC *ctx, bool local_only ) {
int csync_set_local_only(CSYNC *ctx, bool local_only) {
if (ctx == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
if (ctx->status & CSYNC_STATUS_INIT) {
fprintf(stderr, "This function must be called before initialization.");
ctx->error_code = CSYNC_ERR_UNSPEC;
return -1;
}
@ -842,12 +923,20 @@ int csync_set_local_only( CSYNC *ctx, bool local_only ) {
return 0;
}
bool csync_get_local_only( CSYNC *ctx ) {
bool csync_get_local_only(CSYNC *ctx) {
if (ctx == NULL) {
return -1;
}
ctx->error_code = CSYNC_ERR_NONE;
return ctx->options.local_only_mode;
}
CSYNC_ERROR_CODE csync_get_error(CSYNC *ctx) {
if (ctx == NULL) {
return CSYNC_ERR_PARAM;
}
return ctx->error_code;
}
/* vim: set ts=8 sw=2 et cindent: */

View file

@ -72,6 +72,28 @@ extern "C" {
typedef int (*csync_auth_callback) (const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata);
enum csync_error_codes_e {
CSYNC_ERR_NONE = 0,
CSYNC_ERR_LOG,
CSYNC_ERR_LOCK,
CSYNC_ERR_STATEDB_LOAD,
CSYNC_ERR_MODULE,
CSYNC_ERR_TIMESKEW,
CSYNC_ERR_FILESYSTEM,
CSYNC_ERR_TREE,
CSYNC_ERR_MEM,
CSYNC_ERR_PARAM,
CSYNC_ERR_RECONCILE,
CSYNC_ERR_PROPAGATE,
CSYNC_ERR_ACCESS_FAILED,
CSYNC_ERR_REMOTE_CREATE,
CSYNC_ERR_REMOTE_STAT,
CSYNC_ERR_LOCAL_CREATE,
CSYNC_ERR_LOCAL_STAT,
CSYNC_ERR_UNSPEC
};
typedef enum csync_error_codes_e CSYNC_ERROR_CODE;
/**
* Instruction enum. In the file traversal structure, it describes
* the csync state of a file.
@ -383,6 +405,14 @@ int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int fi
*/
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter);
/**
* @brief Get the error code from the last operation.
*
* @return An error code defined by structure CSYNC_ERROR_CODE
*/
CSYNC_ERROR_CODE csync_get_error(CSYNC *ctx);
#ifdef __cplusplus
}
#endif

View file

@ -131,6 +131,9 @@ struct csync_s {
/* replica we want to work on */
enum csync_replica_e replica;
/* error code of the last operation */
enum csync_error_codes_e error_code;
int status;
};

View file

@ -84,6 +84,7 @@ time_t csync_timediff(CSYNC *ctx) {
"Access dienied to remote uri: %s - %s",
ctx->remote.uri,
errbuf);
ctx->error_code = CSYNC_ERR_ACCESS_FAILED;
return -1;
}
csync_vio_closedir(ctx, dp);
@ -105,6 +106,7 @@ time_t csync_timediff(CSYNC *ctx) {
"Unable to create temporary file: %s - %s",
luri,
errbuf);
ctx->error_code = CSYNC_ERR_LOCAL_CREATE;
goto out;
}
csync_vio_close(ctx, fp);
@ -117,6 +119,7 @@ time_t csync_timediff(CSYNC *ctx) {
"Synchronisation is not possible! %s - %s",
luri,
errbuf);
ctx->error_code = CSYNC_ERR_LOCAL_STAT;
goto out;
}
timediff = st->mtime;
@ -133,6 +136,7 @@ time_t csync_timediff(CSYNC *ctx) {
"Unable to create temporary file: %s - %s",
ruri,
errbuf);
ctx->error_code = CSYNC_ERR_REMOTE_CREATE;
goto out;
}
csync_vio_close(ctx, fp);
@ -145,6 +149,7 @@ time_t csync_timediff(CSYNC *ctx) {
"Synchronisation is not possible! %s - %s",
ruri,
errbuf);
ctx->error_code = CSYNC_ERR_REMOTE_STAT;
goto out;
}