]> arthur.barton.de Git - netatalk.git/commitdiff
Fix adouble refcounting
authorRalph Boehme <sloowfranklin@gmail.com>
Tue, 4 Dec 2012 14:58:51 +0000 (15:58 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Tue, 4 Dec 2012 17:58:22 +0000 (18:58 +0100)
Opening a file that doesn't have metadata with ADFLAGS_HF | AFFLAGS_NOHF
resulted in a successfull open (the error from the failed opening
of the nonexistent metadata is suppressed by AFFLAGS_NOHF), but
then the metadata refcount was increased becasue the error condition
was already reset to 0 at the place where we checked it.
Fixing this requires pushing the refcount increment deeper down the stack
into the individual functions where the error condition is still
available.

After fixing this, another bug became apparent in the mostyl empty
function ad_open_rf_v2().

Also fix an if check where what should be a comparison clobbered
a struct field.

libatalk/adouble/ad_flush.c
libatalk/adouble/ad_open.c

index a18c2c47da7f74ef5d274633e74618de13aa667b..cb0be93c024203e613ddff5c52239ace5f19528c 100644 (file)
@@ -237,8 +237,8 @@ int ad_copy_header(struct adouble *add, struct adouble *ads)
     }
     add->ad_rlen = ads->ad_rlen;
 
-    if ((ads->ad_vers == AD_VERSION2) && (add->ad_vers = AD_VERSION_EA)
-        || (ads->ad_vers == AD_VERSION_EA) && (add->ad_vers = AD_VERSION2)) {
+    if (((ads->ad_vers == AD_VERSION2) && (add->ad_vers == AD_VERSION_EA))
+        || ((ads->ad_vers == AD_VERSION_EA) && (add->ad_vers == AD_VERSION2))) {
         cnid_t id;
         memcpy(&id, ad_entry(add, ADEID_PRIVID), sizeof(cnid_t));
         id = htonl(id);
index bc72ff0b56c98c5eb560ec43cae0fbd6ab6fdef0..4f3a832c3632eae8a0992bc2246aaf05dc6247ac 100644 (file)
@@ -1133,7 +1133,9 @@ static int ad_open_hf(const char *path, int adflags, int mode, struct adouble *a
         break;
     }
 
-    if (ret != 0)
+    if (ret == 0)
+        ad->ad_meta_refcount++;
+    else
         ret = ad_error(ad, adflags);
 
     return ret;
@@ -1186,13 +1188,23 @@ EC_CLEANUP:
 
 static int ad_open_rf_v2(const char *path, int adflags, int mode, struct adouble *ad)
 {
+    EC_INIT;
+
     /*
      * ad_open_hf_v2() does the work, but if it failed and adflags are ADFLAGS_NOHF | ADFLAGS_RF
      * ad_open_hf_v2() didn't give an error, but we're supposed to return a reso fork fd
      */
-    if (!AD_RSRC_OPEN(ad) && !(adflags & ADFLAGS_NORF))
-        return -1;
-    return 0;
+
+    LOG(log_debug, logtype_ad, "ad_open_rf_v2(\"%s\"): BEGIN", fullpathname(path));
+
+    if (!AD_META_OPEN(ad) && !(adflags & ADFLAGS_NORF))
+        EC_FAIL;
+    if (AD_META_OPEN(ad))
+        ad->ad_reso_refcount++;
+
+EC_CLEANUP:
+    LOG(log_debug, logtype_ad, "ad_open_rf_v2(\"%s\"): END: %d", fullpathname(path), ret);
+    EC_EXIT;
 }
 
 static int ad_open_rf_ea(const char *path, int adflags, int mode, struct adouble *ad)
@@ -1250,6 +1262,7 @@ static int ad_open_rf_ea(const char *path, int adflags, int mode, struct adouble
     opened = 1;
     ad->ad_rfp->adf_refcount = 1;
     ad->ad_rfp->adf_flags = oflags;
+    ad->ad_reso_refcount++;
 
 #ifndef HAVE_EAFD
     EC_ZERO_LOG( fstat(ad_reso_fileno(ad), &st) );
@@ -1276,6 +1289,7 @@ EC_CLEANUP:
         if (opened && (ad_reso_fileno(ad) != -1)) {
             close(ad_reso_fileno(ad));
             ad_reso_fileno(ad) = -1;
+            ad->ad_reso_refcount--;
             ad->ad_rfp->adf_refcount = 0;
         }
         if (adflags & ADFLAGS_NORF) {
@@ -1658,17 +1672,13 @@ int ad_open(struct adouble *ad, const char *path, int adflags, ...)
     }
 
     if (adflags & ADFLAGS_HF) {
-        ad->ad_meta_refcount++;
         if (ad_open_hf(path, adflags, mode, ad) != 0) {
-            ad->ad_meta_refcount--;
             EC_FAIL;
         }
     }
 
     if (adflags & ADFLAGS_RF) {
-        ad->ad_reso_refcount++;
         if (ad_open_rf(path, adflags, mode, ad) != 0) {
-            ad->ad_reso_refcount--;
             EC_FAIL;
         }
     }