]> arthur.barton.de Git - netatalk.git/commitdiff
FPExchangeFiles must only switch data file, not metadata
authorRalph Boehme <sloowfranklin@gmail.com>
Tue, 13 Aug 2013 14:19:25 +0000 (16:19 +0200)
committerRalph Boehme <sloowfranklin@gmail.com>
Tue, 13 Aug 2013 14:58:08 +0000 (16:58 +0200)
In Netatalk 3, afp_exchangefiles() moves the metadata EAs togehter with
the files, so we must copy the metadata EAs back at then end.

Fixes bug #521.

NEWS
etc/afpd/file.c
include/atalk/adouble.h
libatalk/adouble/ad_open.c

diff --git a/NEWS b/NEWS
index d567d5309e86ff30808c46b5f111301d0c61581d..98e2d2b5d969a81152012627bd00c48b2110f7aa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ Changes in 3.0.5
        set to yes, then Netatalk will attempt to recursively delete any
        vetoed files and directories. FR #82.
 * UPD: systemd unit dir is /usr/lib/systemd/system .
+* FIX: Saving files from application like MS Word may result in the file
+       loosing metadata like the Finder label. Bug #521.
 
 Changes in 3.0.4
 ================
index daaa84a5bd9dd32642cf19399158281a6a74fc6e..f639c49baf7ea8809de4e923d43beaf9a5a0fe16 100644 (file)
@@ -2208,6 +2208,42 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
         }
         goto err_temp_to_dest;
     }
+
+    if (AD_META_OPEN(adsp) || AD_META_OPEN(addp)) {
+        struct adouble adtmp;
+        bool opened_ads, opened_add;
+
+        ad_init(&adtmp, vol);
+        ad_init_offsets(&adtmp);
+
+        if (!AD_META_OPEN(adsp)) {
+            if (ad_open(adsp, p, ADFLAGS_HF) != 0)
+                return -1;
+            opened_ads = true;
+        }
+
+        if (!AD_META_OPEN(addp)) {
+            if (ad_open(addp, upath, ADFLAGS_HF) != 0)
+                return -1;
+            opened_add = true;
+        }
+
+        if (ad_copy_header(&adtmp, adsp) != 0)
+            goto err_temp_to_dest;
+        if (ad_copy_header(adsp, addp) != 0)
+            goto err_temp_to_dest;
+        if (ad_copy_header(addp, &adtmp) != 0)
+            goto err_temp_to_dest;
+        ad_flush(adsp);
+        ad_flush(addp);
+
+        if (opened_ads)
+            ad_close(adsp, ADFLAGS_HF);
+        if (opened_add)
+            ad_close(addp, ADFLAGS_HF);
+    }
+
+    /* FIXME: we should switch ressource fork too */
     
     /* here we need to reopen if crossdev */
     if (sid && ad_setid(addp, destst.st_dev, destst.st_ino,  sid, sdir->d_did, vol->v_stamp)) 
index c0f4098da7b3590da71d01a3c92f44b6a9f573c4..3b764a7689e42299e9d2b8f008dbfa78bd378ace 100644 (file)
@@ -402,6 +402,7 @@ extern int ad_mkdir       (const char *, mode_t);
 struct vol;
 extern void ad_init       (struct adouble *, const struct vol * restrict);
 extern void ad_init_old   (struct adouble *ad, int flags, int options);
+extern int ad_init_offsets(struct adouble *ad);
 extern int ad_open        (struct adouble *ad, const char *path, int adflags, ...);
 extern int ad_openat      (struct adouble *, int dirfd, const char *path, int adflags, ...);
 extern int ad_refresh     (const char *path, struct adouble *);
index 6915cbb189aa3618680d3a1abcb3f5d39132c745..06c3c71e49a7cfaca6ada37276237d0a4ae66f4f 100644 (file)
@@ -311,19 +311,16 @@ static uint32_t get_eid(uint32_t eid)
     return 0;
 }
 
-/* ----------------------------------- */
-static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags)
+
+/**
+ * Initialize offset pointers
+ */
+int ad_init_offsets(struct adouble *ad)
 {
     const struct entry  *eid;
-    uint16_t            ashort;
-    struct stat         st;
 
-    LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path);
-
-    if (ad->ad_magic == AD_MAGIC) {
-        LOG(log_debug, logtype_ad, "new_ad_header(\"%s\"): already initialized", path);
+    if (ad->ad_magic == AD_MAGIC)
         return 0;
-    }
 
     ad->ad_magic = AD_MAGIC;
     ad->ad_version = ad->ad_vers & 0x0f0000;
@@ -346,6 +343,21 @@ static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp,
         eid++;
     }
 
+    return 0;
+}
+
+/* ----------------------------------- */
+static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags)
+{
+    const struct entry  *eid;
+    uint16_t            ashort;
+    struct stat         st;
+
+    LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path);
+
+    if (ad_init_offsets(ad) != 0)
+        return -1;
+
     /* set default creator/type fields */
     memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"\0\0\0\0", 4);
     memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"\0\0\0\0", 4);