]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/adouble/ad_flush.c
Fix ad_reso_size once more...
[netatalk.git] / libatalk / adouble / ad_flush.c
index e0321a398cd43e3edf855a0c3a15ffcaf70caac2..3331074b994ee619d7271e7724ed965cb2f76da6 100644 (file)
@@ -38,6 +38,7 @@
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
 #include <atalk/errchk.h>
+#include <atalk/util.h>
 
 #include "ad_lock.h"
 
@@ -60,6 +61,8 @@ int ad_rebuild_adouble_header(struct adouble *ad)
     char        *buf, *nentp;
     int             len;
 
+    LOG(log_debug, logtype_default, "ad_rebuild_adouble_header");
+
     buf = ad->ad_data;
 
     temp = htonl( ad->ad_magic );
@@ -206,7 +209,9 @@ int ad_copy_header(struct adouble *add, struct adouble *ads)
 
 static int ad_flush_hf(struct adouble *ad)
 {
+    EC_INIT;
     int len;
+    int cwd = -1;
 
     LOG(log_debug, logtype_default, "ad_flush_hf(%s)", adflags2logstr(ad->ad_adflags));
 
@@ -224,7 +229,8 @@ static int ad_flush_hf(struct adouble *ad)
         return -1;
     }
 
-    if ((adf->adf_flags & O_RDWR)) {
+    if ((adf->adf_flags & O_RDWR)
+        || ((ad->ad_adflags & ADFLAGS_DIR) && (ad->ad_adflags & ADFLAGS_RDWR))) {
         if (ad_getentryoff(ad, ADEID_RFORK)) {
             if (ad->ad_rlen > 0xffffffff)
                 ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
@@ -243,10 +249,15 @@ static int ad_flush_hf(struct adouble *ad)
             break;
         case AD_VERSION_EA:
             if (AD_META_OPEN(ad)) {
-                if (sys_fsetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) {
-                    LOG(log_error, logtype_afpd, "ad_flush: sys_fsetxattr error: %s",
-                        strerror(errno));
-                    return -1;
+                if (ad->ad_adflags & ADFLAGS_DIR) {
+                    EC_NEG1_LOG( cwd = open(".", O_RDONLY) );
+                    EC_NEG1_LOG( fchdir(ad_data_fileno(ad)) );
+                    EC_ZERO_LOG( sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) );
+                    EC_NEG1_LOG( fchdir(cwd) );
+                    EC_NEG1_LOG( close(cwd) );
+                    cwd = -1;
+                } else {
+                    EC_ZERO_LOG( sys_fsetxattr(ad_data_fileno(ad), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) );
                 }
             }
             break;
@@ -256,7 +267,14 @@ static int ad_flush_hf(struct adouble *ad)
         }
     }
 
-    return( 0 );
+EC_CLEANUP:
+    if (cwd != -1) {
+        if (fchdir(cwd) != 0) {
+            AFP_PANIC("ad_flush: cant fchdir");
+        }
+        close(cwd);
+    }
+    EC_EXIT;
 }
 
 /* Flush resofork adouble file if any (currently adouble:ea and #ifndef HAVE_EAFD eg Linux) */
@@ -334,11 +352,15 @@ int ad_close(struct adouble *ad, int adflags)
     if (ad == NULL)
         return err;
 
-    LOG(log_debug, logtype_default, "ad_close(%s)", adflags2logstr(adflags));
+    LOG(log_debug, logtype_default,
+        "ad_close(%s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+        adflags2logstr(adflags),
+        ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+        ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+        ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
 
-    /* cf ad_open(): we opened the datafork too for sharemode locks */
-    if ((ad->ad_vers == AD_VERSION_EA) && (ad->ad_adflags & ADFLAGS_SETSHRMD))
-        adflags |= ADFLAGS_DF;
+    if ((ad->ad_vers == AD_VERSION2) && (adflags & ADFLAGS_RF))
+        adflags |= ADFLAGS_HF;
 
     if ((adflags & ADFLAGS_DF)
         && (ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */
@@ -364,8 +386,16 @@ int ad_close(struct adouble *ad, int adflags)
                 err = -1;
             ad->ad_rlen = 0;
             ad_reso_fileno(ad) = -1;
+            adf_lock_free(ad->ad_rfp);
         }
     }
 
+    LOG(log_debug, logtype_default,
+        "ad_close(%s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+        adflags2logstr(adflags), err,
+        ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+        ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+        ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
+
     return err;
 }