]> arthur.barton.de Git - netatalk.git/commitdiff
Various fixes for adouble:v2
authorFrank Lahm <franklahm@googlemail.com>
Wed, 1 Feb 2012 11:47:52 +0000 (12:47 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 1 Feb 2012 11:47:52 +0000 (12:47 +0100)
etc/afpd/file.c
etc/afpd/fork.c
etc/afpd/fork.h
etc/afpd/ofork.c
include/atalk/adouble.h
libatalk/adouble/ad_flush.c
libatalk/adouble/ad_lock.c
libatalk/adouble/ad_open.c
libatalk/vfs/vfs.c

index bc9754f0da54d6be45dd4bbdc7412d2ee1812281..6d253d1ecc43941a8e62b12697be86061c35524c 100644 (file)
@@ -609,6 +609,7 @@ int getfilparams(struct vol *vol,
     struct adouble     ad, *adp;
     int                 opened = 0;
     int rc;    
+    int flags;
 
     LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name);
 
@@ -617,7 +618,7 @@ int getfilparams(struct vol *vol,
 
     if (opened) {
         char *upath;
-        int  flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0;
+        flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0;
 
         adp = of_ad(vol, path, &ad);
         upath = path->u_name;
@@ -639,7 +640,7 @@ int getfilparams(struct vol *vol,
         }
     }
     rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp);
-    ad_close(adp, ADFLAGS_HF);
+    ad_close(adp, ADFLAGS_HF | flags);
 
     return( rc );
 }
@@ -1332,7 +1333,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si
     setvoltime(obj, d_vol );
 
 copy_exit:
-    ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
+    ad_close( adp, ADFLAGS_DF |ADFLAGS_HF | ADFLAGS_SETSHRMD);
     return( retvalue );
 }
 
@@ -1385,19 +1386,7 @@ static int copy_fork(int eid, struct adouble *add, struct adouble *ads)
         dfd = ad_reso_fileno(add);
     }        
 
-    if (add->ad_version == AD_VERSION2)
-        soff = doff = ad_getentryoff(ads, eid);
-    else {
-        if (eid == ADEID_DFORK)
-            soff = doff = ad_getentryoff(ads, eid);
-        else {
-#ifdef HAVE_EAFD
-            soff = doff = 0;
-#else
-            soff = doff = ADEDOFF_RFORK_OSX;
-#endif
-        }
-    }
+    soff = doff = ad_getentryoff(ads, eid);
 
     if ((off_t)-1 == lseek(sfd, soff, SEEK_SET))
        return -1;
@@ -1478,9 +1467,6 @@ int copyfile(const struct vol *s_vol,
     }
 
     adflags = ADFLAGS_DF | ADFLAGS_RF | ADFLAGS_NORF;
-    if (newname) {
-        adflags |= ADFLAGS_HF;
-    }
 
     if (ad_openat(adp, sfd, src, adflags | ADFLAGS_NOHF | ADFLAGS_RDONLY) < 0) {
         ret_err = errno;
@@ -1509,13 +1495,15 @@ int copyfile(const struct vol *s_vol,
         return AFPERR_EXIST;
     }
 
+#if 0
     if (AD_RSRC_OPEN(adp))
         err = copy_fork(ADEID_RFORK, &add, adp);
-    
+#endif
+
     if (err == 0)
         err = copy_fork(ADEID_DFORK, &add, adp);
 
-    if ((err == 0) && (ad_meta_fileno(adp) != -1))
+    if (err == 0)
         err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
 
     if (err < 0)
@@ -1614,7 +1602,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib)
         */
         if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) {
             if ((err = check_attrib(&ad))) {
-                ad_close(&ad, ADFLAGS_HF);
+                ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF);
                return err;
             }
             meta = 1;
@@ -1671,7 +1659,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib)
 
 end:
     if (meta)
-        ad_close(&ad, ADFLAGS_HF);
+        ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF);
 
     if (adp)
         ad_close( &ad, adflags );  /* ad_close removes locks if any */
index 2d3a5ff5283d64305715dcc2d9b98055a67ff3e0..7bd2128b350fe8624189cb04e191ea3024f7672a 100644 (file)
@@ -418,7 +418,7 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si
     }
 
     if ((ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) {
-        ad_close( ofork->of_ad, adflags );
+        ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
         goto openfork_err;
     }
 
@@ -433,7 +433,7 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si
     if (ad_meta_fileno(ofork->of_ad) != -1) {   /* META */
         ad_getattr(ofork->of_ad, &bshort);
         if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
-            ad_close( ofork->of_ad, adflags );
+            ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
             of_dealloc( ofork );
             ofrefnum = 0;
             memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
@@ -452,8 +452,9 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si
         ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
         /* can we access the fork? */
         if (ret < 0) {
+            ofork->of_flags |= AFPFORK_ERROR;
             ret = errno;
-            ad_close( ofork->of_ad, adflags );
+            ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD);
             of_dealloc( ofork );
             switch (ret) {
             case EAGAIN: /* return data anyway */
index 37605e4a07a90b05ba7b24711e179b2792d4e129..b8a6d3a9719b17ddacd6bc8ef1c2f3b1a708b661 100644 (file)
@@ -46,6 +46,7 @@ struct ofork {
 #define AFPFORK_ACCWR   (1<<5)
 #define AFPFORK_ACCMASK (AFPFORK_ACCRD | AFPFORK_ACCWR)
 #define AFPFORK_MODIFIED (1<<6) /* used in FCE for modified files */
+#define AFPFORK_ERROR   (1<<7)  /* used to indicate an error in opening the fork */
 
 #ifdef AFS
 extern struct ofork *writtenfork;
index 362097aed375366a05099ef3e03dca32379f1b6f..5fc6a1d5752285c08f82ec407711ddb64edbf0da 100644 (file)
@@ -383,7 +383,7 @@ void of_dealloc( struct ofork *of)
         free( of->of_ad->ad_m_name );
         free( of->of_ad);
     } else {/* someone's still using it. just free this user's locks */
-        ad_unlock(of->of_ad, of->of_refnum);
+        ad_unlock(of->of_ad, of->of_refnum, of->of_flags & AFPFORK_ERROR ? 0 : 1);
     }
 
     free( of );
@@ -417,7 +417,7 @@ int of_closefork(struct ofork *ofork)
     }
 
     ret = 0;
-    if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
+    if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) {
         ret = -1;
     }
 
index a4a508bb8c2b2b74ed54a3cb4c4f1231fb07697e..5601f4399372cf82480b8974b20793627b2ae555 100644 (file)
@@ -358,7 +358,6 @@ struct adouble {
 
 #define ad_getentrylen(ad,eid)     ((ad)->ad_eid[(eid)].ade_len)
 #define ad_setentrylen(ad,eid,len) ((ad)->ad_eid[(eid)].ade_len = (len))
-#define ad_getentryoff(ad,eid)     ((ad)->ad_eid[(eid)].ade_off)
 #define ad_setentryoff(ad,eid,off) ((ad)->ad_eid[(eid)].ade_off = (off))
 #define ad_entry(ad,eid)           ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off)
 
@@ -379,11 +378,12 @@ extern int fsetrsrcea(struct adouble *ad, int fd, const char *eaname, const void
 /* ad_lock.c */
 extern int ad_testlock      (struct adouble *adp, int eid, off_t off);
 extern uint16_t ad_openforks(struct adouble *adp, uint16_t);
-extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
-extern void ad_unlock(struct adouble *, int user);
-extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
+extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int fork);
+extern void ad_unlock(struct adouble *, int fork, int unlckbrl);
+extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int fork);
 
 /* ad_open.c */
+extern off_t ad_getentryoff(const struct adouble *ad, int eid);
 extern const char *adflags2logstr(int adflags);
 extern int ad_setfuid     (const uid_t );
 extern uid_t ad_getfuid   (void );
index 3331074b994ee619d7271e7724ed965cb2f76da6..dbf1576d886d81861ac14b8a446d6d4add7e5bcc 100644 (file)
@@ -359,6 +359,11 @@ 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 ((ad->ad_vers == AD_VERSION2) && (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;
 
index 6932b33d4bd5be187bae75c843d16af9752e5321..8d3808177692da564f4bed13c8764281df45654e 100644 (file)
@@ -20,6 +20,7 @@
 #include <atalk/logger.h>
 #include <atalk/compat.h>
 #include <atalk/errchk.h>
+#include <atalk/util.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -153,21 +154,21 @@ static void adf_freelock(struct ad_fd *ad, const int i)
  * i converted to using arrays of locks. everytime a lock
  * gets removed, we shift all of the locks down.
  */
-static void adf_unlock(struct ad_fd *ad, const int fork)
+static void adf_unlock(struct adouble *ad, struct ad_fd *adf, const int fork, int unlckbrl)
 {
-    adf_lock_t *lock = ad->adf_lock;
+    adf_lock_t *lock = adf->adf_lock;
     int i;
 
-    for (i = 0; i < ad->adf_lockcount; i++) {
-        if (lock[i].lock.l_start < AD_FILELOCK_BASE
+    for (i = 0; i < adf->adf_lockcount; i++) {
+        if ((unlckbrl && lock[i].lock.l_start < AD_FILELOCK_BASE)
             || lock[i].user == fork) {
             /* we're really going to delete this lock. note: read locks
                are the only ones that allow refcounts > 1 */
-            adf_freelock(ad, i);
+            adf_freelock(adf, i);
             /* we shifted things down, so we need to backtrack */
             i--; 
             /* unlikely but realloc may have change adf_lock */
-            lock = ad->adf_lock;       
+            lock = adf->adf_lock;       
         }
     }
 }
@@ -241,58 +242,6 @@ static int adf_findxlock(struct ad_fd *ad,
  *       2) if the header file doesn't exist, we stick the locks
  *          in the locations specified by AD_FILELOCK_RD/WR.
  */
-#define LOCK_DATA_WR (0)
-#define LOCK_DATA_RD (1)
-#define LOCK_RSRC_WR (2)
-#define LOCK_RSRC_RD (3)
-
-#define LOCK_RSRC_DRD (4)
-#define LOCK_RSRC_DWR (5)
-#define LOCK_DATA_DRD (6)
-#define LOCK_DATA_DWR (7)
-
-#define LOCK_RSRC_NONE (8)
-#define LOCK_DATA_NONE (9)
-
-/* -------------- 
-       translate a data fork lock to an offset
-*/
-
-static off_t df2off(off_t off)
-{
-    off_t start = off;
-       if (off == AD_FILELOCK_OPEN_WR)
-               start = LOCK_DATA_WR;
-       else if (off == AD_FILELOCK_OPEN_RD)
-               start = LOCK_DATA_RD;
-    else if (off == AD_FILELOCK_DENY_RD)
-               start = LOCK_DATA_DRD;
-       else if (off == AD_FILELOCK_DENY_WR)
-               start = LOCK_DATA_DWR;
-       else if (off == AD_FILELOCK_OPEN_NONE)
-               start = LOCK_DATA_NONE;
-       return start;
-}
-
-/* -------------- 
-       translate a resource fork lock to an offset
-*/
-
-static off_t hf2off(off_t off)
-{
-    off_t start = off;
-       if (off == AD_FILELOCK_OPEN_WR)
-               start = LOCK_RSRC_WR;
-       else if (off == AD_FILELOCK_OPEN_RD)
-               start = LOCK_RSRC_RD;
-    else if (off == AD_FILELOCK_DENY_RD)
-               start = LOCK_RSRC_DRD;
-       else if (off == AD_FILELOCK_DENY_WR)
-               start = LOCK_RSRC_DWR;
-       else if (off == AD_FILELOCK_OPEN_NONE)
-               start = LOCK_RSRC_NONE;
-       return start;
-}
 
 /* -------------- 
        translate a resource fork lock to an offset
@@ -358,130 +307,6 @@ static int testlock(const struct ad_fd *adf, off_t off, off_t len)
     return 1;
 }
 
-static uint16_t ad_openforks_v2(struct adouble *ad, uint16_t attrbits)
-{
-  uint16_t ret = 0;
-  struct ad_fd *adf;
-  off_t off;
-
-  if (!(attrbits & (ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
-      off_t len;
-      /* XXX know the locks layout: 
-         AD_FILELOCK_OPEN_WR is first 
-         and use it for merging requests
-      */
-      if (ad_meta_fileno(ad) != -1) {
-          /* there's a resource fork test the four bytes for
-           * data RW/RD and fork RW/RD locks in one request
-          */
-         adf = ad->ad_mdp;
-         off = LOCK_DATA_WR;
-         len = 4;
-      }
-      else {
-          /* no resource fork, only data RD/RW may exist */
-          adf = &ad->ad_data_fork;
-          off = AD_FILELOCK_OPEN_WR;
-          len = 2;
-      }
-      if (!testlock(adf, off, len))
-          return ret;
-  }
-  /* either there's a lock or we already know one 
-     fork is open
-  */
-  if (!(attrbits & ATTRBIT_DOPEN)) {
-      if (ad_meta_fileno(ad) != -1) {
-         adf = ad->ad_mdp;
-         off = LOCK_DATA_WR;
-      }
-      else {
-          adf = &ad->ad_data_fork;
-          off = AD_FILELOCK_OPEN_WR;
-      }
-      ret = testlock(adf, off, 2) > 0? ATTRBIT_DOPEN : 0;
-  }
-
-  if (!(attrbits & ATTRBIT_ROPEN)) {
-      if (ad_meta_fileno(ad) != -1) {
-         adf = ad->ad_mdp;
-          off = LOCK_RSRC_WR;
-          ret |= testlock(adf, off, 2) > 0? ATTRBIT_ROPEN : 0;
-      }
-  }
-
-  return ret;
-}
-
-/* test for sharemode locks, adouble:ea stores them on the datafork */
-static uint16_t ad_openforks_ea(struct adouble *ad, uint16_t attrbits)
-{
-    uint16_t ret = 0;
-    struct ad_fd *adf;
-    off_t off;
-    off_t len;
-
-    if (ad_data_fileno(ad) == -1)
-        return 0;
-
-    if (!(attrbits & (ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
-        /* Test all 4 locks at once */
-        off = AD_FILELOCK_OPEN_WR;
-        len = 4;
-        if (testlock(&ad->ad_data_fork, off, len) == 0)
-            return 0;
-    }
-
-    /* either there's a lock or we already know one fork is open */
-
-    if (!(attrbits & ATTRBIT_DOPEN)) {
-        off = AD_FILELOCK_OPEN_WR;
-        ret = testlock(&ad->ad_data_fork, off, 2) > 0 ? ATTRBIT_DOPEN : 0;
-    }
-
-    if (!(attrbits & ATTRBIT_ROPEN)) {
-        off = AD_FILELOCK_RSRC_OPEN_WR;
-        ret |= testlock(&ad->ad_data_fork, off, 2) > 0? ATTRBIT_ROPEN : 0;
-    }
-
-    return ret;
-}
-
-static int ad_testlock_v2(struct adouble *ad, int eid, const off_t off)
-{
-    struct ad_fd *adf;
-    off_t      lock_offset;
-
-    lock_offset = off;
-    if (eid == ADEID_DFORK) {
-        adf = &ad->ad_data_fork;
-        if (ad_meta_fileno(ad) != -1) {
-            adf = ad->ad_mdp;
-            lock_offset = df2off(off);
-        }
-    } else { /* rfork */
-        if (ad_meta_fileno(ad) == -1) {
-            /* there's no resource fork. return no lock */
-            return 0;
-        }
-        adf = ad->ad_mdp;
-        lock_offset = hf2off(off);
-    }
-    return testlock(adf, lock_offset, 1);
-}
-
-static int ad_testlock_ea(struct adouble *ad, int eid, const off_t off)
-{
-    off_t      lock_offset;
-
-    if (eid == ADEID_DFORK) {
-        lock_offset = off;
-    } else { /* rfork */
-        lock_offset = rf2off(off);
-    }
-    return testlock(&ad->ad_data_fork, lock_offset, 1);
-}
-
 #define LTYPE2STRBUFSIZ 128
 static const char *locktypetostr(int type)
 {
@@ -545,61 +370,21 @@ int ad_lock(struct adouble *ad, uint32_t eid, int locktype, off_t off, off_t len
         shmdstrfromoff(off),
         (intmax_t)len);
 
-    if ((locktype & ADLOCK_FILELOCK) && (len != 1)) {
-        /* safety check */
-        ret = -1;
-        goto exit;
-    }
+    if ((locktype & ADLOCK_FILELOCK) && (len != 1))
+        AFP_PANIC("lock API error");
 
-    lock.l_start = off;
     type = locktype;
 
     if (eid == ADEID_DFORK) {
         adf = &ad->ad_data_fork;
-        if ((ad->ad_vers == AD_VERSION2) && (type & ADLOCK_FILELOCK)) {
-            if (ad_meta_fileno(ad) != -1) { /* META */
-                adf = ad->ad_mdp;
-                lock.l_start = df2off(off);
-            }
-        }
+        lock.l_start = off;
     } else { /* rfork */
-        switch (ad->ad_vers) {
-        case AD_VERSION2:
-            if (ad_meta_fileno(ad) == -1 || ad_reso_fileno(ad) == -1) {
-                /* there's no meta data. return a lock error 
-                 * otherwise if a second process is able to create it
-                 * locks are a mess. */
-                errno = EACCES;
-                ret= -1;
-                goto exit;
-            }
-            if (type & ADLOCK_FILELOCK) {
-                adf = ad->ad_mdp;                      /* either resource or meta data (set in ad_open) */
-                lock.l_start = hf2off(off);
-            } else {
-                /* we really want the resource fork it's a byte lock */
-                adf = &ad->ad_resource_fork;
-                lock.l_start += ad_getentryoff(ad, eid);
-            }
-            break;
-
-        case AD_VERSION_EA:
-            if (type & ADLOCK_FILELOCK) {
-                adf = &ad->ad_data_fork;
-                lock.l_start = rf2off(off);
-            } else {
-                adf = ad->ad_rfp;
-#if HAVE_EAFD
-                lock.l_start = off;
-#else
-                lock.l_start= ADEDOFF_RFORK_OSX + off;
-#endif
-            }
-            break;
-
-        default:
-            ret = -1;
-            goto exit;
+        if (type & ADLOCK_FILELOCK) {
+            adf = &ad->ad_data_fork;
+            lock.l_start = rf2off(off);
+        } else {
+            adf = ad->ad_rfp;
+            lock.l_start = off + ad_getentryoff(ad, ADEID_RFORK);
         }
     }
 
@@ -734,10 +519,10 @@ int ad_tmplock(struct adouble *ad, uint32_t eid, int locktype, off_t off, off_t
 
     lock.l_start = off;
     type = locktype;
+
     if (eid == ADEID_DFORK) {
         adf = &ad->ad_data_fork;
     } else {
-        /* FIXME META */
         adf = &ad->ad_resource_fork;
         if (adf->adf_fd == -1) {
             /* there's no resource fork. return success */
@@ -787,15 +572,16 @@ exit:
 }
 
 /* --------------------- */
-void ad_unlock(struct adouble *ad, const int fork)
+void ad_unlock(struct adouble *ad, const int fork, int unlckbrl)
 {
-    LOG(log_debug, logtype_default, "ad_unlock(\"%s\"): BEGIN", ad->ad_m_name ? ad->ad_m_name : "???");
+    LOG(log_debug, logtype_default, "ad_unlock(\"%s\", unlckbrl: %d): BEGIN",
+        ad->ad_m_name ? ad->ad_m_name : "???", unlckbrl);
 
     if (ad_data_fileno(ad) != -1) {
-        adf_unlock(&ad->ad_data_fork, fork);
+        adf_unlock(ad, &ad->ad_data_fork, fork, unlckbrl);
     }
     if (ad_reso_fileno(ad) != -1) {
-        adf_unlock(&ad->ad_resource_fork, fork);
+        adf_unlock(ad, &ad->ad_resource_fork, fork, unlckbrl);
     }
 
     LOG(log_debug, logtype_default, "ad_unlock(\"%s\"): END", ad->ad_m_name ? ad->ad_m_name : "???");
@@ -814,6 +600,7 @@ void ad_unlock(struct adouble *ad, const int fork)
 int ad_testlock(struct adouble *ad, int eid, const off_t off)
 {
     int ret = 0;
+    off_t lock_offset;
 
     LOG(log_debug, logtype_default, "ad_testlock(\"%s\", %s, off: %jd (%s): BEGIN",
         ad->ad_m_name ? ad->ad_m_name : "???",
@@ -821,18 +608,14 @@ int ad_testlock(struct adouble *ad, int eid, const off_t off)
         (intmax_t)off,
         shmdstrfromoff(off));
 
-    switch (ad->ad_vers) {
-    case AD_VERSION2:
-        ret = ad_testlock_v2(ad, eid, off);
-        break;
-    case AD_VERSION_EA:
-        ret = ad_testlock_ea(ad, eid, off);
-        break;
-    default:
-        ret = -1;
-        break;
+    if (eid == ADEID_DFORK) {
+        lock_offset = off;
+    } else { /* rfork */
+        lock_offset = rf2off(off);
     }
 
+    ret = testlock(&ad->ad_data_fork, lock_offset, 1);
+
     LOG(log_debug, logtype_default, "ad_testlock: END: %d", ret);
     return ret;
 }
@@ -851,12 +634,33 @@ int ad_testlock(struct adouble *ad, int eid, const off_t off)
  */
 uint16_t ad_openforks(struct adouble *ad, uint16_t attrbits)
 {
-    switch (ad->ad_vers) {
-    case AD_VERSION2:
-        return ad_openforks_v2(ad, attrbits);
-    case AD_VERSION_EA:
-        return ad_openforks_ea(ad, attrbits);
-    default:
-        return -1;
+    uint16_t ret = 0;
+    struct ad_fd *adf;
+    off_t off;
+    off_t len;
+
+    if (ad_data_fileno(ad) == -1)
+        return 0;
+
+    if (!(attrbits & (ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
+        /* Test all 4 locks at once */
+        off = AD_FILELOCK_OPEN_WR;
+        len = 4;
+        if (testlock(&ad->ad_data_fork, off, len) == 0)
+            return 0;
     }
+
+    /* either there's a lock or we already know one fork is open */
+
+    if (!(attrbits & ATTRBIT_DOPEN)) {
+        off = AD_FILELOCK_OPEN_WR;
+        ret = testlock(&ad->ad_data_fork, off, 2) > 0 ? ATTRBIT_DOPEN : 0;
+    }
+
+    if (!(attrbits & ATTRBIT_ROPEN)) {
+        off = AD_FILELOCK_RSRC_OPEN_WR;
+        ret |= testlock(&ad->ad_data_fork, off, 2) > 0? ATTRBIT_ROPEN : 0;
+    }
+
+    return ret;
 }
index d9c364c63876202330f1688bfb8590de88d25fbd..4e6941c76555f8adf8a0b625d153b3f3383b8245 100644 (file)
@@ -693,22 +693,28 @@ static int ad_error(struct adouble *ad, int adflags)
     if (adflags & ADFLAGS_NOHF) { /* 1 */
         return 0;
     }
-    if (adflags & ADFLAGS_DF) { /* 2 */
+    if (adflags & (ADFLAGS_DF | ADFLAGS_SETSHRMD | ADFLAGS_CHECK_OF)) { /* 2 */
         ad_close( ad, ADFLAGS_DF );
         err = errno;
     }
     return -1 ;
 }
 
-/* Map ADFLAGS to open() flags */
-static int ad2openflags(int adflags)
+/*!
+ * Map ADFLAGS to open() flags
+ *
+ * @param adfile   (r) the file you really want to open: ADFLAGS_DF or ADFLAGS_HF
+ * @param adflags  (r) flags from ad_open(..., adflags, ...)
+ * @returns            mapped flags suitable for calling open()
+ */
+static int ad2openflags(int adfile, int adflags)
 {
     int oflags = 0;
 
     if (adflags & ADFLAGS_RDWR)
         oflags |= O_RDWR;
     if (adflags & ADFLAGS_RDONLY) {
-        if (adflags & ADFLAGS_SETSHRMD)
+        if ((adfile & ADFLAGS_DF) && (adflags & ADFLAGS_SETSHRMD))
             oflags |= O_RDWR;
         else
             oflags |= O_RDONLY;
@@ -725,14 +731,19 @@ static int ad2openflags(int adflags)
 
 static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble *ad)
 {
+    EC_INIT;
     struct stat st_dir;
     int         oflags;
     mode_t      admode;
     int         st_invalid = -1;
     ssize_t     lsz;
 
-    LOG(log_debug, logtype_default, "ad_open_df(\"%s\", %04o)",
-        fullpathname(path), mode);
+    LOG(log_debug, logtype_default,
+        "ad_open_df(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+        fullpathname(path), adflags2logstr(adflags),
+        ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+        ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+        ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
 
     if (ad_data_fileno(ad) != -1) {
         /* the file is already open, but we want write access: */
@@ -745,10 +756,10 @@ static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble
         /* it's not new anymore */
         ad->ad_data_fork.adf_flags &= ~( O_TRUNC | O_CREAT );
         ad->ad_data_fork.adf_refcount++;
-        return 0;
+        goto EC_CLEANUP;
     }
 
-    oflags = O_NOFOLLOW | ad2openflags(adflags);
+    oflags = O_NOFOLLOW | ad2openflags(ADFLAGS_DF, adflags);
 
     admode = mode;
     if ((adflags & ADFLAGS_CREATE)) {
@@ -767,8 +778,7 @@ static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble
             if ((adflags & ADFLAGS_SETSHRMD) && (adflags & ADFLAGS_RDONLY)) {
                 oflags &= ~O_RDWR;
                 oflags |= O_RDONLY;
-                if ((ad->ad_data_fork.adf_fd = open(path, oflags, admode)) == -1)
-                    return -1;
+                EC_NEG1( ad->ad_data_fork.adf_fd = open(path, oflags, admode) );
                 break;
             }
             return -1;
@@ -776,13 +786,13 @@ static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble
             ad->ad_data_fork.adf_syml = malloc(MAXPATHLEN+1);
             if ((lsz = readlink(path, ad->ad_data_fork.adf_syml, MAXPATHLEN)) <= 0) {
                 free(ad->ad_data_fork.adf_syml);
-                return -1;
+                EC_FAIL;
             }
             ad->ad_data_fork.adf_syml[lsz] = 0;
             ad->ad_data_fork.adf_fd = -2; /* -2 means its a symlink */
             break;
         default:
-            return -1;
+            EC_FAIL;
         }
     }
 
@@ -793,42 +803,56 @@ static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble
     adf_lock_init(&ad->ad_data_fork);
     ad->ad_data_fork.adf_refcount++;
 
-    return 0;
+EC_CLEANUP:
+    LOG(log_debug, logtype_default,
+        "ad_open_df(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+        fullpathname(path), adflags2logstr(adflags), ret,
+        ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+        ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+        ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
+    EC_EXIT;
 }
 
-/* TODO: error handling */
 static int ad_open_hf_v2(const char *path, int adflags, mode_t mode, struct adouble *ad)
 {
+    EC_INIT;
     struct stat st_dir;
     struct stat st_meta;
     struct stat *pst = NULL;
     const char  *ad_p;
-    int         oflags, nocreatflags;
+    int         oflags, nocreatflags, opened = 0;
     mode_t      admode;
     int         st_invalid = -1;
 
+    LOG(log_debug, logtype_default,
+        "ad_open_hf_v2(\"%s\", %s): BEGIN [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+        fullpathname(path), adflags2logstr(adflags),
+        ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+        ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+        ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
+
     if (ad_meta_fileno(ad) != -1) {
         /* the file is already open, but we want write access: */
         if ((adflags & ADFLAGS_RDWR) &&
             /* and it was already denied: */
             (ad->ad_mdp->adf_flags & O_RDONLY)) {
             errno = EACCES;
-            return -1;
+            EC_FAIL;
         }
         ad_refresh(path, ad);
         /* it's not new anymore */
         ad->ad_mdp->adf_flags &= ~( O_TRUNC | O_CREAT );
         ad->ad_mdp->adf_refcount++;
-        return 0;
+        goto EC_CLEANUP;
     }
 
     ad_p = ad->ad_ops->ad_path(path, adflags);
-    oflags = O_NOFOLLOW | ad2openflags(adflags);
+    oflags = O_NOFOLLOW | ad2openflags(ADFLAGS_HF, adflags);
     nocreatflags = oflags & ~(O_CREAT | O_EXCL);
 
-    ad->ad_mdp->adf_fd = open(ad_p, nocreatflags);
+    ad_meta_fileno(ad) = open(ad_p, nocreatflags);
 
-    if (ad->ad_mdp->adf_fd != -1) {
+    if (ad_meta_fileno(ad) != -1) {
         ad->ad_mdp->adf_flags = nocreatflags;
     } else {
         switch (errno) {
@@ -838,15 +862,14 @@ static int ad_open_hf_v2(const char *path, int adflags, mode_t mode, struct adou
             if ((adflags & ADFLAGS_RDONLY) && (adflags & ADFLAGS_SETSHRMD)) {
                 nocreatflags &= ~O_RDWR;
                 nocreatflags |= O_RDONLY;
-                if ((ad->ad_mdp->adf_fd = open(ad_p, nocreatflags)) == -1)
-                    return -1;
+                EC_NEG1( ad_meta_fileno(ad) = open(ad_p, nocreatflags) );
                 ad->ad_mdp->adf_flags = nocreatflags;
                 break;
             }
-            return -1;
+            EC_FAIL;
         case ENOENT:
             if (!(oflags & O_CREAT))
-                return ad_error(ad, adflags);
+                EC_FAIL;
             /*
              * We're expecting to create a new adouble header file here
              */
@@ -859,9 +882,7 @@ static int ad_open_hf_v2(const char *path, int adflags, mode_t mode, struct adou
                 admode = mode;
             admode = ad_hf_mode(admode);
             if (errno == ENOENT) {
-                if (ad->ad_ops->ad_mkrf( ad_p) < 0) {
-                    return ad_error(ad, adflags);
-                }
+                EC_NEG1_LOG( ad->ad_ops->ad_mkrf(ad_p) );
                 admode = mode;
                 st_invalid = ad_mode_st(ad_p, &admode, &st_dir);
                 if ((ad->ad_options & ADVOL_UNIXPRIV))
@@ -870,20 +891,20 @@ static int ad_open_hf_v2(const char *path, int adflags, mode_t mode, struct adou
             }
 
             /* retry with O_CREAT */
-            ad->ad_mdp->adf_fd = open(ad_p, oflags, admode);
-            if ( ad->ad_mdp->adf_fd < 0 )
-                return ad_error(ad, adflags);
-
+            EC_NEG1_LOG( ad_meta_fileno(ad) = open(ad_p, oflags, admode) );
             ad->ad_mdp->adf_flags = oflags;
             /* just created, set owner if admin owner (root) */
             if (!st_invalid)
                 ad_chown(ad_p, &st_dir);
             break;
         default:
-            return -1;
+            EC_FAIL;
         }
     }
 
+    /* Now we've got a new opened fd, we need to check that in the error case */
+    opened = 1;
+
     if (!(ad->ad_mdp->adf_flags & O_CREAT)) {
         /* check for 0 length files, treat them as new. */
         if (fstat(ad->ad_mdp->adf_fd, &st_meta) == 0) {
@@ -900,26 +921,26 @@ static int ad_open_hf_v2(const char *path, int adflags, mode_t mode, struct adou
 
     if ((ad->ad_mdp->adf_flags & ( O_TRUNC | O_CREAT ))) {
         /* This is a new adouble header file, create it */
-        if (new_ad_header(ad, path, pst, adflags) < 0) {
-            int err = errno;
-            /* the file is already deleted, perm, whatever, so return an error */
-            ad_close(ad, adflags);
-            errno = err;
-            return -1;
-        }
+        EC_NEG1_LOG( new_ad_header(ad, path, pst, adflags) );
         ad_flush(ad);
     } else {
         /* Read the adouble header in and parse it.*/
-        if (ad->ad_ops->ad_header_read(path, ad, pst) < 0
-            || ad->ad_ops->ad_header_upgrade(ad, ad_p) < 0) {
-            int err = errno;
-            ad_close(ad, adflags);
-            errno = err;
-            return -1;
-        }
+        EC_NEG1_LOG( ad->ad_ops->ad_header_read(path, ad, pst) );
     }
 
-    return 0;
+EC_CLEANUP:
+    if (ret != 0 && opened && ad_meta_fileno(ad) != -1) {
+        close(ad_meta_fileno(ad));
+        ad_meta_fileno(ad) = -1;
+        ad->ad_mdp->adf_refcount = 0;
+    }
+    LOG(log_debug, logtype_default,
+        "ad_open_hf_v2(\"%s\", %s): END: %d [dfd: %d (ref: %d), mfd: %d (ref: %d), rfd: %d (ref: %d)]",
+        fullpathname(path), adflags2logstr(adflags), ret,
+        ad_data_fileno(ad), ad->ad_data_fork.adf_refcount,
+        ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
+        ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
+    EC_EXIT;
 }
 
 static int ad_open_hf_ea(const char *path, int adflags, int mode, struct adouble *ad)
@@ -936,7 +957,7 @@ static int ad_open_hf_ea(const char *path, int adflags, int mode, struct adouble
         ad_meta_fileno(ad), ad->ad_mdp->adf_refcount,
         ad_reso_fileno(ad), ad->ad_rfp->adf_refcount);
 
-    oflags = O_NOFOLLOW | (ad2openflags(adflags) & ~(O_CREAT | O_TRUNC));
+    oflags = O_NOFOLLOW | (ad2openflags(ADFLAGS_DF, adflags) & ~(O_CREAT | O_TRUNC));
 
     if (ad_meta_fileno(ad) == -2)
         /* symlink */
@@ -1098,7 +1119,7 @@ static int ad_open_rf(const char *path, int adflags, int mode, struct adouble *a
 
     LOG(log_debug, logtype_default, "ad_open_rf(\"%s\"): BEGIN", fullpathname(path));
 
-    oflags = O_NOFOLLOW | (ad2openflags(adflags) & ~O_CREAT);
+    oflags = O_NOFOLLOW | (ad2openflags(ADFLAGS_HF, adflags) & ~O_CREAT);
 
     if (ad_reso_fileno(ad) != -1) {
         /* the file is already open, but we want write access: */
@@ -1185,6 +1206,24 @@ EC_CLEANUP:
  * API functions
  ********************************************************************************* */
 
+off_t ad_getentryoff(const struct adouble *ad, int eid)
+{
+    if (ad->ad_vers == AD_VERSION2)
+        return ad->ad_eid[ADEID_RFORK].ade_off;
+
+    if (eid == ADEID_DFORK) {
+        return 0;
+    } else if (eid == ADEID_RFORK) {
+#ifdef HAVE_EAFD
+        return 0;
+#else
+        return ADEDOFF_RFORK_OSX;
+#endif
+    } else {
+        return ad->ad_eid[eid].ade_off;
+    }
+}
+
 const char *ad_path_ea( const char *path, int adflags _U_)
 {
     return path;
@@ -1467,6 +1506,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 ((ad->ad_vers == AD_VERSION2) && (adflags & ADFLAGS_SETSHRMD)) {
+        /* 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_NORF)
index 57d64ba1ae5294e601c2b118bdaf7b6a93c0e46f..2d150cc40da96e7c456fe909ce37d98cc0596643 100644 (file)
@@ -295,8 +295,6 @@ static int RF_renamefile_adouble(VFS_FUNC_ARGS_RENAMEFILE)
 static int RF_copyfile_adouble(VFS_FUNC_ARGS_COPYFILE)
 /* const struct vol *vol, int sfd, const char *src, const char *dst */
 {
-    return 0;
-#if 0
     EC_INIT;
     bstring s = NULL, d = NULL;
     char *dup1 = NULL;
@@ -341,7 +339,10 @@ static int RF_copyfile_adouble(VFS_FUNC_ARGS_COPYFILE)
         EC_ZERO(bcatcstr(d, name));
     }
 
-    EC_ZERO(copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666));
+    /* ignore errors */
+    if (copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666) != 0)
+        if (errno != ENOENT)
+            EC_FAIL;
 
 EC_CLEANUP:
     bdestroy(s);
@@ -352,7 +353,6 @@ EC_CLEANUP:
     if (dup4) free(dup4);
 
     EC_EXIT;
-#endif
 }
 
 #ifdef HAVE_SOLARIS_ACLS
@@ -580,6 +580,7 @@ static int RF_deletefile_ea(VFS_FUNC_ARGS_DELETEFILE)
 }
 static int RF_copyfile_ea(VFS_FUNC_ARGS_COPYFILE)
 {
+    /* the EA VFS module does this all for us */
     return 0;
 #if 0
     EC_INIT;