[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