From c263a39334c2d48578d9d627b5bf79c97acce02f Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Tue, 3 Jul 2012 14:38:43 +0200 Subject: [PATCH 01/20] Compute server time from http header and adjust mtimes. --- modules/csync_owncloud.c | 54 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index 0726c90710..3f7362f636 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -119,6 +119,10 @@ struct dav_session_s { ne_session *ctx; char *user; char *pwd; + + time_t time_delta; /* The time delta to use. */ + long int time_delta_sum; /* What is the time delta average? */ + int time_delta_cnt; /* How often was the server time gathered? */ }; /* The list of properties that is fetched in PropFind on a collection */ @@ -347,6 +351,9 @@ static int dav_connect(const char *base_url) { return 0; } + dav_session.time_delta_sum = 0; + dav_session.time_delta_cnt = 0; + rc = c_parse_uri( base_url, &scheme, &dav_session.user, &dav_session.pwd, &host, &port, &path ); if( rc < 0 ) { DEBUG_WEBDAV("Failed to parse uri %s", base_url ); @@ -505,14 +512,51 @@ static int fetch_resource_list( const char *curi, struct listdir_context *fetchCtx ) { int ret = 0; + ne_propfind_handler *hdl = NULL; + ne_request *request = NULL; + const char *date_header = NULL; + time_t server_time; + time_t now; + time_t time_diff; + time_t time_diff_delta; /* do a propfind request and parse the results in the results function, set as callback */ - ret = ne_simple_propfind( dav_session.ctx, curi, depth, ls_props, results, fetchCtx ); + /* ret = ne_simple_propfind( dav_session.ctx, curi, depth, ls_props, results, fetchCtx ); */ + + hdl = ne_propfind_create(dav_session.ctx, curi, depth); + + ret = ne_propfind_named(hdl, ls_props, results, fetchCtx); if( ret == NE_OK ) { DEBUG_WEBDAV("Simple propfind OK."); fetchCtx->currResource = fetchCtx->list; + request = ne_propfind_get_request( hdl ); + + date_header = ne_get_response_header( request, "Date" ); + DEBUG_WEBDAV("Server Date from HTTP header value: %s", date_header); + server_time = ne_rfc1123_parse( date_header ); + now = time(NULL); + time_diff = server_time - now; + + dav_session.time_delta_sum += time_diff; + dav_session.time_delta_cnt++; + + /* check the changing of the time delta */ + time_diff_delta = llabs(dav_session.time_delta - time_diff); + if( time_diff_delta > 5 ) { + DEBUG_WEBDAV("WRN: The time delta changed more than 5 second"); + } else if( time_diff_delta == 0) { + DEBUG_WEBDAV("Ok: Time delta remained the same."); + } else { + DEBUG_WEBDAV("Difference to last server time delta: %d", time_diff_delta ); + } + dav_session.time_delta = time_diff; + + /* DEBUG_WEBDAV("%d <0> %d", server_time, now); */ + dav_session.time_delta = time_diff; } + ne_propfind_destroy(hdl); + return ret; } @@ -545,7 +589,13 @@ static csync_vio_file_stat_t *resourceToFileStat( struct resource *res ) DEBUG_WEBDAV("ERROR: Unknown resource type %d", res->type); } - lfs->mtime = res->modtime; + /* Correct the mtime of the file with the server time delta */ + if( dav_session.time_delta_cnt == 0 ) { + DEBUG_WEBDAV("WRN: Delta time not yet computed."); + lfs->mtime = res->modtime; + } else { + lfs->mtime = res->modtime + dav_session.time_delta; + } lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; lfs->size = res->size; lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; From 8ba2f483bfc1623a7cde95d049f51f65cff96562 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 4 Jul 2012 13:56:24 +0200 Subject: [PATCH 02/20] Add a vio capabilites function to let a module define its capabilities. --- modules/csync_owncloud.c | 12 ++++++++++++ src/csync.c | 28 ---------------------------- src/csync.h | 17 ----------------- src/csync_private.h | 1 + src/csync_propagate.c | 2 +- src/vio/csync_vio.c | 11 +++++++++++ src/vio/csync_vio_method.h | 9 +++++++++ 7 files changed, 34 insertions(+), 46 deletions(-) diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index 3f7362f636..0b82f7db16 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -896,6 +896,17 @@ static void install_content_reader( ne_request *req, void *userdata, const ne_st static char*_lastDir = NULL; +/* capabilities are currently: + * bool atomar_copy_support + */ + +static csync_vio_capabilities_t _owncloud_capabilities = { true }; + +static csync_vio_capabilities_t *owncloud_get_capabilities(void) +{ + return &_owncloud_capabilities; +} + static csync_vio_method_handle_t *owncloud_open(const char *durl, int flags, mode_t mode) { @@ -1545,6 +1556,7 @@ static int owncloud_utimes(const char *uri, const struct timeval *times) { csync_vio_method_t _method = { .method_table_size = sizeof(csync_vio_method_t), + .get_capabilities = owncloud_get_capabilities, .open = owncloud_open, .creat = owncloud_creat, .close = owncloud_close, diff --git a/src/csync.c b/src/csync.c index bcd02d1380..89354a9496 100644 --- a/src/csync.c +++ b/src/csync.c @@ -121,7 +121,6 @@ int csync_create(CSYNC **csync, const char *local, const char *remote) { ctx->options.unix_extensions = 0; ctx->options.with_conflict_copys=false; ctx->options.local_only_mode = false; - ctx->options.remote_push_atomar = false; ctx->pwd.uid = getuid(); ctx->pwd.euid = geteuid(); @@ -938,33 +937,6 @@ bool csync_get_local_only(CSYNC *ctx) { return ctx->options.local_only_mode; } -int csync_set_remote_push_atomar(CSYNC *ctx, bool is_atomar) { - if(ctx == NULL) { - return -1; - } - - ctx->error_code = CSYNC_ERR_NONE; - - if (ctx->status & CSYNC_STATUS_PROPAGATE) { - fprintf(stderr, "This function must be called before propagation."); - ctx->error_code = CSYNC_ERR_UNSPEC; - return -1; - } - - ctx->options.remote_push_atomar = is_atomar; - - return 0; -} - -bool csync_get_remote_push_atomar(CSYNC *ctx) { - if (ctx == NULL) { - return -1; - } - ctx->error_code = CSYNC_ERR_NONE; - - return ctx->options.remote_push_atomar; -} - CSYNC_ERROR_CODE csync_get_error(CSYNC *ctx) { if (ctx == NULL) { return CSYNC_ERR_PARAM; diff --git a/src/csync.h b/src/csync.h index 087e5b5729..81d07517cb 100644 --- a/src/csync.h +++ b/src/csync.h @@ -375,23 +375,6 @@ int csync_set_local_only( CSYNC *ctx, bool local_only ); */ bool csync_get_local_only( CSYNC *ctx ); -/** - * @brief Flag to tell csync that the push to remote is atomar and no temp file is needed. - * - * @param local_only Bool flag to indicate atomar remote push - * - * @return 0 on success, less than 0 if an error occured. - */ -int csync_set_remote_push_atomar(CSYNC *ctx, bool is_atomar); - -/** - * @brief Retrieve the flag if the remote push is atomar and needs no temp file in between. - * - * @return 1: remote push is atomar, 0: use temp file to push - */ -bool csync_get_remote_push_atomar( CSYNC *ctx ); - - /* Used for special modes or debugging */ int csync_get_status(CSYNC *ctx); diff --git a/src/csync_private.h b/src/csync_private.h index 2b4d9359a8..b0160b5403 100644 --- a/src/csync_private.h +++ b/src/csync_private.h @@ -108,6 +108,7 @@ struct csync_s { void *handle; csync_vio_method_t *method; csync_vio_method_finish_fn finish_fn; + csync_vio_capabilities_t capabilities; } module; struct { diff --git a/src/csync_propagate.c b/src/csync_propagate.c index 103ce010ee..013013697b 100644 --- a/src/csync_propagate.c +++ b/src/csync_propagate.c @@ -51,7 +51,7 @@ static bool _push_to_tmp_first(CSYNC *ctx) if( ctx->current == REMOTE_REPLCIA ) return true; /* Always push to tmp for destination local file system */ /* If destination is the remote replica check if the switch is set. */ - if( !ctx->options.remote_push_atomar ) return true; /* DO push to tmp first */ + if( !ctx->module.capabilities.atomar_copy_support ) return true; return false; } diff --git a/src/vio/csync_vio.c b/src/vio/csync_vio.c index e4a5811097..2734c0b1d7 100644 --- a/src/vio/csync_vio.c +++ b/src/vio/csync_vio.c @@ -128,6 +128,13 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) { return -1; } + /* Useful defaults to the module capabilities */ + ctx->module.capabilities.atomar_copy_support = false; + + /* Load the module capabilities from the module if it implements the it. */ + if( VIO_METHOD_HAS_FUNC(m, get_capabilities)) { + ctx->module.capabilities = *(m->get_capabilities()); + } *(void **) (&init_fn) = dlsym(ctx->module.handle, "vio_module_init"); if ((err = dlerror()) != NULL) { @@ -166,6 +173,10 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) { return -1; } + if(! VIO_METHOD_HAS_FUNC(m, get_capabilities)) { + CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "module %s has no capabilities fn", module); + } + if (! VIO_METHOD_HAS_FUNC(m, open)) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "module %s has no stat fn", module); return -1; diff --git a/src/vio/csync_vio_method.h b/src/vio/csync_vio_method.h index 54848068b0..6cf246f408 100644 --- a/src/vio/csync_vio_method.h +++ b/src/vio/csync_vio_method.h @@ -35,10 +35,18 @@ typedef struct csync_vio_method_s csync_vio_method_t; +struct csync_vio_capabilities_s { + bool atomar_copy_support; +}; + +typedef struct csync_vio_capabilities_s csync_vio_capabilities_t; + typedef csync_vio_method_t *(*csync_vio_method_init_fn)(const char *method_name, const char *config_args, csync_auth_callback cb, void *userdata); typedef void (*csync_vio_method_finish_fn)(csync_vio_method_t *method); +typedef csync_vio_capabilities_t *(*csync_method_get_capabilities_fn)(void); + typedef csync_vio_method_handle_t *(*csync_method_open_fn)(const char *durl, int flags, mode_t mode); typedef csync_vio_method_handle_t *(*csync_method_creat_fn)(const char *durl, mode_t mode); typedef int (*csync_method_close_fn)(csync_vio_method_handle_t *fhandle); @@ -64,6 +72,7 @@ typedef int (*csync_method_utimes_fn)(const char *uri, const struct timeval time struct csync_vio_method_s { size_t method_table_size; /* Used for versioning */ + csync_method_get_capabilities_fn get_capabilities; csync_method_open_fn open; csync_method_creat_fn creat; csync_method_close_fn close; From 6eb4e707d9da50c0de40144e800502d2f8598363 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 4 Jul 2012 15:03:15 +0200 Subject: [PATCH 03/20] Add module capability about if a post copy size check is required. --- modules/csync_owncloud.c | 4 +-- src/csync_propagate.c | 66 ++++++++++++++++++++------------------ src/vio/csync_vio.c | 1 + src/vio/csync_vio_method.h | 3 ++ 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index 0b82f7db16..83e43b329f 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -898,9 +898,9 @@ static char*_lastDir = NULL; /* capabilities are currently: * bool atomar_copy_support + * bool do_post_copy_stat */ - -static csync_vio_capabilities_t _owncloud_capabilities = { true }; +static csync_vio_capabilities_t _owncloud_capabilities = { true, false }; static csync_vio_capabilities_t *owncloud_get_capabilities(void) { diff --git a/src/csync_propagate.c b/src/csync_propagate.c index 013013697b..8b7e9a69b2 100644 --- a/src/csync_propagate.c +++ b/src/csync_propagate.c @@ -285,46 +285,50 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) { } dfp = NULL; - /* - * Check filesize - */ - ctx->replica = drep; - tstat = csync_vio_file_stat_new(); - if (tstat == NULL) { - strerror_r(errno, errbuf, sizeof(errbuf)); - CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, - "file: %s, command: stat, error: %s", - turi, - errbuf); - rc = -1; - goto out; - } -#if 0 - if (csync_vio_stat(ctx, turi, tstat) < 0) { - switch (errno) { + if( ctx->module.capabilities.do_post_copy_stat ) { + /* + * Check filesize + * In case the transport is secure and/or the stat is expensive, this check + * could be skipped through module capabilities definitions. + */ + + ctx->replica = drep; + tstat = csync_vio_file_stat_new(); + if (tstat == NULL) { + strerror_r(errno, errbuf, sizeof(errbuf)); + CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, + "file: %s, command: stat, error: %s", + turi, + errbuf); + rc = -1; + goto out; + } + + if (csync_vio_stat(ctx, turi, tstat) < 0) { + switch (errno) { case ENOMEM: rc = -1; break; default: rc = 1; break; + } + strerror_r(errno, errbuf, sizeof(errbuf)); + CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, + "file: %s, command: stat, error: %s", + turi, + errbuf); + goto out; } - strerror_r(errno, errbuf, sizeof(errbuf)); - CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, - "file: %s, command: stat, error: %s", - turi, - errbuf); - goto out; - } - if (st->size != tstat->size) { - CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, - "file: %s, error: incorrect filesize (size: %jd should be %jd)", - turi, tstat->size, st->size); - rc = 1; - goto out; + if (st->size != tstat->size) { + CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, + "file: %s, error: incorrect filesize (size: %jd should be %jd)", + turi, tstat->size, st->size); + rc = 1; + goto out; + } } -#endif if (_push_to_tmp_first(ctx)) { /* override original file */ diff --git a/src/vio/csync_vio.c b/src/vio/csync_vio.c index 2734c0b1d7..23a7d65e09 100644 --- a/src/vio/csync_vio.c +++ b/src/vio/csync_vio.c @@ -130,6 +130,7 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) { /* Useful defaults to the module capabilities */ ctx->module.capabilities.atomar_copy_support = false; + ctx->module.capabilities.do_post_copy_stat = true; /* Load the module capabilities from the module if it implements the it. */ if( VIO_METHOD_HAS_FUNC(m, get_capabilities)) { diff --git a/src/vio/csync_vio_method.h b/src/vio/csync_vio_method.h index 6cf246f408..e5876e2050 100644 --- a/src/vio/csync_vio_method.h +++ b/src/vio/csync_vio_method.h @@ -35,8 +35,11 @@ typedef struct csync_vio_method_s csync_vio_method_t; +/* module capabilities definition. + * remember to set useful defaults in csync_vio.c if you add something here. */ struct csync_vio_capabilities_s { bool atomar_copy_support; + bool do_post_copy_stat; }; typedef struct csync_vio_capabilities_s csync_vio_capabilities_t; From de209ecdb9816739ea1eca753475c6c61cd889f3 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 4 Jul 2012 16:32:17 +0200 Subject: [PATCH 04/20] ownCloud: Don't require time sync between server and client. --- modules/csync_owncloud.c | 22 ++++++++++++++++------ src/csync.c | 38 ++++++++++++++++++++++---------------- src/vio/csync_vio.c | 2 ++ src/vio/csync_vio_method.h | 7 +++++-- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index 83e43b329f..8568460013 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -553,7 +553,7 @@ static int fetch_resource_list( const char *curi, dav_session.time_delta = time_diff; /* DEBUG_WEBDAV("%d <0> %d", server_time, now); */ - dav_session.time_delta = time_diff; + } ne_propfind_destroy(hdl); @@ -594,7 +594,7 @@ static csync_vio_file_stat_t *resourceToFileStat( struct resource *res ) DEBUG_WEBDAV("WRN: Delta time not yet computed."); lfs->mtime = res->modtime; } else { - lfs->mtime = res->modtime + dav_session.time_delta; + lfs->mtime = res->modtime - dav_session.time_delta; } lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; lfs->size = res->size; @@ -897,13 +897,18 @@ static void install_content_reader( ne_request *req, void *userdata, const ne_st static char*_lastDir = NULL; /* capabilities are currently: - * bool atomar_copy_support - * bool do_post_copy_stat + * bool atomar_copy_support - oC provides atomar copy + * bool do_post_copy_stat - oC does not want the post copy check + * bool time_sync_required - oC does not require the time sync + * int unix_extensions - oC supports unix extensions. */ -static csync_vio_capabilities_t _owncloud_capabilities = { true, false }; +static csync_vio_capabilities_t _owncloud_capabilities = { true, false, false, 1 }; static csync_vio_capabilities_t *owncloud_get_capabilities(void) { +#ifdef _WIN32 + _owncloud_capabilities.unix_extensions = 0; +#endif return &_owncloud_capabilities; } @@ -1520,6 +1525,8 @@ static int owncloud_utimes(const char *uri, const struct timeval *times) { int rc = NE_OK; char val[255]; char *curi = NULL; + const struct timeval *modtime = times+1; + long newmodtime; curi = _cleanPath( uri ); @@ -1534,7 +1541,10 @@ static int owncloud_utimes(const char *uri, const struct timeval *times) { pname.nspace = NULL; pname.name = "lastmodified"; - snprintf( val, sizeof(val), "%ld", times->tv_sec ); + newmodtime = modtime->tv_sec; + newmodtime += dav_session.time_delta; + + snprintf( val, sizeof(val), "%ld", newmodtime ); DEBUG_WEBDAV("Setting LastModified of %s to %s", curi, val ); ops[0].name = &pname; diff --git a/src/csync.c b/src/csync.c index 89354a9496..32393a024f 100644 --- a/src/csync.c +++ b/src/csync.c @@ -315,28 +315,34 @@ retry_vio_init: } if( !ctx->options.local_only_mode ) { + if(ctx->module.capabilities.time_sync_required) { timediff = csync_timediff(ctx); if (timediff > ctx->options.max_time_difference) { - 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; + 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; + /* 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(ctx->module.capabilities.unix_extensions == -1) { /* detect */ 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; + CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Could not detect filesystem type."); + ctx->error_code = CSYNC_ERR_FILESYSTEM; + rc = -1; + goto out; } + } else { + /* The module specifies the value for the unix_extensions. */ + ctx->options.unix_extensions = ctx->module.capabilities.unix_extensions; + } } if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) { diff --git a/src/vio/csync_vio.c b/src/vio/csync_vio.c index 23a7d65e09..0685427eba 100644 --- a/src/vio/csync_vio.c +++ b/src/vio/csync_vio.c @@ -131,6 +131,8 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) { /* Useful defaults to the module capabilities */ ctx->module.capabilities.atomar_copy_support = false; ctx->module.capabilities.do_post_copy_stat = true; + ctx->module.capabilities.time_sync_required = true; + ctx->module.capabilities.unix_extensions = -1; /* detect automatically */ /* Load the module capabilities from the module if it implements the it. */ if( VIO_METHOD_HAS_FUNC(m, get_capabilities)) { diff --git a/src/vio/csync_vio_method.h b/src/vio/csync_vio_method.h index e5876e2050..814504f98d 100644 --- a/src/vio/csync_vio_method.h +++ b/src/vio/csync_vio_method.h @@ -38,8 +38,11 @@ typedef struct csync_vio_method_s csync_vio_method_t; /* module capabilities definition. * remember to set useful defaults in csync_vio.c if you add something here. */ struct csync_vio_capabilities_s { - bool atomar_copy_support; - bool do_post_copy_stat; + bool atomar_copy_support; /* set to true if the backend provides atomar copy */ + bool do_post_copy_stat; /* true if csync should check the copy afterwards */ + bool time_sync_required; /* true if local and remote need to be time synced */ + int unix_extensions; /* -1: do csync detection, 0: no unix extensions, + 1: extensions available */ }; typedef struct csync_vio_capabilities_s csync_vio_capabilities_t; From b9329f2991514bc2604017b09b34e75cc0d65c4a Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 9 Jul 2012 14:09:34 +0200 Subject: [PATCH 05/20] undef malloc only if not doing UNIT_TESTING. --- src/std/c_lib.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/std/c_lib.h b/src/std/c_lib.h index 04cea91f96..8e67e679c7 100644 --- a/src/std/c_lib.h +++ b/src/std/c_lib.h @@ -34,6 +34,7 @@ #include "c_time.h" #include "c_private.h" +#ifndef UNIT_TESTING #ifdef malloc #undef malloc #endif @@ -44,6 +45,8 @@ #endif #define calloc(x,y) DO_NOT_CALL_CALLOC__USE_C_CALLOC_INSTEAD +#endif + #ifdef realloc #undef realloc #endif From 9eae6d88fd774038eb6b2df508ffd6fccc4bdc8c Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 9 Jul 2012 14:10:04 +0200 Subject: [PATCH 06/20] Add ownCloud directory in tests. --- tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9d2f4831b3..340c761b8a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -52,3 +52,5 @@ macro_add_check_test(check_vio vio_tests/check_vio.c ${TEST_TARGET_LIBRARIES}) # sync macro_add_check_test(check_csync_update csync_tests/check_csync_update.c ${TEST_TARGET_LIBRARIES}) +add_subdirectory(ownCloud) + From 5b79f1feca7a97ba4b1b9e1a6c2621d11f227fd6 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 9 Jul 2012 14:16:20 +0200 Subject: [PATCH 07/20] Added mocka tests for the ownCloud module. --- tests/ownCloud/CMakeLists.txt | 1 + tests/ownCloud/mocka/CMakeLists.txt | 15 ++++++ tests/ownCloud/mocka/ocmod_test.c | 78 +++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 tests/ownCloud/CMakeLists.txt create mode 100644 tests/ownCloud/mocka/CMakeLists.txt create mode 100644 tests/ownCloud/mocka/ocmod_test.c diff --git a/tests/ownCloud/CMakeLists.txt b/tests/ownCloud/CMakeLists.txt new file mode 100644 index 0000000000..fc12494d31 --- /dev/null +++ b/tests/ownCloud/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(mocka) diff --git a/tests/ownCloud/mocka/CMakeLists.txt b/tests/ownCloud/mocka/CMakeLists.txt new file mode 100644 index 0000000000..ee3f86a45c --- /dev/null +++ b/tests/ownCloud/mocka/CMakeLists.txt @@ -0,0 +1,15 @@ +project( ocmod C ) + +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMOCKA_INCLUDE_DIRS} + ${NEON_INCLUDE_DIRS} +) +find_package(CMocka REQUIRED) + +add_definitions(-DUNIT_TESTING=1) + +add_executable(ocmod_test ocmod_test.c) +target_link_libraries(ocmod_test ${CMOCKA_LIBRARIES} ${NEON_LIBRARIES} ${CSYNC_LIBRARY} ) + diff --git a/tests/ownCloud/mocka/ocmod_test.c b/tests/ownCloud/mocka/ocmod_test.c new file mode 100644 index 0000000000..53914aeee7 --- /dev/null +++ b/tests/ownCloud/mocka/ocmod_test.c @@ -0,0 +1,78 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include +#include +#include + +#include "../../modules/csync_owncloud.c" +#include + +// A test case that does nothing and succeeds. +static void null_test_success(void **state) { + (void) state; +} + + +static void connect_test_success(void **state) { + const char *url = "owncloud://kf:12345@localhost/oc"; + int re; + + re = dav_connect( url ); + assert_int_equal( re, 0 ); + assert_int_equal( _connected, 1 ); + assert_int_equal( dav_session.time_delta_sum, 0); + assert_int_equal( dav_session.time_delta_cnt, 0); +} + +static void fetch_a_context() { + struct listdir_context *fetchCtx = NULL; + char *curi = _cleanPath("http://localhost/oc/files/webdav.php/"); + + int rc = 0; + + fetchCtx = c_malloc( sizeof( struct listdir_context )); + fetchCtx->target = curi; + fetchCtx->include_target = 1; + + rc = fetch_resource_list( curi, NE_DEPTH_ONE, fetchCtx ); + assert_int_equal( rc, 0 ); + printf("Results: %d\n", fetchCtx->result_count); + + fetchCtx->currResource = fetchCtx->list; + for( int i = 0; i < fetchCtx->result_count; i++ ) { + assert_true( fetchCtx->currResource != NULL ); + assert_true( fetchCtx->currResource->uri != NULL ); + assert_true( fetchCtx->currResource->name != NULL ); + + printf( " %s -> %s\n", fetchCtx->currResource->uri, fetchCtx->currResource->name ); + fetchCtx->currResource = fetchCtx->currResource->next; + } + +} + + +int main(void) { + const UnitTest tests[] = { + unit_test(null_test_success), + unit_test(connect_test_success), + unit_test(fetch_a_context), + }; + + return run_tests(tests); +} From 9e81fd38e198b1c46d4ab50f45a3706cfc2eaaee Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 9 Jul 2012 14:29:17 +0200 Subject: [PATCH 08/20] Added CMocka find module for cmake. --- cmake/Modules/FindCMocka.cmake | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 cmake/Modules/FindCMocka.cmake diff --git a/cmake/Modules/FindCMocka.cmake b/cmake/Modules/FindCMocka.cmake new file mode 100644 index 0000000000..f0285afdcb --- /dev/null +++ b/cmake/Modules/FindCMocka.cmake @@ -0,0 +1,41 @@ +# - Try to find CMocka, the testing framework +# Once done this will define +# +# CMOCKA_FOUND - system has CMocka +# CMOCKA_INCLUDE_DIRS - the CMocka include directory +# CMOCKA_LIBRARIES - Link these to use CMocka +# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka +# +# Copyright (c) 2007 Andreas Schneider +# (c) 2012 Dominik Schmidt +# (c) 2012 Klaas Freitag +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + +include(GNUInstallDirs) + +find_path(CMOCKA_INCLUDE_DIRS + NAMES + cmocka.h + HINTS + ${CMAKE_INSTALL_INCLUDEDIR} +) + +find_library(CMOCKA_LIBRARIES + NAMES + cmocka + HINTS + ${CMAKE_INSTALL_PREFIX}/lib + ${CMAKE_INSTALL_PREFIX}/lib64 + ${CMAKE_INSTALL_LIBDIR} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Cmocka + REQUIRED_VARS CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIRS +) + + From 43685f69a3b768d80c5a230435c092871a0d9132 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 9 Jul 2012 14:45:05 +0200 Subject: [PATCH 09/20] do the capabilities after the module was initialized. --- src/vio/csync_vio.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/vio/csync_vio.c b/src/vio/csync_vio.c index 0685427eba..70d84417e2 100644 --- a/src/vio/csync_vio.c +++ b/src/vio/csync_vio.c @@ -128,17 +128,6 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) { return -1; } - /* Useful defaults to the module capabilities */ - ctx->module.capabilities.atomar_copy_support = false; - ctx->module.capabilities.do_post_copy_stat = true; - ctx->module.capabilities.time_sync_required = true; - ctx->module.capabilities.unix_extensions = -1; /* detect automatically */ - - /* Load the module capabilities from the module if it implements the it. */ - if( VIO_METHOD_HAS_FUNC(m, get_capabilities)) { - ctx->module.capabilities = *(m->get_capabilities()); - } - *(void **) (&init_fn) = dlsym(ctx->module.handle, "vio_module_init"); if ((err = dlerror()) != NULL) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "loading function failed - %s", err); @@ -160,6 +149,17 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) { return -1; } + /* Useful defaults to the module capabilities */ + ctx->module.capabilities.atomar_copy_support = false; + ctx->module.capabilities.do_post_copy_stat = true; + ctx->module.capabilities.time_sync_required = true; + ctx->module.capabilities.unix_extensions = -1; /* detect automatically */ + + /* Load the module capabilities from the module if it implements the it. */ + if( VIO_METHOD_HAS_FUNC(m, get_capabilities)) { + ctx->module.capabilities = *(m->get_capabilities()); + } + /* Some basic checks */ if (m->method_table_size == 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "module %s method table size is 0", module); From 7b261077a287daab2489bdbc72a5b814d3c380cc Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 9 Jul 2012 14:45:25 +0200 Subject: [PATCH 10/20] Avoid compile warning and use an unsigned variable. --- tests/ownCloud/mocka/ocmod_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ownCloud/mocka/ocmod_test.c b/tests/ownCloud/mocka/ocmod_test.c index 53914aeee7..8551232ccf 100644 --- a/tests/ownCloud/mocka/ocmod_test.c +++ b/tests/ownCloud/mocka/ocmod_test.c @@ -55,7 +55,7 @@ static void fetch_a_context() { printf("Results: %d\n", fetchCtx->result_count); fetchCtx->currResource = fetchCtx->list; - for( int i = 0; i < fetchCtx->result_count; i++ ) { + for( uint i = 0; i < fetchCtx->result_count; i++ ) { assert_true( fetchCtx->currResource != NULL ); assert_true( fetchCtx->currResource->uri != NULL ); assert_true( fetchCtx->currResource->name != NULL ); From 0ed8c57cadd834872f847f792a200bd05fd2af38 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Mon, 9 Jul 2012 16:46:14 +0200 Subject: [PATCH 11/20] make proper logging of the module capabilities. --- src/vio/csync_vio.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/vio/csync_vio.c b/src/vio/csync_vio.c index 70d84417e2..aaa4372192 100644 --- a/src/vio/csync_vio.c +++ b/src/vio/csync_vio.c @@ -160,6 +160,15 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) { ctx->module.capabilities = *(m->get_capabilities()); } + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "capabilities: atomar copy support: %s", + ctx->module.capabilities.atomar_copy_support ? "yes": "no"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "capabilities: post copy stat: %s", + ctx->module.capabilities.do_post_copy_stat ? "yes": "no"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "capabilities: time sync required: %s", + ctx->module.capabilities.time_sync_required ? "yes": "no"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "capabilities: unix extensions: %d", + ctx->module.capabilities.unix_extensions ); + /* Some basic checks */ if (m->method_table_size == 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "module %s method table size is 0", module); From 81e77afaec1fcd10dc876c6b55411172367baf95 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 11 Jul 2012 16:02:43 +0200 Subject: [PATCH 12/20] cleaner logging of time delta. --- modules/csync_owncloud.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index 8568460013..294c3e27f9 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -543,10 +543,12 @@ static int fetch_resource_list( const char *curi, /* check the changing of the time delta */ time_diff_delta = llabs(dav_session.time_delta - time_diff); - if( time_diff_delta > 5 ) { + if( dav_session.time_delta_cnt == 1 ) { + DEBUG_WEBDAV( "The first time_delta is %d", time_diff ); + } else if( dav_session.time_delta_cnt > 1 && time_diff_delta > 5 ) { DEBUG_WEBDAV("WRN: The time delta changed more than 5 second"); } else if( time_diff_delta == 0) { - DEBUG_WEBDAV("Ok: Time delta remained the same."); + DEBUG_WEBDAV("XXXX Ok: Time delta remained the same: %ld.", time_diff); } else { DEBUG_WEBDAV("Difference to last server time delta: %d", time_diff_delta ); } @@ -554,7 +556,10 @@ static int fetch_resource_list( const char *curi, /* DEBUG_WEBDAV("%d <0> %d", server_time, now); */ + } else { + DEBUG_WEBDAV("WRN: propfind named failed with %d", ret); } + ne_propfind_destroy(hdl); return ret; @@ -591,7 +596,6 @@ static csync_vio_file_stat_t *resourceToFileStat( struct resource *res ) /* Correct the mtime of the file with the server time delta */ if( dav_session.time_delta_cnt == 0 ) { - DEBUG_WEBDAV("WRN: Delta time not yet computed."); lfs->mtime = res->modtime; } else { lfs->mtime = res->modtime - dav_session.time_delta; From 59202fffe4fc402c495174fb88111a74266b9b10 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 11 Jul 2012 16:03:31 +0200 Subject: [PATCH 13/20] fixed spaces and logging if timesync is needed for the module. --- src/csync.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/csync.c b/src/csync.c index 32393a024f..4f5bb09f3c 100644 --- a/src/csync.c +++ b/src/csync.c @@ -314,7 +314,7 @@ retry_vio_init: ctx->remote.type = LOCAL_REPLICA; } - if( !ctx->options.local_only_mode ) { + if(!ctx->options.local_only_mode) { if(ctx->module.capabilities.time_sync_required) { timediff = csync_timediff(ctx); if (timediff > ctx->options.max_time_difference) { @@ -331,7 +331,10 @@ retry_vio_init: rc = -1; goto out; } + } else { + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Module does not need time synchronization."); } + if(ctx->module.capabilities.unix_extensions == -1) { /* detect */ if (csync_unix_extensions(ctx) < 0) { CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "Could not detect filesystem type."); From e90b4a13b334fb20803732c02fa512676fffef66 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 11 Jul 2012 16:05:40 +0200 Subject: [PATCH 14/20] Added logging of the time values. --- src/csync_update.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/csync_update.c b/src/csync_update.c index 22190d875f..c69ab32782 100644 --- a/src/csync_update.c +++ b/src/csync_update.c @@ -101,6 +101,8 @@ static int _csync_detect_update(CSYNC *ctx, const char *file, tmp = csync_statedb_get_stat_by_hash(ctx, h); if (tmp && tmp->phash == h) { /* we have an update! */ + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "time compare: %lu <-> %lu", + fs->mtime, tmp->modtime); if (fs->mtime > tmp->modtime) { st->instruction = CSYNC_INSTRUCTION_EVAL; goto out; From 1866956984e916b466bfc42275d82d88662fd2ee Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 11 Jul 2012 16:48:38 +0200 Subject: [PATCH 15/20] use lstat instead of stat to stat files. Avoids problems with links. --- src/std/c_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/std/c_private.h b/src/std/c_private.h index 726520b5b1..f7a0e00f4c 100644 --- a/src/std/c_private.h +++ b/src/std/c_private.h @@ -106,7 +106,7 @@ typedef char _TCHAR; #define _ttelldir telldir #define _tseekdir seekdir #define _tcreat creat -#define _tstat stat +#define _tstat lstat #define _tunlink unlink #define _tmkdir mkdir #define _trmdir rmdir From b74fc47e3fbc396d1e83de8917cb9d1106c81819 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 11 Jul 2012 16:50:25 +0200 Subject: [PATCH 16/20] More unit testing of the ownCloud module with mocka. --- CMakeLists.txt | 4 + tests/ownCloud/mocka/ocmod_test.c | 235 ++++++++++++++++++++++++++++-- 2 files changed, 230 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 957ba9822e..23d5352e25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,10 @@ endif() include(ConfigureChecks.cmake) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) + +set(SOURCE_DIR ${CMAKE_SOURCE_DIR}) +configure_file(config_test.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_test.h) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake) diff --git a/tests/ownCloud/mocka/ocmod_test.c b/tests/ownCloud/mocka/ocmod_test.c index 8551232ccf..77b8030e8a 100644 --- a/tests/ownCloud/mocka/ocmod_test.c +++ b/tests/ownCloud/mocka/ocmod_test.c @@ -15,14 +15,73 @@ */ +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include #include #include #include +#include +#include #include "../../modules/csync_owncloud.c" #include +#include "config_test.h" + +struct oc_credentials { + const char *url; + const char *user; + const char *pwd; + char *oc_server; + +} _credentials; + + +static bool load_oc_config( const char *config ) { + dictionary *dict; + const char* val; + bool re = true; + + dict = iniparser_load( config ); + + if( ! dict ) { + printf("Could not load config %s\n", config); + return false; + } + + val = iniparser_getstr(dict, "global:host"); + if( val ) { + _credentials.url = c_strdup( val ); + } else { + re = false; + } + + val = iniparser_getstr(dict, "global:user"); + if( re && val ) { + _credentials.user = c_strdup( val ); + } else { + re = false; + } + + val = iniparser_getstr(dict, "global:pwd"); + if( re && val ) { + _credentials.pwd = c_strdup( val ); + } else { + re = false; + } + + if( re ) { + asprintf(&(_credentials.oc_server), + "owncloud://%s:%s@%s/files/webdav.php", + _credentials.user, _credentials.pwd, + _credentials.url ); + } + + return re; +} + + // A test case that does nothing and succeeds. static void null_test_success(void **state) { (void) state; @@ -30,22 +89,31 @@ static void null_test_success(void **state) { static void connect_test_success(void **state) { - const char *url = "owncloud://kf:12345@localhost/oc"; - int re; - - re = dav_connect( url ); + + int re = 0; + char buf[255]; + + (void) state; + strcpy(buf, TEST_CONFIG_DIR); + strcat(buf, "test.cfg"); + + assert_true( load_oc_config( buf )); + + re = dav_connect( _credentials.oc_server ); + assert_int_equal( re, 0 ); assert_int_equal( _connected, 1 ); assert_int_equal( dav_session.time_delta_sum, 0); assert_int_equal( dav_session.time_delta_cnt, 0); } -static void fetch_a_context() { +static void fetch_a_context(void **state) { struct listdir_context *fetchCtx = NULL; - char *curi = _cleanPath("http://localhost/oc/files/webdav.php/"); - + char *curi = _cleanPath(_credentials.oc_server); int rc = 0; - + + (void) state; + fetchCtx = c_malloc( sizeof( struct listdir_context )); fetchCtx->target = curi; fetchCtx->include_target = 1; @@ -62,8 +130,154 @@ static void fetch_a_context() { printf( " %s -> %s\n", fetchCtx->currResource->uri, fetchCtx->currResource->name ); fetchCtx->currResource = fetchCtx->currResource->next; + } +} + +static int test_mkdir(const char *dir) { + char path[255]; + + strcpy( path, _credentials.oc_server ); + strcat( path, "/"); + strcat( path, dir ); + + return owncloud_mkdir( path, 775 ); +} + +static void setup_toplevel_dir( void **state ) { + char basepath[255]; + + strcpy( basepath, "tXXXXXX"); + assert_int_equal( c_tmpname(basepath), 0 ); + printf("Using top testing dir %s\n", basepath); + assert_int_equal( test_mkdir( basepath ), 0 ); + *state = (void*) c_strdup(basepath); +} + +static void teardown_toplevel_dir( void **state ) { + (void) state; +} + +static void stat_local_file( csync_stat_t *sb, const char *file ) +{ + const _TCHAR *mpath = NULL; + mpath = c_multibyte(file); + assert_int_not_equal(_tstat(mpath, sb), -1); + c_free_multibyte(mpath); +} + +#define BUFSIZE 4096 +static size_t upload_a_file( void **state, const char *src_name, const char *durl ) { + + char buffer[BUFSIZE+1]; + int size; + char path[256]; + char src_path[256]; + int fh; + csync_vio_method_handle_t *handle; + size_t written; + size_t overall_size = 0; + csync_stat_t sb; + + /* Create the target path */ + strcpy( path, _credentials.oc_server ); + strcat( path, "/"); + strcat( path, (const char*) *state ); + strcat( path, "/"); + strcat( path, durl ); + + handle = owncloud_creat( path, 0644 ); + assert_int_not_equal( handle, NULL ); + + strcpy(src_path, TESTFILES_DIR); + strcat(src_path, src_name); + fh = open(src_path, O_RDONLY); + assert_int_not_equal( fh, -1 ); + + while( (size = read(fh, buffer, BUFSIZE) )>0 ) { + buffer[size] = '\0'; + written = owncloud_write( handle, buffer, size ); + assert_int_equal( size, written ); + overall_size += written; } - + assert_int_equal( owncloud_close(handle), 0); + + /* stat the local file */ + stat_local_file( &sb, src_path ); + + assert_int_equal( overall_size, sb.st_size ); + + close(fh); + + return overall_size; +} + +static void test_upload_files( void **state ) { + const char *bpath = (char*) (*state); + + upload_a_file( state, "test.txt", "t1/test.txt"); + upload_a_file( state, "red_is_the_rose.jpg", "t1/red is the rose.jpg"); + + printf("Base path: %s\n", bpath); + +} + +static void download_a_file( const char* local, void **state, const char *durl) +{ + char buffer[BUFSIZE+1]; + char path[256]; + char local_path[256]; + + csync_vio_method_handle_t *handle; + size_t count; + size_t overall_size = 0; + csync_stat_t sb; + + /* Create the target path */ + strcpy( path, _credentials.oc_server ); + strcat( path, "/"); + strcat( path, (const char*) *state ); + strcat( path, "/"); + strcat( path, durl ); + + handle = owncloud_open( path, O_RDONLY, 0644 ); + assert_int_not_equal( handle, NULL ); + + while( (count = owncloud_read(handle, buffer, BUFSIZE)) > 0 ) { + overall_size += count; + } + assert_int_equal( owncloud_close(handle), 0 ); + + strcpy(local_path, TESTFILES_DIR); + strcat(local_path, local); + stat_local_file( &sb, local_path ); + + /* assert the download size, it has to be the same. */ + assert_int_equal( overall_size, sb.st_size ); + +} + +static void test_download_files( void **state ) { + const char *bpath = (char*) (*state); + + printf("Base path: %s\n", bpath); + + download_a_file( "test.txt", state, "t1/test.txt"); + download_a_file( "red_is_the_rose.jpg", state, "t1/red is the rose.jpg"); +} + +static void test_setup_dirs(void **state) { + const char *basepath = *state; + char path[255]; + + strcpy( path, basepath ); + strcat( path, "/t1" ); + assert_int_equal( test_mkdir( path ), 0 ); + + strcpy( path, basepath ); + strcat( path, "/t2"); + assert_int_equal( test_mkdir( path ), 0 ); + strcat( path, "/Übergröße"); + assert_int_equal( test_mkdir( path ), 0 ); } @@ -72,6 +286,9 @@ int main(void) { unit_test(null_test_success), unit_test(connect_test_success), unit_test(fetch_a_context), + unit_test_setup_teardown(test_setup_dirs, setup_toplevel_dir, teardown_toplevel_dir), + unit_test(test_upload_files), + unit_test(test_download_files), }; return run_tests(tests); From 5f93c490a5934b0fa4355c897ca69fa34e254b88 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 11 Jul 2012 18:01:08 +0200 Subject: [PATCH 17/20] Make ownCloud cmocka test build on the win32 platform. --- CMakeLists.txt | 6 ++++-- tests/CMakeLists.txt | 4 +++- tests/ownCloud/mocka/CMakeLists.txt | 8 +++++--- tests/ownCloud/mocka/ocmod_test.c | 13 +++++++++---- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23d5352e25..bec877d5d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,8 +65,10 @@ add_subdirectory(config) add_subdirectory(doc) find_package(Check) -if (CHECK_FOUND AND UNIT_TESTING) +if (CHECK_FOUND) include(MacroAddCheckTest) +endif (CHECK_FOUND) +if (UNIT_TESTING) add_subdirectory(tests) -endif (CHECK_FOUND AND UNIT_TESTING) +endif(UNIT_TESTING) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 340c761b8a..239a9fb42b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,10 +5,11 @@ set(SUPPORT_LIBRARY support) include_directories( ${CSYNC_PUBLIC_INCLUDE_DIRS} ${CSTDLIB_PUBLIC_INCLUDE_DIRS} - ${CHECK_INCLUDE_DIRS} ${CMAKE_BINARY_DIR} ) +if (CHECK_FOUND) +include_directories(${CHECK_INCLUDE_DIRS}) # create test library add_library(${SUPPORT_LIBRARY} STATIC support.c cmdline.c) target_link_libraries(${SUPPORT_LIBRARY} ${CHECK_LIBRARIES} ${CSYNC_LIBRARY} ${CSTDLIB_LIBRARY}) @@ -51,6 +52,7 @@ macro_add_check_test(check_vio vio_tests/check_vio.c ${TEST_TARGET_LIBRARIES}) # sync macro_add_check_test(check_csync_update csync_tests/check_csync_update.c ${TEST_TARGET_LIBRARIES}) +endif (CHECK_FOUND) add_subdirectory(ownCloud) diff --git a/tests/ownCloud/mocka/CMakeLists.txt b/tests/ownCloud/mocka/CMakeLists.txt index ee3f86a45c..2b4dbf7677 100644 --- a/tests/ownCloud/mocka/CMakeLists.txt +++ b/tests/ownCloud/mocka/CMakeLists.txt @@ -1,15 +1,17 @@ project( ocmod C ) +add_definitions(-DUNIT_TESTING=1) + +find_package(CMocka REQUIRED) + include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMOCKA_INCLUDE_DIRS} ${NEON_INCLUDE_DIRS} ) -find_package(CMocka REQUIRED) -add_definitions(-DUNIT_TESTING=1) add_executable(ocmod_test ocmod_test.c) -target_link_libraries(ocmod_test ${CMOCKA_LIBRARIES} ${NEON_LIBRARIES} ${CSYNC_LIBRARY} ) +target_link_libraries(ocmod_test ${CMOCKA_LIBRARIES} ${NEON_LIBRARIES} ${CSYNC_LIBRARY} ) diff --git a/tests/ownCloud/mocka/ocmod_test.c b/tests/ownCloud/mocka/ocmod_test.c index 77b8030e8a..943ce9ec15 100644 --- a/tests/ownCloud/mocka/ocmod_test.c +++ b/tests/ownCloud/mocka/ocmod_test.c @@ -42,6 +42,10 @@ static bool load_oc_config( const char *config ) { dictionary *dict; const char* val; bool re = true; + char *deflt; + char b; + deflt = &b; + dict = iniparser_load( config ); @@ -50,21 +54,21 @@ static bool load_oc_config( const char *config ) { return false; } - val = iniparser_getstr(dict, "global:host"); + val = iniparser_getstring(dict, "global:host", deflt); if( val ) { _credentials.url = c_strdup( val ); } else { re = false; } - val = iniparser_getstr(dict, "global:user"); + val = iniparser_getstring(dict, "global:user", deflt); if( re && val ) { _credentials.user = c_strdup( val ); } else { re = false; } - val = iniparser_getstr(dict, "global:pwd"); + val = iniparser_getstring(dict, "global:pwd", deflt); if( re && val ) { _credentials.pwd = c_strdup( val ); } else { @@ -111,6 +115,7 @@ static void fetch_a_context(void **state) { struct listdir_context *fetchCtx = NULL; char *curi = _cleanPath(_credentials.oc_server); int rc = 0; + unsigned int i; (void) state; @@ -123,7 +128,7 @@ static void fetch_a_context(void **state) { printf("Results: %d\n", fetchCtx->result_count); fetchCtx->currResource = fetchCtx->list; - for( uint i = 0; i < fetchCtx->result_count; i++ ) { + for( i = 0; i < fetchCtx->result_count; i++ ) { assert_true( fetchCtx->currResource != NULL ); assert_true( fetchCtx->currResource->uri != NULL ); assert_true( fetchCtx->currResource->name != NULL ); From 2b4261f15a3eba38483a74f99e4aa5cb4aaee385 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Wed, 18 Jul 2012 17:00:46 +0200 Subject: [PATCH 18/20] Added functions to generate MD5-Sums based on openssl with tests. --- src/CMakeLists.txt | 4 +- src/csync_util.c | 72 +++++++++++++++++++++++++++++ src/csync_util.h | 8 ++++ tests/ownCloud/mocka/CMakeLists.txt | 3 ++ tests/ownCloud/mocka/md5_test.c | 68 +++++++++++++++++++++++++++ 5 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 tests/ownCloud/mocka/md5_test.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8b6b4812ac..fb77c22f61 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory(std) find_package(SQLite3 REQUIRED) find_package(Iniparser REQUIRED) +find_package(OpenSSL REQUIRED) set(CSYNC_PUBLIC_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} @@ -12,6 +13,7 @@ set(CSYNC_PUBLIC_INCLUDE_DIRS ) set(CSYNC_PRIVATE_INCLUDE_DIRS + ${OPENSSL_INCLUDE_DIRS} ${INIPARSER_INCLUDE_DIRS} ${SQLITE3_INCLUDE_DIRS} ${CSTDLIB_PUBLIC_INCLUDE_DIRS} @@ -28,7 +30,7 @@ set(CSYNC_LINK_LIBRARIES ${CSTDLIB_LIBRARY} ${CSYNC_REQUIRED_LIBRARIES} ${INIPARSER_LIBRARIES} - + ${OPENSSL_LIBRARIES} ${SQLITE3_LIBRARIES} ) diff --git a/src/csync_util.c b/src/csync_util.c index 96e94372c3..0b68dbaaba 100644 --- a/src/csync_util.c +++ b/src/csync_util.c @@ -32,6 +32,14 @@ #include "csync_util.h" #include "vio/csync_vio.h" +#if defined(__APPLE__) +# define COMMON_DIGEST_FOR_OPENSSL +# include +# define SHA1 CC_SHA1 +#else +# include +#endif + #define CSYNC_LOG_CATEGORY_NAME "csync.util" #include "csync_log.h" @@ -326,4 +334,68 @@ uint64_t csync_create_statedb_hash(CSYNC *ctx) { return hash; } +static char* digest_to_out(unsigned char* digest) +{ + char *out = c_malloc(33); + int n; + + if( !digest ) return NULL; + + for (n = 0; n < 16; ++n) { + snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int) *(digest+n)); + } + + return out; +} + +#define BUF_SIZE 512 + +char* csync_file_md5(const char *filename) +{ + const char *tmpFileName; + int fd; + MD5_CTX c; + char buf[ BUF_SIZE+1 ]; + unsigned char digest[16]; + size_t size; + + tmpFileName = c_multibyte( filename ); + + if ( (fd = _topen( tmpFileName, O_RDONLY )) < 0) { + return NULL; + } else { + MD5_Init(&c); + while( (size=read(fd, buf, BUF_SIZE )) > 0) { + buf[size]='\0'; + MD5_Update(&c, buf, size); + } + close(fd); + MD5_Final(digest, &c); + } + + c_free_multibyte(tmpFileName); + return digest_to_out(digest); +} + +char* csync_buffer_md5(const char *str, int length) +{ + MD5_CTX c; + unsigned char digest[16]; + + MD5_Init(&c); + + while (length > 0) { + if (length > 512) { + MD5_Update(&c, str, 512); + } else { + MD5_Update(&c, str, length); + } + length -= 512; + str += 512; + } + + MD5_Final(digest, &c); + return digest_to_out(digest); +} + /* vim: set ts=8 sw=2 et cindent: */ diff --git a/src/csync_util.h b/src/csync_util.h index e7231b85db..96727b4e6e 100644 --- a/src/csync_util.h +++ b/src/csync_util.h @@ -36,5 +36,13 @@ int csync_unix_extensions(CSYNC *ctx); /* Normalize the uri to / */ uint64_t csync_create_statedb_hash(CSYNC *ctx); +/* Calculate the md5 sum for a file given by filename. + * Caller has to free the memory. */ +char* csync_file_md5(const char *filename); + +/* Create an md5 sum from a data pointer with a given length. + * Caller has to free the memory */ +char* csync_buffer_md5(const char *str, int length); + #endif /* _CSYNC_UTIL_H */ /* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */ diff --git a/tests/ownCloud/mocka/CMakeLists.txt b/tests/ownCloud/mocka/CMakeLists.txt index 2b4dbf7677..f329d0e61c 100644 --- a/tests/ownCloud/mocka/CMakeLists.txt +++ b/tests/ownCloud/mocka/CMakeLists.txt @@ -13,5 +13,8 @@ include_directories( add_executable(ocmod_test ocmod_test.c) +add_executable(md5_test md5_test.c) + target_link_libraries(ocmod_test ${CMOCKA_LIBRARIES} ${NEON_LIBRARIES} ${CSYNC_LIBRARY} ) +target_link_libraries(md5_test ${CMOCKA_LIBRARIES} ${CSYNC_LIBRARY} ) diff --git a/tests/ownCloud/mocka/md5_test.c b/tests/ownCloud/mocka/md5_test.c new file mode 100644 index 0000000000..1975b1576c --- /dev/null +++ b/tests/ownCloud/mocka/md5_test.c @@ -0,0 +1,68 @@ +/* + * Copyright 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include "config_test.h" + + +static void test_md5_buffer(void **state) { + const char *t1 = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."; + const char *t2 = "This is a nice md5 test"; + const char *t3 = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."; + + (void) state; + assert_string_equal( csync_buffer_md5(t1, strlen(t1)), "dbcb1ed05ecf975f532604f2d2000246"); + assert_string_equal( csync_buffer_md5(t2, strlen(t2)), "65236ae09754bca371fb869384040141"); + assert_string_equal( csync_buffer_md5(t3, strlen(t3)), "651f37892a9df60ed087bc7a1c660fec"); +} + +static void test_md5_files(void **state) { + char path[255]; + (void) state; + + strcpy(path, TESTFILES_DIR); + strcat(path, "test.txt"); + assert_string_equal( csync_file_md5(path), "f3971ce599093756e6018513d0835134"); + + strcpy(path, TESTFILES_DIR); + strcat(path, "red_is_the_rose.jpg"); + assert_string_equal( csync_file_md5(path), "baf8eeb2a36af94f033fa0094c50c2d5"); + +} + + +int main(void) { + const UnitTest tests[] = { + unit_test(test_md5_buffer), + unit_test(test_md5_files) + }; + + return run_tests(tests); +} From b47ac922add4ad82fc32f62d9893a98a54f3cb58 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Thu, 19 Jul 2012 10:50:18 +0200 Subject: [PATCH 19/20] ownCloud: handle time delta and access the config file. --- modules/csync_owncloud.c | 95 ++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 19 deletions(-) diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index 294c3e27f9..0ccff3b28f 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -18,7 +18,7 @@ * along with this program = NULL, if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - +#define _GNU_SOURCE #include #include #include @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -40,6 +42,7 @@ #include "c_lib.h" #include "csync.h" +#include "csync_misc.h" #include "c_private.h" #include "vio/csync_vio_module.h" @@ -54,6 +57,10 @@ #define DEBUG_WEBDAV(...) CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, __VA_ARGS__) #endif +#define OC_TIMEDELTA_FAIL (NE_REDIRECT +1) +#define OC_PROPFIND_FAIL (NE_REDIRECT +2) + + enum resource_type { resr_normal = 0, resr_collection, @@ -120,6 +127,7 @@ struct dav_session_s { char *user; char *pwd; + time_t prev_delta; time_t time_delta; /* The time delta to use. */ long int time_delta_sum; /* What is the time delta average? */ int time_delta_cnt; /* How often was the server time gathered? */ @@ -353,6 +361,7 @@ static int dav_connect(const char *base_url) { dav_session.time_delta_sum = 0; dav_session.time_delta_cnt = 0; + dav_session.prev_delta = 0; rc = c_parse_uri( base_url, &scheme, &dav_session.user, &dav_session.pwd, &host, &port, &path ); if( rc < 0 ) { @@ -541,21 +550,24 @@ static int fetch_resource_list( const char *curi, dav_session.time_delta_sum += time_diff; dav_session.time_delta_cnt++; + /* Store the previous time delta */ + dav_session.prev_delta = dav_session.time_delta; + /* check the changing of the time delta */ time_diff_delta = llabs(dav_session.time_delta - time_diff); if( dav_session.time_delta_cnt == 1 ) { DEBUG_WEBDAV( "The first time_delta is %d", time_diff ); - } else if( dav_session.time_delta_cnt > 1 && time_diff_delta > 5 ) { - DEBUG_WEBDAV("WRN: The time delta changed more than 5 second"); - } else if( time_diff_delta == 0) { - DEBUG_WEBDAV("XXXX Ok: Time delta remained the same: %ld.", time_diff); + } else if( dav_session.time_delta_cnt > 1 ) { + if( time_diff_delta > 5 ) { + DEBUG_WEBDAV("WRN: The time delta changed more than 5 second"); + ret = OC_TIMEDELTA_FAIL; + } else { + DEBUG_WEBDAV("Ok: Time delta remained (almost) the same: %ld.", time_diff); + } } else { DEBUG_WEBDAV("Difference to last server time delta: %d", time_diff_delta ); } dav_session.time_delta = time_diff; - - /* DEBUG_WEBDAV("%d <0> %d", server_time, now); */ - } else { DEBUG_WEBDAV("WRN: propfind named failed with %d", ret); } @@ -595,11 +607,7 @@ static csync_vio_file_stat_t *resourceToFileStat( struct resource *res ) } /* Correct the mtime of the file with the server time delta */ - if( dav_session.time_delta_cnt == 0 ) { - lfs->mtime = res->modtime; - } else { - lfs->mtime = res->modtime - dav_session.time_delta; - } + lfs->mtime = res->modtime; lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; lfs->size = res->size; lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; @@ -708,6 +716,7 @@ static int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) { buf->fields = _fs.fields; buf->type = _fs.type; buf->mtime = _fs.mtime; + buf->size = _fs.size; buf->mode = _stat_perms( _fs.type ); } else { @@ -729,9 +738,14 @@ static int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) { rc = fetch_resource_list( curi, NE_DEPTH_ONE, fetchCtx ); if( rc != NE_OK ) { - errno = ne_session_error_errno( dav_session.ctx ); + if( rc == OC_TIMEDELTA_FAIL ) { + DEBUG_WEBDAV("WRN: Time delta changed too much!"); + /* FIXME: Reasonable user warning */ + } else { + errno = ne_session_error_errno( dav_session.ctx ); - DEBUG_WEBDAV("stat fails with errno %d", errno ); + DEBUG_WEBDAV("stat fails with errno %d", errno ); + } free_fetchCtx(fetchCtx); return -1; } @@ -1202,7 +1216,6 @@ static int owncloud_close(csync_vio_method_handle_t *fhandle) { errno = EBADF; ret = -1; } - if (rc == NE_OK) { if ( ne_get_status( writeCtx->req )->klass != 2 ) { DEBUG_WEBDAV("Error - PUT status value no 2xx"); @@ -1546,6 +1559,8 @@ static int owncloud_utimes(const char *uri, const struct timeval *times) { pname.name = "lastmodified"; newmodtime = modtime->tv_sec; + DEBUG_WEBDAV("Add a time delta to modtime %lu: %ld", + modtime->tv_sec, dav_session.time_delta); newmodtime += dav_session.time_delta; snprintf( val, sizeof(val), "%ld", newmodtime ); @@ -1590,21 +1605,65 @@ csync_vio_method_t _method = { .utimes = owncloud_utimes }; +static char *oc_csync_conf_dir() +{ + char *home = NULL; + char *conf_dir = NULL; + + home = csync_get_user_home_dir(); + if( asprintf( &conf_dir, "%s/%s/%s", home, CSYNC_CONF_DIR, CSYNC_CONF_FILE) == -1 ) { + return NULL; + } + return conf_dir; +} + +#define OWNCLOUD_INI_TIMEDELTA "ownCloud:time_delta" + csync_vio_method_t *vio_module_init(const char *method_name, const char *args, csync_auth_callback cb, void *userdata) { + char *config = NULL; + dictionary *dict = NULL; + (void) method_name; (void) args; + _authcb = cb; _userdata = userdata; _connected = 0; /* triggers dav_connect to go through the whole neon setup */ - /* DEBUG_WEBDAV("********** vio_module_init "); */ + /* Load the last time delta from config file. */ + config = oc_csync_conf_dir(); + + if( config ) { + dict = iniparser_load(config); + if( dict ) { + dav_session.prev_delta = iniparser_getint(dict, OWNCLOUD_INI_TIMEDELTA, 0); + DEBUG_WEBDAV( "Init: Previous time delta: %d", dav_session.prev_delta ); + iniparser_freedict( dict ); + } + } return &_method; } void vio_module_shutdown(csync_vio_method_t *method) { + char *config = NULL; + dictionary *dict = NULL; + char entry[32]; + char val[10]; + (void) method; + strcpy( entry, OWNCLOUD_INI_TIMEDELTA ); + + config = oc_csync_conf_dir(); + if( config ) { + dict = iniparser_load(config); + if( dict ) { + sprintf( val, "%ld", dav_session.prev_delta ); + iniparser_setstr( dict, entry, val ); + iniparser_freedict( dict ); + } + } SAFE_FREE( dav_session.user ); SAFE_FREE( dav_session.pwd ); @@ -1615,6 +1674,4 @@ void vio_module_shutdown(csync_vio_method_t *method) { } - - /* vim: set ts=4 sw=4 et cindent: */ From 8402b5b6fabf111b0ed7db00402ae45cc80b31a6 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Thu, 19 Jul 2012 15:39:53 +0200 Subject: [PATCH 20/20] ownCloud: removed config file access again, correct handling of timediff. --- modules/csync_owncloud.c | 50 ++-------------------------------------- 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c index 0ccff3b28f..afb9daec64 100644 --- a/modules/csync_owncloud.c +++ b/modules/csync_owncloud.c @@ -28,8 +28,6 @@ #include #include -#include - #include #include #include @@ -1559,10 +1557,11 @@ static int owncloud_utimes(const char *uri, const struct timeval *times) { pname.name = "lastmodified"; newmodtime = modtime->tv_sec; +#if TIMEDELTA DEBUG_WEBDAV("Add a time delta to modtime %lu: %ld", modtime->tv_sec, dav_session.time_delta); newmodtime += dav_session.time_delta; - +#endif snprintf( val, sizeof(val), "%ld", newmodtime ); DEBUG_WEBDAV("Setting LastModified of %s to %s", curi, val ); @@ -1605,25 +1604,8 @@ csync_vio_method_t _method = { .utimes = owncloud_utimes }; -static char *oc_csync_conf_dir() -{ - char *home = NULL; - char *conf_dir = NULL; - - home = csync_get_user_home_dir(); - if( asprintf( &conf_dir, "%s/%s/%s", home, CSYNC_CONF_DIR, CSYNC_CONF_FILE) == -1 ) { - return NULL; - } - return conf_dir; -} - -#define OWNCLOUD_INI_TIMEDELTA "ownCloud:time_delta" - csync_vio_method_t *vio_module_init(const char *method_name, const char *args, csync_auth_callback cb, void *userdata) { - char *config = NULL; - dictionary *dict = NULL; - (void) method_name; (void) args; @@ -1631,39 +1613,11 @@ csync_vio_method_t *vio_module_init(const char *method_name, const char *args, _userdata = userdata; _connected = 0; /* triggers dav_connect to go through the whole neon setup */ - /* Load the last time delta from config file. */ - config = oc_csync_conf_dir(); - - if( config ) { - dict = iniparser_load(config); - if( dict ) { - dav_session.prev_delta = iniparser_getint(dict, OWNCLOUD_INI_TIMEDELTA, 0); - DEBUG_WEBDAV( "Init: Previous time delta: %d", dav_session.prev_delta ); - iniparser_freedict( dict ); - } - } - return &_method; } void vio_module_shutdown(csync_vio_method_t *method) { - char *config = NULL; - dictionary *dict = NULL; - char entry[32]; - char val[10]; - (void) method; - strcpy( entry, OWNCLOUD_INI_TIMEDELTA ); - - config = oc_csync_conf_dir(); - if( config ) { - dict = iniparser_load(config); - if( dict ) { - sprintf( val, "%ld", dav_session.prev_delta ); - iniparser_setstr( dict, entry, val ); - iniparser_freedict( dict ); - } - } SAFE_FREE( dav_session.user ); SAFE_FREE( dav_session.pwd );