]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/adouble/ad_flush.c
Fixes
[netatalk.git] / libatalk / adouble / ad_flush.c
index a02c223c0172451cf366cff390650f74fd62d12b..abc697bdeff14aa48fcb0fea70b84658868b3e37 100644 (file)
@@ -147,8 +147,21 @@ int ad_copy_header(struct adouble *add, struct adouble *ads)
 int ad_flush(struct adouble *ad)
 {
     int len;
+    struct ad_fd *adf;
 
-    if (( ad->ad_mdp->adf_flags & O_RDWR )) {
+    switch (ad->ad_flags) {
+    case AD_VERSION2:
+        adf = ad->ad_mdp;
+        break;
+    case AD_VERSION_EA:
+        adf = &ad->ad_data_fork;
+        break;
+    default:
+        LOG(log_error, logtype_afpd, "ad_flush: unexpected adouble version");
+        return -1;
+    }
+
+    if ((adf->adf_flags & O_RDWR)) {
         if (ad_getentryoff(ad, ADEID_RFORK)) {
             if (ad->ad_rlen > 0xffffffff)
                 ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
@@ -188,6 +201,9 @@ int ad_close(struct adouble *ad, int adflags)
 {
     int err = 0;
 
+    if (ad == NULL)
+        return err;
+
     LOG(log_debug, logtype_default, "ad_close(%s)", adflags2logstr(adflags));
 
     if ((adflags & ADFLAGS_DF)
@@ -204,12 +220,55 @@ int ad_close(struct adouble *ad, int adflags)
         adf_lock_free(&ad->ad_data_fork);
     }
 
-    if ((adflags & ADFLAGS_HF)
-        && (ad_meta_fileno(ad) != -1 && !(--ad->ad_mdp->adf_refcount))) {
-        if (close( ad_meta_fileno(ad) ) < 0)
-            err = -1;
-        ad_meta_fileno(ad) = -1;
-        adf_lock_free(ad->ad_mdp);
+    if ((adflags & ADFLAGS_HF)) {
+        switch (ad->ad_flags) {
+        case AD_VERSION2:
+            if ((ad_meta_fileno(ad) != -1) && !(--ad->ad_mdp->adf_refcount)) {
+                if (close( ad_meta_fileno(ad) ) < 0)
+                    err = -1;
+                ad_meta_fileno(ad) = -1;
+                adf_lock_free(ad->ad_mdp);
+            }
+            break;
+
+        case AD_VERSION_EA:
+            if ((ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */ 
+                && !(--ad->ad_data_fork.adf_refcount)) {
+                if (close( ad_data_fileno(ad) ) < 0)
+                    err = -1;
+                ad_data_fileno(ad) = -1;
+                adf_lock_free(&ad->ad_data_fork);
+            }
+            break;
+
+        default:
+            LOG(log_error, logtype_default, "ad_close: unknown AD version");
+            errno = EIO;
+            return -1;
+        }
+    }
+
+    if ((adflags & ADFLAGS_RF)) {
+        switch (ad->ad_flags) {
+        case AD_VERSION2:
+            /* Do nothing as ADFLAGS_RF == ADFLAGS_HF */
+            break;
+
+        case AD_VERSION_EA:
+            if ((ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */ 
+                && !(--ad->ad_data_fork.adf_refcount)) {
+                if (close( ad_data_fileno(ad) ) < 0)
+                    err = -1;
+                ad_data_fileno(ad) = -1;
+                adf_lock_free(&ad->ad_data_fork);
+            }
+            break;
+
+        default:
+            LOG(log_error, logtype_default, "ad_close: unknown AD version");
+            errno = EIO;
+            return -1;
+        }
     }
 
     return err;