diff -r ab34fc9ecf1d -r 888aa263c0f1 dav/sync.c --- a/dav/sync.c Sat Oct 19 11:15:04 2019 +0200 +++ b/dav/sync.c Sat Oct 19 15:46:33 2019 +0200 @@ -3236,16 +3236,17 @@ } } - DavXmlNode *xattr_prop = dav_get_property_ns(res, DAV_PROPS_NS, "xattributes"); - if(xattr_prop) { - XAttributes *xattr = xml_get_attributes(xattr_prop); - if(xattr) { - if(!sync_store_xattr(dir, path, xattr)) { - if(local->xattr_hash) { - free(local->xattr_hash); - } - local->xattr_hash = xattr->hash; + if((dir->metadata & FINFO_XATTR) == FINFO_XATTR) { + DavXmlNode *xattr_prop = dav_get_property_ns(res, DAV_PROPS_NS, "xattributes"); + XAttributes *xattr = NULL; + if(xattr_prop) { + xattr = xml_get_attributes(xattr_prop); + } + if(!sync_store_xattr(dir, path, xattr)) { + if(local->xattr_hash) { + free(local->xattr_hash); } + local->xattr_hash = xattr ? xattr->hash : NULL; } } @@ -3257,16 +3258,53 @@ } int sync_store_xattr(SyncDirectory *dir, const char *path, XAttributes *xattr) { - for(int i=0;inattr;i++) { + // create a map of all currently available local attributes + ssize_t nelm = 0; + char **list = xattr_list(path, &nelm); + UcxMap *current_xattr = NULL; + if(nelm > 0) { + current_xattr = ucx_map_new(nelm + 8); + for(int i=0;inattr : 0; + for(int i=0;ivalues[i]; if(xattr_set(path, xattr->names[i], value.ptr, value.length)) { - fprintf( - stderr, + fprintf(stderr, "Cannot store xattr '%s' for file: %s\n", xattr->names[i], path); } - } + + if(current_xattr) { + // to detect which xattributes are removed, we remove all new + // attributes from the map and all remaining attributes must + // be removed with xattr_remove + char *value = ucx_map_cstr_remove(current_xattr, xattr->names[i]); + if(value) { + free(value); + } + } + } + + if(current_xattr) { + UcxMapIterator i = ucx_map_iterator(current_xattr); + char *value = NULL; + UCX_MAP_FOREACH(key, value, i) { + (void)xattr_remove(path, value); // don't print error + free(value); + } + ucx_map_free(current_xattr); + } + return 0; } @@ -3628,20 +3666,20 @@ } static void update_metadata_hashes(LocalResource *local, MetadataHashes hashes) { - if(hashes.tags) { + if(hashes.update_tags) { if(local->tags_hash) { free(local->tags_hash); local->tags_hash = NULL; } local->tags_hash = hashes.tags; } - if(hashes.tags_remote) { + if(hashes.update_tags_remote) { if(local->remote_tags_hash) { free(local->remote_tags_hash); } local->remote_tags_hash = hashes.tags_remote; } - if(hashes.xattr) { + if(hashes.update_xattr) { if(local->xattr_hash) { free(local->xattr_hash); } @@ -4196,14 +4234,15 @@ DavResource *res, LocalResource *local) { - MetadataHashes hashes = {NULL, NULL, NULL}; + MetadataHashes hashes = {NULL, NULL, NULL, 0, 0, 0}; if(dir->tagconfig) { // get local tags DavBool changed = 0; char *tags_hash = NULL; UcxList *tags = sync_get_file_tags(dir, local, &changed, &tags_hash); if(changed || local->tags_updated) { - hashes.tags = tags_hash; + hashes.tags = tags_hash; + hashes.update_tags = 1; DavBool store_tags = TRUE; // get remote tags @@ -4268,9 +4307,14 @@ if(local->xattr_updated) { if(local->xattr) { resource_set_xattr(res, local->xattr); - hashes.xattr = strdup(local->xattr->hash); + hashes.xattr = local->xattr ? strdup(local->xattr->hash) : NULL; + hashes.update_xattr = 1; } else { dav_remove_property(res, "idavprops:xattributes"); + if(local->xattr_hash) { + free(local->xattr_hash); + local->xattr_hash = NULL; + } } } return hashes;