diff -r 0f4c59ac8c74 -r 14e7101d7604 dav/sync.c --- a/dav/sync.c Thu Oct 03 12:00:25 2019 +0200 +++ b/dav/sync.c Sun Oct 06 13:27:24 2019 +0200 @@ -1039,6 +1039,8 @@ // if hashing is enabled we can compare the hash of the remote file // with the local file to test if a file is really modified + DavBool update_db = FALSE; + char *update_hash = NULL; if (!iscollection && !link && (ret == REMOTE_CHANGE_MODIFIED || ret == REMOTE_CHANGE_CONFLICT_LOCAL_MODIFIED) && @@ -1052,9 +1054,23 @@ if(local_hash) { if(!strcmp(hash, local_hash)) { ret = REMOTE_NO_CHANGE; + update_db = TRUE; + update_hash = local_hash; + + // if local already exists, update the hash here + // because it is possible that there are metadata updates + // and in this case the db will updated later and needs + // the current hash + if(local) { + if(local->hash) { + free(local->hash); + } + local->hash = local_hash; + } + } else { + free(local_hash); } } - free(local_hash); } // if a file is not modified, check if the metadata has changed @@ -1104,6 +1120,29 @@ break; } + // if update_db is set, a file was modified on the server, but we already + // have the file content, but we need to update the db + if(ret == REMOTE_NO_CHANGE && update_db) { + if(!local) { + local = calloc(1, sizeof(LocalResource)); + local->path = strdup(res->path); + + ucx_map_cstr_put(db->resources, local->path, local); + } + + // update local res + SYS_STAT s; + if(!sys_stat(local_path, &s)) { + sync_set_metadata_from_stat(local, &s); + } else { + fprintf(stderr, "stat failed for file: %s : %s", local_path, strerror(errno)); + } + local_resource_set_etag(local, etag); + if(!local->hash) { + local->hash = update_hash; + } // else: hash already updated + } + free(local_path); return ret; } @@ -2151,8 +2190,15 @@ DavBool equal = FALSE; int changed = remote_resource_is_changed(sn, dir, db, res, local_res, &equal); if(equal) { + char *etag = dav_get_string_property(res, "D:getetag"); if(local_res->metadata_updated) { ls_update = ucx_list_prepend(ls_update, local_res); + } else if(etag) { + // update etag in db + if(local_res->etag) { + free(local_res->etag); + } + local_res->etag = strdup(etag); } } else if(cdt && changed) { printf("conflict: %s\n", local_res->path); @@ -2256,9 +2302,6 @@ remove(locktokenfile); } - //ucx_map_free_content(db->resources, (ucx_destructor)local_resource_free); - //ucx_map_free(db->resources); - dav_session_destroy(sn); // Report @@ -2866,15 +2909,14 @@ { // mtime and size unchanged, content also likely unchanged return 0; - } else if(SYNC_HASHING(dir) && db_res->hash) { - // in case of activated hashing, we check if the content - // has really changed - + } else if(SYNC_HASHING(dir)) { // res->hash missing (see above) char *local_path = util_concat_path(dir->path, local_resource_path(res)); res->hash = util_file_hash(local_path); free(local_path); - if(res->hash && !strcmp(res->hash, db_res->hash)) { + + // check if the content has really changed + if(res->hash && db_res->hash && !strcmp(res->hash, db_res->hash)) { return 0; } }