[Pkg-owncloud-commits] [ocsync] 01/08: Imported Upstream version 0.90.0
Sandro Knauß
hefee-guest at alioth.debian.org
Wed Sep 11 19:47:04 UTC 2013
This is an automated email from the git hooks/post-receive script.
hefee-guest pushed a commit to branch master
in repository ocsync.
commit e1368bf27fbb152b1eca9c3e91fdc19584a18f72
Author: Sandro Knauß <bugs at sandroknauss.de>
Date: Wed Sep 11 19:56:34 2013 +0200
Imported Upstream version 0.90.0
---
.tag | 2 +-
CMakeLists.txt | 4 +-
ChangeLog | 22 +-
client/csync_auth.c | 6 +-
client/csync_client.c | 2 +-
cmake/Modules/DefineCMakeDefaults.cmake | 3 +
cmake/Modules/DefineCompilerFlags.cmake | 63 +++--
config/ocsync_exclude.conf | 8 +-
modules/csync_dummy.c | 2 +-
modules/csync_owncloud.c | 257 ++++++++++++++------
modules/csync_owncloud.h | 23 +-
modules/csync_owncloud_recursive_propfind.c | 10 +-
modules/csync_owncloud_util.c | 27 +++
modules/csync_sftp.c | 2 +-
modules/csync_sftp2.c | 2 +-
modules/csync_smb.c | 4 +-
src/csync.c | 241 ++++++++++---------
src/csync.h | 63 ++++-
src/csync_exclude.c | 46 ++--
src/csync_exclude.h | 19 +-
src/csync_lock.c | 2 +-
src/csync_log.c | 2 +-
src/csync_log.h | 6 +
src/csync_misc.c | 1 +
src/csync_misc.h | 7 +
src/csync_private.h | 14 +-
src/csync_propagate.c | 313 ++++++++++++++++++++-----
src/csync_propagate.h | 5 +
src/csync_reconcile.c | 4 +-
src/csync_rename.cc | 8 +-
src/csync_rename.h | 2 +-
src/csync_statedb.c | 231 ++++++++++++------
src/csync_time.c | 10 +-
src/csync_update.c | 76 ++++--
src/csync_util.c | 92 ++++++--
src/httpbf/src/httpbf.c | 83 +++++--
src/httpbf/src/httpbf.h | 18 +-
src/httpbf/tests/hbf_send_test.c | 2 +-
src/std/c_file.c | 100 ++++++--
src/std/c_file.h | 10 +
src/std/c_macro.h | 3 +
src/std/c_private.h | 7 +-
src/std/c_string.c | 31 ++-
src/std/c_string.h | 9 +
src/vio/csync_vio.c | 12 +-
src/vio/csync_vio.h | 2 +-
src/vio/csync_vio_file_stat.h | 4 +-
src/vio/csync_vio_local.c | 37 +--
src/vio/csync_vio_local.h | 2 +-
src/vio/csync_vio_method.h | 2 +-
tests/csync_tests/check_csync_exclude.c | 21 +-
tests/csync_tests/check_csync_statedb_query.c | 11 +-
tests/csync_tests/check_csync_update.c | 17 +-
tests/httpbf_tests/hbf_send_test.c | 4 +-
tests/ownCloud/ownCloud/Test.pm | 13 +-
tests/ownCloud/t3.pl | 19 ++
tests/ownCloud/t4.pl | 25 +-
57 files changed, 1422 insertions(+), 589 deletions(-)
diff --git a/.tag b/.tag
index 8386637..c1a8fe0 100644
--- a/.tag
+++ b/.tag
@@ -1 +1 @@
-1a25644d60e5ac1d70b23b8e91acddca22cbcc51
+12b9b87c6100fc75b62d7ad68ad97d917bca08b6
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b75a9ff..04077ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,12 +7,12 @@ cmake_minimum_required(VERSION 2.6.0)
set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0")
-set(APPLICATION_VERSION_MINOR "80")
+set(APPLICATION_VERSION_MINOR "90")
set(APPLICATION_VERSION_PATCH "0")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
-set(LIBRARY_VERSION "0.2.0")
+set(LIBRARY_VERSION "0.2.1")
set(LIBRARY_SOVERSION "0")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
diff --git a/ChangeLog b/ChangeLog
index 10ec4a4..0cdf741 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,26 @@
ChangeLog
==========
-version 0.80.0 (released 2013 *06 *25)
+version 0.90.0 (released 2013-09-04, ownCloud Client 1.4)
+ * Added API to get progress information from csync.
+ * Added c_rename function to csync std.
+ * Fix: Do renames of files before any puts.
+ * Improved database integrity checks.
+ * Improvements of database writing efficiendy.
+ * Fix: stat file on win32 even if its opened by application.
+ * httpbf: configurable block size and threshold.
+ * Many fixes found by a Coverity check.
+ * Fix: use correct stat struct on all platforms
+ * Fix: download resuming.
+ * ownCloud module: Bandwith limitation added.
+ * Added ability to remove ignored files automatically.
+ * Fix: Use int64_t and friends
+ * Fix: Removed all compile warnings.
+ * Left excluded files and links in csync's tree to be able to show.
+ them to the user.
+ * Add OC-Total-Length header for better quota handling.
+ * Report inbetween progress
+
+version 0.80.0 (released 2013-06-25)
* Big file chunking (e.g. up/download of big files should now be no
problem anymore)
* Resuming (download of big files will resume)
diff --git a/client/csync_auth.c b/client/csync_auth.c
index 2f23205..f0ea1f3 100644
--- a/client/csync_auth.c
+++ b/client/csync_auth.c
@@ -125,13 +125,13 @@ int csync_getpass(const char *prompt,
int verify,
void *userdata
) {
- /* unused variables */
- (void) userdata;
-
HANDLE h;
DWORD mode = 0;
int ok;
+ /* unused variables */
+ (void) userdata;
+
/* fgets needs at least len - 1 */
if (prompt == NULL || buf == NULL || len < 2) {
return -1;
diff --git a/client/csync_client.c b/client/csync_client.c
index 468342d..92e61b6 100644
--- a/client/csync_client.c
+++ b/client/csync_client.c
@@ -283,7 +283,7 @@ int main(int argc, char **argv) {
if (arguments.exclude_file != NULL) {
if (csync_add_exclude_list(csync, arguments.exclude_file) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
fprintf(stderr, "csync_add_exclude_list - %s: %s\n",
arguments.exclude_file, errbuf);
rc = 1;
diff --git a/cmake/Modules/DefineCMakeDefaults.cmake b/cmake/Modules/DefineCMakeDefaults.cmake
index 72893c3..783583a 100644
--- a/cmake/Modules/DefineCMakeDefaults.cmake
+++ b/cmake/Modules/DefineCMakeDefaults.cmake
@@ -18,6 +18,9 @@ set(CMAKE_COLOR_MAKEFILE ON)
set(GENERIC_LIB_VERSION "0.1.0")
set(GENERIC_LIB_SOVERSION "0")
+# set -Werror
+set(CMAKE_ENABLE_WERROR ON)
+
# Set the default build type to release with debug info
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo
diff --git a/cmake/Modules/DefineCompilerFlags.cmake b/cmake/Modules/DefineCompilerFlags.cmake
index 550cc09..fa7bd23 100644
--- a/cmake/Modules/DefineCompilerFlags.cmake
+++ b/cmake/Modules/DefineCompilerFlags.cmake
@@ -3,38 +3,47 @@
include(CheckCCompilerFlag)
include(MacroCheckCCompilerFlagSSP)
-if (UNIX AND NOT WIN32)
- #
- # Define GNUCC compiler flags
- #
- if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
+#
+# Define GNUCC compiler flags
+#
+if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
+
+ # add -Wconversion ?
+ # cannot be pedantic with sqlite3 directly linked
+ if (NOT CSYNC_STATIC_COMPILE_DIR)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
+ endif()
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute -D_GNU_SOURCE")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__STDC_FORMAT_MACROS=1")
- # add -Wconversion ?
- # cannot be pedantic with sqlite3 directly linked
- if (NOT CSYNC_STATIC_COMPILE_DIR)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
- endif()
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
+ set(CSYNC_STRICT OFF CACHE BOOL "Strict error checking, enabled -Werror and friends")
+ if (CSYNC_STRICT)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+ endif(CSYNC_STRICT)
- # with -fPIC
- check_c_compiler_flag("-fPIC" WITH_FPIC)
- if (WITH_FPIC)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
- endif (WITH_FPIC)
+ # with -fPIC
+ check_c_compiler_flag("-fPIC" WITH_FPIC)
+ if (WITH_FPIC AND NOT WIN32)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+ endif (WITH_FPIC AND NOT WIN32)
- check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
- if (WITH_STACK_PROTECTOR)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
- endif (WITH_STACK_PROTECTOR)
+ check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
+ if (WITH_STACK_PROTECTOR AND NOT WIN32)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
+ endif (WITH_STACK_PROTECTOR AND NOT WIN32)
- check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
+ if (WITH_OPTIMIZATION)
+ check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O -D_FORTIFY_SOURCE=2")
endif (WITH_FORTIFY_SOURCE)
- endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
+ endif (WITH_OPTIMIZATION)
+endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
+if (UNIX AND NOT WIN32)
#
# Check for large filesystem support
#
@@ -63,5 +72,7 @@ if (UNIX AND NOT WIN32)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
endif (_lfs_CFLAGS)
-
+else(UNIX AND NOT WIN32)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FILE_OFFSET_BITS=64")
endif (UNIX AND NOT WIN32)
+
diff --git a/config/ocsync_exclude.conf b/config/ocsync_exclude.conf
index 9cc35ed..d2b4dda 100644
--- a/config/ocsync_exclude.conf
+++ b/config/ocsync_exclude.conf
@@ -2,6 +2,12 @@
# lines starting with '#' are ignored.
#
# You can use shell wildcard patterns. See the manpage of sh(1)
+#
+# If a pattern starts with ']', the ']' is removed from the pattern,
+# And the files that matches that pattern will be ignored, but if
+# their parent directory is removed on the other side, the file will
+# be removed. Otherwise, ignored file prevent the directory from
+# being removed.
.beagle
.ccache
@@ -19,7 +25,7 @@
.thumbnails
*.~*
-.directory
+]*.directory
# exclude all object file
# *.o
diff --git a/modules/csync_dummy.c b/modules/csync_dummy.c
index fa2c1c2..8f82c67 100644
--- a/modules/csync_dummy.c
+++ b/modules/csync_dummy.c
@@ -76,7 +76,7 @@ static ssize_t dummy_write(csync_vio_method_handle_t *fhandle, const void *buf,
return 0;
}
-static off_t dummy_lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence) {
+static int64_t dummy_lseek(csync_vio_method_handle_t *fhandle, int64_t offset, int whence) {
(void) fhandle;
(void) offset;
(void) whence;
diff --git a/modules/csync_owncloud.c b/modules/csync_owncloud.c
index e6d372a..a37c6e0 100644
--- a/modules/csync_owncloud.c
+++ b/modules/csync_owncloud.c
@@ -21,6 +21,7 @@
#include "csync_owncloud.h"
+#include <inttypes.h>
/*
* free the fetchCtx
@@ -59,7 +60,6 @@ int _connected = 0; /* flag to indicate if a connection exists
the dav_session is valid */
csync_auth_callback _authcb;
-csync_progress_callback _progresscb;
long long chunked_total_size = 0;
long long chunked_done = 0;
@@ -93,6 +93,11 @@ static void clean_caches() {
char _buffer[PUT_BUFFER_SIZE];
+/* Differance in usec between two time */
+static int64_t _timediff(struct timeval x , struct timeval y)
+{
+ return (y.tv_sec - x.tv_sec)*1000000 + (y.tv_usec - x.tv_usec);
+}
/*
* helper method to build up a user text for SSL problems, called from the
@@ -125,7 +130,6 @@ static int verify_sslcert(void *userdata, int failures,
const ne_ssl_certificate *cert = certificate;
(void) userdata;
- (void) userdata;
memset( problem, 0, LEN );
while( cert ) {
@@ -165,7 +169,7 @@ static int verify_sslcert(void *userdata, int failures,
/* call the csync callback */
DEBUG_WEBDAV("Call the csync callback for SSL problems");
memset( buf, 0, NE_ABUFSIZ );
- (*_authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, dav_session.userdata );
+ (*_authcb) ( problem, buf, NE_ABUFSIZ-1, 1, 0, NULL );
if( buf[0] == 'y' || buf[0] == 'Y') {
ret = 0;
} else {
@@ -204,12 +208,12 @@ static int ne_auth( void *userdata, const char *realm, int attempt,
/* call the csync callback */
DEBUG_WEBDAV("Call the csync callback for %s", realm );
memset( buf, 0, NE_ABUFSIZ );
- (*_authcb) ("Enter your username: ", buf, NE_ABUFSIZ-1, 1, 0, dav_session.userdata );
+ (*_authcb) ("Enter your username: ", buf, NE_ABUFSIZ-1, 1, 0, NULL );
if( strlen(buf) < NE_ABUFSIZ ) {
strcpy( username, buf );
}
memset( buf, 0, NE_ABUFSIZ );
- (*_authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, dav_session.userdata );
+ (*_authcb) ("Enter your password: ", buf, NE_ABUFSIZ-1, 0, 0, NULL );
if( strlen(buf) < NE_ABUFSIZ) {
strcpy( password, buf );
}
@@ -370,7 +374,7 @@ static void post_request_hook(ne_request *req, void *userdata, const ne_status *
/*
* this hook is called just after a request has been created, before its sent.
- * Here it is used to set the session cookie if available.
+ * Here it is used to set the proxy connection header if available.
*/
static void request_created_hook(ne_request *req, void *userdata,
const char *method, const char *requri)
@@ -381,32 +385,95 @@ static void request_created_hook(ne_request *req, void *userdata,
if( !req ) return;
- if(dav_session.session_key) {
- /* DEBUG_WEBDAV("Setting PHPSESSID to %s", dav_session.session_key); */
- ne_add_request_header(req, "Cookie", dav_session.session_key);
- }
-
if(dav_session.proxy_type) {
/* required for NTLM */
ne_add_request_header(req, "Proxy-Connection", "Keep-Alive");
}
}
+/*
+ * this hook is called just before a request has been sent.
+ * Here it is used to set the session cookie if available.
+ */
+static void pre_send_hook(ne_request *req, void *userdata,
+ ne_buffer *header)
+{
+ (void) userdata;
+
+ if( !req ) return;
+
+ if(dav_session.session_key) {
+ ne_buffer_concat(header, "Cookie: ", dav_session.session_key, "\r\n", NULL);
+ }
+}
+
+static int post_send_hook(ne_request *req, void *userdata,
+ const ne_status *status)
+{
+ const char *location;
+
+ (void) userdata;
+ (void) status;
+
+ location = ne_get_response_header(req, "Location");
+
+ if( !location ) return NE_OK;
+
+ if( dav_session.redir_callback ) {
+ if( dav_session.redir_callback( dav_session.csync_ctx, location ) ) {
+ return NE_REDIRECT;
+ } else {
+ return NE_RETRY;
+ }
+ }
+
+ return NE_REDIRECT;
+}
+
/* called from neon */
static void ne_notify_status_cb (void *userdata, ne_session_status status,
const ne_session_status_info *info)
{
struct transfer_context *tc = (struct transfer_context*) userdata;
+ struct timeval now;
+ int bandwidth_limit = 0;
- if (_progresscb && (status == ne_status_sending || status == ne_status_recving)) {
- if (info->sr.total > 0)
- _progresscb(tc->url, CSYNC_NOTIFY_PROGRESS,
+ if ((status == ne_status_sending || status == ne_status_recving)) {
+ if (info->sr.total > 0) {
+ oc_notify_progress( tc->url, CSYNC_NOTIFY_PROGRESS,
chunked_done + info->sr.progress,
- chunked_total_size ? chunked_total_size : info->sr.total,
- dav_session.userdata);
-
- if (chunked_total_size && info->sr.total == info->sr.progress)
+ chunked_total_size ? chunked_total_size : info->sr.total );
+ }
+ if (chunked_total_size && info->sr.total > 0 && info->sr.total == info->sr.progress) {
chunked_done += info->sr.total;
+ DEBUG_WEBDAV("Chunk upload completed for '%s' (%lld bytes out of %lld)", tc->url , chunked_done, chunked_total_size);
+ }
+ }
+
+ /* throttle connection */
+ if (status == ne_status_sending) bandwidth_limit = dav_session.bandwidth_limit_upload;
+ if (status == ne_status_recving) bandwidth_limit = dav_session.bandwidth_limit_download;
+ if (bandwidth_limit > 0 && gettimeofday(&now, NULL) == 0) {
+ int64_t diff = _timediff(tc->last_time, now);
+ int64_t len = info->sr.progress - tc->last_progress;
+ if (len > 0 && diff > 0 && (1000000 * len / diff) > (int64_t)bandwidth_limit) {
+ int64_t wait_time = (1000000 * len / bandwidth_limit) - diff;
+ if (wait_time > 0) {
+ usleep(wait_time);
+ }
+ }
+ tc->last_progress = info->sr.progress;
+ gettimeofday(&tc->last_time, NULL);
+ } else if (bandwidth_limit < 0 && bandwidth_limit > -100 && gettimeofday(&now, NULL) == 0) {
+ int64_t diff = _timediff(tc->last_time, now);
+ if (diff > 0) {
+ // -bandwidth_limit is the % of bandwidth
+ int64_t wait_time = -diff * (1 + 100.0 / bandwidth_limit);
+ if (wait_time > 0) {
+ usleep(wait_time);
+ }
+ }
+ gettimeofday(&tc->last_time, NULL);
}
}
@@ -518,12 +585,15 @@ static int dav_connect(const char *base_url) {
ne_ssl_trust_default_ca( dav_session.ctx );
ne_ssl_set_verify( dav_session.ctx, verify_sslcert, 0 );
}
- ne_redirect_register( dav_session.ctx );
- /* Hook to get the Session ID */
- ne_hook_post_headers( dav_session.ctx, post_request_hook, NULL );
- /* Hook called when a request is built. It sets the PHPSESSID header */
+ /* Hook called when a request is created. It sets the proxy connection header. */
ne_hook_create_request( dav_session.ctx, request_created_hook, NULL );
+ /* Hook called after response headers are read. It gets the Session ID. */
+ ne_hook_post_headers( dav_session.ctx, post_request_hook, NULL );
+ /* Hook called before a request is sent. It sets the cookies. */
+ ne_hook_pre_send( dav_session.ctx, pre_send_hook, NULL );
+ /* Hook called after request is dispatched. Used for handling possible redirections. */
+ ne_hook_post_send( dav_session.ctx, post_send_hook, NULL );
/* Proxy support */
proxystate = configureProxy( dav_session.ctx );
@@ -691,9 +761,9 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
req_status->reason_phrase);
ret = NE_CONNECT;
set_error_message(req_status->reason_phrase);
- if (_progresscb) {
- _progresscb(uri, CSYNC_NOTIFY_ERROR, req_status->code, (long long)(req_status->reason_phrase) ,dav_session.userdata);
- }
+ oc_notify_progress( uri, CSYNC_NOTIFY_ERROR,
+ req_status->code,
+ (intptr_t)(req_status->reason_phrase) );
}
DEBUG_WEBDAV("Simple propfind result code %d.", req_status->code);
} else {
@@ -730,16 +800,6 @@ static struct listdir_context *fetch_resource_list(const char *uri, int depth)
if( hdl )
ne_propfind_destroy(hdl);
- if( ret == NE_REDIRECT ) {
- const ne_uri *redir_ne_uri = NULL;
- char *redir_uri = NULL;
- redir_ne_uri = ne_redirect_location(dav_session.ctx);
- if( redir_ne_uri ) {
- redir_uri = ne_uri_unparse(redir_ne_uri);
- DEBUG_WEBDAV("Permanently moved to %s", redir_uri);
- }
- }
-
if( ret != NE_OK ) {
free_fetchCtx(fetchCtx);
return NULL;
@@ -911,8 +971,9 @@ static int content_reader(void *userdata, const char *buf, size_t len)
/* DEBUG_WEBDAV("Writing %scompressed %d bytes", (writeCtx->decompress ? "" : "NON "), len); */
written = write(writeCtx->fd, buf, len);
if( len != written ) {
- DEBUG_WEBDAV("WRN: content_reader wrote wrong num of bytes: %zu, %zu", len, written);
+ DEBUG_WEBDAV("WRN: content_reader wrote wrong num of bytes: %zu, %zu %d %d", len, written, errno, writeCtx->fd);
}
+ writeCtx->get_size += len;
return NE_OK;
} else {
errno = EBADF;
@@ -1152,6 +1213,11 @@ static int _user_want_abort()
return csync_abort_requested(dav_session.csync_ctx);
}
+static void _log_callback(const char *func, const char *text)
+{
+ csync_log(dav_session.csync_ctx, CSYNC_LOG_PRIORITY_TRACE, func, "%s", text);
+}
+
static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_handle_t *hdl ) {
int rc = 0;
int neon_stat;
@@ -1160,8 +1226,8 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
fhandle_t *fh = (fhandle_t *) src;
int fd;
int error_code = 0;
- const char *error_string = NULL;
char *clean_uri = NULL;
+ int64_t file_size;
if( ! write_ctx ) {
errno = EINVAL;
@@ -1179,7 +1245,9 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
chunked_total_size = 0;
chunked_done = 0;
- DEBUG_WEBDAV("Sendfile handling request type %s.", write_ctx->method);
+ gettimeofday(&write_ctx->last_time, NULL);
+
+ DEBUG_WEBDAV("Sendfile handling request type %s. fd %d", write_ctx->method, fd);
/*
* Copy from the file descriptor if method == PUT
@@ -1198,6 +1266,13 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
do {
Hbf_State state = HBF_SUCCESS;
hbf_transfer_t *trans = hbf_init_transfer(clean_uri);
+ hbf_set_log_callback(trans, _log_callback);
+ if (dav_session.hbf_block_size > 0) {
+ trans->threshold = trans->block_size = dav_session.hbf_block_size;
+ }
+ if (dav_session.hbf_threshold > 0) {
+ trans->threshold = dav_session.hbf_threshold;
+ }
finished = true;
if (!trans) {
@@ -1205,6 +1280,10 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
rc = 1;
} else {
state = hbf_splitlist(trans, fd);
+ file_size = trans->stat_size;
+ (void) file_size;
+ DEBUG_WEBDAV("about to send %d block", trans->block_cnt);
+
/* Reuse chunk info that was stored in database if existing. */
if (dav_session.chunk_info && dav_session.chunk_info->transfer_id) {
@@ -1213,9 +1292,9 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
trans->transfer_id = dav_session.chunk_info->transfer_id;
}
- if (state == HBF_SUCCESS && _progresscb) {
+ if (state == HBF_SUCCESS) {
ne_set_notifier(dav_session.ctx, ne_notify_status_cb, write_ctx);
- _progresscb(write_ctx->url, CSYNC_NOTIFY_START_UPLOAD, 0 , 0, dav_session.userdata);
+ oc_notify_progress(write_ctx->url, CSYNC_NOTIFY_START_UPLOAD, 0, 0);
}
/* Register the abort callback */
@@ -1245,8 +1324,11 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
}
if( finished ) {
- error_string = hbf_error_string(state);
+ SAFE_FREE(dav_session.error_string);
+ dav_session.error_string = c_strdup(hbf_error_string(trans, state));
error_code = hbf_fail_http_code(trans);
+ set_errno_from_http_errcode(error_code);
+
rc = 1;
if (dav_session.chunk_info) {
dav_session.chunk_info->start_id = trans->start_id;
@@ -1258,11 +1340,11 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
hbf_free_transfer(trans);
} while( !finished );
- if (_progresscb) {
- ne_set_notifier(dav_session.ctx, 0, 0);
- _progresscb(write_ctx->url, rc != 0 ? CSYNC_NOTIFY_ERROR :
- CSYNC_NOTIFY_FINISHED_UPLOAD, error_code,
- (long long)(error_string), dav_session.userdata);
+ ne_set_notifier(dav_session.ctx, 0, 0);
+ if( rc == 0 ) {
+ DEBUG_WEBDAV(" * Upload finished %s", write_ctx->url);
+ } else {
+ oc_notify_progress(write_ctx->url, CSYNC_NOTIFY_ERROR, error_code, (intptr_t)(dav_session.error_string));
}
} else if( c_streq( write_ctx->method, "GET") ) {
/* GET a file to the file descriptor */
@@ -1270,10 +1352,8 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
int retry = 0;
DEBUG_WEBDAV(" -- GET on %s", write_ctx->url);
write_ctx->fd = fd;
- if (_progresscb) {
- ne_set_notifier(dav_session.ctx, ne_notify_status_cb, write_ctx);
- _progresscb(write_ctx->url, CSYNC_NOTIFY_START_DOWNLOAD, 0 , 0, dav_session.userdata);
- }
+ ne_set_notifier(dav_session.ctx, ne_notify_status_cb, write_ctx);
+ oc_notify_progress(write_ctx->url, CSYNC_NOTIFY_START_DOWNLOAD, 0 , 0);
do {
csync_stat_t sb;
@@ -1291,12 +1371,12 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
/* Allow compressed content by setting the header */
ne_add_request_header( write_ctx->req, "Accept-Encoding", "gzip" );
- if (fstat(fd, &sb) >= 0 && sb.st_size > 0) {
+ if (_tfstat(fd, &sb) >= 0 && sb.st_size > 0) {
char brange[64];
- ne_snprintf(brange, sizeof brange, "bytes=%lld-", (long long) sb.st_size);
+ snprintf(brange, sizeof brange, "bytes=%"PRId64"-", (int64_t) sb.st_size);
ne_add_request_header(write_ctx->req, "Range", brange);
ne_add_request_header(write_ctx->req, "Accept-Ranges", "bytes");
- DEBUG_WEBDAV("Retry with range %s", brange);
+ DEBUG_WEBDAV("Retry with range %s fd %d", brange, fd);
}
/* hook called before the content is parsed to set the correct reader,
@@ -1315,7 +1395,6 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
set_errno_from_neon_errcode(neon_stat);
DEBUG_WEBDAV("Error GET: Neon: %d, errno %d", neon_stat, errno);
- error_string = dav_session.error_string;
error_code = errno;
rc = 1;
} else {
@@ -1334,7 +1413,8 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
rc = 1;
}
error_code = status->code;
- error_string = status->reason_phrase;
+ SAFE_FREE(dav_session.error_string);
+ dav_session.error_string = c_strdup(status->reason_phrase);
} else {
DEBUG_WEBDAV("http request all cool, result code %d", status->code);
}
@@ -1349,14 +1429,16 @@ static int owncloud_sendfile(csync_vio_method_handle_t *src, csync_vio_method_ha
}
break;
} while (1);
- if (_progresscb) {
- ne_set_notifier(dav_session.ctx, 0, 0);
- _progresscb(write_ctx->url, (rc != NE_OK) ? CSYNC_NOTIFY_ERROR :
- CSYNC_NOTIFY_FINISHED_DOWNLOAD, error_code ,
- (long long)(error_string), dav_session.userdata);
+
+ ne_set_notifier(dav_session.ctx, 0, 0);
+ if( rc == 0 ) {
+ DEBUG_WEBDAV(" ** Finished download %s", write_ctx->url);
+ } else {
+ oc_notify_progress( write_ctx->url, CSYNC_NOTIFY_ERROR, error_code , (intptr_t)(dav_session.error_string));
}
} else {
DEBUG_WEBDAV("Unknown method!");
+ errno = ERRNO_GENERAL_ERROR;
rc = -1;
}
@@ -1405,7 +1487,7 @@ static ssize_t owncloud_read(csync_vio_method_handle_t *fhandle, void *buf, size
return len;
}
-static off_t owncloud_lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence) {
+static int64_t owncloud_lseek(csync_vio_method_handle_t *fhandle, int64_t offset, int whence) {
(void) fhandle;
(void) offset;
(void) whence;
@@ -1452,14 +1534,12 @@ static csync_vio_file_stat_t *owncloud_readdir(csync_vio_method_handle_t *dhandl
struct listdir_context *fetchCtx = dhandle;
- if( fetchCtx->currResource ) {
- // DEBUG_WEBDAV("readdir method called for %s", fetchCtx->currResource->uri);
- } else {
+ if( fetchCtx == NULL) {
/* DEBUG_WEBDAV("An empty dir or at end"); */
return NULL;
}
- while( fetchCtx && fetchCtx->currResource ) {
+ while( fetchCtx->currResource ) {
resource* currResource = fetchCtx->currResource;
char *escaped_path = NULL;
@@ -1480,7 +1560,6 @@ static csync_vio_file_stat_t *owncloud_readdir(csync_vio_method_handle_t *dhandl
}
/* This is the target URI */
- DEBUG_WEBDAV( "Skipping target resource.");
SAFE_FREE( escaped_path );
}
@@ -1519,9 +1598,9 @@ static int owncloud_mkdir(const char *uri, mode_t mode) {
* To keep csync vio_mkdirs working errno EEXIST has to be returned. */
if (errno == EPERM && http_result_code_from_session() == 405) {
errno = EEXIST;
- } else if (rc != NE_OK && _progresscb) {
- _progresscb(uri, CSYNC_NOTIFY_ERROR, http_result_code_from_session(),
- (long long)(dav_session.error_string) ,dav_session.userdata);
+ } else if (rc != NE_OK) {
+ oc_notify_progress(uri, CSYNC_NOTIFY_ERROR, http_result_code_from_session(),
+ (intptr_t)(dav_session.error_string) );
}
}
SAFE_FREE( path );
@@ -1579,9 +1658,9 @@ static int owncloud_rename(const char *olduri, const char *newuri) {
errno = ENOENT;
} else {
set_errno_from_neon_errcode(rc);
- if (rc != NE_OK && _progresscb) {
- _progresscb(olduri, CSYNC_NOTIFY_ERROR, http_result_code_from_session(),
- (long long)(dav_session.error_string) ,dav_session.userdata);
+ if (rc != NE_OK) {
+ oc_notify_progress(olduri, CSYNC_NOTIFY_ERROR, http_result_code_from_session(),
+ (intptr_t)(dav_session.error_string) );
}
}
}
@@ -1723,10 +1802,6 @@ static int owncloud_set_property(const char *key, void *data) {
dav_session.proxy_port = *(int*)(data);
return 0;
}
- if (c_streq(key, "progress_callback")) {
- _progresscb = *(csync_progress_callback*)(data);
- return 0;
- }
if (c_streq(key, "read_timeout") || c_streq(key, "timeout")) {
dav_session.read_timeout = *(int*)(data);
return 0;
@@ -1748,6 +1823,34 @@ static int owncloud_set_property(const char *key, void *data) {
dav_session.no_recursive_propfind = *(bool*)(data);
return 0;
}
+ if( c_streq(key, "hbf_block_size")) {
+ dav_session.hbf_block_size = *(int64_t*)(data);
+ return 0;
+ }
+ if( c_streq(key, "hbf_threshold")) {
+ dav_session.hbf_threshold = *(int64_t*)(data);
+ return 0;
+ }
+ if( c_streq(key, "bandwidth_limit_upload")) {
+ dav_session.bandwidth_limit_upload = *(int*)(data);
+ return 0;
+ }
+ if( c_streq(key, "bandwidth_limit_download")) {
+ dav_session.bandwidth_limit_download = *(int*)(data);
+ return 0;
+ }
+ if( c_streq(key, "overall_progress_data")) {
+ dav_session.overall_progress_data = (csync_overall_progress_t*)(data);
+ }
+ if( c_streq(key, "redirect_callback")) {
+ if (data) {
+ csync_owncloud_redirect_callback_t* cb_wrapper = data;
+
+ dav_session.redir_callback = *cb_wrapper;
+ } else {
+ dav_session.redir_callback = NULL;
+ }
+ }
return -1;
}
@@ -1784,12 +1887,12 @@ csync_vio_method_t *vio_module_init(const char *method_name, const char *args,
csync_auth_callback cb, void *userdata) {
(void) method_name;
(void) args;
+ (void) userdata;
_authcb = cb;
_connected = 0; /* triggers dav_connect to go through the whole neon setup */
memset(&dav_session, 0, sizeof(dav_session));
- dav_session.userdata = userdata;
return &_method;
}
diff --git a/modules/csync_owncloud.h b/modules/csync_owncloud.h
index ba879fd..08fb567 100644
--- a/modules/csync_owncloud.h
+++ b/modules/csync_owncloud.h
@@ -83,7 +83,7 @@ typedef struct resource {
char *name; /* The filename only */
enum resource_type type;
- off_t size;
+ int64_t size;
time_t modtime;
char* md5;
@@ -110,7 +110,7 @@ struct propfind_recursive_element {
struct resource *children;
};
typedef struct propfind_recursive_element propfind_recursive_element_t;
-void clear_propfind_recursive_cache();
+void clear_propfind_recursive_cache(void);
struct listdir_context *get_listdir_context_from_cache(const char *curi);
struct listdir_context *fetch_resource_list_recursive(const char *uri, const char *curi);
@@ -126,8 +126,15 @@ struct transfer_context {
const char *method; /* the HTTP method, either PUT or GET */
ne_decompress *decompress; /* the decompress context */
char *url;
+
+ /* Used for limiting the bandwidth */
+ struct timeval last_time;
+ ne_off_t last_progress;
+ int64_t get_size;
};
+typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
+
/* Struct with the WebDAV session */
struct dav_session_s {
ne_session *ctx;
@@ -147,11 +154,19 @@ struct dav_session_s {
int read_timeout;
CSYNC *csync_ctx;
- void *userdata;
csync_hbf_info_t *chunk_info;
bool no_recursive_propfind;
+ int64_t hbf_block_size;
+ int64_t hbf_threshold;
+
+ /* If 0, it is disabled. If >0, in Byte/seconds. If < 0, in % of the available bandwidth*/
+ int bandwidth_limit_upload;
+ int bandwidth_limit_download;
+
+ csync_overall_progress_t *overall_progress_data;
+ csync_owncloud_redirect_callback_t redir_callback;
};
extern struct dav_session_s dav_session;
@@ -177,4 +192,6 @@ char *_cleanPath( const char* uri );
int _stat_perms( int type );
csync_vio_file_stat_t *resourceToFileStat( struct resource *res );
+void oc_notify_progress(const char *file, enum csync_notify_type_e kind, int64_t current_size, int64_t full_size);
+
#endif /* CSYNC_OWNCLOUD_H */
diff --git a/modules/csync_owncloud_recursive_propfind.c b/modules/csync_owncloud_recursive_propfind.c
index a4d68c8..68ec550 100644
--- a/modules/csync_owncloud_recursive_propfind.c
+++ b/modules/csync_owncloud_recursive_propfind.c
@@ -54,7 +54,7 @@ static void _tree_destructor(void *data) {
SAFE_FREE(element);
}
-void clear_propfind_recursive_cache()
+void clear_propfind_recursive_cache(void)
{
c_rbtree_destroy(propfind_recursive_cache, _tree_destructor);
propfind_recursive_cache = NULL;
@@ -224,7 +224,7 @@ static void results_recursive(void *userdata,
/*
* fetches a resource list from the WebDAV server. This is equivalent to list dir.
*/
-extern csync_progress_callback _progresscb;
+
struct listdir_context *fetch_resource_list_recursive(const char *uri, const char *curi)
{
int ret = 0;
@@ -253,11 +253,9 @@ struct listdir_context *fetch_resource_list_recursive(const char *uri, const cha
req_status->reason_phrase);
ret = NE_CONNECT;
set_error_message(req_status->reason_phrase);
- if (_progresscb) {
- _progresscb(uri, CSYNC_NOTIFY_ERROR, req_status->code, (long long)(req_status->reason_phrase) ,dav_session.userdata);
- }
+ oc_notify_progress(uri, CSYNC_NOTIFY_ERROR, req_status->code, (intptr_t)(req_status->reason_phrase));
}
- DEBUG_WEBDAV("Recursive propfind result code %d.", req_status->code);
+ DEBUG_WEBDAV("Recursive propfind result code %d.", req_status ? req_status->code : 0);
} else {
if( ret == NE_ERROR && req_status->code == 404) {
errno = ENOENT;
diff --git a/modules/csync_owncloud_util.c b/modules/csync_owncloud_util.c
index b264da4..70818dc 100644
--- a/modules/csync_owncloud_util.c
+++ b/modules/csync_owncloud_util.c
@@ -20,6 +20,7 @@
*/
#include "csync_owncloud.h"
+#include "csync_misc.h"
void set_error_message( const char *msg )
{
@@ -333,3 +334,29 @@ int _stat_perms( int type ) {
}
return ret;
}
+
+void oc_notify_progress(const char *file, enum csync_notify_type_e kind, int64_t current_size, int64_t full_size)
+{
+ csync_progress_callback progress_cb = csync_get_progress_callback(dav_session.csync_ctx);
+
+ csync_overall_progress_t overall_progress;
+ ZERO_STRUCT(overall_progress);
+
+ if( dav_session.overall_progress_data) {
+ overall_progress = *dav_session.overall_progress_data;
+ }
+
+ if (progress_cb) {
+ CSYNC_PROGRESS progress;
+ progress.kind = kind;
+ progress.path = file;
+ progress.curr_bytes = current_size;
+ progress.file_size = full_size;
+ progress.overall_transmission_size = overall_progress.byte_sum;
+ progress.current_overall_bytes = overall_progress.byte_current+current_size;
+ progress.overall_file_count = overall_progress.file_count;
+ progress.current_file_no = overall_progress.current_file_no;
+
+ progress_cb(&progress, csync_get_userdata(dav_session.csync_ctx));
+ }
+}
diff --git a/modules/csync_sftp.c b/modules/csync_sftp.c
index 4111aa5..672f26e 100644
--- a/modules/csync_sftp.c
+++ b/modules/csync_sftp.c
@@ -612,7 +612,7 @@ static ssize_t _sftp_write(csync_vio_method_handle_t *fhandle, const void *buf,
return rc;
}
-static off_t _sftp_lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence) {
+static int64_t _sftp_lseek(csync_vio_method_handle_t *fhandle, int64_t offset, int whence) {
/* FIXME: really implement seek for lseek? */
(void) whence;
sftp_seek(fhandle, offset);
diff --git a/modules/csync_sftp2.c b/modules/csync_sftp2.c
index 0bd375b..8a590ed 100644
--- a/modules/csync_sftp2.c
+++ b/modules/csync_sftp2.c
@@ -456,7 +456,7 @@ static ssize_t _write(csync_vio_method_handle_t *fhandle, const void *buf, size_
return rc;
}
-static off_t _lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence) {
+static int64_t _lseek(csync_vio_method_handle_t *fhandle, int64_t offset, int whence) {
/* FIXME: really implement seek for lseek? */
(void) whence;
diff --git a/modules/csync_smb.c b/modules/csync_smb.c
index 60d69c9..407617e 100644
--- a/modules/csync_smb.c
+++ b/modules/csync_smb.c
@@ -173,12 +173,12 @@ static ssize_t _write(csync_vio_method_handle_t *fhandle, const void *buf, size_
return smbc_write(handle->fd, (char *) buf, count);
}
-static off_t _lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence) {
+static int64_t _lseek(csync_vio_method_handle_t *fhandle, int64_t offset, int whence) {
smb_fhandle_t *handle = NULL;
if (fhandle == NULL) {
errno = EBADF;
- return (off_t) -1;
+ return (int64_t) -1;
}
handle = (smb_fhandle_t *) fhandle;
diff --git a/src/csync.c b/src/csync.c
index 89683aa..099f584 100644
--- a/src/csync.c
+++ b/src/csync.c
@@ -221,7 +221,7 @@ int csync_init(CSYNC *ctx) {
}
if (csync_exclude_load(ctx, exclude) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Could not load %s - %s", exclude,
errbuf);
}
@@ -235,27 +235,11 @@ int csync_init(CSYNC *ctx) {
}
if (csync_exclude_load(ctx, exclude) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "Could not load %s - %s", exclude,
errbuf);
}
- /* create/load statedb */
- if (! csync_is_statedb_disabled(ctx)) {
- rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db",
- ctx->local.uri);
- if (rc < 0) {
- goto out;
- }
- CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Journal: %s", ctx->statedb.file);
-
- if (csync_statedb_load(ctx, ctx->statedb.file) < 0) {
- ctx->error_code = CSYNC_ERR_STATEDB_LOAD;
- rc = -1;
- goto out;
- }
- }
-
ctx->local.type = LOCAL_REPLICA;
/* check for uri */
@@ -333,12 +317,10 @@ 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);
+ /* Install progress callbacks in the module. */
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
ctx->error_code = CSYNC_ERR_TREE;
rc = -1;
@@ -394,6 +376,23 @@ int csync_update(CSYNC *ctx) {
}
SAFE_FREE(lock);
+
+ /* create/load statedb */
+ if (! csync_is_statedb_disabled(ctx)) {
+ rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db",
+ ctx->local.uri);
+ if (rc < 0) {
+ return rc;
+ }
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Journal: %s", ctx->statedb.file);
+
+ if (csync_statedb_load(ctx, ctx->statedb.file) < 0) {
+ ctx->error_code = CSYNC_ERR_STATEDB_LOAD;
+ rc = -1;
+ return rc;
+ }
+ }
+
csync_memstat_check(ctx);
/* update detection for local replica */
@@ -507,9 +506,16 @@ int csync_propagate(CSYNC *ctx) {
}
ctx->error_code = CSYNC_ERR_NONE;
+ rc = csync_init_progress(ctx);
+ if (rc < 0) {
+ if( ctx->error_code == CSYNC_ERR_NONE )
+ ctx->error_code = csync_errno_to_csync_error( CSYNC_ERR_PROPAGATE);
+ return -1;
+ }
+
ctx->current = REMOTE_REPLICA;
ctx->replica = ctx->remote.type;
- rc = csync_propagate_rename_dirs(ctx);
+ rc = csync_propagate_renames(ctx);
if (rc < 0) {
if( ctx->error_code == CSYNC_ERR_NONE )
ctx->error_code = csync_errno_to_csync_error( CSYNC_ERR_PROPAGATE);
@@ -550,6 +556,8 @@ int csync_propagate(CSYNC *ctx) {
"Propagation for remote replica took %.2f seconds visiting %zu files.",
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
+ csync_finalize_progress(ctx);
+
if (rc < 0) {
if( ctx->error_code == CSYNC_ERR_NONE )
ctx->error_code = csync_errno_to_csync_error( CSYNC_ERR_PROPAGATE);
@@ -699,10 +707,7 @@ static void _tree_destructor(void *data) {
csync_file_stat_t *freedata = NULL;
freedata = (csync_file_stat_t *) data;
- SAFE_FREE(freedata->md5);
- SAFE_FREE(freedata->destpath);
- SAFE_FREE(freedata->error_string);
- SAFE_FREE(freedata);
+ csync_file_stat_free(freedata);
}
static int _merge_and_write_statedb(CSYNC *ctx) {
@@ -717,7 +722,7 @@ static int _merge_and_write_statedb(CSYNC *ctx) {
if (ctx->status >= CSYNC_STATUS_DONE) {
/* merge trees */
if (csync_merge_file_trees(ctx) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to merge trees: %s",
errbuf);
rc = -1;
@@ -731,7 +736,7 @@ static int _merge_and_write_statedb(CSYNC *ctx) {
"Writing the statedb of %zu files to disk took %.2f seconds",
c_rbtree_size(ctx->local.tree), c_secdiff(finish, start));
} else {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Unable to write statedb: %s",
errbuf);
rc = -1;
@@ -746,6 +751,52 @@ static int _merge_and_write_statedb(CSYNC *ctx) {
return rc;
}
+/* reset all the list to empty.
+ * used by csync_commit and csync_destroy */
+static void _csync_clean_ctx(CSYNC *ctx)
+{
+ c_list_t * walk;
+
+ while (ctx->progress_info) {
+ csync_progressinfo_t *next = ctx->progress_info->next;
+ csync_statedb_free_progressinfo(ctx->progress_info);
+ ctx->progress_info = next;
+ }
+
+ /* destroy the rbtrees */
+ if (c_rbtree_size(ctx->local.tree) > 0) {
+ c_rbtree_destroy(ctx->local.tree, _tree_destructor);
+ }
+
+ if (c_rbtree_size(ctx->remote.tree) > 0) {
+ c_rbtree_destroy(ctx->remote.tree, _tree_destructor);
+ }
+
+ csync_rename_destroy(ctx);
+
+ for (walk = c_list_last(ctx->local.ignored_cleanup); walk != NULL; walk = c_list_prev(walk)) {
+ SAFE_FREE(walk->data);
+ }
+ for (walk = c_list_last(ctx->remote.ignored_cleanup); walk != NULL; walk = c_list_prev(walk)) {
+ SAFE_FREE(walk->data);
+ }
+
+ /* free memory */
+ c_rbtree_free(ctx->local.tree);
+ c_list_free(ctx->local.list);
+ c_list_free(ctx->local.ignored_cleanup);
+ c_rbtree_free(ctx->remote.tree);
+ c_list_free(ctx->remote.list);
+ c_list_free(ctx->remote.ignored_cleanup);
+
+ ctx->remote.list = 0;
+ ctx->local.list = 0;
+ ctx->remote.ignored_cleanup = 0;
+ ctx->local.ignored_cleanup = 0;
+
+ SAFE_FREE(ctx->statedb.file);
+}
+
int csync_commit(CSYNC *ctx) {
int rc = 0;
char *lock = NULL;
@@ -768,54 +819,10 @@ int csync_commit(CSYNC *ctx) {
csync_vio_commit(ctx);
- while (ctx->progress) {
- csync_progressinfo_t *next = ctx->progress->next;
- csync_statedb_free_progressinfo(ctx->progress);
- ctx->progress = next;
- }
-
- /* destroy the rbtrees */
- if (c_rbtree_size(ctx->local.tree) > 0) {
- c_rbtree_destroy(ctx->local.tree, _tree_destructor);
- }
-
- if (c_rbtree_size(ctx->remote.tree) > 0) {
- c_rbtree_destroy(ctx->remote.tree, _tree_destructor);
- }
-
- csync_rename_destroy(ctx);
-
- /* free memory */
- c_rbtree_free(ctx->local.tree);
- c_list_free(ctx->local.list);
- c_rbtree_free(ctx->remote.tree);
- c_list_free(ctx->remote.list);
-
- ctx->remote.list = 0;
- ctx->local.list = 0;
+ _csync_clean_ctx(ctx);
ctx->remote.read_from_db = 0;
- /* create/load statedb */
- if (! csync_is_statedb_disabled(ctx)) {
- if(!ctx->statedb.file) {
- rc = asprintf(&ctx->statedb.file, "%s/.csync_journal.db",
- ctx->local.uri);
- if (rc < 0) {
- ctx->error_code = CSYNC_ERR_MEM;
- CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Failed to assemble statedb file name.");
- goto out;
- }
- }
- CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Journal: %s", ctx->statedb.file);
-
- if (csync_statedb_load(ctx, ctx->statedb.file) < 0) {
- ctx->error_code = CSYNC_ERR_STATEDB_LOAD;
- rc = -1;
- goto out;
- }
- }
-
/* Create new trees */
if (c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp) < 0) {
ctx->error_code = CSYNC_ERR_TREE;
@@ -829,6 +836,12 @@ int csync_commit(CSYNC *ctx) {
goto out;
}
+ /* reset the progress */
+ ctx->overall_progress.file_count = 0;
+ ctx->overall_progress.current_file_no = 0;
+ ctx->overall_progress.byte_sum = 0;
+ ctx->overall_progress.byte_current = 0;
+
ctx->status = CSYNC_STATUS_INIT;
ctx->error_code = CSYNC_ERR_NONE;
SAFE_FREE(ctx->error_string);
@@ -865,7 +878,7 @@ int csync_destroy(CSYNC *ctx) {
/* The other steps happen anyway, what else can we do? */
}
- /* clear exclude list */
+ /* destroy exclude list */
csync_exclude_destroy(ctx);
/* remove the lock file */
@@ -873,32 +886,11 @@ int csync_destroy(CSYNC *ctx) {
csync_lock_remove(ctx, lock);
}
- while (ctx->progress) {
- csync_progressinfo_t *next = ctx->progress->next;
- csync_statedb_free_progressinfo(ctx->progress);
- ctx->progress = next;
- }
-
- /* destroy the rbtrees */
- if (c_rbtree_size(ctx->local.tree) > 0) {
- c_rbtree_destroy(ctx->local.tree, _tree_destructor);
- }
-
- if (c_rbtree_size(ctx->remote.tree) > 0) {
- c_rbtree_destroy(ctx->remote.tree, _tree_destructor);
- }
-
- csync_rename_destroy(ctx);
+ _csync_clean_ctx(ctx);
- /* free memory */
- c_rbtree_free(ctx->local.tree);
- c_list_free(ctx->local.list);
- c_rbtree_free(ctx->remote.tree);
- c_list_free(ctx->remote.list);
SAFE_FREE(ctx->local.uri);
SAFE_FREE(ctx->remote.uri);
SAFE_FREE(ctx->options.config_dir);
- SAFE_FREE(ctx->statedb.file);
SAFE_FREE(ctx->error_string);
#ifdef WITH_ICONV
@@ -930,6 +922,11 @@ int csync_add_exclude_list(CSYNC *ctx, const char *path) {
return csync_exclude_load(ctx, path);
}
+void csync_clear_exclude_list(CSYNC *ctx)
+{
+ csync_exclude_clear(ctx);
+}
+
const char *csync_get_config_dir(CSYNC *ctx) {
if (ctx == NULL) {
return NULL;
@@ -1186,23 +1183,6 @@ int csync_set_iconv_codec(const char *from)
}
#endif
-int csync_set_progress_callback(CSYNC* ctx, csync_progress_callback cb)
-{
- if (ctx == NULL) {
- return -1;
- }
- if (cb == NULL ) {
- ctx->error_code = CSYNC_ERR_PARAM;
- return -1;
- }
-
- ctx->error_code = CSYNC_ERR_NONE;
- ctx->callbacks.progresscb = cb;
-
- return 0;
-
-}
-
void csync_request_abort(CSYNC *ctx)
{
if (ctx != NULL) {
@@ -1226,4 +1206,39 @@ int csync_abort_requested(CSYNC *ctx)
}
}
+void csync_file_stat_free(csync_file_stat_t *st)
+{
+ if (st) {
+ SAFE_FREE(st->md5);
+ SAFE_FREE(st->error_string);
+ SAFE_FREE(st->destpath);
+ SAFE_FREE(st);
+ }
+}
+
+int csync_set_progress_callback(CSYNC* ctx, csync_progress_callback cb)
+{
+ if (ctx == NULL) {
+ return -1;
+ }
+ if (cb == NULL ) {
+ ctx->error_code = CSYNC_ERR_PARAM;
+ return -1;
+ }
+
+ ctx->callbacks.progress_cb = cb;
+
+ return 0;
+
+}
+
+csync_progress_callback csync_get_progress_callback(CSYNC *ctx)
+{
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ return ctx->callbacks.progress_cb;
+}
+
/* vim: set ts=8 sw=2 et cindent: */
diff --git a/src/csync.h b/src/csync.h
index ba48241..3937721 100644
--- a/src/csync.h
+++ b/src/csync.h
@@ -117,13 +117,43 @@ enum csync_ftw_type_e {
CSYNC_FTW_TYPE_SKIP
};
+enum csync_notify_type_e {
+ CSYNC_NOTIFY_INVALID,
+ CSYNC_NOTIFY_START_SYNC_SEQUENCE,
+ CSYNC_NOTIFY_START_DOWNLOAD,
+ CSYNC_NOTIFY_START_UPLOAD,
+ CSYNC_NOTIFY_PROGRESS,
+ CSYNC_NOTIFY_FINISHED_DOWNLOAD,
+ CSYNC_NOTIFY_FINISHED_UPLOAD,
+ CSYNC_NOTIFY_FINISHED_SYNC_SEQUENCE,
+ CSYNC_NOTIFY_START_DELETE,
+ CSYNC_NOTIFY_END_DELETE,
+ CSYNC_NOTIFY_ERROR
+};
+
+struct csync_progress_s {
+ enum csync_notify_type_e kind;
+
+ /* individual file progress information */
+ const char *path;
+ int64_t curr_bytes;
+ int64_t file_size;
+
+ /* overall progress */
+ int64_t overall_transmission_size;
+ int64_t current_overall_bytes;
+ int64_t overall_file_count;
+ int64_t current_file_no;
+
+};
+typedef struct csync_progress_s CSYNC_PROGRESS;
/**
* CSync File Traversal structure.
*
* This structure is passed to the visitor function for every file
* which is seen.
- * Note: The file size is missing here because type off_t is depending
+ * Note: The file size is missing here because type int64_t is depending
* on the large file support in your build. Make sure to check
* that cmake and the callback app are compiled with the same
* setting for it, such as:
@@ -269,6 +299,13 @@ const char *csync_version(int req_version);
int csync_add_exclude_list(CSYNC *ctx, const char *path);
/**
+ * @brief Removes all items imported from exclude lists.
+ *
+ * @param ctx The context to add the exclude list.
+ */
+void csync_clear_exclude_list(CSYNC *ctx);
+
+/**
* @brief Get the config directory.
*
* @param ctx The csync context.
@@ -508,20 +545,24 @@ const char *csync_get_error_string(CSYNC *ctx);
*/
int csync_set_module_property(CSYNC *ctx, const char *key, void *value);
-enum csync_notify_type_e { CSYNC_NOTIFY_START_DOWNLOAD, CSYNC_NOTIFY_START_UPLOAD,
- CSYNC_NOTIFY_PROGRESS, CSYNC_NOTIFY_FINISHED_DOWNLOAD,
- CSYNC_NOTIFY_FINISHED_UPLOAD, CSYNC_NOTIFY_ERROR };
-
-typedef void (*csync_progress_callback) (const char *remote_url, enum csync_notify_type_e kind,
- long long o1, long long o2, void *userdata);
/**
- * @brief Set a progress callback
+ * @brief Callback definition for file progress callback.
*
- * @param ctx The csync context.
+ * @param progress A struct containing progress information.
*
- * @param cb The callback
+ * @param userdata User defined data for the callback.
*/
-int csync_set_progress_callback(CSYNC *ctx, csync_progress_callback cb);
+typedef void (*csync_progress_callback)( CSYNC_PROGRESS *progress, void *userdata);
+
+/**
+ * @brief Set a progress callback.
+ *
+ * This callback reports about up- or download progress of a individual file
+ * as well as overall progress.
+ */
+int csync_set_progress_callback( CSYNC *ctx, csync_progress_callback cb);
+
+csync_progress_callback csync_get_progress_callback(CSYNC *ctx);
/**
* @brief Aborts the current sync run as soon as possible. Can be called from another thread.
diff --git a/src/csync_exclude.c b/src/csync_exclude.c
index e6ae5ca..792d36c 100644
--- a/src/csync_exclude.c
+++ b/src/csync_exclude.c
@@ -59,7 +59,7 @@ int csync_exclude_load(CSYNC *ctx, const char *fname) {
int fd = -1;
int i = 0;
int rc = -1;
- off_t size;
+ int64_t size;
char *buf = NULL;
char *entry = NULL;
const _TCHAR *wfname;
@@ -88,11 +88,12 @@ int csync_exclude_load(CSYNC *ctx, const char *fname) {
goto out;
}
buf = c_malloc(size);
+ memset(buf, 0, size);
+
if (read(fd, buf, size) != size) {
rc = -1;
goto out;
}
- close(fd);
/* FIXME: Don't add duplicates */
entry = buf;
@@ -120,20 +121,26 @@ out:
return rc;
}
+void csync_exclude_clear(CSYNC *ctx) {
+ c_strlist_clear(ctx->excludes);
+}
+
void csync_exclude_destroy(CSYNC *ctx) {
c_strlist_destroy(ctx->excludes);
}
-int csync_excluded(CSYNC *ctx, const char *path) {
+CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path) {
size_t i;
const char *p;
char *bname;
int rc;
- int match = 0;
+ CSYNC_EXCLUDE_TYPE match = CSYNC_NOT_EXCLUDED;
+ CSYNC_EXCLUDE_TYPE type = CSYNC_NOT_EXCLUDED;
+ const char *it;
/* exclude the lock file */
if (c_streq( path, CSYNC_LOCK_FILE )) {
- return 1;
+ return CSYNC_FILE_SILENTLY_EXCLUDED;
}
if (! ctx->options.unix_extensions) {
@@ -147,26 +154,21 @@ int csync_excluded(CSYNC *ctx, const char *path) {
case '>':
case '<':
case '|':
- return 1;
+ return CSYNC_FILE_EXCLUDE_INVALID_CHAR;
default:
break;
}
}
}
- rc = csync_fnmatch(".csync_journal.db*", path, 0);
- if (rc == 0) {
- return 1;
- }
-
bname = c_basename(path);
if (bname == NULL) {
- return 0;
+ return CSYNC_NOT_EXCLUDED;
}
rc = csync_fnmatch(".csync_journal.db*", bname, 0);
if (rc == 0) {
- match = 1;
+ match = CSYNC_FILE_SILENTLY_EXCLUDED;
goto out;
}
@@ -174,15 +176,23 @@ int csync_excluded(CSYNC *ctx, const char *path) {
goto out;
}
- for (i = 0; match == 0 && i < ctx->excludes->count; i++) {
- rc = csync_fnmatch(ctx->excludes->vector[i], path, 0);
+ for (i = 0; match == CSYNC_NOT_EXCLUDED && i < ctx->excludes->count; i++) {
+ it = ctx->excludes->vector[i];
+ type = CSYNC_FILE_EXCLUDE_LIST;
+ /* Ecludes starting with ']' means it can be cleanup */
+ if (it[0] == ']') {
+ ++it;
+ type = CSYNC_FILE_EXCLUDE_AND_REMOVE;
+ }
+
+ rc = csync_fnmatch(it, path, 0);
if (rc == 0) {
- match = 1;
+ match = type;
}
- rc = csync_fnmatch(ctx->excludes->vector[i], bname, 0);
+ rc = csync_fnmatch(it, bname, 0);
if (rc == 0) {
- match = 1;
+ match = type;
}
}
diff --git a/src/csync_exclude.h b/src/csync_exclude.h
index 6f76592..fdafc5f 100644
--- a/src/csync_exclude.h
+++ b/src/csync_exclude.h
@@ -21,6 +21,14 @@
#ifndef _CSYNC_EXCLUDE_H
#define _CSYNC_EXCLUDE_H
+enum csync_exclude_type_e {
+ CSYNC_NOT_EXCLUDED = 0,
+ CSYNC_FILE_SILENTLY_EXCLUDED,
+ CSYNC_FILE_EXCLUDE_AND_REMOVE,
+ CSYNC_FILE_EXCLUDE_LIST,
+ CSYNC_FILE_EXCLUDE_INVALID_CHAR
+};
+typedef enum csync_exclude_type_e CSYNC_EXCLUDE_TYPE;
/**
* @brief Load exclude list
*
@@ -32,6 +40,13 @@
int csync_exclude_load(CSYNC *ctx, const char *fname);
/**
+ * @brief Clear the exclude list in memory.
+ *
+ * @param ctx The synchronizer context.
+ */
+void csync_exclude_clear(CSYNC *ctx);
+
+/**
* @brief Destroy the exclude list in memory.
*
* @param ctx The synchronizer context.
@@ -46,9 +61,9 @@ void csync_exclude_destroy(CSYNC *ctx);
* @param ctx The synchronizer context.
* @param path The patch to check.
*
- * @return 1 if excluded, 0 if not.
+ * @return 2 if excluded and needs cleanup, 1 if excluded, 0 if not.
*/
-int csync_excluded(CSYNC *ctx, const char *path);
+CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path);
#endif /* _CSYNC_EXCLUDE_H */
diff --git a/src/csync_lock.c b/src/csync_lock.c
index 6ad9bfe..4329ba1 100644
--- a/src/csync_lock.c
+++ b/src/csync_lock.c
@@ -41,7 +41,7 @@
#define CSYNC_LOG_CATEGORY_NAME "csync.lock"
#include "csync_log.h"
-#ifndef _WIN32
+#ifdef _DO_CREATE_A_LOCK_FILE
static int _csync_lock_create(CSYNC *ctx, const char *lockfile) {
int fd = -1;
pid_t pid = 0;
diff --git a/src/csync_log.c b/src/csync_log.c
index c780e92..d3a5848 100644
--- a/src/csync_log.c
+++ b/src/csync_log.c
@@ -50,7 +50,7 @@ static int current_timestring(int hires, char *buf, size_t len)
if (hires) {
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
- snprintf(buf, len, "%s.%06ld", tbuf, tv.tv_usec);
+ snprintf(buf, len, "%s.%06ld", tbuf, (long) tv.tv_usec);
} else {
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
snprintf(buf, len, "%s", tbuf);
diff --git a/src/csync_log.h b/src/csync_log.h
index e6494fc..9d90356 100644
--- a/src/csync_log.h
+++ b/src/csync_log.h
@@ -33,11 +33,17 @@
#define _CSYNC_LOG_H
/* GCC have printf type attribute check. */
+#ifndef PRINTF_ATTRIBUTE
#ifdef __GNUC__
+#ifdef _WIN32
+#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__gnu_printf__, a, b)))
+#else
#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#endif
#else
#define PRINTF_ATTRIBUTE(a,b)
#endif /* __GNUC__ */
+#endif /* ndef PRINTF_ATTRIBUTE */
enum csync_log_priority_e {
CSYNC_LOG_PRIORITY_NOLOG = 0,
diff --git a/src/csync_misc.c b/src/csync_misc.c
index 0deac97..6d6f97b 100644
--- a/src/csync_misc.c
+++ b/src/csync_misc.c
@@ -146,6 +146,7 @@ int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
#include <shlwapi.h>
int csync_fnmatch(__const char *__pattern, __const char *__name, int __flags) {
+ (void) __flags;
if(PathMatchSpec(__name, __pattern))
return 0;
else
diff --git a/src/csync_misc.h b/src/csync_misc.h
index b6f19ce..36867c9 100644
--- a/src/csync_misc.h
+++ b/src/csync_misc.h
@@ -44,4 +44,11 @@ struct csync_hbf_info_s {
};
typedef struct csync_hbf_info_s csync_hbf_info_t;
+typedef struct {
+ int64_t file_count;
+ int64_t current_file_no;
+ int64_t byte_sum;
+ int64_t byte_current;
+} csync_overall_progress_t;
+
#endif /* _CSYNC_MISC_H */
diff --git a/src/csync_private.h b/src/csync_private.h
index 70d1170..7aacece 100644
--- a/src/csync_private.h
+++ b/src/csync_private.h
@@ -39,6 +39,7 @@
#include "c_lib.h"
#include "c_private.h"
#include "csync.h"
+#include "csync_misc.h"
#ifdef WITH_ICONV
#include <iconv.h>
@@ -81,7 +82,6 @@ enum csync_replica_e {
typedef struct csync_file_stat_s csync_file_stat_t;
-
/**
* @brief csync public structure
*/
@@ -89,7 +89,7 @@ struct csync_s {
struct {
csync_auth_callback auth_function;
csync_log_callback log_function;
- csync_progress_callback progresscb;
+ csync_progress_callback progress_cb;
void *userdata;
} callbacks;
c_strlist_t *excludes;
@@ -106,6 +106,7 @@ struct csync_s {
c_rbtree_t *tree;
c_list_t *list;
enum csync_replica_e type;
+ c_list_t *ignored_cleanup;
} local;
struct {
@@ -114,6 +115,7 @@ struct csync_s {
c_list_t *list;
enum csync_replica_e type;
int read_from_db;
+ c_list_t *ignored_cleanup;
} remote;
struct {
@@ -144,7 +146,9 @@ struct csync_s {
uid_t euid;
} pwd;
- struct csync_progressinfo_s *progress;
+ csync_overall_progress_t overall_progress;
+
+ struct csync_progressinfo_s *progress_info;
/* replica we are currently walking */
enum csync_replica_e current;
@@ -172,7 +176,7 @@ struct csync_s {
struct csync_file_stat_s {
uint64_t phash; /* u64 */
time_t modtime; /* u64 */
- off_t size; /* u64 */
+ int64_t size; /* u64 */
size_t pathlen; /* u64 */
uint64_t inode; /* u64 */
uid_t uid; /* u32 */
@@ -198,6 +202,8 @@ __attribute__ ((packed))
#endif
;
+void csync_file_stat_free(csync_file_stat_t *st);
+
/*
* context for the treewalk function
*/
diff --git a/src/csync_propagate.c b/src/csync_propagate.c
index 7dc37bc..767a69e 100644
--- a/src/csync_propagate.c
+++ b/src/csync_propagate.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <inttypes.h>
#include <time.h>
#include <limits.h>
@@ -67,6 +68,36 @@ static void _csync_file_stat_set_error(csync_file_stat_t *st, const char *error)
st->error_string = c_strdup(error);
}
+/* Recursively mark the parent flder as an error */
+static void _csync_report_parent_error(CSYNC *ctx, csync_file_stat_t *st) {
+ const char *dir = NULL;
+ uint64_t h;
+ c_rbnode_t* node;
+
+ dir = c_dirname(st->path);
+ if (!dir) return;
+
+ h = c_jhash64((uint8_t *) dir, strlen(dir), 0);
+ node = c_rbtree_find(ctx->local.tree, &h);
+
+ if (!node) {
+ /* Not in the local tree, mark the remote tree as an error then */
+ node = c_rbtree_find(ctx->remote.tree, &h);
+ }
+
+ if (node) {
+ st = node->data;
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,
+ "Mark parent directoy `%s` as an error",
+ dir);
+
+ _csync_file_stat_set_error(st, "Error within the directory");
+ _csync_report_parent_error(ctx, st);
+ }
+
+ SAFE_FREE(dir);
+}
+
/* Record the error in the ctx->progress
pi may be a previous csync_progressinfo_t from the database.
If pi is NULL, a new one is created, else it is re-used
@@ -74,6 +105,7 @@ static void _csync_file_stat_set_error(csync_file_stat_t *st, const char *error)
static void _csync_record_error(CSYNC *ctx, csync_file_stat_t *st, csync_progressinfo_t *pi)
{
_csync_file_stat_set_error(st, csync_get_error_string(ctx));
+ _csync_report_parent_error(ctx, st);
if (pi) {
pi->error++;
SAFE_FREE(pi->error_string);
@@ -88,8 +120,8 @@ static void _csync_record_error(CSYNC *ctx, csync_file_stat_t *st, csync_progres
pi->error = 1;
}
pi->error_string = st->error_string ? c_strdup(st->error_string) : NULL;
- pi->next = ctx->progress;
- ctx->progress = pi;
+ pi->next = ctx->progress_info;
+ ctx->progress_info = pi;
}
static bool _push_to_tmp_first(CSYNC *ctx)
@@ -103,6 +135,26 @@ static bool _push_to_tmp_first(CSYNC *ctx)
return false;
}
+static void _notify_progress(CSYNC *ctx, const char *file, int64_t filesize, enum csync_notify_type_e kind)
+{
+ if (ctx == NULL) {
+ return;
+ }
+ if (ctx->callbacks.progress_cb) {
+ CSYNC_PROGRESS progress;
+ progress.kind = kind;
+ progress.path = file;
+ progress.curr_bytes = 0;
+ progress.file_size = filesize;
+ progress.overall_transmission_size = ctx->overall_progress.byte_sum;
+ progress.current_overall_bytes = ctx->overall_progress.byte_current;
+ progress.overall_file_count = ctx->overall_progress.file_count;
+ progress.current_file_no = ctx->overall_progress.current_file_no;
+
+ ctx->callbacks.progress_cb(&progress, ctx->callbacks.userdata);
+ }
+}
+
static bool _use_fd_based_push(CSYNC *ctx)
{
if(!ctx) return false;
@@ -159,6 +211,10 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
csync_hbf_info_t hbf_info = { 0, 0 };
csync_progressinfo_t *progress_info = NULL;
+
+ enum csync_notify_type_e notify_start_kind = CSYNC_NOTIFY_START_UPLOAD;
+ enum csync_notify_type_e notify_end_kind = CSYNC_NOTIFY_FINISHED_UPLOAD;
+
/* Check if there is progress info stored in the database for this file */
progress_info = csync_statedb_get_progressinfo(ctx, st->phash, st->modtime, st->md5);
rep_bak = ctx->replica;
@@ -201,6 +257,9 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
case REMOTE_REPLICA:
srep = ctx->remote.type;
drep = ctx->local.type;
+ notify_start_kind = CSYNC_NOTIFY_START_DOWNLOAD;
+ notify_end_kind = CSYNC_NOTIFY_FINISHED_DOWNLOAD;
+
if (_csync_build_remote_uri(ctx, &suri, st->path) < 0) {
rc = -1;
goto out;
@@ -214,6 +273,10 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
break;
}
+ /* Increment by one as its started now. */
+ ctx->overall_progress.current_file_no++;
+ _notify_progress(ctx, duri, 0, notify_start_kind);
+
/* Check if the file is still untouched since the update run. */
if (do_pre_copy_stat) {
vst = csync_vio_file_stat_new();
@@ -227,8 +290,10 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
st->size != vst->size) {
/* The size or modtime has changed. Skip this file copy for now. */
rc = 1; /* soft problem */
+ SAFE_FREE(st->error_string);
+ st->error_string = c_strdup("File was updated meantime, publish next time.");
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
- "Source file has changed since update run, SKIP it for now.");
+ "Source file %s has changed since update run, SKIP it for now.", suri);
goto out;
}
csync_vio_file_stat_destroy(vst);
@@ -252,7 +317,7 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
rc = 1;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: open(O_RDONLY), error: %s",
suri, errbuf );
@@ -265,7 +330,7 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
turi = c_strdup(progress_info->tmpfile);
/* Try to see if we can resume. */
ctx->replica = drep;
- dfp = csync_vio_open(ctx, turi, O_APPEND|O_NOCTTY, 0);
+ dfp = csync_vio_open(ctx, turi, O_WRONLY|O_APPEND|O_NOCTTY, 0);
if (dfp) {
goto start_fd_based;
}
@@ -335,7 +400,7 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
prev_tdir = c_strdup(tdir);
if (csync_vio_mkdirs(ctx, tdir, C_DIR_MODE) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN,
"dir: %s, command: mkdirs, error: %s",
tdir, errbuf);
@@ -343,14 +408,14 @@ static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
break;
case ENOMEM:
rc = -1;
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: open(O_CREAT), error: %s",
turi, errbuf);
goto out;
break;
default:
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: open(O_CREAT), error: %s",
turi, errbuf);
@@ -380,14 +445,34 @@ start_fd_based:
}
if( rc != 0 ) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ if (rc == -1) {
+ /* Severe error */
+ switch(errno) {
+ case EINVAL:
+ ctx->error_code = CSYNC_ERR_PARAM;
+ break;
+ case ERRNO_USER_ABORT:
+ ctx->error_code = CSYNC_ERR_ABORTED;
+ break;
+ case ERRNO_GENERAL_ERROR:
+ default:
+ ctx->error_code = CSYNC_ERR_PROPAGATE;
+ break;
+ }
+ /* fetch the error string from module. */
+ ctx->error_string = csync_vio_get_error_string(ctx);
+ }
+
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: sendfile, error: %s from errno %d",
- suri, errbuf, errno);
+ suri, c_streq(errbuf, "") ? csync_vio_get_error_string(ctx): errbuf, errno);
if (_push_to_tmp_first(ctx)) {
csync_vio_file_stat_t* sb = csync_vio_file_stat_new();
- if (csync_vio_stat(ctx, turi, sb) == 0 && sb->size > 0) {
+ if (csync_vio_stat(ctx, turi, sb) == 0 && sb->size > 0
+ && errno != EIO) {
+ /* EIO is mapped to error from owncloud like 500 for which we don't want to resume */
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,
"keeping tmp file: %s", turi);
if (!progress_info) {
@@ -437,7 +522,7 @@ start_fd_based:
if (bread < 0) {
/* read error */
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: read, error: %s",
suri, errbuf);
@@ -452,7 +537,7 @@ start_fd_based:
bwritten = csync_vio_write(ctx, dfp, buf, bread);
if (bwritten < 0 || bread != bwritten) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: write, error: bread = %zu, bwritten = %zu - %s",
duri,
@@ -466,7 +551,7 @@ start_fd_based:
}
ctx->replica = srep;
if (csync_vio_close(ctx, sfp) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: close, error: %s",
suri,
@@ -481,7 +566,7 @@ start_fd_based:
/* stop if no space left or quota exceeded */
case ENOSPC:
case EDQUOT:
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: close, error: %s",
turi,
@@ -490,7 +575,7 @@ start_fd_based:
goto out;
break;
default:
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: close, error: %s",
turi,
@@ -510,7 +595,7 @@ start_fd_based:
ctx->replica = drep;
tstat = csync_vio_file_stat_new();
if (tstat == NULL) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: stat, error: %s",
turi,
@@ -528,7 +613,7 @@ start_fd_based:
rc = 1;
break;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: stat, error: %s",
turi,
@@ -538,7 +623,7 @@ start_fd_based:
if (st->size != tstat->size) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
- "file: %s, error: incorrect filesize (size: %jd should be %jd)",
+ "file: %s, error: incorrect filesize (size: %" PRId64 " should be %" PRId64 ")",
turi, tstat->size, st->size);
rc = 1;
goto out;
@@ -569,7 +654,7 @@ start_fd_based:
rc = 1;
break;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: rename, error: %s",
duri,
@@ -588,7 +673,7 @@ start_fd_based:
rc = 1;
break;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: chmod, error: %s",
duri,
@@ -623,6 +708,10 @@ start_fd_based:
/* set instruction for the statedb merger */
st->instruction = CSYNC_INSTRUCTION_UPDATED;
+ /* Notify the progress */
+ ctx->overall_progress.byte_current += st->size;
+ _notify_progress(ctx, duri, st->size, notify_end_kind);
+
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "PUSHED file: %s", duri);
rc = 0;
@@ -679,7 +768,7 @@ static int _backup_path(CSYNC *ctx, char** duri, const char* uri, const char* pa
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"filename : %s",info->filename);
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"extension: %s",info->extension);
- if (asprintf(duri, "%s/%s%s_conflict-%s%s", uri,info->directory ,info->filename,timestring,info->extension) < 0) {
+ if (asprintf(duri, "%s/%s%s_conflict-%s%s", uri, info->directory , info->filename, timestring, info->extension) < 0) {
rc = -1;
}
@@ -731,10 +820,7 @@ static int _csync_backup_file(CSYNC *ctx, csync_file_stat_t *st, char **duri) {
default:
break;
}
- }
-
- else
- {
+ } else {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"instruction not allowed: %i %s",st->instruction,csync_instruction_str(st->instruction));
rc = -1;
goto out;
@@ -755,7 +841,7 @@ static int _csync_backup_file(CSYNC *ctx, csync_file_stat_t *st, char **duri) {
rc = 1;
break;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: rename, error: %s",
*duri,
@@ -798,7 +884,6 @@ static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) {
struct timeval times[2];
char *suri = NULL;
char *duri = NULL;
- const char *tmd5 = NULL;
c_rbnode_t *node = NULL;
char *tdir = NULL;
csync_file_stat_t *other = NULL;
@@ -832,6 +917,7 @@ static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) {
if( !(st->path && st->destpath) ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Rename failed: src or dest path empty");
rc = -1;
+ goto out;
}
if (_csync_build_remote_uri(ctx, &suri, st->path) < 0) {
rc = -1;
@@ -849,9 +935,9 @@ static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) {
default:
break;
}
- CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Renaming %s => %s", suri, duri);
if (! c_streq(suri, duri) && rc > -1) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Renaming %s => %s", suri, duri);
while ((rc = csync_vio_rename(ctx, suri, duri)) != 0) {
switch (errno) {
case ENOENT:
@@ -870,14 +956,14 @@ static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) {
}
if (csync_vio_mkdirs(ctx, tdir, C_DIR_MODE) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN,
"dir: %s, command: mkdirs, error: %s",
tdir, errbuf);
}
break;
default:
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"dir: %s, command: rename, error: %s",
suri,
@@ -899,14 +985,15 @@ static int _csync_rename_file(CSYNC *ctx, csync_file_stat_t *st) {
}
- /* The the uniq ID for the destination */
- if (st->type != CSYNC_FTW_TYPE_DIR)
- tmd5 = _get_md5(ctx, st->destpath);
-
if( rc > -1 ) {
/* set the mtime which is needed in statedb_get_uniqid */
if( other ) {
- other->md5 = tmd5;
+ if (st->type != CSYNC_FTW_TYPE_DIR) {
+ other->md5 = _get_md5(ctx, st->destpath);
+ } else {
+ /* For directories, re-use the old md5 */
+ other->md5 = c_strdup(st->md5);
+ }
}
/* set instruction for the statedb merger */
st->instruction = CSYNC_INSTRUCTION_DELETED;
@@ -950,8 +1037,7 @@ static int _csync_conflict_file(CSYNC *ctx, csync_file_stat_t *st) {
rc = _csync_backup_file(ctx, st, &conflict_file_name);
- if(rc>=0)
- {
+ if(rc >= 0 ) {
rc = _csync_push_file(ctx, st);
}
@@ -964,12 +1050,12 @@ static int _csync_conflict_file(CSYNC *ctx, csync_file_stat_t *st) {
if( c_compare_file(uri, conflict_file_name) == 1 ) {
/* the files are byte wise equal. The conflict can be erased. */
- if (csync_vio_local_unlink(conflict_file_name) < 0) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "REMOVE of csync conflict file %s failed.", conflict_file_name );
- } else {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "REMOVED csync conflict file %s as files are equal.",
- conflict_file_name );
- }
+ if (csync_vio_local_unlink(conflict_file_name) < 0) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "REMOVE of csync conflict file %s failed.", conflict_file_name );
+ } else {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "REMOVED csync conflict file %s as files are equal.",
+ conflict_file_name );
+ }
}
}
}
@@ -1012,6 +1098,7 @@ static int _csync_remove_file(CSYNC *ctx, csync_file_stat_t *st) {
break;
}
+ _notify_progress(ctx, uri, st->size, CSYNC_NOTIFY_START_DELETE);
if (csync_vio_unlink(ctx, uri) < 0) {
switch (errno) {
case ENOMEM:
@@ -1021,7 +1108,7 @@ static int _csync_remove_file(CSYNC *ctx, csync_file_stat_t *st) {
rc = 1;
break;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, command: unlink, error: %s",
uri,
@@ -1031,6 +1118,7 @@ static int _csync_remove_file(CSYNC *ctx, csync_file_stat_t *st) {
/* set instruction for the statedb merger */
st->instruction = CSYNC_INSTRUCTION_DELETED;
+ _notify_progress(ctx, uri, st->size, CSYNC_NOTIFY_END_DELETE);
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "REMOVED file: %s", uri);
@@ -1101,7 +1189,7 @@ static int _csync_new_dir(CSYNC *ctx, csync_file_stat_t *st) {
rc = 1;
break;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"dir: %s, command: mkdirs, error: %s",
uri,
@@ -1120,7 +1208,7 @@ static int _csync_new_dir(CSYNC *ctx, csync_file_stat_t *st) {
rc = 1;
break;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"dir: %s, command: chmod, error: %s",
uri,
@@ -1213,7 +1301,7 @@ static int _csync_sync_dir(CSYNC *ctx, csync_file_stat_t *st) {
rc = 1;
break;
}
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"dir: %s, command: chmod, error: %s",
uri,
@@ -1299,7 +1387,7 @@ static int _csync_remove_dir(CSYNC *ctx, csync_file_stat_t *st) {
if (csync_vio_rmdir(ctx, uri) < 0) {
switch (errno) {
case ENOMEM:
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL,
"dir: %s, command: rmdir, error: %s",
uri,
@@ -1331,7 +1419,7 @@ static int _csync_remove_dir(CSYNC *ctx, csync_file_stat_t *st) {
rc = 0;
break;
default:
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"dir: %s, command: rmdir, error: %s",
uri,
@@ -1359,28 +1447,23 @@ out:
return rc;
}
-static int _cmp_char( const void *d1, const void *d2 )
-{
- const char *c1 = (const char*) d1;
- const char *c2 = (const char*) d2;
- // CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "COMPARE: %s <-> %s", c1, c2);
- if( c_streq(c1, c2) ) return 0;
- return 1;
-}
-
static int _csync_propagation_cleanup(CSYNC *ctx) {
c_list_t *list = NULL;
c_list_t *walk = NULL;
+ c_list_t *walk2 = NULL;
+ c_list_t *ignored_cleanup = NULL;
char *uri = NULL;
char *dir = NULL;
switch (ctx->current) {
case LOCAL_REPLICA:
list = ctx->local.list;
+ ignored_cleanup = ctx->local.ignored_cleanup;
uri = ctx->local.uri;
break;
case REMOTE_REPLICA:
list = ctx->remote.list;
+ ignored_cleanup = ctx->remote.ignored_cleanup;
uri = ctx->remote.uri;
break;
default:
@@ -1403,10 +1486,34 @@ static int _csync_propagation_cleanup(CSYNC *ctx) {
pst = (csync_file_stat_t **) walk->data;
st = *(pst);
+
+ /* Cleanup ignored files */
+ for (walk2 = c_list_last(ignored_cleanup); walk2 != NULL; walk2 = c_list_prev(walk2)) {
+ const char *fn = (const char*) walk2->data;
+ /* check if the file name does not starts with the path to remove. */
+ if (strlen(fn) < st->pathlen || fn[st->pathlen] != '/'
+ || strncmp(fn, st->path, st->pathlen) != 0) {
+ continue;
+ }
+
+ if (asprintf(&dir, "%s/%s", uri, fn) < 0) {
+ return -1;
+ }
+
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Removing ignored file %s ", dir);
+
+ if (csync_vio_unlink(ctx, dir) < 0) {
+ return -1;
+ }
+
+ SAFE_FREE(dir);
+ }
+
if (asprintf(&dir, "%s/%s", uri, st->path) < 0) {
return -1;
}
+
if (csync_vio_rmdir(ctx, dir) < 0) {
_csync_remove_error(ctx, st, uri);
} else {
@@ -1422,6 +1529,48 @@ static int _csync_propagation_cleanup(CSYNC *ctx) {
return 0;
}
+static int _csync_propagation_file_count_visitor(void *obj, void *data) {
+ csync_file_stat_t *st = NULL;
+ CSYNC *ctx = NULL;
+
+ st = (csync_file_stat_t *) obj;
+ ctx = (CSYNC *) data;
+
+ if (st == NULL) {
+ return -1;
+ }
+ if (ctx == NULL) {
+ return -1;
+ }
+
+ switch(st->type) {
+ case CSYNC_FTW_TYPE_SLINK:
+ break;
+ case CSYNC_FTW_TYPE_FILE:
+ switch (st->instruction) {
+ case CSYNC_INSTRUCTION_NEW:
+ case CSYNC_INSTRUCTION_SYNC:
+ case CSYNC_INSTRUCTION_CONFLICT:
+ ctx->overall_progress.file_count++;
+ ctx->overall_progress.byte_sum += st->size;
+ break;
+ default:
+ break;
+ }
+ break;
+ case CSYNC_FTW_TYPE_DIR:
+ /*
+ * No counting of directories.
+ */
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
static int _csync_propagation_file_visitor(void *obj, void *data) {
csync_file_stat_t *st = NULL;
CSYNC *ctx = NULL;
@@ -1447,12 +1596,6 @@ static int _csync_propagation_file_visitor(void *obj, void *data) {
goto err;
}
break;
- case CSYNC_INSTRUCTION_RENAME:
- if ((rc = _csync_rename_file(ctx, st)) < 0) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"FAIL RENAME: %s",st->path);
- goto err;
- }
- break;
case CSYNC_INSTRUCTION_SYNC:
if ((rc = _csync_sync_file(ctx, st)) < 0) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"FAIL SYNC: %s",st->path);
@@ -1553,6 +1696,46 @@ int csync_propagate_rename_file(CSYNC *ctx, csync_file_stat_t *st) {
return _csync_rename_file(ctx, st);
}
+/* Count the files to transmit for both up- and download, ie. in both replicas. */
+int csync_init_progress(CSYNC *ctx) {
+
+ if (ctx == NULL) {
+ return -1;
+ }
+
+ if (ctx->callbacks.progress_cb == NULL) {
+ return 0;
+ }
+
+ ctx->current = REMOTE_REPLICA;
+ ctx->replica = ctx->remote.type;
+
+ if (c_rbtree_walk(ctx->remote.tree, (void *) ctx, _csync_propagation_file_count_visitor) < 0) {
+ ctx->error_code = CSYNC_ERR_TREE;
+ return -1;
+ }
+ ctx->current = LOCAL_REPLICA;
+ ctx->replica = ctx->local.type;
+
+ if (c_rbtree_walk(ctx->local.tree, (void *) ctx, _csync_propagation_file_count_visitor) < 0) {
+ ctx->error_code = CSYNC_ERR_TREE;
+ return -1;
+ }
+
+ /* Notify the progress */
+ csync_set_module_property(ctx, "overall_progress_data", &(ctx->overall_progress));
+
+ _notify_progress(ctx, NULL, 0, CSYNC_NOTIFY_START_SYNC_SEQUENCE);
+
+ return 0;
+}
+
+void csync_finalize_progress(CSYNC *ctx) {
+ _notify_progress(ctx, NULL, 0, CSYNC_NOTIFY_FINISHED_SYNC_SEQUENCE);
+
+ csync_set_module_property(ctx, "overall_progress_data", NULL);
+}
+
int csync_propagate_files(CSYNC *ctx) {
c_rbtree_t *tree = NULL;
diff --git a/src/csync_propagate.h b/src/csync_propagate.h
index ce3249f..088a36a 100644
--- a/src/csync_propagate.h
+++ b/src/csync_propagate.h
@@ -66,6 +66,11 @@
int csync_propagate_files(CSYNC *ctx);
int csync_propagate_rename_file(CSYNC *ctx, csync_file_stat_t *st);
+
+int csync_init_progress(CSYNC *ctx);
+
+void csync_finalize_progress(CSYNC *ctx);
+
/**
* }@
*/
diff --git a/src/csync_reconcile.c b/src/csync_reconcile.c
index c42d00a..3b57339 100644
--- a/src/csync_reconcile.c
+++ b/src/csync_reconcile.c
@@ -30,6 +30,8 @@
#define CSYNC_LOG_CATEGORY_NAME "csync.reconciler"
#include "csync_log.h"
+#include "inttypes.h"
+
#define ACCEPTED_TIME_DIFF 5
#define ONE_HOUR 3600
@@ -108,7 +110,7 @@ static int _csync_merge_algorithm_visitor(void *obj, void *data) {
len = strlen( tmp->path );
h = c_jhash64((uint8_t *) tmp->path, len, 0);
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,"PHash of temporar opposite: %ld", h);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "PHash of temporary opposite: %" PRIu64, h);
node = c_rbtree_find(tree, &h);
}
if(node) {
diff --git a/src/csync_rename.cc b/src/csync_rename.cc
index 96b2c44..74d1bea 100644
--- a/src/csync_rename.cc
+++ b/src/csync_rename.cc
@@ -54,12 +54,12 @@ struct csync_rename_s {
std::vector<renameop> todo;
};
-static int _csync_rename_dir_record(void *obj, void *data) {
+static int _csync_rename_record(void *obj, void *data) {
CSYNC *ctx = reinterpret_cast<CSYNC*>(data);
csync_rename_s* d = csync_rename_s::get(ctx);
csync_file_stat_t *st = reinterpret_cast<csync_file_stat_t *>(obj);
- if (st->type != CSYNC_FTW_TYPE_DIR || st->instruction != CSYNC_INSTRUCTION_RENAME)
+ if ( st->instruction != CSYNC_INSTRUCTION_RENAME)
return 0;
csync_rename_s::renameop op = { st };
@@ -92,12 +92,12 @@ char* csync_rename_adjust_path(CSYNC* ctx, const char* path)
return c_strdup(path);
}
-int csync_propagate_rename_dirs(CSYNC* ctx)
+int csync_propagate_renames(CSYNC* ctx)
{
csync_rename_s* d = csync_rename_s::get(ctx);
d->folder_renamed_to.clear();
- if (c_rbtree_walk(ctx->remote.tree, (void *) ctx, _csync_rename_dir_record) < 0) {
+ if (c_rbtree_walk(ctx->remote.tree, (void *) ctx, _csync_rename_record) < 0) {
return -1;
}
diff --git a/src/csync_rename.h b/src/csync_rename.h
index ef5c790..ee9c51a 100644
--- a/src/csync_rename.h
+++ b/src/csync_rename.h
@@ -29,7 +29,7 @@ extern "C" {
char *csync_rename_adjust_path(CSYNC *ctx, const char *path);
void csync_rename_destroy(CSYNC *ctx);
void csync_rename_record(CSYNC *ctx, const char *from, const char *to);
-int csync_propagate_rename_dirs(CSYNC* ctx);
+int csync_propagate_renames(CSYNC* ctx);
#ifdef __cplusplus
}
diff --git a/src/csync_statedb.c b/src/csync_statedb.c
index ab4507a..df5ec60 100644
--- a/src/csync_statedb.c
+++ b/src/csync_statedb.c
@@ -30,6 +30,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <errno.h>
#include "c_lib.h"
#include "csync_private.h"
@@ -38,11 +39,16 @@
#include "csync_misc.h"
#include "c_string.h"
+#include "c_jhash.h"
#define CSYNC_LOG_CATEGORY_NAME "csync.statedb"
#include "csync_log.h"
+#include "csync_rename.h"
#define BUF_SIZE 16
+#define HASH_QUERY "SELECT * FROM metadata WHERE phash=?1"
+
+static sqlite3_stmt* _by_hash_stmt = NULL;
void csync_set_statedb_exists(CSYNC *ctx, int val) {
ctx->statedb.exists = val;
@@ -56,11 +62,12 @@ int csync_get_statedb_exists(CSYNC *ctx) {
static void _csync_win32_hide_file( const char *file ) {
#ifdef _WIN32
_TCHAR *fileName;
+ DWORD dwAttrs;
+
if( !file ) return;
fileName = c_multibyte( file );
-
- DWORD dwAttrs = GetFileAttributesW(fileName);
+ dwAttrs = GetFileAttributesW(fileName);
if (dwAttrs==INVALID_FILE_ATTRIBUTES) return;
@@ -102,10 +109,12 @@ static int _csync_check_db_integrity(CSYNC *ctx) {
static int _csync_statedb_check(CSYNC *ctx, const char *statedb) {
- int fd = -1, rc;
+ int fd = -1;
+ int rc;
ssize_t r;
char buf[BUF_SIZE] = {0};
const _TCHAR *wstatedb;
+ csync_stat_t sb;
/* check db version */
#ifdef _WIN32
@@ -116,30 +125,43 @@ static int _csync_statedb_check(CSYNC *ctx, const char *statedb) {
fd = _topen(wstatedb, O_RDONLY);
if (fd >= 0) {
- r = read(fd, (void *) buf, sizeof(buf) - 1);
- close(fd);
- if (r >= 0) {
- buf[BUF_SIZE - 1] = '\0';
- if (c_streq(buf, "SQLite format 3")) {
- if (sqlite3_open(statedb, &ctx->statedb.db ) == SQLITE_OK) {
- rc = _csync_check_db_integrity(ctx);
- sqlite3_close(ctx->statedb.db);
- ctx->statedb.db = 0;
-
- if( rc >= 0 ) {
- /* everything is fine */
- c_free_multibyte(wstatedb);
- return 0;
+ /* Check size. Size of zero is a valid database actually. */
+ rc = _tfstat(fd, &sb);
+
+ if (rc == 0) {
+ if (sb.st_size == 0) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Database size is zero byte!");
+ close(fd);
+ } else {
+ r = read(fd, (void *) buf, sizeof(buf) - 1);
+ close(fd);
+ if (r >= 0) {
+ buf[BUF_SIZE - 1] = '\0';
+ if (c_streq(buf, "SQLite format 3")) {
+ if (sqlite3_open(statedb, &ctx->statedb.db ) == SQLITE_OK) {
+ rc = _csync_check_db_integrity(ctx);
+ if( sqlite3_close(ctx->statedb.db) != 0 ) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "WARN: sqlite3_close error!");
+ }
+ ctx->statedb.db = 0;
+
+ if( rc >= 0 ) {
+ /* everything is fine */
+ c_free_multibyte(wstatedb);
+ return 0;
+ }
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Integrity check failed!");
+ } else {
+ // FIXME: Better error analysis.
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "database corrupted, removing!");
+ }
+ } else {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "sqlite version mismatch");
}
- CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Integrity check failed!");
- } else {
- // FIXME: Better error analysis.
- CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "database corrupted, removing!");
}
- } else {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "sqlite version mismatch");
}
}
+ /* if it comes here, the database is broken and should be recreated. */
_tunlink(wstatedb);
}
@@ -147,7 +169,9 @@ static int _csync_statedb_check(CSYNC *ctx, const char *statedb) {
/* create database */
rc = sqlite3_open(statedb, &ctx->statedb.db);
- sqlite3_close(ctx->statedb.db);
+ if( sqlite3_close(ctx->statedb.db) != 0 ) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "WARN: sqlite3_close error!");
+ }
ctx->statedb.db = 0;
if (rc == SQLITE_OK) {
@@ -264,7 +288,10 @@ int csync_statedb_write(CSYNC *ctx) {
return -1;
}
/* close the temporary database */
- sqlite3_close(ctx->statedb.db);
+ rc = sqlite3_close(ctx->statedb.db);
+ if( rc == SQLITE_BUSY ) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "WARN: sqlite3_close got busy!");
+ }
/* remove a possible corrupted file if it exists */
wstatedb_tmp = c_multibyte(statedb_tmp);
@@ -288,7 +315,7 @@ int csync_statedb_write(CSYNC *ctx) {
}
/* progress info */
- if (csync_statedb_write_progressinfo(ctx, ctx->progress) < 0) {
+ if (csync_statedb_write_progressinfo(ctx, ctx->progress_info) < 0) {
return -1;
}
@@ -300,19 +327,55 @@ int csync_statedb_close(CSYNC *ctx, const char *statedb, int jwritten) {
int rc = 0;
_TCHAR *wstatedb_tmp = NULL;
+ /* deallocate query resources */
+ rc = sqlite3_finalize(_by_hash_stmt);
+ _by_hash_stmt = NULL;
+
/* close the temporary database */
rc = sqlite3_close(ctx->statedb.db);
if( rc == SQLITE_BUSY ) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "WARN: sqlite3_close got busy!");
}
+ ctx->statedb.db = NULL;
+
if (asprintf(&statedb_tmp, "%s.ctmp", statedb) < 0) {
return -1;
}
- /* if we successfully synchronized, overwrite the original statedb */
+ /* If we successfully synchronized, overwrite the original statedb */
+
+ /*
+ * Check the integrity of the tmp db. If ok, overwrite the old database with
+ * the tmp db.
+ */
if (jwritten) {
- rc = c_copy(statedb_tmp, statedb, 0644);
+ /* statedb check returns either
+ * 0 : database exists and is fine
+ * 1 : new database was set up
+ * -1 : error.
+ */
+ if (_csync_statedb_check(ctx, statedb_tmp) >= 0) {
+ /* New statedb is valid. */
+
+ /* Move the tmp-db to the real one. */
+ if (c_rename(statedb_tmp, statedb) < 0) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
+ "Renaming tmp db to original db failed. (errno=%d)", errno);
+ rc = -1;
+ } else {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
+ "Successfully moved tmp db to original db.");
+ }
+ } else {
+ wstatedb_tmp = c_multibyte(statedb_tmp);
+ _tunlink(wstatedb_tmp);
+
+ /* new statedb_tmp is not integer. */
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, " ## csync tmp statedb corrupt. Original one is not replaced. ");
+ c_free_multibyte(wstatedb_tmp);
+ rc = -1;
+ }
}
wstatedb_tmp = c_multibyte(statedb_tmp);
@@ -463,6 +526,9 @@ static int _insert_metadata_visitor(void *obj, void *data) {
CSYNC *ctx = NULL;
sqlite3_stmt *stmt = NULL;
const char *md5 = "";
+ uint64_t phash = 0;
+ size_t pathlen;
+ const char *path;
int rc = -1;
fs = (csync_file_stat_t *) obj;
@@ -492,13 +558,19 @@ static int _insert_metadata_visitor(void *obj, void *data) {
/* As we only sync the local tree we need this flag here */
case CSYNC_INSTRUCTION_UPDATED:
case CSYNC_INSTRUCTION_CONFLICT:
+
+ path = csync_rename_adjust_path(ctx, fs->path);
+ pathlen = strlen(path);
+ phash = c_jhash64((uint8_t *) path, pathlen, 0);
+
+
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,
"SQL statement: INSERT INTO metadata_temp \n"
"\t\t\t(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5) VALUES \n"
"\t\t\t(%lld, %lu, %s, %lld, %u, %u, %u, %lu, %d, %s);",
- (long long signed int) fs->phash,
- (long unsigned int) fs->pathlen,
- fs->path,
+ (long long signed int) phash,
+ (long unsigned int) pathlen,
+ path,
(long long signed int) fs->inode,
fs->uid,
fs->gid,
@@ -510,14 +582,14 @@ static int _insert_metadata_visitor(void *obj, void *data) {
/*
* The phash needs to be long long unsigned int or it segfaults on PPC
*/
- sqlite3_bind_int64(stmt, 1, (long long signed int) fs->phash);
- sqlite3_bind_int64(stmt, 2, (long unsigned int) fs->pathlen);
- sqlite3_bind_text( stmt, 3, fs->path, fs->pathlen, SQLITE_STATIC);
+ sqlite3_bind_int64(stmt, 1, (long long signed int) phash);
+ sqlite3_bind_int64(stmt, 2, (long unsigned int) pathlen);
+ sqlite3_bind_text( stmt, 3, path, pathlen, SQLITE_STATIC);
sqlite3_bind_int64(stmt, 4, (long long signed int) fs->inode);
sqlite3_bind_int( stmt, 5, fs->uid);
sqlite3_bind_int( stmt, 6, fs->gid);
sqlite3_bind_int( stmt, 7, fs->mode);
- sqlite3_bind_int64(stmt, 8, fs->modtime);
+ sqlite3_bind_int64(stmt, 8, (long long signed int) fs->modtime);
sqlite3_bind_int( stmt, 9, fs->type);
/* The md5 sum might be zero for directories. They will be investigated in the next
@@ -533,7 +605,8 @@ static int _insert_metadata_visitor(void *obj, void *data) {
rc = -1;
}
- sqlite3_reset(stmt);
+ sqlite3_reset(stmt);
+ SAFE_FREE(path);
break;
default:
@@ -617,71 +690,78 @@ int csync_statedb_insert_metadata(CSYNC *ctx) {
/* caller must free the memory */
csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx, uint64_t phash) {
csync_file_stat_t *st = NULL;
- c_strlist_t *result = NULL;
- char *stmt = NULL;
size_t len = 0;
+ int column_count = 0;
+ int rc;
- stmt = sqlite3_mprintf("SELECT * FROM metadata WHERE phash='%lld'",
- (long long signed int) phash);
- if (stmt == NULL) {
- return NULL;
+ if( _by_hash_stmt == NULL ) {
+ rc = sqlite3_prepare_v2(ctx->statedb.db, HASH_QUERY, strlen(HASH_QUERY), &_by_hash_stmt, NULL);
+ if( rc != SQLITE_OK ) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for hash query.");
+ return NULL;
+ }
}
- result = csync_statedb_query(ctx, stmt);
- sqlite3_free(stmt);
- if (result == NULL) {
+ if( _by_hash_stmt == NULL ) {
return NULL;
}
- if (result->count != 0 && result->count < 10) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Amount of result columns wrong, db version mismatch!");
- }
- if(result->count > 7) {
+ column_count = sqlite3_column_count(_by_hash_stmt);
+
+ sqlite3_bind_int64(_by_hash_stmt, 1, (long long signed int)phash);
+ rc = sqlite3_step(_by_hash_stmt);
+
+ if( rc == SQLITE_ROW ) {
+ if(column_count > 7) {
/* phash, pathlen, path, inode, uid, gid, mode, modtime */
- len = strlen(result->vector[2]);
+ len = sqlite3_column_int(_by_hash_stmt, 1);
st = c_malloc(sizeof(csync_file_stat_t) + len + 1);
if (st == NULL) {
- c_strlist_destroy(result);
- return NULL;
+ return NULL;
}
/* clear the whole structure */
ZERO_STRUCTP(st);
/*
- * FIXME:
- * We use an INTEGER(8) which is signed to the phash in the sqlite3 db,
- * but the phash is an uint64_t. So for some values we get a string like
- * "1.66514565505016e+19". For such a string strtoull() returns 1.
- * phash = 1
- *
- * st->phash = strtoull(result->vector[0], NULL, 10);
- */
+ * FIXME:
+ * We use an INTEGER(8) which is signed to the phash in the sqlite3 db,
+ * but the phash is an uint64_t. So for some values we get a string like
+ * "1.66514565505016e+19". For such a string strtoull() returns 1.
+ * phash = 1
+ *
+ * st->phash = strtoull(result->vector[0], NULL, 10);
+ */
/* The query suceeded so use the phash we pass to the function. */
st->phash = phash;
- st->pathlen = atoi(result->vector[1]);
- memcpy(st->path, (len ? result->vector[2] : ""), len + 1);
- st->inode = atoi(result->vector[3]);
- st->uid = atoi(result->vector[4]);
- st->gid = atoi(result->vector[5]);
- st->mode = atoi(result->vector[6]);
- st->modtime = strtoul(result->vector[7], NULL, 10);
+ st->pathlen = sqlite3_column_int(_by_hash_stmt, 1);
+ memcpy(st->path, (len ? (char*) sqlite3_column_text(_by_hash_stmt, 2) : ""), len + 1);
+ st->inode = sqlite3_column_int(_by_hash_stmt,3);
+ st->uid = sqlite3_column_int(_by_hash_stmt, 4);
+ st->gid = sqlite3_column_int(_by_hash_stmt, 5);
+ st->mode = sqlite3_column_int(_by_hash_stmt, 6);
+ st->modtime = strtoul((char*)sqlite3_column_text(_by_hash_stmt, 7), NULL, 10);
- if(st && result->count > 8 && result->vector[8]) {
- st->type = atoi(result->vector[8]);
+ if(st && column_count > 8 ) {
+ st->type = sqlite3_column_int(_by_hash_stmt, 8);
}
- if(result->count > 9 && result->vector[9]) {
- st->md5 = c_strdup( result->vector[9] );
+ if(column_count > 9 && sqlite3_column_text(_by_hash_stmt, 9)) {
+ st->md5 = c_strdup( (char*) sqlite3_column_text(_by_hash_stmt, 9) );
}
+ }
} else {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "No result record found for phash = %llu",
- (long long unsigned int) phash);
- SAFE_FREE(st);
+ /* SQLITE_DONE says there is no further row. That's not an error. */
+ if (rc != SQLITE_DONE) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "sqlite hash query fail: %s", sqlite3_errmsg(ctx->statedb.db));
+ }
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "No result record found for phash = %llu",
+ (long long unsigned int) phash);
+ SAFE_FREE(st);
}
- c_strlist_destroy(result);
+ sqlite3_reset(_by_hash_stmt);
return st;
}
@@ -782,7 +862,6 @@ c_strlist_t *csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
return list;
}
-
/* query the statedb, caller must free the memory */
c_strlist_t *csync_statedb_query(CSYNC *ctx, const char *statement) {
int err = SQLITE_OK;
diff --git a/src/csync_time.c b/src/csync_time.c
index 3d4182e..04b5b6f 100644
--- a/src/csync_time.c
+++ b/src/csync_time.c
@@ -80,7 +80,7 @@ time_t csync_timediff(CSYNC *ctx) {
* To prevent problems especially with pam_csync we shouldn't try to create the
* remote directory here. Just fail!
*/
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL,
"Access dienied to remote uri: %s - %s",
ctx->remote.uri,
@@ -102,7 +102,7 @@ time_t csync_timediff(CSYNC *ctx) {
ctx->replica = ctx->local.type;
fp = csync_vio_creat(ctx, luri, 0644);
if (fp == NULL) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL,
"Unable to create temporary file: %s - %s",
luri,
@@ -115,7 +115,7 @@ time_t csync_timediff(CSYNC *ctx) {
/* Get the modification time */
st = csync_vio_file_stat_new();
if (csync_vio_stat(ctx, luri, st) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL,
"Synchronisation is not possible! %s - %s",
luri,
@@ -132,7 +132,7 @@ time_t csync_timediff(CSYNC *ctx) {
fp = csync_vio_creat(ctx, ruri, 0644);
if (fp == NULL) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL,
"Unable to create temporary file: %s - %s",
ruri,
@@ -145,7 +145,7 @@ time_t csync_timediff(CSYNC *ctx) {
/* Get the modification time */
st = csync_vio_file_stat_new();
if (csync_vio_stat(ctx, ruri, st) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL,
"Synchronisation is not possible! %s - %s",
ruri,
diff --git a/src/csync_update.c b/src/csync_update.c
index ee99cd4..917c619 100644
--- a/src/csync_update.c
+++ b/src/csync_update.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <inttypes.h>
#include "c_lib.h"
#include "c_jhash.h"
@@ -86,6 +87,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
const char *path = NULL;
csync_file_stat_t *st = NULL;
csync_file_stat_t *tmp = NULL;
+ CSYNC_EXCLUDE_TYPE excluded;
if ((file == NULL) || (fs == NULL)) {
errno = EINVAL;
@@ -114,6 +116,25 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
len = strlen(path);
+ /* Check if file is excluded */
+ excluded = csync_excluded(ctx, path);
+ if (excluded != CSYNC_NOT_EXCLUDED) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", path, excluded);
+ if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
+ switch (ctx->current) {
+ case LOCAL_REPLICA:
+ ctx->local.ignored_cleanup = c_list_append(ctx->local.ignored_cleanup, c_strdup(path));
+ break;
+ case REMOTE_REPLICA:
+ ctx->remote.ignored_cleanup = c_list_append(ctx->remote.ignored_cleanup, c_strdup(path));
+ break;
+ default:
+ break;
+ }
+ return 0;
+ }
+ }
+
h = _hash_of_file(ctx, file );
if( h == 0 ) {
return -1;
@@ -162,6 +183,10 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
st->instruction = CSYNC_INSTRUCTION_NONE;
goto out;
}
+ if (excluded > CSYNC_NOT_EXCLUDED || type == CSYNC_FTW_TYPE_SLINK) {
+ st->instruction = CSYNC_INSTRUCTION_IGNORE;
+ goto out;
+ }
/* Update detection: Check if a database entry exists.
* If not, the file is either new or has been renamed. To see if it is
@@ -184,14 +209,14 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
#endif
if(tmp && tmp->phash == h ) { /* there is an entry in the database */
/* we have an update! */
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Database entry found, compare: %lu <-> %lu, md5: %s <-> %s",
- fs->mtime, tmp->modtime, fs->md5, tmp->md5);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Database entry found, compare: %" PRId64 " <-> %" PRId64 ", md5: %s <-> %s, inode: %" PRId64 " <-> %" PRId64,
+ ((int64_t) fs->mtime), ((int64_t) tmp->modtime), fs->md5, tmp->md5, (int64_t) fs->inode, (int64_t) tmp->inode);
if( !fs->md5) {
st->instruction = CSYNC_INSTRUCTION_EVAL;
goto out;
}
if((ctx->current == REMOTE_REPLICA && !c_streq(fs->md5, tmp->md5 ))
- || (ctx->current == LOCAL_REPLICA && fs->mtime != tmp->modtime)) {
+ || (ctx->current == LOCAL_REPLICA && (fs->mtime != tmp->modtime || fs->inode != tmp->inode))) {
// if (!fs->mtime > tmp->modtime) {
st->instruction = CSYNC_INSTRUCTION_EVAL;
goto out;
@@ -202,7 +227,7 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
if (ctx->current == LOCAL_REPLICA) {
tmp = csync_statedb_get_stat_by_inode(ctx, fs->inode);
if (tmp && tmp->inode == fs->inode && (tmp->modtime == fs->mtime || fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY)) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "inodes: %ld <-> %ld", tmp->inode, fs->inode);
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "inodes: %" PRId64 " <-> %" PRId64, (int64_t) tmp->inode, (int64_t) fs->inode);
/* inode found so the file has been renamed */
st->instruction = CSYNC_INSTRUCTION_RENAME;
if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) {
@@ -224,14 +249,21 @@ static int _csync_detect_update(CSYNC *ctx, const char *file,
out:
+ /* Set the ignored error string. */
+ if (st->instruction == CSYNC_INSTRUCTION_IGNORE) {
+ if (excluded == CSYNC_FILE_EXCLUDE_LIST) {
+ st->error_string = c_strdup("File listed on ignore list.");
+ } else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) {
+ st->error_string = c_strdup("File contains invalid characters.");
+ }
+ }
if (st->instruction != CSYNC_INSTRUCTION_NONE && st->instruction != CSYNC_INSTRUCTION_IGNORE
&& type != CSYNC_FTW_TYPE_DIR) {
st->child_modified = 1;
}
ctx->current_fs = st;
- if( tmp) SAFE_FREE(tmp->md5);
- SAFE_FREE(tmp);
+ csync_file_stat_free(tmp);
st->inode = fs->inode;
st->mode = fs->mode;
st->size = fs->size;
@@ -305,15 +337,15 @@ int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs,
if( !st ) {
return 0;
}
- SAFE_FREE(st->md5);
- SAFE_FREE(st->destpath);
- SAFE_FREE(st->error_string);
- SAFE_FREE(st);
+ csync_file_stat_free(st);
+ st = NULL;
type = CSYNC_FTW_TYPE_SKIP;
break;
case CSYNC_FTW_FLAG_SLINK:
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "symlink: %s - not supported", file);
+ type = CSYNC_FTW_TYPE_SLINK;
+ break;
case CSYNC_FTW_FLAG_DNR:
case CSYNC_FTW_FLAG_DP:
case CSYNC_FTW_FLAG_SLN:
@@ -426,7 +458,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
ctx->error_code = CSYNC_ERR_PROXY;
goto error;
} else {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"opendir failed for %s - %s (errno %d)",
uri, errbuf, errno);
@@ -460,7 +492,7 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
goto error;
}
- /* Create relative path for checking the exclude list */
+ /* Create relative path */
switch (ctx->current) {
case LOCAL_REPLICA:
path = filename + strlen(ctx->local.uri) + 1;
@@ -472,9 +504,8 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
break;
}
- /* Check if file is excluded */
- if (csync_excluded(ctx, path)) {
- CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded", path);
+ /* skip ".csync_journal.db" and ".csync_journal.db.ctmp" */
+ if (c_streq(path, ".csync_journal.db") || c_streq(path, ".csync_journal.db.ctmp")) {
csync_vio_file_stat_destroy(dirent);
dirent = NULL;
SAFE_FREE(filename);
@@ -524,8 +555,11 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
fs->md5 = md5;
fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MD5;
}
-
- CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Uniq ID from Database: %s -> %s", path, fs->md5 ? fs->md5 : "<NULL>" );
+ if( c_streq(md5, "")) {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Uniq ID from Database is EMPTY: %s", path);
+ } else {
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Uniq ID from Database: %s -> %s", path, fs->md5 ? fs->md5 : "<NULL>" );
+ }
}
previous_fs = ctx->current_fs;
@@ -533,13 +567,15 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
/* Call walker function for each file */
rc = fn(ctx, filename, fs, flag);
- if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified)
+ if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified) {
previous_fs->child_modified = ctx->current_fs->child_modified;
+ }
- if( ! do_read_from_db )
+ if( ! do_read_from_db ) {
csync_vio_file_stat_destroy(fs);
- else
+ } else {
SAFE_FREE(fs->md5);
+ }
if (rc < 0) {
csync_vio_closedir(ctx, dh);
diff --git a/src/csync_util.c b/src/csync_util.c
index 162be0e..cc6cef6 100644
--- a/src/csync_util.c
+++ b/src/csync_util.c
@@ -34,6 +34,7 @@
#define CSYNC_LOG_CATEGORY_NAME "csync.util"
#include "csync_log.h"
+#include "csync_statedb.h"
typedef struct {
const char *instr_str;
@@ -143,7 +144,7 @@ static int _merge_file_trees_visitor(void *obj, void *data) {
new_stat = c_malloc(sizeof(csync_file_stat_t) + fs->pathlen + 1);
if (new_stat == NULL) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, merge malloc, error: %s",
fs->path,
@@ -160,7 +161,7 @@ static int _merge_file_trees_visitor(void *obj, void *data) {
new_stat->error_string = c_strdup(fs->error_string);
if (c_rbtree_insert(tree, new_stat) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
SAFE_FREE(new_stat);
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, rb tree insert, error: %s",
@@ -183,12 +184,19 @@ static int _merge_file_trees_visitor(void *obj, void *data) {
case LOCAL_REPLICA:
/* If there is a destpath, this is a rename and the target must be used. */
if( fs->destpath ) {
- asprintf(&uri, "%s/%s", ctx->local.uri, fs->destpath);
+ if (asprintf(&uri, "%s/%s", ctx->local.uri, fs->destpath) < 0) {
+ rc = -1;
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
+ CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file uri alloc failed: %s",
+ errbuf);
+ SAFE_FREE(fs->destpath);
+ goto out;
+ }
SAFE_FREE(fs->destpath);
} else {
if (asprintf(&uri, "%s/%s", ctx->local.uri, fs->path) < 0) {
rc = -1;
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file uri alloc failed: %s",
errbuf);
goto out;
@@ -198,7 +206,7 @@ static int _merge_file_trees_visitor(void *obj, void *data) {
case REMOTE_REPLICA:
if (asprintf(&uri, "%s/%s", ctx->remote.uri, fs->path) < 0) {
rc = -1;
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "file uri alloc failed: %s",
errbuf);
goto out;
@@ -211,7 +219,7 @@ static int _merge_file_trees_visitor(void *obj, void *data) {
/* get file stat of the file on the replica */
vst = csync_vio_file_stat_new();
if (csync_vio_stat(ctx, uri, vst) < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
"file: %s, updating stat failed, error: %s",
uri,
@@ -243,7 +251,9 @@ static int _merge_file_trees_visitor(void *obj, void *data) {
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "file: %s, instruction: UPDATED (%s)", uri, fs->md5);
- fs->instruction = CSYNC_INSTRUCTION_NONE;
+ if (fs->instruction != CSYNC_INSTRUCTION_ERROR) {
+ fs->instruction = CSYNC_INSTRUCTION_NONE;
+ }
rc = 0;
out:
@@ -257,6 +267,49 @@ out:
return rc;
}
+static int _fix_errors_visitor(void *obj, void *data) {
+ csync_file_stat_t *fs = NULL;
+ csync_file_stat_t *tfs = NULL;
+
+ CSYNC *ctx = NULL;
+
+ int rc = -1;
+
+ fs = (csync_file_stat_t *) obj;
+ ctx = (CSYNC *) data;
+
+ /* search for ERROR */
+ if (fs->instruction != CSYNC_INSTRUCTION_ERROR
+ || fs->type == CSYNC_FTW_TYPE_DIR) {
+ rc = 0;
+ goto out;
+ }
+
+ /* check if the file is new or has been synced */
+ tfs = csync_statedb_get_stat_by_hash(ctx, fs->phash);
+ if (tfs == NULL) {
+ rc = 0;
+ goto out;
+ }
+
+ /* update file stat */
+ fs->inode = tfs->inode;
+ fs->modtime = tfs->modtime;
+
+ fs->instruction = CSYNC_INSTRUCTION_UPDATED;
+
+ rc = 0;
+out:
+ csync_file_stat_free(tfs);
+
+ if (rc != 0) {
+ fs->instruction = CSYNC_INSTRUCTION_ERROR;
+ }
+
+ return rc;
+}
+
+
/*
* merge the local tree with the new files from remote and update the
* inode numbers
@@ -264,28 +317,23 @@ out:
int csync_merge_file_trees(CSYNC *ctx) {
int rc = -1;
- /* walk over remote tree, stat on local system */
- ctx->current = LOCAL_REPLICA;
- ctx->replica = ctx->local.type;
+ /* walk over the local tree, in case of error take the value from the database */
+ ctx->current = REMOTE_REPLICA;
+ ctx->replica = ctx->remote.type;
- rc = c_rbtree_walk(ctx->remote.tree, ctx, _merge_file_trees_visitor);
+ rc = c_rbtree_walk(ctx->local.tree, ctx, _fix_errors_visitor);
if (rc < 0) {
goto out;
}
-#if 0
- /* We don't have to merge the remote tree atm. */
-
- /* walk over local tree, stat on remote system */
- ctx->current = REMOTE_REPLICA;
- ctx->replica = ctx->remote.type;
+ /* walk over remote tree, stat on local system */
+ ctx->current = LOCAL_REPLICA;
+ ctx->replica = ctx->local.type;
- rc = c_rbtree_walk(ctx->local.tree, ctx, _merge_file_trees_visitor);
+ rc = c_rbtree_walk(ctx->remote.tree, ctx, _merge_file_trees_visitor);
if (rc < 0) {
goto out;
}
-#endif
-
out:
return rc;
}
@@ -328,11 +376,11 @@ out:
void csync_win32_set_file_hidden( const char *file, bool h ) {
#ifdef _WIN32
const _TCHAR *fileName;
+ DWORD dwAttrs;
if( !file ) return;
fileName = c_multibyte( file );
-
- DWORD dwAttrs = GetFileAttributesW(fileName);
+ dwAttrs = GetFileAttributesW(fileName);
if (dwAttrs==INVALID_FILE_ATTRIBUTES) return;
diff --git a/src/httpbf/src/httpbf.c b/src/httpbf/src/httpbf.c
index da1ea56..aeed142 100644
--- a/src/httpbf/src/httpbf.c
+++ b/src/httpbf/src/httpbf.c
@@ -22,11 +22,13 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/timeb.h>
#include <sys/time.h>
+#include <inttypes.h>
#include "httpbf.h"
@@ -37,12 +39,25 @@
#ifdef NDEBUG
#define DEBUG_HBF(...)
#else
-#define DEBUG_HBF(...) printf(__VA_ARGS__)
+#define DEBUG_HBF(...) { if(transfer->log_cb) { \
+ char buf[1024]; \
+ snprintf(buf, 1024, __VA_ARGS__); \
+ transfer->log_cb(__FUNCTION__, buf); \
+ } }
#endif
#define DEFAULT_BLOCK_SIZE (10*1024*1024)
-static int transfer_id( struct stat *sb ) {
+/* Platform specific defines go here. */
+#ifdef _WIN32
+#define _hbf_fstat _fstat64
+typedef struct stat64 hbf_stat_t;
+#else
+#define _hbf_fstat fstat
+typedef struct stat hbf_stat_t;
+#endif
+
+static int transfer_id( hbf_stat_t *sb ) {
struct timeval tp;
int res;
int r;
@@ -78,16 +93,17 @@ hbf_transfer_t *hbf_init_transfer( const char *dest_uri ) {
transfer->error_string = NULL;
transfer->start_id = 0;
transfer->block_size = DEFAULT_BLOCK_SIZE;
+ transfer->threshold = transfer->block_size;
return transfer;
}
/* Create the splitlist of a given file descriptor */
Hbf_State hbf_splitlist(hbf_transfer_t *transfer, int fd ) {
- struct stat sb;
- off_t num_blocks;
- off_t blk_size;
- off_t remainder = 0;
+ hbf_stat_t sb;
+ int64_t num_blocks;
+ int64_t blk_size;
+ int64_t remainder = 0;
if( ! transfer ) {
return HBF_PARAM_FAIL;
@@ -98,7 +114,7 @@ Hbf_State hbf_splitlist(hbf_transfer_t *transfer, int fd ) {
return HBF_PARAM_FAIL;
}
- if( fstat(fd, &sb) < 0 ) {
+ if( _hbf_fstat(fd, &sb) < 0 ) {
DEBUG_HBF("Failed to stat the file descriptor: errno = %d", errno);
return HBF_FILESTAT_FAIL;
}
@@ -111,8 +127,15 @@ Hbf_State hbf_splitlist(hbf_transfer_t *transfer, int fd ) {
transfer->calc_size = 0;
#endif
+ DEBUG_HBF("hbf_splitlist: block_size: %" PRId64 " threshold: %" PRId64 " st_size: %" PRId64 "\n", transfer->block_size, transfer->threshold, sb.st_size );
+
+
/* calc the number of blocks to split in */
blk_size = transfer->block_size;
+ if (sb.st_size < transfer->threshold) {
+ blk_size = transfer->threshold;
+ }
+
num_blocks = sb.st_size / blk_size;
/* there migth be a remainder. */
@@ -129,9 +152,12 @@ Hbf_State hbf_splitlist(hbf_transfer_t *transfer, int fd ) {
blk_size = 0;
}
+ DEBUG_HBF("hbf_splitlist: num_blocks: %" PRId64 " rmainder: %" PRId64 " blk_size: %" PRId64 "\n", num_blocks, remainder, blk_size );
+
+
if( num_blocks ) {
int cnt;
- off_t overall = 0;
+ int64_t overall = 0;
/* create a datastructure for the transfer data */
transfer->block_arr = calloc(num_blocks, sizeof(hbf_block_t*));
transfer->block_cnt = num_blocks;
@@ -157,7 +183,10 @@ Hbf_State hbf_splitlist(hbf_transfer_t *transfer, int fd ) {
overall += block->size;
/* store the block data into the result array in the transfer */
*((transfer->block_arr)+cnt) = block;
+
+ DEBUG_HBF("hbf_splitlist: created block %d (start: %" PRId64 " size: %" PRId64 ")\n", cnt, block->start, block->size );
}
+
#ifndef NDEBUG
transfer->calc_size = overall;
#endif
@@ -245,16 +274,18 @@ static char* get_transfer_url( hbf_transfer_t *transfer, int indx ) {
* returns HBF_TRANSFER_SUCCESS if the transfer of this block was a success
* returns HBF_SUCCESS if the server aknoweldge that he received all the blocks
*/
-static int dav_request( ne_request *req, int fd, hbf_block_t *blk ) {
+static int _hbf_dav_request(hbf_transfer_t *transfer, ne_request *req, int fd, hbf_block_t *blk ) {
Hbf_State state = HBF_TRANSFER_SUCCESS;
int res;
const ne_status *req_status = NULL;
const char *etag = NULL;
+ (void) transfer;
+
if( ! (blk && req) ) return HBF_PARAM_FAIL;
ne_set_request_body_fd(req, fd, blk->start, blk->size);
- /* DEBUG_HBF("HBF: Block: %d , Start: %ld and Size: %ld\n", blk->seq_number, blk->start, blk->size ); */
+ DEBUG_HBF("HBF: Block: %d , Start: %" PRId64 " and Size: %" PRId64 "\n", blk->seq_number, blk->start, blk->size );
res = ne_request_dispatch(req);
req_status = ne_get_status( req );
@@ -315,7 +346,7 @@ static int dav_request( ne_request *req, int fd, hbf_block_t *blk ) {
static Hbf_State validate_source_file( hbf_transfer_t *transfer ) {
Hbf_State state = HBF_SUCCESS;
- struct stat sb;
+ hbf_stat_t sb;
if( transfer == NULL ) {
state = HBF_PARAM_FAIL;
@@ -328,7 +359,7 @@ static Hbf_State validate_source_file( hbf_transfer_t *transfer ) {
}
if( state == HBF_SUCCESS ) {
- int rc = fstat( transfer->fd, &sb );
+ int rc = _hbf_fstat( transfer->fd, &sb );
if( rc != 0 ) {
state = HBF_STAT_FAIL;
}
@@ -405,8 +436,8 @@ Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const cha
if( ! block ) state = HBF_PARAM_FAIL;
if( transfer->abort_cb ) {
- int abort = (transfer->abort_cb)();
- if( abort ) {
+ int do_abort = (transfer->abort_cb)();
+ if( do_abort ) {
state = HBF_USER_ABORTED;
}
}
@@ -432,10 +463,13 @@ Hbf_State hbf_transfer( ne_session *session, hbf_transfer_t *transfer, const cha
ne_request *req = ne_request_create(session, verb, transfer_url);
if( req ) {
+ char buf[21];
+ snprintf(buf, sizeof(buf), "%"PRId64, transfer->stat_size);
+ ne_add_request_header(req, "OC-Total-Length", buf);
if( transfer->block_cnt > 1 ) {
ne_add_request_header(req, "OC-Chunked", "1");
}
- state = dav_request( req, transfer->fd, block );
+ state = _hbf_dav_request(transfer, req, transfer->fd, block );
if( state != HBF_TRANSFER_SUCCESS && state != HBF_SUCCESS) {
if( transfer->error_string ) free( transfer->error_string );
@@ -491,9 +525,10 @@ int hbf_fail_http_code( hbf_transfer_t *transfer )
return 200;
}
-const char *hbf_error_string( Hbf_State state )
+const char *hbf_error_string(hbf_transfer_t *transfer, Hbf_State state)
{
const char *re;
+ int cnt;
switch( state ) {
case HBF_SUCCESS:
re = "Ok.";
@@ -543,6 +578,15 @@ const char *hbf_error_string( Hbf_State state )
case HBF_FAIL:
default:
+ for( cnt = 0; cnt < transfer->block_cnt; cnt++ ) {
+ int block_id = (cnt + transfer->start_id) % transfer->block_cnt;
+ hbf_block_t *block = transfer->block_arr[block_id];
+
+ if( block->state != HBF_NOT_TRANSFERED && block->state != HBF_TRANSFER_SUCCESS
+ && block->http_error_msg != NULL) {
+ return block->http_error_msg;
+ }
+ }
re = "Unknown error.";
}
return re;
@@ -554,3 +598,10 @@ void hbf_set_abort_callback( hbf_transfer_t *transfer, hbf_abort_callback cb)
transfer->abort_cb = cb;
}
}
+
+void hbf_set_log_callback(hbf_transfer_t* transfer, hbf_log_callback cb)
+{
+ if( transfer ) {
+ transfer->log_cb = cb;
+ }
+}
diff --git a/src/httpbf/src/httpbf.h b/src/httpbf/src/httpbf.h
index 4418cdd..fb379fa 100644
--- a/src/httpbf/src/httpbf.h
+++ b/src/httpbf/src/httpbf.h
@@ -62,8 +62,8 @@ typedef struct hbf_block_s hbf_block_t;
struct hbf_block_s {
int seq_number;
- off_t start;
- off_t size;
+ int64_t start;
+ int64_t size;
Hbf_State state;
int http_result_code;
@@ -75,6 +75,8 @@ struct hbf_block_s {
/* Callback for to check on abort */
typedef int (*hbf_abort_callback) ();
+typedef void (*hbf_log_callback) (const char *, const char *);
+
typedef struct hbf_transfer_s hbf_transfer_t;
@@ -89,13 +91,16 @@ struct hbf_transfer_s {
int status_code;
char *error_string;
- off_t stat_size;
+ int64_t stat_size;
time_t modtime;
- off_t block_size;
+ int64_t block_size;
+ int64_t threshold;
hbf_abort_callback abort_cb;
+ hbf_log_callback log_cb;
+
#ifndef NDEBUG
- off_t calc_size;
+ int64_t calc_size;
#endif
};
@@ -107,9 +112,10 @@ Hbf_State hbf_splitlist( hbf_transfer_t *transfer, int fd );
void hbf_free_transfer( hbf_transfer_t *transfer );
-const char *hbf_error_string( Hbf_State state );
+const char *hbf_error_string(hbf_transfer_t* transfer, Hbf_State state);
void hbf_set_abort_callback( hbf_transfer_t *transfer, hbf_abort_callback cb);
+void hbf_set_log_callback( hbf_transfer_t *transfer, hbf_log_callback cb);
/* returns an http (error) code of the transmission. If the transmission
* succeeded, the code is 200. If it failed, its the error code of the
diff --git a/src/httpbf/tests/hbf_send_test.c b/src/httpbf/tests/hbf_send_test.c
index 7e8eea0..d39b7c0 100644
--- a/src/httpbf/tests/hbf_send_test.c
+++ b/src/httpbf/tests/hbf_send_test.c
@@ -112,7 +112,7 @@ static void test_hbf_splitlist_odd( void **state ){
/* checks on the block list */
int seen_zero_seq = 0;
int prev_seq = -1;
- off_t prev_block_end = -1;
+ int64_t prev_block_end = -1;
for( i=0; i < list->block_cnt; i++) {
hbf_block_t *blk = list->block_arr[i];
diff --git a/src/std/c_file.c b/src/std/c_file.c
index 228b378..ce2fcae 100644
--- a/src/std/c_file.c
+++ b/src/std/c_file.c
@@ -31,6 +31,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
+#include <stdio.h>
#include "c_file.h"
#include "c_string.h"
@@ -60,6 +61,27 @@ int c_isfile(const char *path) {
}
/* copy file from src to dst, overwrites dst */
+#ifdef _WIN32
+int c_copy(const char* src, const char *dst, mode_t mode) {
+ int rc = -1;
+ _TCHAR *wsrc = 0;
+ _TCHAR *wdst = 0;
+ (void) mode; /* unused on win32 */
+ if(src && dst) {
+ wsrc = c_multibyte(src);
+ wdst = c_multibyte(dst);
+ if (CopyFileW(wsrc, wdst, FALSE)) {
+ rc = 0;
+ }
+ c_free_multibyte(wsrc);
+ c_free_multibyte(wdst);
+ if( rc < 0 ) {
+ errno = GetLastError();
+ }
+ }
+ return rc;
+}
+#else
int c_copy(const char* src, const char *dst, mode_t mode) {
int srcfd = -1;
int dstfd = -1;
@@ -68,23 +90,6 @@ int c_copy(const char* src, const char *dst, mode_t mode) {
csync_stat_t sb;
char buf[4096];
-#ifdef _WIN32
- if(src && dst) {
- _TCHAR *wsrc = c_multibyte(src);
- _TCHAR *wdst = c_multibyte(dst);
- if (CopyFileW(wsrc, wdst, FALSE)) {
- rc = 0;
- }
- c_free_multibyte(wsrc);
- c_free_multibyte(wdst);
-
- if( rc < 0 ) {
- errno = GetLastError();
- }
- }
- return rc;
-#else
-
/* Win32 does not come here. */
if (c_streq(src, dst)) {
return -1;
@@ -151,17 +156,74 @@ int c_copy(const char* src, const char *dst, mode_t mode) {
rc = 0;
out:
- if (srcfd > 0) {
+ if (srcfd >= 0) {
close(srcfd);
}
- if (dstfd > 0) {
+ if (dstfd >= 0) {
close(dstfd);
}
if (rc < 0) {
unlink(dst);
}
return rc;
+}
+#endif // _WIN32
+
+int c_rename( const char *src, const char *dst ) {
+ _TCHAR *nuri = NULL;
+ _TCHAR *ouri = NULL;
+ int rc = 0;
+
+ nuri = c_multibyte(dst);
+ if (nuri == NULL) {
+ return -1;
+ }
+
+ ouri = c_multibyte(src);
+ if (ouri == NULL) {
+ c_free_multibyte(nuri);
+ return -1;
+ }
+
+#ifdef _WIN32
+ {
+#define MAX_TRIES_RENAME 3
+ int err = 0;
+ int cnt = 0;
+
+ do {
+ BOOL ok;
+ ok = MoveFileExW(ouri,
+ nuri,
+ MOVEFILE_COPY_ALLOWED +
+ MOVEFILE_REPLACE_EXISTING +
+ MOVEFILE_WRITE_THROUGH);
+ if (!ok) {
+ /* error */
+ err = GetLastError();
+ if( (err == ERROR_ACCESS_DENIED ||
+ err == ERROR_LOCK_VIOLATION ||
+ err == ERROR_SHARING_VIOLATION) && cnt < MAX_TRIES_RENAME ) {
+ cnt++;
+ Sleep(cnt*100);
+ continue;
+ }
+ }
+ break;
+ } while( 1 );
+ if( err != 0 ) {
+ errno = err;
+ rc = -1;
+ }
+ }
+#else
+ rc = rename(ouri, nuri);
#endif
+
+ c_free_multibyte(nuri);
+ c_free_multibyte(ouri);
+
+ return rc;
}
int c_compare_file( const char *f1, const char *f2 ) {
diff --git a/src/std/c_file.h b/src/std/c_file.h
index a30e6aa..17f41e2 100644
--- a/src/std/c_file.h
+++ b/src/std/c_file.h
@@ -74,6 +74,16 @@ int c_copy(const char *src, const char *dst, mode_t mode);
int c_compare_file( const char *f1, const char *f2 );
/**
+ * @brief move a file from source to destination.
+ *
+ * @param src Path to the source file
+ * @param dst Path to the destination file
+ *
+ * @return 0 on success, less than 0 on error with errno set.
+ */
+int c_rename( const char *src, const char *dst );
+
+/**
* }@
*/
#endif /* _C_FILE_H */
diff --git a/src/std/c_macro.h b/src/std/c_macro.h
index ca762ad..9d4d384 100644
--- a/src/std/c_macro.h
+++ b/src/std/c_macro.h
@@ -54,6 +54,9 @@
/** Get the size of an array */
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+/** Macro to make strerror_r work with -Werror=unused-result */
+#define C_STRERROR(errno, buf, size) if(strerror_r(errno, buf, size)) {}
+
/**
* }@
*/
diff --git a/src/std/c_private.h b/src/std/c_private.h
index 94499c9..6415cb3 100644
--- a/src/std/c_private.h
+++ b/src/std/c_private.h
@@ -64,9 +64,6 @@ typedef struct stat csync_stat_t;
#ifndef HAVE_LSTAT
#define lstat _stat
#endif
-#ifdef _WIN32
-#define fstat _fstat64
-#endif
#ifndef O_NOATIME
#define O_NOATIME 0
@@ -79,7 +76,7 @@ typedef struct stat csync_stat_t;
/* tchar definitions for clean win32 filenames */
#define _UNICODE
-#if defined _WIN32 && defined _UNICODE
+#if defined _WIN32 && defined _UNICODE
typedef wchar_t _TCHAR;
#define _topen _wopen
#define _tdirent _wdirent
@@ -92,6 +89,7 @@ typedef wchar_t _TCHAR;
#define _tseekdir _wseekdir
#define _tcreat _wcreat
#define _tstat _wstat64
+#define _tfstat _fstat64
#define _tunlink _wunlink
#define _tmkdir _wmkdir
#define _trmdir _wrmdir
@@ -110,6 +108,7 @@ typedef char _TCHAR;
#define _tseekdir seekdir
#define _tcreat creat
#define _tstat lstat
+#define _tfstat fstat
#define _tunlink unlink
#define _tmkdir mkdir
#define _trmdir rmdir
diff --git a/src/std/c_string.c b/src/std/c_string.c
index 0e67372..5390d93 100644
--- a/src/std/c_string.c
+++ b/src/std/c_string.c
@@ -113,6 +113,7 @@ static char *c_iconv(const char* str, enum iconv_direction dir)
}
assert(ret != (size_t)-1);
+ (void) ret; // silence Werror=unused-but-set-variable
return out_in;
}
@@ -198,7 +199,7 @@ int c_strlist_add(c_strlist_t *strlist, const char *string) {
return 0;
}
-void c_strlist_destroy(c_strlist_t *strlist) {
+void c_strlist_clear(c_strlist_t *strlist) {
size_t i = 0;
if (strlist == NULL) {
@@ -208,6 +209,17 @@ void c_strlist_destroy(c_strlist_t *strlist) {
for (i = 0; i < strlist->count; i++) {
SAFE_FREE(strlist->vector[i]);
}
+
+ strlist->count = 0;
+}
+
+void c_strlist_destroy(c_strlist_t *strlist) {
+
+ if (strlist == NULL) {
+ return;
+ }
+
+ c_strlist_clear(strlist);
SAFE_FREE(strlist->vector);
SAFE_FREE(strlist);
}
@@ -279,11 +291,13 @@ char *c_lowercase(const char* str) {
char* c_utf8(const _TCHAR *wstr)
{
char *dst = NULL;
-#ifdef _WIN32
+#ifdef _WIN32
+ size_t len;
+ int size_needed;
if(!wstr) return NULL;
- size_t len = wcslen( wstr );
+ len = wcslen( wstr );
/* Call once to get the required size. */
- int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
+ size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, len, NULL, 0, NULL, NULL);
if( size_needed > 0 ) {
dst = c_malloc(1+size_needed);
memset(dst, 0, 1+size_needed);
@@ -304,11 +318,14 @@ _TCHAR* c_multibyte(const char *str)
{
_TCHAR *dst = NULL;
#ifdef _WIN32
+ int size_needed = 0;
+ int size_char = 0;
+ size_t len;
if(!str) return NULL;
- size_t len = strlen( str );
- int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
+ len = strlen( str );
+ size_needed = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
if(size_needed > 0) {
- int size_char = (size_needed+1)*sizeof(_TCHAR);
+ size_char = (size_needed+1)*sizeof(_TCHAR);
dst = c_malloc(size_char);
memset(dst, 0, size_char);
MultiByteToWideChar(CP_UTF8, 0, str, -1, dst, size_needed);
diff --git a/src/std/c_string.h b/src/std/c_string.h
index 48919dc..f80ba8d 100644
--- a/src/std/c_string.h
+++ b/src/std/c_string.h
@@ -103,6 +103,15 @@ c_strlist_t *c_strlist_expand(c_strlist_t *strlist, size_t size);
int c_strlist_add(c_strlist_t *strlist, const char *string);
/**
+ * @brief Removes all strings from the list.
+ *
+ * Frees the strings.
+ *
+ * @param strlist Stringlist to clear
+ */
+void c_strlist_clear(c_strlist_t *strlist);
+
+/**
* @brief Destroy the memory of the stringlist.
*
* Frees the strings and the stringlist.
diff --git a/src/vio/csync_vio.c b/src/vio/csync_vio.c
index 0b27988..f073608 100644
--- a/src/vio/csync_vio.c
+++ b/src/vio/csync_vio.c
@@ -106,14 +106,14 @@ int csync_vio_init(CSYNC *ctx, const char *module, const char *args) {
#ifdef __APPLE__
if (lstat(path, &sb) < 0) {
- SAFE_FREE(path);
-
char path_tmp[1024];
+ char* path2 = NULL;
uint32_t size = sizeof(path_tmp);
+ SAFE_FREE(path);
+
if (_NSGetExecutablePath(path_tmp, &size) == 0)
printf("executable path is %s\n", path_tmp);
- char* path2 = NULL;
path2 = c_dirname(path_tmp);
if (asprintf(&path, "%s/../Plugins/ocsync_%s.%s", path2, module, MODULE_EXTENSION) < 0) {
@@ -366,8 +366,8 @@ int csync_vio_sendfile(CSYNC *ctx, csync_vio_handle_t *sfp, csync_vio_handle_t *
return rc;
}
-off_t csync_vio_lseek(CSYNC *ctx, csync_vio_handle_t *fhandle, off_t offset, int whence) {
- off_t ro = 0;
+int64_t csync_vio_lseek(CSYNC *ctx, csync_vio_handle_t *fhandle, int64_t offset, int whence) {
+ int64_t ro = 0;
switch(ctx->replica) {
case REMOTE_REPLICA:
@@ -511,7 +511,7 @@ int csync_vio_mkdirs(CSYNC *ctx, const char *uri, mode_t mode) {
return -1;
}
} else if (errno != ENOENT) {
- strerror_r(errno, errbuf, sizeof(errbuf));
+ C_STRERROR(errno, errbuf, sizeof(errbuf));
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "csync_vio_mkdirs stat failed: %s",
errbuf);
csync_vio_file_stat_destroy(st);
diff --git a/src/vio/csync_vio.h b/src/vio/csync_vio.h
index c840999..a3ba622 100644
--- a/src/vio/csync_vio.h
+++ b/src/vio/csync_vio.h
@@ -43,7 +43,7 @@ int csync_vio_close(CSYNC *ctx, csync_vio_handle_t *handle);
ssize_t csync_vio_read(CSYNC *ctx, csync_vio_handle_t *fhandle, void *buf, size_t count);
ssize_t csync_vio_write(CSYNC *ctx, csync_vio_handle_t *fhandle, const void *buf, size_t count);
int csync_vio_sendfile(CSYNC *ctx, csync_vio_handle_t *sfp, csync_vio_handle_t *dst);
-off_t csync_vio_lseek(CSYNC *ctx, csync_vio_handle_t *fhandle, off_t offset, int whence);
+int64_t csync_vio_lseek(CSYNC *ctx, csync_vio_handle_t *fhandle, int64_t offset, int whence);
csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name);
int csync_vio_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle);
diff --git a/src/vio/csync_vio_file_stat.h b/src/vio/csync_vio_file_stat.h
index 93a7f70..f8a1dbb 100644
--- a/src/vio/csync_vio_file_stat.h
+++ b/src/vio/csync_vio_file_stat.h
@@ -93,8 +93,8 @@ struct csync_vio_file_stat_s {
time_t mtime;
time_t ctime;
- off_t size;
- off_t blksize;
+ int64_t size;
+ int64_t blksize;
unsigned long blkcount;
mode_t mode;
diff --git a/src/vio/csync_vio_local.c b/src/vio/csync_vio_local.c
index 1427bbc..7f5f3b4 100644
--- a/src/vio/csync_vio_local.c
+++ b/src/vio/csync_vio_local.c
@@ -140,11 +140,11 @@ ssize_t csync_vio_local_write(csync_vio_method_handle_t *fhandle, const void *bu
return n;
}
-off_t csync_vio_local_lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence) {
+int64_t csync_vio_local_lseek(csync_vio_method_handle_t *fhandle, int64_t offset, int whence) {
fhandle_t *handle = NULL;
if (fhandle == NULL) {
- return (off_t) -1;
+ return (int64_t) -1;
}
handle = (fhandle_t *) fhandle;
@@ -296,6 +296,9 @@ static time_t FileTimeToUnixTime(FILETIME *filetime, DWORD *remainder)
int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
csync_stat_t sb;
_TCHAR *wuri = c_multibyte( uri );
+#ifdef _WIN32
+ HANDLE h;
+#endif
if( _tstat(wuri, &sb) < 0) {
c_free_multibyte(wuri);
return -1;
@@ -356,8 +359,8 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
buf->inode = sb.st_ino;
#ifdef _WIN32
/* Get the Windows file id as an inode replacement. */
- HANDLE h = CreateFileW( wuri, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL+FILE_FLAG_BACKUP_SEMANTICS, NULL );
+ h = CreateFileW( wuri, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL+FILE_FLAG_BACKUP_SEMANTICS, NULL );
if( h == INVALID_HANDLE_VALUE ) {
errno = GetLastError();
c_free_multibyte(wuri);
@@ -365,7 +368,7 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
} else {
FILETIME ftCreate, ftAccess, ftWrite;
- SYSTEMTIME stUTC;
+// SYSTEMTIME stUTC;
BY_HANDLE_FILE_INFORMATION fileInfo;
@@ -435,28 +438,7 @@ int csync_vio_local_stat(const char *uri, csync_vio_file_stat_t *buf) {
}
int csync_vio_local_rename(const char *olduri, const char *newuri) {
- _TCHAR *nuri = c_multibyte(newuri);
- _TCHAR *ouri = c_multibyte(olduri);
- int re = -1;
-
-#ifdef _WIN32
- if(ouri && nuri) {
- if (MoveFileExW(ouri, nuri, MOVEFILE_COPY_ALLOWED + MOVEFILE_REPLACE_EXISTING + MOVEFILE_WRITE_THROUGH ) != 0) {
- /* Success */
- re = 0;
- } else {
- errno = GetLastError();
- }
- /* CSYNC_LOG( CSYNC_LOG_PRIORITY_DEBUG, "ERR: Could not rename, error %d", errno ); */
- } else {
- errno = ENOENT;
- }
-#else
- re = rename(ouri, nuri);
-#endif
- c_free_multibyte(nuri);
- c_free_multibyte(ouri);
- return re;
+ return c_rename(olduri, newuri);
}
int csync_vio_local_unlink(const char *uri) {
@@ -477,6 +459,7 @@ int csync_vio_local_chmod(const char *uri, mode_t mode) {
int csync_vio_local_chown(const char *uri, uid_t owner, gid_t group) {
#ifdef _WIN32
+ (void) uri, (void) owner, (void) group;
return 0;
#else
return chown(uri, owner, group);
diff --git a/src/vio/csync_vio_local.h b/src/vio/csync_vio_local.h
index 8f70265..240f28e 100644
--- a/src/vio/csync_vio_local.h
+++ b/src/vio/csync_vio_local.h
@@ -31,7 +31,7 @@ csync_vio_method_handle_t *csync_vio_local_creat(const char *durl, mode_t mode);
int csync_vio_local_close(csync_vio_method_handle_t *fhandle);
ssize_t csync_vio_local_read(csync_vio_method_handle_t *fhandle, void *buf, size_t count);
ssize_t csync_vio_local_write(csync_vio_method_handle_t *fhandle, const void *buf, size_t count);
-off_t csync_vio_local_lseek(csync_vio_method_handle_t *fhandle, off_t offset, int whence);
+int64_t csync_vio_local_lseek(csync_vio_method_handle_t *fhandle, int64_t offset, int whence);
csync_vio_method_handle_t *csync_vio_local_opendir(const char *name);
int csync_vio_local_closedir(csync_vio_method_handle_t *dhandle);
diff --git a/src/vio/csync_vio_method.h b/src/vio/csync_vio_method.h
index 5516b6d..fd955c0 100644
--- a/src/vio/csync_vio_method.h
+++ b/src/vio/csync_vio_method.h
@@ -60,7 +60,7 @@ typedef int (*csync_method_close_fn)(csync_vio_method_handle_t *fhandle);
typedef ssize_t (*csync_method_read_fn)(csync_vio_method_handle_t *fhandle, void *buf, size_t count);
typedef ssize_t (*csync_method_write_fn)(csync_vio_method_handle_t *fhandle, const void *buf, size_t count);
typedef int (*csync_method_sendfile_fn)(csync_vio_method_handle_t *src, csync_vio_method_handle_t *dst);
-typedef off_t (*csync_method_lseek_fn)(csync_vio_method_handle_t *fhandle, off_t offset, int whence);
+typedef int64_t (*csync_method_lseek_fn)(csync_vio_method_handle_t *fhandle, int64_t offset, int whence);
typedef csync_vio_method_handle_t *(*csync_method_opendir_fn)(const char *name);
typedef int (*csync_method_closedir_fn)(csync_vio_method_handle_t *dhandle);
diff --git a/tests/csync_tests/check_csync_exclude.c b/tests/csync_tests/check_csync_exclude.c
index 295fdd6..dab7492 100644
--- a/tests/csync_tests/check_csync_exclude.c
+++ b/tests/csync_tests/check_csync_exclude.c
@@ -76,29 +76,32 @@ static void check_csync_excluded(void **state)
int rc;
rc = csync_excluded(csync, ".kde/share/config/kwin.eventsrc");
- assert_int_equal(rc, 0);
+ assert_int_equal(rc, CSYNC_NOT_EXCLUDED);
rc = csync_excluded(csync, ".kde4/cache-maximegalon/cache1.txt");
- assert_int_equal(rc, 1);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
rc = csync_excluded(csync, ".mozilla/plugins");
- assert_int_equal(rc, 1);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
/*
* Test for patterns in subdirs. '.beagle' is defined as a pattern and has
* to be found in top dir as well as in directories underneath.
*/
rc = csync_excluded(csync, ".beagle");
- assert_int_equal(rc, 1);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
rc = csync_excluded(csync, "foo/.beagle");
- assert_int_equal(rc, 1);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
rc = csync_excluded(csync, "foo/bar/.beagle");
- assert_int_equal(rc, 1);
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST);
rc = csync_excluded(csync, ".csync_journal.db");
- assert_int_equal(rc, 1);
+ assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
rc = csync_excluded(csync, ".csync_journal.db.ctmp");
- assert_int_equal(rc, 1);
+ assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
rc = csync_excluded(csync, "subdir/.csync_journal.db");
- assert_int_equal(rc, 1);
+ assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED);
+
+ rc = csync_excluded(csync, "my.directory");
+ assert_int_equal(rc, CSYNC_FILE_EXCLUDE_AND_REMOVE);
}
int torture_run_tests(void)
diff --git a/tests/csync_tests/check_csync_statedb_query.c b/tests/csync_tests/check_csync_statedb_query.c
index 99efee9..7aa8969 100644
--- a/tests/csync_tests/check_csync_statedb_query.c
+++ b/tests/csync_tests/check_csync_statedb_query.c
@@ -28,6 +28,9 @@ static void setup(void **state)
rc = csync_init(csync);
assert_int_equal(rc, 0);
+ rc = csync_statedb_load(csync, TESTDB);
+ assert_int_equal(rc, 0);
+
*state = csync;
}
@@ -192,7 +195,7 @@ static void check_csync_statedb_create_tables(void **state)
stmt = sqlite3_mprintf("INSERT INTO metadata_temp"
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5) VALUES"
"(%lu, %d, '%q', %d, %d, %d, %d, %ld, %d, '%q');",
- (ulong)42,
+ (unsigned long)42,
42,
"It's a rainy day",
42,
@@ -231,7 +234,8 @@ static void check_csync_statedb_insert_metadata(void **state)
assert_int_equal(rc, 0);
for (i = 0; i < 100; i++) {
- st = c_malloc(sizeof(csync_file_stat_t));
+ st = c_malloc(sizeof(csync_file_stat_t) + 30 );
+ snprintf(st->path, 29, "file_%d" , i );
st->phash = i;
rc = c_rbtree_insert(csync->local.tree, (void *) st);
@@ -249,7 +253,8 @@ static void check_csync_statedb_write(void **state)
int i, rc;
for (i = 0; i < 100; i++) {
- st = c_malloc(sizeof(csync_file_stat_t));
+ st = c_malloc(sizeof(csync_file_stat_t) + 30);
+ snprintf(st->path, 29, "file_%d" , i );
st->phash = i;
rc = c_rbtree_insert(csync->local.tree, (void *) st);
diff --git a/tests/csync_tests/check_csync_update.c b/tests/csync_tests/check_csync_update.c
index 7b26136..f7623be 100644
--- a/tests/csync_tests/check_csync_update.c
+++ b/tests/csync_tests/check_csync_update.c
@@ -2,6 +2,8 @@
#include "csync_update.c"
+#define TESTDB "/tmp/check_csync/journal.db"
+
static void setup(void **state)
{
CSYNC *csync;
@@ -19,6 +21,9 @@ static void setup(void **state)
assert_int_equal(rc, 0);
rc = csync_init(csync);
assert_int_equal(rc, 0);
+ rc = csync_statedb_load(csync, TESTDB);
+ assert_int_equal(rc, 0);
+
*state = csync;
}
@@ -40,6 +45,8 @@ static void setup_ftw(void **state)
assert_int_equal(rc, 0);
rc = csync_init(csync);
assert_int_equal(rc, 0);
+ rc = csync_statedb_load(csync, TESTDB);
+ assert_int_equal(rc, 0);
*state = csync;
}
@@ -205,7 +212,7 @@ static void check_csync_detect_update_db_none(void **state)
/* the instruction should be set to new */
st = c_rbtree_node_data(csync->local.tree->root);
- assert_int_equal(st->instruction, CSYNC_INSTRUCTION_EVAL);
+ assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
/* set the instruction to UPDATED that it gets written to the statedb */
st->instruction = CSYNC_INSTRUCTION_UPDATED;
@@ -234,7 +241,7 @@ static void check_csync_detect_update_db_eval(void **state)
/* the instruction should be set to new */
st = c_rbtree_node_data(csync->local.tree->root);
- assert_int_equal(st->instruction, CSYNC_INSTRUCTION_EVAL);
+ assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
/* set the instruction to UPDATED that it gets written to the statedb */
st->instruction = CSYNC_INSTRUCTION_UPDATED;
@@ -258,15 +265,15 @@ static void check_csync_detect_update_db_rename(void **state)
assert_int_equal(rc, 0);
stmt = sqlite3_mprintf("INSERT INTO metadata"
"(phash, pathlen, path, inode, uid, gid, mode, modtime,type,md5) VALUES"
- "(%lu, %d, '%q', %d, %d, %d, %d, %lu, %d, '%q');",
- 42,
+ "(%lld, %d, '%q', %d, %d, %d, %d, %lld, %d, '%q');",
+ (long long signed int)42,
42,
"I_was_wurst_before_I_became_wurstsalat",
619070,
42,
42,
42,
- 42,
+ (long long signed int)42,
0,
"4711");
diff --git a/tests/httpbf_tests/hbf_send_test.c b/tests/httpbf_tests/hbf_send_test.c
index 4264edf..878d8b4 100644
--- a/tests/httpbf_tests/hbf_send_test.c
+++ b/tests/httpbf_tests/hbf_send_test.c
@@ -77,7 +77,7 @@ static void test_get_transfer_url_bigfile( void **state ) {
list = hbf_init_transfer( url );
assert_non_null( list );
- list->block_size = (1024*1024); /* block size 1 MB */
+ list->threshold = list->block_size = (1024*1024); /* block size 1 MB */
/* open a file */
fd = open( test_file("church.jpg"), O_RDONLY );
@@ -150,7 +150,7 @@ static void test_hbf_splitlist_odd( void **state ){
if( 1 ) {
int seen_zero_seq = 0;
int prev_seq = -1;
- off_t prev_block_end = -1;
+ int64_t prev_block_end = -1;
for( i=0; i < list->block_cnt; i++) {
hbf_block_t *blk = list->block_arr[i];
diff --git a/tests/ownCloud/ownCloud/Test.pm b/tests/ownCloud/ownCloud/Test.pm
index 2f67385..644068a 100644
--- a/tests/ownCloud/ownCloud/Test.pm
+++ b/tests/ownCloud/ownCloud/Test.pm
@@ -49,7 +49,7 @@ our $localDir = "turbo";
@ISA = qw(Exporter);
@EXPORT = qw( initTesting createRemoteDir createLocalDir cleanup csync assertLocalDirs assertLocalAndRemoteDir
- glob_put put_to_dir localDir remoteDir localCleanup createLocalFile);
+ glob_put put_to_dir localDir remoteDir localCleanup createLocalFile remoteCleanup);
sub fromFileName($)
{
@@ -137,21 +137,22 @@ sub cleanup()
print "\nInterrupt before cleanup in 4 seconds...\n";
sleep(4);
- remoteCleanup( );
+ remoteCleanup( '' );
localCleanup( '' );
}
-sub remoteCleanup( )
+sub remoteCleanup($)
{
- $d->open( -url => $owncloud );
+ my ($dir) = @_;
+ $d->open( -url => $owncloud . $dir );
print "Cleaning Remote!\n";
- my $re = $d->delete( $owncloud );
+ my $re = $d->delete( $owncloud . $dir );
if( $re == 0 ) {
- print "Failed to clenup directory <$owncloud>\n";
+ print "Failed to clenup directory <$owncloud $dir>\n";
}
return $re;
}
diff --git a/tests/ownCloud/t3.pl b/tests/ownCloud/t3.pl
index 0cfa8a0..45b5c23 100755
--- a/tests/ownCloud/t3.pl
+++ b/tests/ownCloud/t3.pl
@@ -52,12 +52,31 @@ system( "rm -rf " . localDir() . 'remoteToLocal1' );
system( "echo \"my file\" >> /tmp/myfile.txt" );
put_to_dir( '/tmp/myfile.txt', 'remoteToLocal1/rtl1/rtl11' );
+
csync();
assertLocalAndRemoteDir( '', 0);
#TODO: test that newfile.dat and myfile.txt exists in newdir/rtl1
# and test that there is no newdir/rtl11/test.txt
+move( localDir() . 'newdir/myfile.txt', localDir() . 'newdir/oldfile.txt' );
+system( "echo \"super new\" >> " . localDir() . 'newdir/myfile.txt' );
+
+#Add some files for the next test.
+system( "echo \"un\" > " . localDir() . '1.txt' );
+system( "echo \"deux\" > " . localDir() . '2.txt' );
+
+csync();
+assertLocalAndRemoteDir( '', 0);
+
+unlink( localDir() . '1.txt' );
+move( localDir() . '2.txt', localDir() . '1.txt' );
+
+csync();
+assertLocalAndRemoteDir( '', 0);
+
+
+
cleanup();
# --
diff --git a/tests/ownCloud/t4.pl b/tests/ownCloud/t4.pl
old mode 100644
new mode 100755
index 7f0287a..959fd93
--- a/tests/ownCloud/t4.pl
+++ b/tests/ownCloud/t4.pl
@@ -15,7 +15,7 @@ use ownCloud::Test;
use strict;
-print "Hello, this is t4, a tester for files that cannot be stated\n";
+print "Hello, this is t4, a tester for A) files that cannot be stated and B) excluded files\n";
# stat error occours on windsows when the file is busy for example
initTesting();
@@ -30,7 +30,7 @@ csync();
# Check if the files from toremote1 are now in t1/remoteToLocal1
# they should have taken the way via the ownCloud.
print "Assert the local file copy\n";
-assertLocalAndRemoteDir( 'test_stat', 0 );
+assertLocalAndRemoteDir( '', 0 );
system( "echo foobar2 >> " . localDir() . 'test_stat/file.txt' );
@@ -42,6 +42,9 @@ csync();
# TODO: some check here.
+
+print("Restore the original rights");
+
system( "chmod 700 " . localDir() . 'test_stat' );
system( "echo foobar3 >> " . localDir() . 'test_stat/file.txt' );
@@ -49,10 +52,26 @@ csync();
print "Check if everything is still the same\n";
-assertLocalAndRemoteDir( 'test_stat', 0 );
+assertLocalAndRemoteDir( '', 0 );
# TODO: Check that the file content is fine on the server and that there was no conflict
+print("Added a file that is on the ignore list\n");
+# (*.directory is in the ignored list that needs cleanup)
+# (it is names with _conflict) because i want the conflicft detection of assertLocalAndRemoteDir to work
+system( "echo dir >> " . localDir() . 'test_stat/file_conflict.directory' );
+csync();
+# The file_conflict.directory is seen as a conflict
+assertLocalAndRemoteDir( '', 1 );
+# TODO: check that the file_conflict.directory is indeed NOT on the server
+
+print("Remove a directory containing a local file\n");
+remoteCleanup('test_stat');
+csync();
+assertLocalAndRemoteDir( '', 0 );
+
+
+
cleanup();
# --
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/ocsync.git
More information about the Pkg-owncloud-commits
mailing list