]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/adouble/ad_flush.c
Merge branch-allea
[netatalk.git] / libatalk / adouble / ad_flush.c
index a451c1c6839ab85345604b12483eb03a03ad5e5f..86a624e069cd4f7d557be7c545a7da4ef5ecd24b 100644 (file)
@@ -53,7 +53,7 @@ static const uint32_t set_eid[] = {
 /*
  * Prepare ad->ad_data buffer from struct adouble for writing on disk
  */
-int ad_rebuild_adouble_header(struct adouble *ad)
+int ad_rebuild_adouble_header_v2(struct adouble *ad)
 {
     uint32_t       eid;
     uint32_t       temp;
@@ -61,7 +61,7 @@ int ad_rebuild_adouble_header(struct adouble *ad)
     char        *buf, *nentp;
     int             len;
 
-    LOG(log_debug, logtype_default, "ad_rebuild_adouble_header");
+    LOG(log_debug, logtype_default, "ad_rebuild_adouble_header_v2");
 
     buf = ad->ad_data;
 
@@ -78,9 +78,8 @@ int ad_rebuild_adouble_header(struct adouble *ad)
     nentp = buf;
     buf += sizeof( nent );
     for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) {
-        if ( ad->ad_eid[ eid ].ade_off == 0 ) {
+        if (ad->ad_eid[ eid ].ade_off == 0)
             continue;
-        }
         temp = htonl( EID_DISK(eid) );
         memcpy(buf, &temp, sizeof( temp ));
         buf += sizeof( temp );
@@ -97,20 +96,53 @@ int ad_rebuild_adouble_header(struct adouble *ad)
     nent = htons( nent );
     memcpy(nentp, &nent, sizeof( nent ));
 
-    switch (ad->ad_vers) {
-    case AD_VERSION2:
-        len = ad_getentryoff(ad, ADEID_RFORK);
-        break;
-    case AD_VERSION_EA:
-        len = AD_DATASZ_EA;
-        break;
-    default:
-        LOG(log_error, logtype_afpd, "Unexpected adouble version");
-        len = 0;
-        break;
+    return ad_getentryoff(ad, ADEID_RFORK);
+}
+
+int ad_rebuild_adouble_header_ea(struct adouble *ad)
+{
+    uint32_t       eid;
+    uint32_t       temp;
+    uint16_t       nent;
+    char        *buf, *nentp;
+    int             len;
+
+    LOG(log_debug, logtype_default, "ad_rebuild_adouble_header_ea");
+
+    buf = ad->ad_data;
+
+    temp = htonl( ad->ad_magic );
+    memcpy(buf, &temp, sizeof( temp ));
+    buf += sizeof( temp );
+
+    temp = htonl( ad->ad_version );
+    memcpy(buf, &temp, sizeof( temp ));
+    buf += sizeof( temp );
+
+    buf += sizeof( ad->ad_filler );
+
+    nentp = buf;
+    buf += sizeof( nent );
+    for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) {
+        if ((ad->ad_eid[ eid ].ade_off == 0) || (eid == ADEID_RFORK))
+            continue;
+        temp = htonl( EID_DISK(eid) );
+        memcpy(buf, &temp, sizeof( temp ));
+        buf += sizeof( temp );
+
+        temp = htonl( ad->ad_eid[ eid ].ade_off );
+        memcpy(buf, &temp, sizeof( temp ));
+        buf += sizeof( temp );
+
+        temp = htonl( ad->ad_eid[ eid ].ade_len );
+        memcpy(buf, &temp, sizeof( temp ));
+        buf += sizeof( temp );
+        nent++;
     }
+    nent = htons( nent );
+    memcpy(nentp, &nent, sizeof( nent ));
 
-    return len;
+    return AD_DATASZ_EA;
 }
 
 /*!
@@ -135,6 +167,7 @@ static int ad_rebuild_adouble_header_osx(struct adouble *ad, char *adbuf)
     memcpy(buf, &temp, sizeof( temp ));
     buf += sizeof( temp );
 
+    memset(buf, 0, sizeof(ad->ad_filler));
     buf += sizeof( ad->ad_filler );
 
     nent = htons(ADEID_NUM_OSX);
@@ -183,27 +216,34 @@ int ad_copy_header(struct adouble *add, struct adouble *ads)
     uint32_t       len;
 
     for ( eid = 0; eid < ADEID_MAX; eid++ ) {
-        if ( ads->ad_eid[ eid ].ade_off == 0 ) {
-            continue;
-        }
-
-        if ( add->ad_eid[ eid ].ade_off == 0 ) {
+        if ( ads->ad_eid[ eid ].ade_off == 0 || add->ad_eid[ eid ].ade_off == 0 )
             continue;
-        }
 
         len = ads->ad_eid[ eid ].ade_len;
-        if (!len) {
+        if (!len || len != add->ad_eid[ eid ].ade_len)
             continue;
-        }
 
-        if (eid != ADEID_COMMENT && add->ad_eid[ eid ].ade_len != len ) {
+        switch (eid) {
+        case ADEID_COMMENT:
+        case ADEID_PRIVDEV:
+        case ADEID_PRIVINO:
+        case ADEID_PRIVSYN:
+        case ADEID_PRIVID:
             continue;
+        default:
+            ad_setentrylen( add, eid, len );
+            memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len );
         }
-
-        ad_setentrylen( add, eid, len );
-        memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len );
     }
     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)) {
+        cnid_t id;
+        memcpy(&id, ad_entry(add, ADEID_PRIVID), sizeof(cnid_t));
+        id = htonl(id);
+        memcpy(ad_entry(add, ADEID_PRIVID), &id, sizeof(cnid_t));
+    }
     return 0;
 }
 
@@ -254,6 +294,7 @@ static int ad_flush_hf(struct adouble *ad)
                     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) );
@@ -358,6 +399,14 @@ int ad_close(struct adouble *ad, int adflags)
         ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
         ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
 
+    if (adflags & (ADFLAGS_SETSHRMD | ADFLAGS_CHECK_OF)) {
+        /* sharemode locks are stored in the data fork, adouble:v2 needs this extra handling */
+        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 */
         && --ad->ad_data_fork.adf_refcount == 0) {
@@ -382,6 +431,7 @@ 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);
         }
     }