]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/adouble/ad_open.c
Merge 2-2
[netatalk.git] / libatalk / adouble / ad_open.c
index 6b6aa6a4378c6de6e398c918195dfa74253dbcb4..79016b5feac43e1d6fed2110e2d5e320610470e9 100644 (file)
@@ -45,6 +45,7 @@
 #include <atalk/logger.h>
 #include <atalk/adouble.h>
 #include <atalk/util.h>
+#include <atalk/unix.h>
 #include <atalk/ea.h>
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
@@ -104,11 +105,11 @@ static uid_t default_uid = -1;
 
 /* Forward declarations */
 static int ad_mkrf(const char *path);
-static int ad_header_read(const char *path, struct adouble *ad, struct stat *hst);
+static int ad_header_read(const char *path, struct adouble *ad, const struct stat *hst);
 static int ad_header_upgrade(struct adouble *ad, const char *name);
 
 static int ad_mkrf_ea(const char *path);
-static int ad_header_read_ea(const char *path, struct adouble *ad, struct stat *hst);
+static int ad_header_read_ea(const char *path, struct adouble *ad, const struct stat *hst);
 static int ad_header_upgrade_ea(struct adouble *ad, const char *name);
 static int ad_reso_size(const char *path, int adflags, struct adouble *ad);
 static int ad_mkrf_osx(const char *path);
@@ -117,7 +118,7 @@ static int ad_mkrf_osx(const char *path);
 static struct adouble_fops ad_adouble = {
     &ad_path,
     &ad_mkrf,
-    &ad_rebuild_adouble_header,
+    &ad_rebuild_adouble_header_v2,
     &ad_header_read,
     &ad_header_upgrade,
 };
@@ -130,19 +131,11 @@ static struct adouble_fops ad_adouble_ea = {
     &ad_path_osx,
     &ad_mkrf_osx,
 #endif
-    &ad_rebuild_adouble_header,
+    &ad_rebuild_adouble_header_ea,
     &ad_header_read_ea,
     &ad_header_upgrade_ea,
 };
 
-static struct adouble_fops ad_osx = {
-    &ad_path_osx,
-    &ad_mkrf_osx,
-    &ad_rebuild_adouble_header,
-    &ad_header_read,
-    &ad_header_upgrade,
-};
-
 static const struct entry entry_order2[ADEID_NUM_V2 + 1] = {
     {ADEID_NAME,        ADEDOFF_NAME_V2,     ADEDLEN_INIT},
     {ADEID_COMMENT,     ADEDOFF_COMMENT_V2,  ADEDLEN_INIT},
@@ -434,7 +427,7 @@ static void parse_entries(struct adouble *ad, char *buf, uint16_t nentries)
  * NOTE: we're assuming that the resource fork is kept at the end of
  *       the file. also, mmapping won't work for the hfs fs until it
  *       understands how to mmap header files. */
-static int ad_header_read(const char *path _U_, struct adouble *ad, struct stat *hst)
+static int ad_header_read(const char *path _U_, struct adouble *ad, const struct stat *hst)
 {
     char                *buf = ad->ad_data;
     uint16_t            nentries;
@@ -443,7 +436,7 @@ static int ad_header_read(const char *path _U_, struct adouble *ad, struct stat
     struct stat         st;
 
     /* read the header */
-    if ((header_len = adf_pread( ad->ad_mdp, buf, AD_DATASZ, 0)) < 0) {
+    if ((header_len = adf_pread( ad->ad_mdp, buf, AD_DATASZ2, 0)) < 0) {
         return -1;
     }
     if (header_len < AD_HEADER_LEN) {
@@ -509,8 +502,46 @@ static int ad_header_read(const char *path _U_, struct adouble *ad, struct stat
     return 0;
 }
 
+/* error here means it's not ad ._ adouble:osx file and thus we return 1 */
+int ad_valid_header_osx(const char *path)
+{
+    EC_INIT;
+    int fd = -1;
+    struct adouble      adosx;
+    char                *buf = &adosx.ad_data[0];
+    ssize_t             header_len;
+
+    LOG(log_debug, logtype_afpd, "ad_valid_header_osx(\"%s\"): BEGIN", fullpathname(path));
+
+    EC_NEG1( fd = open(path, O_RDONLY) );
+
+    /* read the header */
+    EC_NEG1( header_len = read(fd, buf, AD_DATASZ_OSX) );
+
+    if (header_len < AD_HEADER_LEN)
+        EC_FAIL;
+
+    memcpy(&adosx.ad_magic, buf, sizeof(adosx.ad_magic));
+    memcpy(&adosx.ad_version, buf + ADEDOFF_VERSION, sizeof(adosx.ad_version));
+    adosx.ad_magic = ntohl(adosx.ad_magic);
+    adosx.ad_version = ntohl(adosx.ad_version);
+
+    if ((adosx.ad_magic != AD_MAGIC) || (adosx.ad_version != AD_VERSION2)) {
+        LOG(log_error, logtype_afpd, "ad_valid_header_osx: not an adouble:ox file");
+        EC_FAIL;
+    }
+
+EC_CLEANUP:
+    LOG(log_debug, logtype_afpd, "ad_valid_header_osx(\"%s\"): END: %d", fullpathname(path), ret);
+    if (fd != -1)
+        close(fd);
+    if (ret != 0)
+        return 1;
+    return 0;
+}
+
 /* Read an ._ file, only uses the resofork, finderinfo is taken from EA */
-static int ad_header_read_osx(const char *path _U_, struct adouble *ad, struct stat *hst)
+static int ad_header_read_osx(const char *path _U_, struct adouble *ad, const struct stat *hst)
 {
     EC_INIT;
     struct adouble      adosx;
@@ -579,7 +610,7 @@ EC_CLEANUP:
     EC_EXIT;
 }
 
-static int ad_header_read_ea(const char *path, struct adouble *ad, struct stat *hst _U_)
+static int ad_header_read_ea(const char *path, struct adouble *ad, const struct stat *hst _U_)
 {
     uint16_t nentries;
     int      len;
@@ -1062,7 +1093,8 @@ static int ad_open_hf_ea(const char *path, int adflags, int mode, struct adouble
         LOG(log_debug, logtype_default, "ad_open_hf_ea(\"%s\"): created metadata EA", path);
     }
 
-    ad->ad_mdp->adf_refcount++;
+    if (ad_meta_fileno(ad) != -1)
+        ad->ad_mdp->adf_refcount++;
     (void)ad_reso_size(path, adflags, ad);
 
 EC_CLEANUP:
@@ -1147,13 +1179,18 @@ EC_CLEANUP:
     EC_EXIT;
 }
 
-/*!
- * Open ressource fork
- *
- * Only for adouble:ea, a nullop otherwise because adouble:v2 has the ressource fork as part
- * of the adouble file which is openend by ADFLAGS_HF.
- */
-static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *ad)
+static int ad_open_rf_v2(const char *path, int adflags, int mode, struct adouble *ad)
+{
+    /*
+     * 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;
+}
+
+static int ad_open_rf_ea(const char *path, int adflags, int mode, struct adouble *ad)
 {
     EC_INIT;
     int oflags;
@@ -1165,9 +1202,6 @@ static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *a
     struct stat st;
 #endif
 
-    if (ad->ad_vers != AD_VERSION_EA)
-        return 0;
-
     LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): BEGIN", fullpathname(path));
 
     oflags = O_NOFOLLOW | (ad2openflags(ad, ADFLAGS_RF, adflags) & ~O_CREAT);
@@ -1186,7 +1220,7 @@ static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *a
         goto EC_CLEANUP;
     }
 #ifdef HAVE_EAFD
-    if (ad_meta_fileno(ad) == -1)
+    if (ad_meta_fileno(ad) < 0)
         EC_FAIL;
     if ((ad_reso_fileno(ad) = sys_getxattrfd(ad_meta_fileno(ad), AD_EA_RESO, oflags)) == -1) {
         if (!(adflags & ADFLAGS_CREATE)) {
@@ -1253,6 +1287,28 @@ EC_CLEANUP:
     EC_EXIT;
 }
 
+/*!
+ * Open ressource fork
+ */
+static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *ad)
+{
+    int ret = 0;
+
+    switch (ad->ad_vers) {
+    case AD_VERSION2:
+        ret = ad_open_rf_v2(path, adflags, mode, ad);
+        break;
+    case AD_VERSION_EA:
+        ret = ad_open_rf_ea(path, adflags, mode, ad);
+        break;
+    default:
+        ret = -1;
+        break;
+    }
+
+    return ret;
+}
+
 /***********************************************************************************
  * API functions
  ********************************************************************************* */
@@ -1560,10 +1616,11 @@ int ad_open(struct adouble *ad, const char *path, int adflags, ...)
         /* Checking for open forks requires sharemode lock support (ie RDWR instead of RDONLY) */
         adflags |= ADFLAGS_SETSHRMD;
 
+    if (adflags & ADFLAGS_SETSHRMD)
+        /* sharemode locks are stored in the data fork */
+        adflags |= ADFLAGS_DF;
+
     if (ad->ad_vers == AD_VERSION2) {
-        if (adflags & ADFLAGS_SETSHRMD)
-            /* sharemode locks are stored in the data fork, adouble:v2 needs this extra handling here */
-            adflags |= ADFLAGS_DF;
         if (adflags & ADFLAGS_RF)
             adflags |= ADFLAGS_HF;
         if (adflags & ADFLAGS_NORF)
@@ -1766,3 +1823,28 @@ EC_CLEANUP:
 
     return ret;
 }
+
+/* build a resource fork mode from the data fork mode:
+ * remove X mode and extend header to RW if R or W (W if R for locking),
+ */
+mode_t ad_hf_mode(mode_t mode)
+{
+    mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
+    /* fnctl lock need write access */
+    if ((mode & S_IRUSR))
+        mode |= S_IWUSR;
+    if ((mode & S_IRGRP))
+        mode |= S_IWGRP;
+    if ((mode & S_IROTH))
+        mode |= S_IWOTH;
+
+    /* if write mode set add read mode */
+    if ((mode & S_IWUSR))
+        mode |= S_IRUSR;
+    if ((mode & S_IWGRP))
+        mode |= S_IRGRP;
+    if ((mode & S_IWOTH))
+        mode |= S_IROTH;
+
+    return mode;
+}