dav/sync.c

changeset 663
888aa263c0f1
parent 662
ab34fc9ecf1d
child 667
6cdcd3e4e368
--- 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;i<xattr->nattr;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;i<nelm;i++) {
+            // use the xattr name as key and store any value
+            ucx_map_cstr_put(current_xattr, list[i], list[i]);
+        }
+    }
+    if(list) {
+        free(list);
+    }
+    
+    // store extended attributes
+    size_t nattr = xattr ? xattr->nattr : 0;
+    for(int i=0;i<nattr;i++) {
         sstr_t value = xattr->values[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;

mercurial