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_MINOR "70")
|
||||
set(APPLICATION_VERSION_PATCH "3")
|
||||
set(APPLICATION_VERSION_PATCH "4")
|
||||
|
||||
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
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
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_GENERATOR "TGZ")
|
||||
|
|
|
@ -49,7 +49,11 @@ mark_as_advanced(NEON_INCLUDE_DIRS NEON_LIBRARIES)
|
|||
# be defined in the owncloud module.
|
||||
# If neon was not compiled with LFS its also ok since the underlying system
|
||||
# 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 )
|
||||
MESSAGE(STATUS "neon-config executable: ${NEON_CONFIG_EXECUTABLE}")
|
||||
|
|
|
@ -9,3 +9,6 @@ max_depth = 50
|
|||
# NOT IN USE:
|
||||
# sync symbolic links if the remote filesystem supports it.
|
||||
#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;
|
||||
|
||||
if (dav_session.session_key)
|
||||
return; /* We already have a session cookie, and we should ignore other ones */
|
||||
|
||||
if(!(status && req)) return;
|
||||
if( status->klass == 2 || status->code == 401 ) {
|
||||
/* successful request */
|
||||
|
@ -599,10 +602,17 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
|
|||
} else if( *sc_end == ';' ) {
|
||||
/* We are at the end of the session key. */
|
||||
int keylen = sc_end-sc_val;
|
||||
if( key ) SAFE_FREE(key);
|
||||
key = c_malloc(keylen+1);
|
||||
strncpy( key, sc_val, keylen );
|
||||
key[keylen] = '\0';
|
||||
if( key ) {
|
||||
int oldlen = strlen(key);
|
||||
key = c_realloc(key, oldlen + 2 + keylen+1);
|
||||
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 */
|
||||
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" );
|
||||
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.",
|
||||
content_type ? content_type: "<empty>");
|
||||
errno = ERRNO_WRONG_CONTENT;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1055,17 +1073,17 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
|||
/* 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 %llu", (unsigned long long) time_diff );
|
||||
DEBUG_WEBDAV( "The first time_delta is %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");
|
||||
// errno = ERRNO_TIMEDELTA;
|
||||
// ret = OC_TIMEDELTA_FAIL;
|
||||
} 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 {
|
||||
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;
|
||||
} else {
|
||||
|
@ -1108,6 +1126,24 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
|
|||
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.
|
||||
*/
|
||||
|
@ -1236,7 +1272,8 @@ static int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) {
|
|||
}
|
||||
|
||||
/* 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);
|
||||
if (!fetchCtx) {
|
||||
return -1;
|
||||
|
@ -1374,7 +1411,7 @@ static char*_lastDir = NULL;
|
|||
* int unix_extensions - oC supports unix extensions.
|
||||
* 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)
|
||||
{
|
||||
|
@ -1808,7 +1845,8 @@ static csync_vio_method_handle_t *owncloud_opendir(const char *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 ) {
|
||||
/* errno is set properly in fetch_resource_list */
|
||||
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) {
|
||||
int rc = NE_OK;
|
||||
int len = 0;
|
||||
ne_request *req = NULL;
|
||||
|
||||
char *path = _cleanPath( uri );
|
||||
(void) mode; /* unused */
|
||||
|
@ -1898,16 +1935,12 @@ static int owncloud_mkdir(const char *uri, mode_t mode) {
|
|||
}
|
||||
DEBUG_WEBDAV("MKdir on %s", path );
|
||||
|
||||
req = ne_request_create(dav_session.ctx, "MKCOL", path);
|
||||
rc = ne_simple_request(dav_session.ctx, req);
|
||||
|
||||
rc = ne_mkcol(dav_session.ctx, path );
|
||||
set_errno_from_neon_errcode(rc);
|
||||
/* Special for mkcol: it returns 405 if the directory already exists.
|
||||
* 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;
|
||||
} else {
|
||||
set_errno_from_neon_errcode(rc);
|
||||
}
|
||||
}
|
||||
SAFE_FREE( path );
|
||||
|
||||
|
@ -2083,7 +2116,7 @@ static int owncloud_set_property(const char *key, void *data) {
|
|||
_progresscb = *(csync_progress_callback*)(data);
|
||||
return 0;
|
||||
}
|
||||
if (c_streq(key, "read_timeout")) {
|
||||
if (c_streq(key, "read_timeout") || c_streq(key, "timeout")) {
|
||||
dav_session.read_timeout = *(int*)(data);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -304,7 +304,7 @@ static int _sftp_connect(const char *uri) {
|
|||
break;
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
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 "
|
||||
"server key to confuse your client into thinking the key does not "
|
||||
"exist\n");
|
||||
|
|
|
@ -332,6 +332,9 @@ retry_vio_init:
|
|||
if (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) {
|
||||
ctx->error_code = CSYNC_ERR_TREE;
|
||||
rc = -1;
|
||||
|
|
|
@ -51,7 +51,7 @@ extern "C" {
|
|||
/* csync version */
|
||||
#define LIBCSYNC_VERSION_MAJOR 0
|
||||
#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, \
|
||||
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",
|
||||
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);
|
||||
|
||||
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 (!list->vector[base+8][0])
|
||||
continue; /* If md5 is empty, the file was removed on the server */
|
||||
|
||||
fs = csync_vio_file_stat_new();
|
||||
fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE;
|
||||
|
||||
|
|
|
@ -132,6 +132,7 @@ struct csync_s {
|
|||
bool local_only_mode;
|
||||
bool remote_push_atomar;
|
||||
int log_verbosity;
|
||||
int timeout;
|
||||
#ifdef WITH_ICONV
|
||||
iconv_t iconv_cd;
|
||||
#endif
|
||||
|
|
|
@ -1037,6 +1037,27 @@ out:
|
|||
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) {
|
||||
c_list_t *list = NULL;
|
||||
char errbuf[256] = {0};
|
||||
|
@ -1108,13 +1129,13 @@ static int _csync_remove_dir(CSYNC *ctx, csync_file_stat_t *st) {
|
|||
|
||||
rc = 0;
|
||||
out:
|
||||
SAFE_FREE(uri);
|
||||
|
||||
/* set instruction for the statedb merger */
|
||||
if (rc != 0) {
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
_csync_remove_error(ctx, st, uri);
|
||||
}
|
||||
|
||||
SAFE_FREE(uri);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1310,8 +1331,7 @@ static int _csync_propagation_cleanup(CSYNC *ctx) {
|
|||
}
|
||||
|
||||
if (csync_vio_rmdir(ctx, dir) < 0) {
|
||||
/* Write it back to statedb, that we try to delete it next time. */
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
_csync_remove_error(ctx, st, uri);
|
||||
} else {
|
||||
st->instruction = CSYNC_INSTRUCTION_DELETED;
|
||||
}
|
||||
|
|
|
@ -142,9 +142,6 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
|||
switch (other->instruction) {
|
||||
/* file on other replica is new too */
|
||||
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( other->size == cur->size &&
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
/* } else if (cur->modtime < other->modtime) { */
|
||||
} else if (other->modtime - cur->modtime > ACCEPTED_TIME_DIFF) {
|
||||
/* 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
|
||||
|
|
|
@ -26,6 +26,7 @@ int c_mkdirs(const char *path, mode_t mode) {
|
|||
if (_tstat(wpath, &sb) == 0) {
|
||||
if (! S_ISDIR(sb.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
c_free_multibyte(wpath);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -43,13 +44,17 @@ int c_mkdirs(const char *path, mode_t mode) {
|
|||
if (_tstat(swpath, &sb) == 0) {
|
||||
if (! S_ISDIR(sb.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
c_free_multibyte(swpath);
|
||||
c_free_multibyte(wpath);
|
||||
return -1;
|
||||
}
|
||||
} else if (errno != ENOENT) {
|
||||
c_free_multibyte(swpath);
|
||||
c_free_multibyte(wpath);
|
||||
return -1;
|
||||
} else if (c_mkdirs(subpath, mode) < 0) {
|
||||
c_free_multibyte(swpath);
|
||||
c_free_multibyte(wpath);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +79,8 @@ int c_rmdirs(const char *path) {
|
|||
char *fname = NULL;
|
||||
_TCHAR *wfname = NULL;
|
||||
_TCHAR *wpath = c_multibyte(path);
|
||||
|
||||
char *rd_name = NULL;
|
||||
|
||||
if ((d = _topendir(wpath)) != NULL) {
|
||||
while( _tstat(wpath, &sb) == 0) {
|
||||
/* if we can remove the directory we're done */
|
||||
|
@ -87,27 +93,30 @@ int c_rmdirs(const char *path) {
|
|||
case EBADF:
|
||||
break; /* continue */
|
||||
default:
|
||||
c_free_multibyte(wpath);
|
||||
_tclosedir(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((dp = _treaddir(d)) != NULL) {
|
||||
size_t len;
|
||||
rd_name = c_utf8(dp->d_name);
|
||||
/* skip '.' and '..' */
|
||||
if (dp->d_name[0] == '.' &&
|
||||
(dp->d_name[1] == '\0' ||
|
||||
(dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) {
|
||||
continue;
|
||||
if( c_streq( rd_name, "." ) || c_streq( rd_name, ".." ) ) {
|
||||
c_free_utf8(rd_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
len = strlen(path) + _tcslen(dp->d_name) + 2;
|
||||
len = strlen(path) + strlen(rd_name) + 2;
|
||||
fname = c_malloc(len);
|
||||
if (fname == NULL) {
|
||||
c_free_multibyte(wpath);
|
||||
c_free_utf8(rd_name);
|
||||
_tclosedir(d);
|
||||
return -1;
|
||||
}
|
||||
snprintf(fname, len, "%s/%s", path, dp->d_name);
|
||||
wfname = c_multibyte(fname);
|
||||
snprintf(fname, len, "%s/%s", path, rd_name);
|
||||
wfname = c_multibyte(fname);
|
||||
|
||||
/* stat the file */
|
||||
if (_tstat(wfname, &sb) != -1) {
|
||||
|
@ -120,7 +129,9 @@ int c_rmdirs(const char *path) {
|
|||
if (errno == EACCES) {
|
||||
_tclosedir(d);
|
||||
SAFE_FREE(fname);
|
||||
c_free_multibyte(wfname);
|
||||
c_free_multibyte(wpath);
|
||||
c_free_multibyte(wfname);
|
||||
c_free_utf8(rd_name);
|
||||
return -1;
|
||||
}
|
||||
c_rmdirs(fname);
|
||||
|
@ -130,7 +141,8 @@ int c_rmdirs(const char *path) {
|
|||
}
|
||||
} /* lstat */
|
||||
SAFE_FREE(fname);
|
||||
c_free_multibyte(wfname);
|
||||
c_free_multibyte(wfname);
|
||||
c_free_utf8(rd_name);
|
||||
} /* readdir */
|
||||
|
||||
_trewinddir(d);
|
||||
|
@ -138,6 +150,7 @@ int c_rmdirs(const char *path) {
|
|||
} else {
|
||||
return -1;
|
||||
}
|
||||
c_free_multibyte(wpath);
|
||||
|
||||
_tclosedir(d);
|
||||
return 0;
|
||||
|
|
|
@ -77,7 +77,6 @@ typedef struct stat csync_stat_t;
|
|||
|
||||
#if defined _WIN32 && defined _UNICODE
|
||||
typedef wchar_t _TCHAR;
|
||||
#define _tcslen wcslen
|
||||
#define _topen _wopen
|
||||
#define _tdirent _wdirent
|
||||
#define _TDIR _WDIR
|
||||
|
@ -97,7 +96,6 @@ typedef wchar_t _TCHAR;
|
|||
#else
|
||||
typedef char _TCHAR;
|
||||
#define _tdirent dirent
|
||||
#define _tcslen strlen
|
||||
#define _topen open
|
||||
#define _TDIR DIR
|
||||
#define _topendir opendir
|
||||
|
|
|
@ -281,7 +281,7 @@ char* c_utf8(const _TCHAR *wstr)
|
|||
char *dst = NULL;
|
||||
#ifdef _WIN32
|
||||
if(!wstr) return NULL;
|
||||
size_t len = _tcslen( wstr );
|
||||
size_t len = wcslen( wstr );
|
||||
/* Call once to get the required size. */
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
|
||||
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 ) {
|
||||
DWORD err = GetLastError();
|
||||
/* 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 {
|
||||
FILETIME ftCreate, ftAccess, ftWrite;
|
||||
SYSTEMTIME stUTC;
|
||||
|
|
Loading…
Reference in a new issue