mirror of
https://github.com/nextcloud/desktop.git
synced 2024-10-24 21:35:47 +03:00
Merge remote-tracking branch 'freitag/dav' into davbf
This commit is contained in:
commit
0906312c02
17 changed files with 127 additions and 46 deletions
|
@ -8,7 +8,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
||||||
|
|
||||||
set(APPLICATION_VERSION_MAJOR "0")
|
set(APPLICATION_VERSION_MAJOR "0")
|
||||||
set(APPLICATION_VERSION_MINOR "70")
|
set(APPLICATION_VERSION_MINOR "70")
|
||||||
set(APPLICATION_VERSION_PATCH "3")
|
set(APPLICATION_VERSION_PATCH "4")
|
||||||
|
|
||||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||||
### versions
|
### versions
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR "70")
|
set(CPACK_PACKAGE_VERSION_MINOR "70")
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH "3")
|
set(CPACK_PACKAGE_VERSION_PATCH "4")
|
||||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||||
|
|
||||||
set(CPACK_GENERATOR "TGZ")
|
set(CPACK_GENERATOR "TGZ")
|
||||||
|
|
|
@ -49,7 +49,11 @@ mark_as_advanced(NEON_INCLUDE_DIRS NEON_LIBRARIES)
|
||||||
# be defined in the owncloud module.
|
# be defined in the owncloud module.
|
||||||
# If neon was not compiled with LFS its also ok since the underlying system
|
# If neon was not compiled with LFS its also ok since the underlying system
|
||||||
# than probably supports large files anyway.
|
# than probably supports large files anyway.
|
||||||
FIND_PROGRAM( NEON_CONFIG_EXECUTABLE NAMES neon-config )
|
IF( CMAKE_FIND_ROOT_PATH )
|
||||||
|
FIND_PROGRAM( NEON_CONFIG_EXECUTABLE NAMES neon-config HINTS ${CMAKE_FIND_ROOT_PATH}/bin )
|
||||||
|
ELSE( CMAKE_FIND_ROOT_PATH )
|
||||||
|
FIND_PROGRAM( NEON_CONFIG_EXECUTABLE NAMES neon-config )
|
||||||
|
ENDIF( CMAKE_FIND_ROOT_PATH )
|
||||||
|
|
||||||
IF ( NEON_CONFIG_EXECUTABLE )
|
IF ( NEON_CONFIG_EXECUTABLE )
|
||||||
MESSAGE(STATUS "neon-config executable: ${NEON_CONFIG_EXECUTABLE}")
|
MESSAGE(STATUS "neon-config executable: ${NEON_CONFIG_EXECUTABLE}")
|
||||||
|
|
|
@ -9,3 +9,6 @@ max_depth = 50
|
||||||
# NOT IN USE:
|
# NOT IN USE:
|
||||||
# sync symbolic links if the remote filesystem supports it.
|
# sync symbolic links if the remote filesystem supports it.
|
||||||
#sync_symbolic_links = false
|
#sync_symbolic_links = false
|
||||||
|
|
||||||
|
# connection timeout in seconds
|
||||||
|
timeout = 30
|
||||||
|
|
|
@ -571,6 +571,9 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
||||||
|
|
||||||
(void) userdata;
|
(void) userdata;
|
||||||
|
|
||||||
|
if (dav_session.session_key)
|
||||||
|
return; /* We already have a session cookie, and we should ignore other ones */
|
||||||
|
|
||||||
if(!(status && req)) return;
|
if(!(status && req)) return;
|
||||||
if( status->klass == 2 || status->code == 401 ) {
|
if( status->klass == 2 || status->code == 401 ) {
|
||||||
/* successful request */
|
/* successful request */
|
||||||
|
@ -599,10 +602,17 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
||||||
} else if( *sc_end == ';' ) {
|
} else if( *sc_end == ';' ) {
|
||||||
/* We are at the end of the session key. */
|
/* We are at the end of the session key. */
|
||||||
int keylen = sc_end-sc_val;
|
int keylen = sc_end-sc_val;
|
||||||
if( key ) SAFE_FREE(key);
|
if( key ) {
|
||||||
key = c_malloc(keylen+1);
|
int oldlen = strlen(key);
|
||||||
strncpy( key, sc_val, keylen );
|
key = c_realloc(key, oldlen + 2 + keylen+1);
|
||||||
key[keylen] = '\0';
|
strcpy(key + oldlen, "; ");
|
||||||
|
strncpy(key + oldlen + 2, sc_val, keylen);
|
||||||
|
key[oldlen + 2 + keylen] = '\0';
|
||||||
|
} else {
|
||||||
|
key = c_malloc(keylen+1);
|
||||||
|
strncpy( key, sc_val, keylen );
|
||||||
|
key[keylen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
/* now search for a ',' to find a potential other header entry */
|
/* now search for a ',' to find a potential other header entry */
|
||||||
while(cnt < len && *sc_end != ',') {
|
while(cnt < len && *sc_end != ',') {
|
||||||
|
@ -1030,10 +1040,18 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||||
*/
|
*/
|
||||||
content_type = ne_get_response_header( request, "Content-Type" );
|
content_type = ne_get_response_header( request, "Content-Type" );
|
||||||
if( !(content_type && c_streq(content_type, "application/xml; charset=utf-8") ) ) {
|
if( !(content_type && c_streq(content_type, "application/xml; charset=utf-8") ) ) {
|
||||||
|
ssize_t resp_size;
|
||||||
|
char buffer[4096];
|
||||||
|
ZERO_STRUCT(buffer);
|
||||||
|
|
||||||
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
|
DEBUG_WEBDAV("ERROR: Content type of propfind request not XML: %s.",
|
||||||
content_type ? content_type: "<empty>");
|
content_type ? content_type: "<empty>");
|
||||||
errno = ERRNO_WRONG_CONTENT;
|
errno = ERRNO_WRONG_CONTENT;
|
||||||
set_error_message("Server error: PROPFIND reply is not XML formatted!");
|
set_error_message("Server error: PROPFIND reply is not XML formatted!");
|
||||||
|
|
||||||
|
/* Read the response buffer to log the actual problem. */
|
||||||
|
resp_size = ne_read_response_block(request, buffer, 4095);
|
||||||
|
DEBUG_WEBDAV("ERROR: Content was of size %ld: %s", resp_size, buffer );
|
||||||
ret = NE_CONNECT;
|
ret = NE_CONNECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1055,17 +1073,17 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||||
/* check the changing of the time delta */
|
/* check the changing of the time delta */
|
||||||
time_diff_delta = llabs(dav_session.time_delta - time_diff);
|
time_diff_delta = llabs(dav_session.time_delta - time_diff);
|
||||||
if( dav_session.time_delta_cnt == 1 ) {
|
if( dav_session.time_delta_cnt == 1 ) {
|
||||||
DEBUG_WEBDAV( "The first time_delta is %llu", (unsigned long long) time_diff );
|
DEBUG_WEBDAV( "The first time_delta is %ld", time_diff );
|
||||||
} else if( dav_session.time_delta_cnt > 1 ) {
|
} else if( dav_session.time_delta_cnt > 1 ) {
|
||||||
if( time_diff_delta > 5 ) {
|
if( time_diff_delta > 5 ) {
|
||||||
DEBUG_WEBDAV("WRN: The time delta changed more than 5 second");
|
DEBUG_WEBDAV("WRN: The time delta changed more than 5 second");
|
||||||
// errno = ERRNO_TIMEDELTA;
|
// errno = ERRNO_TIMEDELTA;
|
||||||
// ret = OC_TIMEDELTA_FAIL;
|
// ret = OC_TIMEDELTA_FAIL;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_WEBDAV("Ok: Time delta remained (almost) the same: %llu.", (unsigned long long) time_diff);
|
DEBUG_WEBDAV("Ok: Time delta remained (almost) the same: %ld.", time_diff);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG_WEBDAV("Difference to last server time delta: %llu", (unsigned long long) time_diff_delta );
|
DEBUG_WEBDAV("Difference to last server time delta: %ld", time_diff_delta );
|
||||||
}
|
}
|
||||||
dav_session.time_delta = time_diff;
|
dav_session.time_delta = time_diff;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1108,6 +1126,24 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
||||||
return fetchCtx;
|
return fetchCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct listdir_context *fetch_resource_list_attempts(const char *uri, int depth)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
struct listdir_context *fetchCtx = NULL;
|
||||||
|
for(i = 0; i < 10; ++i) {
|
||||||
|
fetchCtx = fetch_resource_list(uri, depth);
|
||||||
|
if(fetchCtx) break;
|
||||||
|
/* only loop in case the content is not XML formatted. Otherwise for every
|
||||||
|
* non successful stat (for non existing directories) its tried 10 times. */
|
||||||
|
if( errno != ERRNO_WRONG_CONTENT ) break;
|
||||||
|
|
||||||
|
DEBUG_WEBDAV("=> Errno after fetch resource list for %s: %d", uri, errno);
|
||||||
|
DEBUG_WEBDAV(" New attempt %i", i);
|
||||||
|
}
|
||||||
|
return fetchCtx;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* helper: convert a resource struct to file_stat struct.
|
* helper: convert a resource struct to file_stat struct.
|
||||||
*/
|
*/
|
||||||
|
@ -1236,7 +1272,8 @@ static int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fetch data via a propfind call. */
|
/* fetch data via a propfind call. */
|
||||||
fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE);
|
/* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE); */
|
||||||
|
fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE);
|
||||||
DEBUG_WEBDAV("=> Errno after fetch resource list for %s: %d", uri, errno);
|
DEBUG_WEBDAV("=> Errno after fetch resource list for %s: %d", uri, errno);
|
||||||
if (!fetchCtx) {
|
if (!fetchCtx) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1374,7 +1411,7 @@ static char*_lastDir = NULL;
|
||||||
* int unix_extensions - oC supports unix extensions.
|
* int unix_extensions - oC supports unix extensions.
|
||||||
* bool propagate_on_fd - oC supports the send_file method.
|
* bool propagate_on_fd - oC supports the send_file method.
|
||||||
*/
|
*/
|
||||||
static csync_vio_capabilities_t _owncloud_capabilities = { true, false, false, 1, true };
|
static csync_vio_capabilities_t _owncloud_capabilities = { true, false, false, 0, true };
|
||||||
|
|
||||||
static csync_vio_capabilities_t *owncloud_capabilities(void)
|
static csync_vio_capabilities_t *owncloud_capabilities(void)
|
||||||
{
|
{
|
||||||
|
@ -1808,7 +1845,8 @@ static csync_vio_method_handle_t *owncloud_opendir(const char *uri) {
|
||||||
|
|
||||||
dav_connect( uri );
|
dav_connect( uri );
|
||||||
|
|
||||||
fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE );
|
/* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE ); */
|
||||||
|
fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE);
|
||||||
if( !fetchCtx ) {
|
if( !fetchCtx ) {
|
||||||
/* errno is set properly in fetch_resource_list */
|
/* errno is set properly in fetch_resource_list */
|
||||||
DEBUG_WEBDAV("Errno set to %d", errno);
|
DEBUG_WEBDAV("Errno set to %d", errno);
|
||||||
|
@ -1874,7 +1912,6 @@ static csync_vio_file_stat_t *owncloud_readdir(csync_vio_method_handle_t *dhandl
|
||||||
static int owncloud_mkdir(const char *uri, mode_t mode) {
|
static int owncloud_mkdir(const char *uri, mode_t mode) {
|
||||||
int rc = NE_OK;
|
int rc = NE_OK;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
ne_request *req = NULL;
|
|
||||||
|
|
||||||
char *path = _cleanPath( uri );
|
char *path = _cleanPath( uri );
|
||||||
(void) mode; /* unused */
|
(void) mode; /* unused */
|
||||||
|
@ -1898,16 +1935,12 @@ static int owncloud_mkdir(const char *uri, mode_t mode) {
|
||||||
}
|
}
|
||||||
DEBUG_WEBDAV("MKdir on %s", path );
|
DEBUG_WEBDAV("MKdir on %s", path );
|
||||||
|
|
||||||
req = ne_request_create(dav_session.ctx, "MKCOL", path);
|
rc = ne_mkcol(dav_session.ctx, path );
|
||||||
rc = ne_simple_request(dav_session.ctx, req);
|
set_errno_from_neon_errcode(rc);
|
||||||
|
|
||||||
/* Special for mkcol: it returns 405 if the directory already exists.
|
/* Special for mkcol: it returns 405 if the directory already exists.
|
||||||
* To keep csync vio_mkdirs working errno EEXIST has to be returned. */
|
* To keep csync vio_mkdirs working errno EEXIST has to be returned. */
|
||||||
if( ne_get_status(req)->code == 405 ) {
|
if (errno == EPERM && http_result_code_from_session() == 405)
|
||||||
errno = EEXIST;
|
errno = EEXIST;
|
||||||
} else {
|
|
||||||
set_errno_from_neon_errcode(rc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SAFE_FREE( path );
|
SAFE_FREE( path );
|
||||||
|
|
||||||
|
@ -2083,7 +2116,7 @@ static int owncloud_set_property(const char *key, void *data) {
|
||||||
_progresscb = *(csync_progress_callback*)(data);
|
_progresscb = *(csync_progress_callback*)(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (c_streq(key, "read_timeout")) {
|
if (c_streq(key, "read_timeout") || c_streq(key, "timeout")) {
|
||||||
dav_session.read_timeout = *(int*)(data);
|
dav_session.read_timeout = *(int*)(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,7 +304,7 @@ static int _sftp_connect(const char *uri) {
|
||||||
break;
|
break;
|
||||||
case SSH_SERVER_FOUND_OTHER:
|
case SSH_SERVER_FOUND_OTHER:
|
||||||
fprintf(stderr, "csync_sftp - the host key for this server was not "
|
fprintf(stderr, "csync_sftp - the host key for this server was not "
|
||||||
"found but an other type of key exists.\n");
|
"found but another type of key exists.\n");
|
||||||
fprintf(stderr, "csync_sftp - an attacker might change the default "
|
fprintf(stderr, "csync_sftp - an attacker might change the default "
|
||||||
"server key to confuse your client into thinking the key does not "
|
"server key to confuse your client into thinking the key does not "
|
||||||
"exist\n");
|
"exist\n");
|
||||||
|
|
|
@ -332,6 +332,9 @@ retry_vio_init:
|
||||||
if (ctx->callbacks.progresscb)
|
if (ctx->callbacks.progresscb)
|
||||||
csync_vio_set_property(ctx, "progress_callback", &ctx->callbacks.progresscb);
|
csync_vio_set_property(ctx, "progress_callback", &ctx->callbacks.progresscb);
|
||||||
|
|
||||||
|
if (ctx->options.timeout)
|
||||||
|
csync_vio_set_property(ctx, "timeout", &ctx->options.timeout);
|
||||||
|
|
||||||
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
|
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
|
||||||
ctx->error_code = CSYNC_ERR_TREE;
|
ctx->error_code = CSYNC_ERR_TREE;
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
|
|
@ -51,7 +51,7 @@ extern "C" {
|
||||||
/* csync version */
|
/* csync version */
|
||||||
#define LIBCSYNC_VERSION_MAJOR 0
|
#define LIBCSYNC_VERSION_MAJOR 0
|
||||||
#define LIBCSYNC_VERSION_MINOR 70
|
#define LIBCSYNC_VERSION_MINOR 70
|
||||||
#define LIBCSYNC_VERSION_MICRO 3
|
#define LIBCSYNC_VERSION_MICRO 4
|
||||||
|
|
||||||
#define LIBCSYNC_VERSION_INT CSYNC_VERSION_INT(LIBCSYNC_VERSION_MAJOR, \
|
#define LIBCSYNC_VERSION_INT CSYNC_VERSION_INT(LIBCSYNC_VERSION_MAJOR, \
|
||||||
LIBCSYNC_VERSION_MINOR, \
|
LIBCSYNC_VERSION_MINOR, \
|
||||||
|
|
|
@ -144,6 +144,10 @@ int csync_config_load(CSYNC *ctx, const char *config) {
|
||||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Config: sync_symbolic_links = %d",
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Config: sync_symbolic_links = %d",
|
||||||
ctx->options.sync_symbolic_links);
|
ctx->options.sync_symbolic_links);
|
||||||
|
|
||||||
|
ctx->options.timeout = iniparser_getint(dict, "global:timeout", 0);
|
||||||
|
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Config: timeout = %d",
|
||||||
|
ctx->options.timeout);
|
||||||
|
|
||||||
iniparser_freedict(dict);
|
iniparser_freedict(dict);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -125,6 +125,9 @@ csync_vio_method_handle_t *csync_dbtree_opendir(CSYNC *ctx, const char *name)
|
||||||
}
|
}
|
||||||
if( cnt < tpath_len ) continue;
|
if( cnt < tpath_len ) continue;
|
||||||
|
|
||||||
|
if (!list->vector[base+8][0])
|
||||||
|
continue; /* If md5 is empty, the file was removed on the server */
|
||||||
|
|
||||||
fs = csync_vio_file_stat_new();
|
fs = csync_vio_file_stat_new();
|
||||||
fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,7 @@ struct csync_s {
|
||||||
bool local_only_mode;
|
bool local_only_mode;
|
||||||
bool remote_push_atomar;
|
bool remote_push_atomar;
|
||||||
int log_verbosity;
|
int log_verbosity;
|
||||||
|
int timeout;
|
||||||
#ifdef WITH_ICONV
|
#ifdef WITH_ICONV
|
||||||
iconv_t iconv_cd;
|
iconv_t iconv_cd;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1037,6 +1037,27 @@ out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If a remove operation failed, we need to update the st so the information
|
||||||
|
that will be stored in the database will make it so that we try to remove
|
||||||
|
again on the next sync. */
|
||||||
|
static void _csync_remove_error(CSYNC *ctx, csync_file_stat_t *st, char *uri) {
|
||||||
|
/* Write it back to statedb, that we try to delete it next time. */
|
||||||
|
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||||
|
|
||||||
|
if (ctx->replica == LOCAL_REPLICA) {
|
||||||
|
/* Update the mtime */
|
||||||
|
csync_vio_file_stat_t* vst = csync_vio_file_stat_new();
|
||||||
|
if (csync_vio_stat(ctx, uri, vst) == 0) {
|
||||||
|
st->inode = vst->inode;
|
||||||
|
st->modtime = vst->mtime;
|
||||||
|
}
|
||||||
|
csync_vio_file_stat_destroy(vst);
|
||||||
|
|
||||||
|
/* don't write the md5 to the database */
|
||||||
|
SAFE_FREE(st->md5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int _csync_remove_dir(CSYNC *ctx, csync_file_stat_t *st) {
|
static int _csync_remove_dir(CSYNC *ctx, csync_file_stat_t *st) {
|
||||||
c_list_t *list = NULL;
|
c_list_t *list = NULL;
|
||||||
char errbuf[256] = {0};
|
char errbuf[256] = {0};
|
||||||
|
@ -1108,13 +1129,13 @@ static int _csync_remove_dir(CSYNC *ctx, csync_file_stat_t *st) {
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
SAFE_FREE(uri);
|
|
||||||
|
|
||||||
/* set instruction for the statedb merger */
|
/* set instruction for the statedb merger */
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
_csync_remove_error(ctx, st, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SAFE_FREE(uri);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1310,8 +1331,7 @@ static int _csync_propagation_cleanup(CSYNC *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (csync_vio_rmdir(ctx, dir) < 0) {
|
if (csync_vio_rmdir(ctx, dir) < 0) {
|
||||||
/* Write it back to statedb, that we try to delete it next time. */
|
_csync_remove_error(ctx, st, uri);
|
||||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
|
||||||
} else {
|
} else {
|
||||||
st->instruction = CSYNC_INSTRUCTION_DELETED;
|
st->instruction = CSYNC_INSTRUCTION_DELETED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,9 +142,6 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||||
switch (other->instruction) {
|
switch (other->instruction) {
|
||||||
/* file on other replica is new too */
|
/* file on other replica is new too */
|
||||||
case CSYNC_INSTRUCTION_NEW:
|
case CSYNC_INSTRUCTION_NEW:
|
||||||
/* if (cur->modtime > other->modtime) { */
|
|
||||||
CSYNC_LOG( CSYNC_LOG_PRIORITY_DEBUG, "** size compare: %lld <-> %lld", (long long) cur->size,
|
|
||||||
(long long) other->size);
|
|
||||||
if(cur->modtime - other->modtime > ACCEPTED_TIME_DIFF) {
|
if(cur->modtime - other->modtime > ACCEPTED_TIME_DIFF) {
|
||||||
if( other->size == cur->size &&
|
if( other->size == cur->size &&
|
||||||
_time_dst_off( cur->modtime, other->modtime, ONE_HOUR ) ) {
|
_time_dst_off( cur->modtime, other->modtime, ONE_HOUR ) ) {
|
||||||
|
@ -164,8 +161,6 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||||
other->instruction = CSYNC_INSTRUCTION_NONE;
|
other->instruction = CSYNC_INSTRUCTION_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* } else if (cur->modtime < other->modtime) { */
|
|
||||||
} else if (other->modtime - cur->modtime > ACCEPTED_TIME_DIFF) {
|
} else if (other->modtime - cur->modtime > ACCEPTED_TIME_DIFF) {
|
||||||
/* Check if we have the dst problem. Older versions of ocsync wrote a wrong
|
/* Check if we have the dst problem. Older versions of ocsync wrote a wrong
|
||||||
* (ie. localized) mtime to the files which can be ignored if the size is equal
|
* (ie. localized) mtime to the files which can be ignored if the size is equal
|
||||||
|
|
|
@ -26,6 +26,7 @@ int c_mkdirs(const char *path, mode_t mode) {
|
||||||
if (_tstat(wpath, &sb) == 0) {
|
if (_tstat(wpath, &sb) == 0) {
|
||||||
if (! S_ISDIR(sb.st_mode)) {
|
if (! S_ISDIR(sb.st_mode)) {
|
||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
|
c_free_multibyte(wpath);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,13 +44,17 @@ int c_mkdirs(const char *path, mode_t mode) {
|
||||||
if (_tstat(swpath, &sb) == 0) {
|
if (_tstat(swpath, &sb) == 0) {
|
||||||
if (! S_ISDIR(sb.st_mode)) {
|
if (! S_ISDIR(sb.st_mode)) {
|
||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
|
c_free_multibyte(swpath);
|
||||||
|
c_free_multibyte(wpath);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else if (errno != ENOENT) {
|
} else if (errno != ENOENT) {
|
||||||
c_free_multibyte(swpath);
|
c_free_multibyte(swpath);
|
||||||
|
c_free_multibyte(wpath);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (c_mkdirs(subpath, mode) < 0) {
|
} else if (c_mkdirs(subpath, mode) < 0) {
|
||||||
c_free_multibyte(swpath);
|
c_free_multibyte(swpath);
|
||||||
|
c_free_multibyte(wpath);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +79,8 @@ int c_rmdirs(const char *path) {
|
||||||
char *fname = NULL;
|
char *fname = NULL;
|
||||||
_TCHAR *wfname = NULL;
|
_TCHAR *wfname = NULL;
|
||||||
_TCHAR *wpath = c_multibyte(path);
|
_TCHAR *wpath = c_multibyte(path);
|
||||||
|
char *rd_name = NULL;
|
||||||
|
|
||||||
if ((d = _topendir(wpath)) != NULL) {
|
if ((d = _topendir(wpath)) != NULL) {
|
||||||
while( _tstat(wpath, &sb) == 0) {
|
while( _tstat(wpath, &sb) == 0) {
|
||||||
/* if we can remove the directory we're done */
|
/* if we can remove the directory we're done */
|
||||||
|
@ -87,27 +93,30 @@ int c_rmdirs(const char *path) {
|
||||||
case EBADF:
|
case EBADF:
|
||||||
break; /* continue */
|
break; /* continue */
|
||||||
default:
|
default:
|
||||||
|
c_free_multibyte(wpath);
|
||||||
_tclosedir(d);
|
_tclosedir(d);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((dp = _treaddir(d)) != NULL) {
|
while ((dp = _treaddir(d)) != NULL) {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
rd_name = c_utf8(dp->d_name);
|
||||||
/* skip '.' and '..' */
|
/* skip '.' and '..' */
|
||||||
if (dp->d_name[0] == '.' &&
|
if( c_streq( rd_name, "." ) || c_streq( rd_name, ".." ) ) {
|
||||||
(dp->d_name[1] == '\0' ||
|
c_free_utf8(rd_name);
|
||||||
(dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) {
|
continue;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(path) + _tcslen(dp->d_name) + 2;
|
len = strlen(path) + strlen(rd_name) + 2;
|
||||||
fname = c_malloc(len);
|
fname = c_malloc(len);
|
||||||
if (fname == NULL) {
|
if (fname == NULL) {
|
||||||
|
c_free_multibyte(wpath);
|
||||||
|
c_free_utf8(rd_name);
|
||||||
_tclosedir(d);
|
_tclosedir(d);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
snprintf(fname, len, "%s/%s", path, dp->d_name);
|
snprintf(fname, len, "%s/%s", path, rd_name);
|
||||||
wfname = c_multibyte(fname);
|
wfname = c_multibyte(fname);
|
||||||
|
|
||||||
/* stat the file */
|
/* stat the file */
|
||||||
if (_tstat(wfname, &sb) != -1) {
|
if (_tstat(wfname, &sb) != -1) {
|
||||||
|
@ -120,7 +129,9 @@ int c_rmdirs(const char *path) {
|
||||||
if (errno == EACCES) {
|
if (errno == EACCES) {
|
||||||
_tclosedir(d);
|
_tclosedir(d);
|
||||||
SAFE_FREE(fname);
|
SAFE_FREE(fname);
|
||||||
c_free_multibyte(wfname);
|
c_free_multibyte(wpath);
|
||||||
|
c_free_multibyte(wfname);
|
||||||
|
c_free_utf8(rd_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
c_rmdirs(fname);
|
c_rmdirs(fname);
|
||||||
|
@ -130,7 +141,8 @@ int c_rmdirs(const char *path) {
|
||||||
}
|
}
|
||||||
} /* lstat */
|
} /* lstat */
|
||||||
SAFE_FREE(fname);
|
SAFE_FREE(fname);
|
||||||
c_free_multibyte(wfname);
|
c_free_multibyte(wfname);
|
||||||
|
c_free_utf8(rd_name);
|
||||||
} /* readdir */
|
} /* readdir */
|
||||||
|
|
||||||
_trewinddir(d);
|
_trewinddir(d);
|
||||||
|
@ -138,6 +150,7 @@ int c_rmdirs(const char *path) {
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
c_free_multibyte(wpath);
|
||||||
|
|
||||||
_tclosedir(d);
|
_tclosedir(d);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -77,7 +77,6 @@ typedef struct stat csync_stat_t;
|
||||||
|
|
||||||
#if defined _WIN32 && defined _UNICODE
|
#if defined _WIN32 && defined _UNICODE
|
||||||
typedef wchar_t _TCHAR;
|
typedef wchar_t _TCHAR;
|
||||||
#define _tcslen wcslen
|
|
||||||
#define _topen _wopen
|
#define _topen _wopen
|
||||||
#define _tdirent _wdirent
|
#define _tdirent _wdirent
|
||||||
#define _TDIR _WDIR
|
#define _TDIR _WDIR
|
||||||
|
@ -97,7 +96,6 @@ typedef wchar_t _TCHAR;
|
||||||
#else
|
#else
|
||||||
typedef char _TCHAR;
|
typedef char _TCHAR;
|
||||||
#define _tdirent dirent
|
#define _tdirent dirent
|
||||||
#define _tcslen strlen
|
|
||||||
#define _topen open
|
#define _topen open
|
||||||
#define _TDIR DIR
|
#define _TDIR DIR
|
||||||
#define _topendir opendir
|
#define _topendir opendir
|
||||||
|
|
|
@ -281,7 +281,7 @@ char* c_utf8(const _TCHAR *wstr)
|
||||||
char *dst = NULL;
|
char *dst = NULL;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if(!wstr) return NULL;
|
if(!wstr) return NULL;
|
||||||
size_t len = _tcslen( wstr );
|
size_t len = wcslen( wstr );
|
||||||
/* Call once to get the required size. */
|
/* Call once to get the required size. */
|
||||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
|
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
|
||||||
if( size_needed > 0 ) {
|
if( size_needed > 0 ) {
|
||||||
|
|
|
@ -361,6 +361,10 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
||||||
if( h == INVALID_HANDLE_VALUE ) {
|
if( h == INVALID_HANDLE_VALUE ) {
|
||||||
DWORD err = GetLastError();
|
DWORD err = GetLastError();
|
||||||
/* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "ERR: Failed to create a handle for %s: %ld", uri,err ); */
|
/* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "ERR: Failed to create a handle for %s: %ld", uri,err ); */
|
||||||
|
csync_vio_file_stat_destroy(buf);
|
||||||
|
c_free_multibyte(wuri);
|
||||||
|
return -1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
FILETIME ftCreate, ftAccess, ftWrite;
|
FILETIME ftCreate, ftAccess, ftWrite;
|
||||||
SYSTEMTIME stUTC;
|
SYSTEMTIME stUTC;
|
||||||
|
|
Loading…
Reference in a new issue