]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/adouble/ad_conv.c
Resource fork conversion from AppleDouble v2 broken, bug #568
[netatalk.git] / libatalk / adouble / ad_conv.c
index ff0eebcc497aa6c24ca5ca5320f8b1163ef7e340..43f4332baab3e4fe2a4ed464e62e2998fe2ff95d 100644 (file)
@@ -65,6 +65,7 @@ static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struc
 
     switch (S_IFMT & sp->st_mode) {
     case S_IFREG:
+    case S_IFDIR:
         break;
     default:
         return 0;
@@ -151,11 +152,13 @@ static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struc
         EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
 
         /* Create a adouble:ea resource fork */
-        EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) );
+        EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_RF|ADFLAGS_RDWR|ADFLAGS_CREATE|ADFLAGS_SETSHRMD, 0666) );
 
         EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) );
         adea.ad_rlen = adv2.ad_rlen;
         ad_flush(&adea);
+        fchmod(ad_reso_fileno(&adea), sp->st_mode & 0666);
+        fchown(ad_reso_fileno(&adea), sp->st_uid, sp->st_gid);
     }
 
 EC_CLEANUP:
@@ -173,9 +176,12 @@ static int ad_conv_v22ea(const char *path, const struct stat *sp, const struct v
 
     become_root();
 
-    EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
-    EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
+    if (ad_conv_v22ea_hf(path, sp, vol) != 0)
+        goto delete;
+    if (ad_conv_v22ea_rf(path, sp, vol) != 0)
+        goto delete;
 
+delete:
     EC_NULL( adpath = ad_path(path, adflags) );
     LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
         path, fullpathname(adpath));
@@ -198,25 +204,41 @@ static int ad_conv_dehex(const char *path, const struct stat *sp, const struct v
 {
     EC_INIT;
     static char buf[MAXPATHLEN];
-    const char *p;
     int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
     bstring newpath = NULL;
+    static bstring str2e = NULL;
+    static bstring str2f = NULL;
+    static bstring strdot = NULL;
+    static bstring strcolon = NULL;
+    char *newadpath = NULL;
+
+    if (str2e == NULL) {
+        str2e = bfromcstr(":2e");
+        str2f = bfromcstr(":2f");
+        strdot = bfromcstr(".");
+        strcolon = bfromcstr(":");
+    }
 
     LOG(log_debug, logtype_ad,"ad_conv_dehex(\"%s\"): BEGIN", fullpathname(path));
 
     *newpathp = NULL;
 
-    if ((p = strchr(path, ':')) == NULL)
+    if (((strstr(path, ":2e")) == NULL) && ((strstr(path, ":2f")) == NULL) )
         goto EC_CLEANUP;
 
     EC_NULL( newpath = bfromcstr(path) );
 
-    EC_ZERO( bfindreplace(newpath, bfromcstr(":2e"), bfromcstr("."), 0) );
-    EC_ZERO( bfindreplace(newpath, bfromcstr(":2f"), bfromcstr(":"), 0) );
+    EC_ZERO( bfindreplace(newpath, str2e, strdot, 0) );
+    EC_ZERO( bfindreplace(newpath, str2f, strcolon, 0) );
     
     become_root();
-    if (adflags != ADFLAGS_DIR)
-        rename(vol->ad_path(path, 0), vol->ad_path(bdata(newpath), 0));
+    if (adflags != ADFLAGS_DIR) {
+        if ((newadpath = strdup(vol->ad_path(bdata(newpath), 0))) == NULL) {
+            unbecome_root();
+            EC_FAIL;
+        }
+        rename(vol->ad_path(path, 0), newadpath);
+    }
     rename(path, bdata(newpath));
     unbecome_root();
 
@@ -226,6 +248,8 @@ static int ad_conv_dehex(const char *path, const struct stat *sp, const struct v
 EC_CLEANUP:
     if (newpath)
         bdestroy(newpath);
+    if (newadpath)
+        free(newadpath);
     EC_EXIT;
 }
 
@@ -250,6 +274,9 @@ int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, c
     if (newpath)
         *newpath = NULL;
 
+    if (vol->v_flags & AFPVOL_RO)
+        EC_EXIT_STATUS(0);
+
     if ((vol->v_adouble == AD_VERSION_EA) && !(vol->v_flags & AFPVOL_NOV2TOEACONV))
         EC_ZERO( ad_conv_v22ea(path, sp, vol) );