]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/fork.c
1) try a better workaround for deadlocks when both the server and the client are...
[netatalk.git] / etc / afpd / fork.c
index 32008c1db55d02f16a899e7a4c224be9a82077f1..07ce3ab19f6e3a91ba69d4afef569cbf964df1a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.43 2003-01-12 14:40:01 didg Exp $
+ * $Id: fork.c,v 1.68 2009-10-25 06:12:51 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
 #endif /* HAVE_CONFIG_H */
 
 #include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
+
 #include <dirent.h>
 #include <string.h>
 #include <errno.h>
+
+#include <atalk/adouble.h>
 #include <atalk/logger.h>
 
 #include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/time.h>
 #include <sys/socket.h>
 
-#include <netatalk/endian.h>
 #include <netatalk/at.h>
 
 #include <atalk/dsi.h>
 #include <atalk/atp.h>
 #include <atalk/asp.h>
 #include <atalk/afp.h>
-#include <atalk/adouble.h>
+
 #include <atalk/util.h>
-#ifdef CNID_DB
 #include <atalk/cnid.h>
-#endif
 
 #include "fork.h"
 #include "file.h"
 #include "desktop.h"
 #include "volume.h"
 
-#define BYTELOCK_MAX 0x7FFFFFFFU
-#define BYTELOCK_MAXL 0x7FFFFFFFFFFFFFFFULL
-
-struct ofork           *writtenfork;
-extern int getmetadata(struct vol *vol,
-                 u_int16_t bitmap,
-                 char *path, struct dir *dir, struct stat *st,
-                 char *buf, int *buflen, struct adouble *adp, int attrbits );
-
-static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
-struct ofork   *ofork;
-u_int16_t              bitmap;
-char           *buf;
-int                    *buflen;
-const u_int16_t     attrbits;
+#ifdef DEBUG1
+#define Debug(a) ((a)->options.flags & OPTION_DEBUG)
+#else
+#define Debug(a) (0)
+#endif
+
+#ifdef AFS
+struct ofork *writtenfork;
+#endif
+
+static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_t *buflen)
 {
-    struct stat                st;
-    char               *upath;
+    struct path         path;
+    struct stat                *st;
 
     struct adouble     *adp;
     struct dir         *dir;
@@ -80,7 +67,7 @@ const u_int16_t     attrbits;
         return( AFPERR_BITMAP );
     }
 
-    if ( ad_hfileno( ofork->of_ad ) == -1 ) {
+    if ( ad_reso_fileno( ofork->of_ad ) == -1 ) { /* META ? */
         adp = NULL;
     } else {
         adp = ofork->of_ad;
@@ -89,64 +76,113 @@ const u_int16_t     attrbits;
     vol = ofork->of_vol;
     dir = ofork->of_dir;
 
+    if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding()))) {
+        return( AFPERR_MISC );
+    }
+    path.m_name = of_name(ofork);
+    st = &path.st;
     if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) | 
                     (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) | 
                     (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
-        if ( ad_dfileno( ofork->of_ad ) == -1 ) {
-            upath = mtoupath(vol, ofork->of_name);
+        if ( ad_data_fileno( ofork->of_ad ) == -1 ) {
             if (movecwd(vol, dir) < 0)
                 return( AFPERR_NOOBJ );
-            if ( stat( upath, &st ) < 0 )
+            if ( stat( path.u_name, st ) < 0 )
                 return( AFPERR_NOOBJ );
         } else {
-            if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
+            if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) {
                 return( AFPERR_BITMAP );
             }
         }
     }
-    return getmetadata(vol, bitmap, ofork->of_name, dir, &st, buf, buflen, adp, attrbits );    
+    return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp );
 }
 
-/* -------------------------
+/* ---------------------------- */
+static off_t get_off_t(char **ibuf, int is64)
+{
+    u_int32_t             temp;
+    off_t                 ret;
+
+    ret = 0;
+    memcpy(&temp, *ibuf, sizeof( temp ));
+    ret = ntohl(temp); /* ntohl is unsigned */
+    *ibuf += sizeof(temp);
+
+    if (is64) {
+        memcpy(&temp, *ibuf, sizeof( temp ));
+        *ibuf += sizeof(temp);
+        ret = ntohl(temp)| (ret << 32);
+    }
+    else {
+       ret = (int)ret; /* sign extend */
+    }
+    return ret;
+}
+
+/* ---------------------- */
+static int set_off_t(off_t offset, char *rbuf, int is64)
+{
+    u_int32_t  temp;
+    int        ret;
+
+    ret = 0;
+    if (is64) {
+        temp = htonl(offset >> 32);
+        memcpy(rbuf, &temp, sizeof( temp ));
+        rbuf += sizeof(temp);
+        ret = sizeof( temp );
+        offset &= 0xffffffff;
+    }
+    temp = htonl(offset);
+    memcpy(rbuf, &temp, sizeof( temp ));
+    ret += sizeof( temp );
+
+    return ret;
+}
+
+/* ------------------------ 
 */
-#define SHARE 0
-#define EXCL  1
-static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what, int mode)
+static int is_neg(int is64, off_t val)
 {
-    int lockmode;
-    int lockop;
-    
-    /* NOTE: we can't write lock a read-only file. on those, we just
-     * make sure that we have a read lock set. that way, we at least prevent
-     * someone else from really setting a deny read/write on the file. 
-     */
-    lockmode = (ad_getoflags(adp, eid) & O_RDWR) ?ADLOCK_WR : ADLOCK_RD;
-    lockop = (mode == EXCL)?lockmode:ADLOCK_RD;
-    
-    return ad_lock(adp, eid, lockop | ADLOCK_FILELOCK | ADLOCK_UPGRADE,
-                        what, 1, ofrefnum);
+    if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
+       return 1;
+    return 0;
+}
+
+static int sum_neg(int is64, off_t offset, off_t reqcount) 
+{
+    if (is_neg(is64, offset +reqcount) ) 
+       return 1;
+    return 0;
 }
 
 /* -------------------------
 */
-extern int ad_testlock(struct adouble *adp, int eid, int off);
+static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what)
+{
+    return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
+}
 
-static int getforkmode(struct adouble *adp, int eid, int what)
+/* -------------------------
+*/
+int getforkmode(struct adouble *adp, int eid, int what)
 {
     return ad_testlock(adp, eid,  what);
 }
 
-static int afp_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
+/* -------------------------
+*/
+static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
 {
     int ret;
     int readset;
     int writeset;
     int denyreadset;
     int denywriteset;
-    int mode;    
 
     if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
-        return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE, SHARE);
+        return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
     }
 
     if ((access & (OPENACC_RD | OPENACC_DRD))) {
@@ -166,14 +202,13 @@ static int afp_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
         /* boolean logic is not enough, because getforkmode is not always telling the
          * true 
          */
-        mode = ((access & OPENACC_DRD))?EXCL: SHARE;
         if ((access & OPENACC_RD)) {
-            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD, mode);
+            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
             if (ret)
                 return ret;
         }
         if ((access & OPENACC_DRD)) {
-            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD, SHARE);
+            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
             if (ret)
                 return ret;
         }
@@ -193,34 +228,34 @@ static int afp_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
             errno = EACCES;
             return -1;
         }   
-        mode = ((access & OPENACC_DWR))?EXCL: SHARE;
         if ((access & OPENACC_WR)) {
-            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR, mode);
+            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
             if (ret)
                 return ret;
         }
         if ((access & OPENACC_DWR)) {
-            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR, SHARE);
+            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
             if (ret)
                 return ret;
         }
     }
+    if ( access == (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD)) {
+        return ad_excl_lock(adp, eid);
+    }
     return 0;
 }
 
 /* ----------------------- */
-int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
     struct vol         *vol;
     struct dir         *dir;
     struct ofork       *ofork, *opened;
     struct adouble      *adsame = NULL;
-    int                        buflen, ret, adflags, eid, lockop;
+    size_t             buflen;
+    int                        ret, adflags, eid;
     u_int32_t           did;
-    u_int16_t          vid, bitmap, access, ofrefnum, attrbits = 0;
+    u_int16_t          vid, bitmap, access, ofrefnum;
     char               fork, *path, *upath;
     struct stat         *st;
     u_int16_t           bshort;
@@ -255,7 +290,7 @@ int         ibuflen, *rbuflen;
     }
 
     if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
-       return afp_errno;    
+       return get_afp_errno(AFPERR_PARAM);    
     }
 
     if (*s_path->m_name == '\0') {
@@ -272,13 +307,20 @@ int               ibuflen, *rbuflen;
     case EACCES:
         return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
     default:
-        LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
+        LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
         return AFPERR_PARAM;
     }
     /* FIXME should we check it first ? */
     upath = s_path->u_name;
-    if (check_access(upath, access ) < 0) {
-        return AFPERR_ACCESS;
+    if (!vol_unix_priv(vol)) {
+        if (check_access(upath, access ) < 0) {
+            return AFPERR_ACCESS;
+        }
+    }
+    else {
+        if (file_access(s_path, access ) < 0) {
+            return AFPERR_ACCESS;
+        }
     }
 
     st   = &s_path->st;
@@ -290,9 +332,6 @@ int         ibuflen, *rbuflen;
        FIXME: add the fork we are opening? 
     */
     if ((opened = of_findname(s_path))) {
-        attrbits = ((opened->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
-        attrbits |= ((opened->of_ad->ad_hf.adf_refcount > opened->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
-                   
         adsame = opened->of_ad;
     }
 
@@ -333,6 +372,7 @@ int         ibuflen, *rbuflen;
                     * fork if the user wants to open it for write acess. */
                     if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
                         goto openfork_err;
+                    ofork->of_flags |= AFPFORK_OPEN;
                 }
                 break;
             case EMFILE :
@@ -345,14 +385,16 @@ int               ibuflen, *rbuflen;
                 goto openfork_err;
                 break;
             default:
-                LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
+                LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
                 ret = AFPERR_PARAM;
                 goto openfork_err;
                 break;
             }
         }
-        /* the fork is open */
-        ofork->of_flags |= AFPFORK_OPEN;
+        else {
+            /* the ressource fork is open too */
+            ofork->of_flags |= AFPFORK_OPEN;
+        }
     } else {
         /* try opening in read-only mode */
         ret = AFPERR_NOOBJ;
@@ -370,11 +412,14 @@ int               ibuflen, *rbuflen;
                         goto openfork_err;
                     }
                     adflags = ADFLAGS_DF;
-                    ofork->of_flags |= AFPFORK_OPEN;
                 }
                 /* else we don't set AFPFORK_OPEN because there's no ressource fork file 
                  * We need to check AFPFORK_OPEN in afp_closefork(). eg fork open read-only
                  * then create in open read-write.
+                 * FIXME , it doesn't play well with byte locking example:
+                 * ressource fork open read only
+                 * locking set on it (no effect, there's no file!)
+                 * ressource fork open read write now
                 */
                 break;
             case EMFILE :
@@ -387,27 +432,25 @@ int               ibuflen, *rbuflen;
                 goto openfork_err;
                 break;
             default:
-                LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
+                LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
                 goto openfork_err;
                 break;
             }
         }
         else {
-            /* the fork is open */
+            /* the ressource fork is open too */
             ofork->of_flags |= AFPFORK_OPEN;
         }
     }
 
-    if ((adflags & ADFLAGS_HF) &&
-            (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
-        ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
-        memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
-               ad_getentrylen( ofork->of_ad, ADEID_NAME ));
-        ad_flush( ofork->of_ad, adflags );
+    if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
+        if (ad_setname(ofork->of_ad, path)) {
+            ad_flush( ofork->of_ad );
+        }
     }
 
     if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
-                              &buflen, attrbits )) != AFP_OK ) {
+                              &buflen )) != AFP_OK ) {
         ad_close( ofork->of_ad, adflags );
         goto openfork_err;
     }
@@ -420,7 +463,7 @@ int         ibuflen, *rbuflen;
     /* check  WriteInhibit bit if we have a ressource fork
      * the test is done here, after some Mac trafic capture 
      */
-    if (ad_hfileno(ofork->of_ad) != -1) {
+    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 );
@@ -436,9 +479,9 @@ int         ibuflen, *rbuflen;
      */
 
     /* don't try to lock non-existent rforks. */
-    if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
+    if ((eid == ADEID_DFORK) || (ad_meta_fileno(ofork->of_ad) != -1)) { /* META */
 
-        ret = afp_setmode(ofork->of_ad, eid, access, ofrefnum);
+        ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
         /* can we access the fork? */
         if (ret < 0) {
             ret = errno;
@@ -454,7 +497,7 @@ int         ibuflen, *rbuflen;
                 break;
             default:
                 *rbuflen = 0;
-                LOG(log_error, logtype_afpd, "afp_openfork: ad_lock: %s", strerror(errno) );
+                LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_lock: %s", s_path->m_name, strerror(ret) );
                 return( AFPERR_PARAM );
             }
         }
@@ -475,28 +518,28 @@ openfork_err:
     return ret;
 }
 
-int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int afp_setforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen)
 {
     struct ofork       *ofork;
-    int32_t            size;
+    off_t              size;
     u_int16_t          ofrefnum, bitmap;
     int                 err;
-
+    int                 is64;
+    int                 eid;
+    off_t              st_size;
+    
     ibuf += 2;
+
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
     ibuf += sizeof( ofrefnum );
+
     memcpy(&bitmap, ibuf, sizeof(bitmap));
     bitmap = ntohs(bitmap);
     ibuf += sizeof( bitmap );
-    memcpy(&size, ibuf, sizeof( size ));
-    size = ntohl( size );
 
     *rbuflen = 0;
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
-        LOG(log_error, logtype_afpd, "afp_setforkparams: of_find could not locate open fork refnum: %u", ofrefnum );
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
+        LOG(log_error, logtype_afpd, "afp_setforkparams: of_find(%d) could not locate fork", ofrefnum );
         return( AFPERR_PARAM );
     }
 
@@ -506,31 +549,76 @@ int               ibuflen, *rbuflen;
     if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
         return AFPERR_ACCESS;
 
-    if (size < 0)
+    if ( ofork->of_flags & AFPFORK_DATA) {
+        eid = ADEID_DFORK;
+    } else if (ofork->of_flags & AFPFORK_RSRC) {
+        eid = ADEID_RFORK;
+    } else
         return AFPERR_PARAM;
 
-    if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
+    if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) )) 
+                  && eid == ADEID_RFORK 
+         ) ||
+         ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) )) 
+                  && eid == ADEID_DFORK)) {
+        return AFPERR_BITMAP;
+    }
+    
+    is64 = 0;
+    if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
+        if (afp_version >= 30) {
+            is64 = 4;
+        }
+        else 
+           return AFPERR_BITMAP;
+    }
+
+    if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
+        return AFPERR_PARAM ;
+    
+    size = get_off_t(&ibuf, is64);
+
+    if (size < 0)
+        return AFPERR_PARAM; /* Some MacOS don't return an error they just don't change the size! */
+
+
+    if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
+       st_size = ad_size(ofork->of_ad, eid);
+       err = -2;
+       if (st_size > size && 
+             ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) 
+            goto afp_setfork_err;
+
         err = ad_dtruncate( ofork->of_ad, size );
+        if (st_size > size)
+           ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);  
         if (err < 0)
             goto afp_setfork_err;
-    } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
-               (ofork->of_flags & AFPFORK_RSRC)) {
+    } else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
         ad_refresh( ofork->of_ad );
+
+       st_size = ad_size(ofork->of_ad, eid);
+       err = -2;
+       if (st_size > size && 
+              ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
+            goto afp_setfork_err;
+       }
         err = ad_rtruncate(ofork->of_ad, size);
+        if (st_size > size)
+           ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);  
         if (err < 0)
             goto afp_setfork_err;
 
-        if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
-            LOG(log_error, logtype_afpd, "afp_setforkparams: ad_flush: %s",
-                strerror(errno) );
-            return( AFPERR_PARAM );
+        if (ad_flush( ofork->of_ad ) < 0) {
+            LOG(log_error, logtype_afpd, "afp_setforkparams(%s): ad_flush: %s", of_name(ofork), strerror(errno) );
+            return AFPERR_PARAM;
         }
     } else
         return AFPERR_BITMAP;
 
 #ifdef AFS
     if ( flushfork( ofork ) < 0 ) {
-        LOG(log_error, logtype_afpd, "afp_setforkparams: flushfork: %s", strerror(errno) );
+        LOG(log_error, logtype_afpd, "afp_setforkparams(%s): flushfork: %s", of_name(ofork), strerror(errno) );
     }
 #endif /* AFS */
 
@@ -565,62 +653,17 @@ afp_setfork_err:
 #define ENDBIT(a)  ((a) & 0x80)
 #define UNLOCKBIT(a) ((a) & 0x01)
 
-static off_t get_off_t(ibuf, is64)
-char   **ibuf;
-int     is64;
-{
-    u_int32_t             temp;
-    off_t                 ret;
-
-    memcpy(&temp, *ibuf, sizeof( temp ));
-    ret = ntohl(temp); /* ntohl is unsigned */
-    *ibuf += sizeof(temp);
-
-    if (is64) {
-        memcpy(&temp, *ibuf, sizeof( temp ));
-        *ibuf += sizeof(temp);
-        ret = ntohl(temp)| (ret << 32);
-    }
-    return ret;
-}
-
-/* ---------------------- */
-static int set_off_t(offset, rbuf, is64)
-off_t   offset;
-char   *rbuf;
-int     is64;
-{
-    u_int32_t  temp;
-    int        ret;
-
-    ret = 0;
-    if (is64) {
-        temp = htonl(offset >> 32);
-        memcpy(rbuf, &temp, sizeof( temp ));
-        rbuf += sizeof(temp);
-        ret = sizeof( temp );
-        offset &= 0xffffffff;
-    }
-    temp = htonl(offset);
-    memcpy(rbuf, &temp, sizeof( temp ));
-    ret += sizeof( temp );
-
-    return ret;
-}
 
 /* ---------------------- */
-static int byte_lock(obj, ibuf, ibuflen, rbuf, rbuflen, is64 )
-AFPObj  *obj;
-char   *ibuf, *rbuf;
-int    ibuflen, *rbuflen;
-int     is64;
+static int byte_lock(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
 {
     struct ofork       *ofork;
     off_t               offset, length;
     int                 eid;
     u_int16_t          ofrefnum;
     u_int8_t            flags;
-
+    int                 lockop;
+    
     *rbuflen = 0;
 
     /* figure out parameters */
@@ -630,8 +673,8 @@ int     is64;
     memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
     ibuf += sizeof(ofrefnum);
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
-        LOG(log_error, logtype_afpd, "afp_bytelock: of_find");
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
+        LOG(log_error, logtype_afpd, "afp_bytelock: of_find(%d) could not locate fork", ofrefnum );
         return( AFPERR_PARAM );
     }
 
@@ -645,39 +688,29 @@ int     is64;
     offset = get_off_t(&ibuf, is64);
     length = get_off_t(&ibuf, is64);
 
-    if (is64) {
-        if (length == -1)
-            length = BYTELOCK_MAXL;
-        else if (length <= 0) {
-            return AFPERR_PARAM;
-        } else if ((length >= AD_FILELOCK_BASE) &&
-                   (ad_hfileno(ofork->of_ad) == -1)) {
-            return AFPERR_LOCK;
-        }
-    }
-    else {
-        if (length == 0xFFFFFFFF)
-            length = BYTELOCK_MAX;
-        else if (!length || (length & (1 << 31))) {
-            return AFPERR_PARAM;
-        } else if ((length >= AD_FILELOCK_BASE) &&
-                   (ad_hfileno(ofork->of_ad) == -1)) {
-            return AFPERR_LOCK;
-        }
+    /* FIXME AD_FILELOCK test is surely wrong */
+    if (length == -1)
+        length = BYTELOCK_MAX;
+     else if (!length || is_neg(is64, length)) {
+       return AFPERR_PARAM;
+     } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/
+        return AFPERR_LOCK;
     }
-    
-    if (ENDBIT(flags))
-        offset += ad_size(ofork->of_ad, eid);
 
+    if (ENDBIT(flags)) {
+        offset += ad_size(ofork->of_ad, eid);
+        /* FIXME what do we do if file size > 2 GB and 
+           it's not byte_lock_ext?
+        */
+    }
     if (offset < 0)    /* error if we have a negative offset */
         return AFPERR_PARAM;
 
     /* if the file is a read-only file, we use read locks instead of
      * write locks. that way, we can prevent anyone from initiating
      * a write lock. */
-    if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
-                ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
-                 ADLOCK_WR : ADLOCK_RD), offset, length,
+    lockop = UNLOCKBIT(flags) ? ADLOCK_CLR : ADLOCK_WR;
+    if (ad_lock(ofork->of_ad, eid, lockop, offset, length,
                 ofork->of_refnum) < 0) {
         switch (errno) {
         case EACCES:
@@ -701,19 +734,13 @@ int     is64;
 }
 
 /* --------------------------- */
-int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj;
-char   *ibuf, *rbuf;
-int    ibuflen, *rbuflen;
+int afp_bytelock(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
    return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
 }
 
 /* --------------------------- */
-int afp_bytelock_ext(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj;
-char   *ibuf, *rbuf;
-int    ibuflen, *rbuflen;
+int afp_bytelock_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
    return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
 }
@@ -721,35 +748,29 @@ int       ibuflen, *rbuflen;
 #undef UNLOCKBIT
 
 /* --------------------------- */
-static __inline__ int crlf( of )
-struct ofork   *of;
+static int crlf(struct ofork *of)
 {
     struct extmap      *em;
 
-    if ( ad_hfileno( of->of_ad ) == -1 ||
-            memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
-                    8) == 0 ) {
-        if (( em = getextmap( of->of_name )) == NULL ||
-                memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
-            return( 1 );
-        } else {
-            return( 0 );
-        }
-    } else {
-        if ( memcmp( ufinderi,
-                     ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
-            return( 1 );
-        } else {
-            return( 0 );
-        }
+    if ( ad_meta_fileno( of->of_ad ) == -1 || !memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI),8)) { /* META */
+        /* no resource fork or no finderinfo, use our files extension mapping */
+        if (!( em = getextmap( of_name(of) )) || memcmp( "TEXT", em->em_type, sizeof( em->em_type ))) {
+            return 0;
+        } 
+        /* file type is TEXT */
+        return 1;
+
+    } else if ( !memcmp( "TEXT", ad_entry( of->of_ad, ADEID_FINDERI ), 4 )) {
+        return 1;
     }
+    return 0;
 }
 
 
-static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
-                                    int offset, u_char nlmask,
+static ssize_t read_file(struct ofork *ofork, int eid,
+                                    off_t offset, u_char nlmask,
                                     u_char nlchar, char *rbuf,
-                                    int *rbuflen, const int xlate)
+                                    size_t *rbuflen, const int xlate)
 {
     ssize_t cc;
     int eof = 0;
@@ -757,11 +778,11 @@ static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
 
     cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
     if ( cc < 0 ) {
-        LOG(log_error, logtype_afpd, "afp_read: ad_read: %s", strerror(errno) );
+        LOG(log_error, logtype_afpd, "afp_read(%s): ad_read: %s", of_name(ofork), strerror(errno) );
         *rbuflen = 0;
         return( AFPERR_PARAM );
     }
-    if ( cc < *rbuflen ) {
+    if ( (size_t)cc < *rbuflen ) {
         eof = 1;
     }
 
@@ -814,16 +835,12 @@ static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
  *
  * with dsi, should we check that reqcount < server quantum? 
 */
-static int read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
-int is64;
+static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
 {
     struct ofork       *ofork;
-    off_t              size;
     off_t              offset, saveoff, reqcount, savereqcount;
-    int                        cc, err, eid, xlate = 0;
+    ssize_t            cc, err;
+    int                        eid, xlate = 0;
     u_int16_t          ofrefnum;
     u_char             nlmask, nlchar;
     
@@ -832,7 +849,7 @@ int is64;
     ibuf += sizeof( u_short );
 
     if (NULL == ( ofork = of_find( ofrefnum )) ) {
-        LOG(log_error, logtype_afpd, "afp_read: of_find");
+        LOG(log_error, logtype_afpd, "afp_read: of_find(%d) could not locate fork", ofrefnum );
         err = AFPERR_PARAM;
         goto afp_read_err;
     }
@@ -875,38 +892,28 @@ int is64;
         goto afp_read_err;
     }
 
-    /* reqcount isn't always truthful. we need to deal with that. */
-    size = ad_size(ofork->of_ad, eid);
-
-    if (offset >= size) {
-        err = AFPERR_EOF;
-        goto afp_read_err;
-    }
-
     savereqcount = reqcount;
     saveoff = offset;
-    if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount) < 0) {
+    if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
         err = AFPERR_LOCK;
         goto afp_read_err;
     }
 
 #define min(a,b)       ((a)<(b)?(a):(b))
     *rbuflen = min( reqcount, *rbuflen );
-    err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
-                    xlate);
+    err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, xlate);
     if (err < 0)
         goto afp_read_done;
 
     /* dsi can stream requests. we can only do this if we're not checking
      * for an end-of-line character. oh well. */
     if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
-        DSI *dsi = obj->handle;
+        DSI    *dsi = obj->handle;
+        off_t  size;
+
+        /* reqcount isn't always truthful. we need to deal with that. */
+        size = ad_size(ofork->of_ad, eid);
 
-        if (obj->options.flags & OPTION_DEBUG) {
-            printf( "(read) reply: %d/%d, %d\n", *rbuflen,
-                    (int) reqcount, dsi->clientID);
-            bprint(rbuf, *rbuflen);
-        }
         /* subtract off the offset */
         size -= offset;
         if (reqcount > size) {
@@ -919,19 +926,19 @@ int is64;
         /* dsi_readinit() returns size of next read buffer. by this point,
          * we know that we're sending some data. if we fail, something
          * horrible happened. */
-        if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
+        if ((cc = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
             goto afp_read_exit;
-
+        *rbuflen = cc;
         /* due to the nature of afp packets, we have to exit if we get
            an error. we can't do this with translation on. */
-#ifdef HAVE_SENDFILE_READ
-        if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
-            if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
-                            dsi->datasize) < 0) {
-                if (errno == EINVAL)
+#if 0 /* ifdef WITH_SENDFILE */
+        /* FIXME with OS X deadlock partial workaround we can't use sendfile */
+        if (!(xlate || Debug(obj) )) {
+            if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize) < 0) {
+                if (errno == EINVAL || errno == ENOSYS)
                     goto afp_read_loop;
                 else {
-                    LOG(log_error, logtype_afpd, "afp_read: ad_readfile: %s", strerror(errno));
+                    LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s", of_name(ofork), strerror(errno));
                     goto afp_read_exit;
                 }
             }
@@ -941,21 +948,21 @@ int is64;
         }
 
 afp_read_loop:
-#endif /* HAVE_SENDFILE_READ */
+#endif 
 
         /* fill up our buffer. */
         while (*rbuflen > 0) {
-            cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
-                           rbuflen, xlate);
+            cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,rbuflen, xlate);
             if (cc < 0)
                 goto afp_read_exit;
 
             offset += *rbuflen;
+#ifdef DEBUG1
             if (obj->options.flags & OPTION_DEBUG) {
                 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
                 bprint(rbuf, *rbuflen);
             }
-
+#endif
             /* dsi_read() also returns buffer size of next allocation */
             cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
             if (cc < 0)
@@ -966,14 +973,14 @@ afp_read_loop:
         goto afp_read_done;
 
 afp_read_exit:
-        LOG(log_error, logtype_afpd, "afp_read: %s", strerror(errno));
+        LOG(log_error, logtype_afpd, "afp_read(%s): %s", of_name(ofork), strerror(errno));
         dsi_readdone(dsi);
-        ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
-        obj->exit(1);
+        ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
+        obj->exit(EXITERR_CLNT);
     }
 
 afp_read_done:
-    ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
+    ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
     return err;
 
 afp_read_err:
@@ -982,28 +989,19 @@ afp_read_err:
 }
 
 /* ---------------------- */
-int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
-AFPObj  *obj;
-char   *ibuf, *rbuf;
-int    ibuflen, *rbuflen;
+int afp_read(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
 }
 
 /* ---------------------- */
-int afp_read_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
-AFPObj  *obj;
-char   *ibuf, *rbuf;
-int    ibuflen, *rbuflen;
+int afp_read_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
 }
 
 /* ---------------------- */
-int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int afp_flush(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
     struct vol *vol;
     u_int16_t vid;
@@ -1020,10 +1018,7 @@ int              ibuflen, *rbuflen;
     return( AFP_OK );
 }
 
-int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int afp_flushfork(AFPObj *obj _U_, char        *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
     struct ofork       *ofork;
     u_int16_t          ofrefnum;
@@ -1032,35 +1027,64 @@ int             ibuflen, *rbuflen;
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
-        LOG(log_error, logtype_afpd, "afp_flushfork: of_find");
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
+        LOG(log_error, logtype_afpd, "afp_flushfork: of_find(%d) could not locate fork", ofrefnum );
         return( AFPERR_PARAM );
     }
 
     if ( flushfork( ofork ) < 0 ) {
-        LOG(log_error, logtype_afpd, "afp_flushfork: %s", strerror(errno) );
+        LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", of_name(ofork), strerror(errno) );
+    }
+
+    return( AFP_OK );
+}
+
+/*
+  FIXME
+  There is a lot to tell about fsync, fdatasync, F_FULLFSYNC.
+  fsync(2) on OSX is implemented differently than on other platforms.
+  see: http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf.
+ */
+int afp_syncfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
+{
+    struct ofork        *ofork;
+    u_int16_t           ofrefnum;
+
+    *rbuflen = 0;
+    ibuf += 2;
+
+    memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
+    ibuf += sizeof( ofrefnum );
+
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
+        LOG(log_error, logtype_afpd, "afpd_syncfork: of_find(%d) could not locate fork", ofrefnum );
+        return( AFPERR_PARAM );
+    }
+
+    if ( flushfork( ofork ) < 0 ) {
+       LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) );
+       return AFPERR_MISC;
     }
 
     return( AFP_OK );
 }
 
 /* this is very similar to closefork */
-int flushfork( ofork )
-struct ofork   *ofork;
+int flushfork(struct ofork *ofork)
 {
     struct timeval tv;
 
     int err = 0, doflush = 0;
 
-    if ( ad_dfileno( ofork->of_ad ) != -1 &&
-            fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
-        LOG(log_error, logtype_afpd, "flushfork: dfile(%d) %s",
-            ad_dfileno(ofork->of_ad), strerror(errno) );
+    if ( ad_data_fileno( ofork->of_ad ) != -1 &&
+            fsync( ad_data_fileno( ofork->of_ad )) < 0 ) {
+        LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s",
+            of_name(ofork), ad_data_fileno(ofork->of_ad), strerror(errno) );
         err = -1;
     }
 
-    if ( ad_hfileno( ofork->of_ad ) != -1 && 
-           (ofork->of_flags & AFPFORK_RSRC)) {
+    if ( ad_reso_fileno( ofork->of_ad ) != -1 &&  /* HF */
+        (ofork->of_flags & AFPFORK_RSRC)) {
 
         /* read in the rfork length */
         ad_refresh(ofork->of_ad);
@@ -1073,73 +1097,43 @@ struct ofork    *ofork;
         }
 
         /* flush the header */
-        if (doflush && ad_flush(ofork->of_ad, ADFLAGS_HF) < 0)
+        if (doflush && ad_flush(ofork->of_ad) < 0)
                 err = -1;
 
-        if (fsync( ad_hfileno( ofork->of_ad )) < 0)
+        if (fsync( ad_reso_fileno( ofork->of_ad )) < 0)
             err = -1;
 
         if (err < 0)
-            LOG(log_error, logtype_afpd, "flushfork: hfile(%d) %s",
-                ad_hfileno(ofork->of_ad), strerror(errno) );
+            LOG(log_error, logtype_afpd, "flushfork(%s): hfile(%d) %s",
+                of_name(ofork), ad_reso_fileno(ofork->of_ad), strerror(errno) );
     }
 
     return( err );
 }
 
-int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
     struct ofork       *ofork;
-    struct timeval      tv;
-    int                        adflags, doflush = 0;
     u_int16_t          ofrefnum;
 
     *rbuflen = 0;
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
-        LOG(log_error, logtype_afpd, "afp_closefork: of_find");
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
+        LOG(log_error, logtype_afpd, "afp_closefork: of_find(%d) could not locate fork", ofrefnum );
         return( AFPERR_PARAM );
     }
-
-    adflags = 0;
-    if ((ofork->of_flags & AFPFORK_OPEN)) {
-        if ((ofork->of_flags & AFPFORK_DATA) && (ad_dfileno( ofork->of_ad ) != -1)) {
-            adflags |= ADFLAGS_DF;
-        }
-        if ( ad_hfileno( ofork->of_ad ) != -1 ) {
-            adflags |= ADFLAGS_HF;
-            /*
-             * Only set the rfork's length if we're closing the rfork.
-             */
-            if ((ofork->of_flags & AFPFORK_RSRC)) {
-                ad_refresh( ofork->of_ad );
-                if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
-                    ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,tv.tv_sec);
-                   doflush++;
-                }
-                if ( doflush ) {
-                    ad_flush( ofork->of_ad, adflags );
-                }
-            }
-        }
-
-        if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
-            LOG(log_error, logtype_afpd, "afp_closefork: ad_close: %s", strerror(errno) );
-            return( AFPERR_PARAM );
-        }
+    if ( of_closefork( ofork ) < 0 ) {
+        LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) );
+        return( AFPERR_PARAM );
     }
 
-    of_dealloc( ofork );
     return( AFP_OK );
 }
 
 
-static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
+static ssize_t write_file(struct ofork *ofork, int eid,
                                      off_t offset, char *rbuf,
                                      size_t rbuflen, const int xlate)
 {
@@ -1167,7 +1161,7 @@ static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
         case ENOSPC :
             return( AFPERR_DFULL );
         default :
-            LOG(log_error, logtype_afpd, "afp_write: ad_write: %s", strerror(errno) );
+            LOG(log_error, logtype_afpd, "afp_write(%s): ad_write: %s", of_name(ofork), strerror(errno) );
             return( AFPERR_PARAM );
         }
     }
@@ -1175,14 +1169,11 @@ static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
     return cc;
 }
 
+
 /* FPWrite. NOTE: on an error, we always use afp_write_err as
  * the client may have sent us a bunch of data that's not reflected 
  * in reqcount et al. */
-static int write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
-AFPObj              *obj;
-char                *ibuf, *rbuf;
-int                 ibuflen, *rbuflen;
-int                 is64;
+static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
 {
     struct ofork       *ofork;
     off_t              offset, saveoff, reqcount;
@@ -1200,8 +1191,8 @@ int                 is64;
     offset   = get_off_t(&ibuf, is64);
     reqcount = get_off_t(&ibuf, is64);
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
-        LOG(log_error, logtype_afpd, "afp_write: of_find");
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
+        LOG(log_error, logtype_afpd, "afp_write: of_find(%d) could not locate fork", ofrefnum );
         err = AFPERR_PARAM;
         goto afp_write_err;
     }
@@ -1236,7 +1227,7 @@ int                 is64;
 
     /* offset can overflow on 64-bit capable filesystems.
      * report disk full if that's going to happen. */
-    if (offset + reqcount < 0) {
+     if (sum_neg(is64, offset, reqcount)) {
         err = AFPERR_DFULL;
         goto afp_write_err;
     }
@@ -1249,7 +1240,7 @@ int                 is64;
 
     saveoff = offset;
     if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
-                   reqcount) < 0) {
+                   reqcount, ofork->of_refnum) < 0) {
         err = AFPERR_LOCK;
         goto afp_write_err;
     }
@@ -1264,15 +1255,16 @@ int                 is64;
             return( AFPERR_PARAM );
         }
 
+#ifdef DEBUG1
         if (obj->options.flags & OPTION_DEBUG) {
             printf("(write) len: %d\n", *rbuflen);
             bprint(rbuf, *rbuflen);
         }
-
+#endif
         if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
                              xlate)) < 0) {
             *rbuflen = 0;
-            ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
+            ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
             return cc;
         }
         offset += cc;
@@ -1285,11 +1277,10 @@ int                 is64;
 
             /* find out what we have already and write it out. */
             cc = dsi_writeinit(dsi, rbuf, *rbuflen);
-            if (!cc ||
-                    (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
+            if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
                 dsi_writeflush(dsi);
                 *rbuflen = 0;
-                ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
+                ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
                 return cc;
             }
             offset += cc;
@@ -1311,7 +1302,7 @@ int                 is64;
                     dsi_writeflush(dsi);
                     *rbuflen = 0;
                     ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
-                               reqcount);
+                               reqcount,  ofork->of_refnum);
                     return cc;
                 }
 
@@ -1323,16 +1314,11 @@ int                 is64;
             /* loop until everything gets written. currently
                     * dsi_write handles the end case by itself. */
             while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
-                if ( obj->options.flags & OPTION_DEBUG ) {
-                    printf("(write) command cont'd: %d\n", cc);
-                    bprint(rbuf, cc);
-                }
-
                 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
                     dsi_writeflush(dsi);
                     *rbuflen = 0;
                     ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
-                               reqcount);
+                               reqcount,  ofork->of_refnum);
                     return cc;
                 }
                 offset += cc;
@@ -1341,8 +1327,8 @@ int                 is64;
         break;
     }
 
-    ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
-    if ( ad_hfileno( ofork->of_ad ) != -1 )
+    ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount,  ofork->of_refnum);
+    if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */
         ofork->of_flags |= AFPFORK_DIRTY;
 
     *rbuflen = set_off_t (offset, rbuf, is64);
@@ -1353,16 +1339,14 @@ afp_write_err:
         dsi_writeinit(obj->handle, rbuf, *rbuflen);
         dsi_writeflush(obj->handle);
     }
-
-    *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
+    if (err != AFP_OK) {
+        *rbuflen = 0;
+    }
     return err;
 }
 
 /* ---------------------------- */
-int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
-AFPObj              *obj;
-char                *ibuf, *rbuf;
-int                 ibuflen, *rbuflen;
+int afp_write(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
 }
@@ -1370,25 +1354,18 @@ int                 ibuflen, *rbuflen;
 /* ---------------------------- 
  * FIXME need to deal with SIGXFSZ signal
 */
-int afp_write_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
-AFPObj              *obj;
-char                *ibuf, *rbuf;
-int                 ibuflen, *rbuflen;
+int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
 }
 
 /* ---------------------------- */
-int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj      *obj;
-char   *ibuf, *rbuf;
-int            ibuflen, *rbuflen;
+int afp_getforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
     struct ofork       *ofork;
-    int                        buflen, ret;
+    int             ret;
     u_int16_t          ofrefnum, bitmap;
-    u_int16_t          attrbits = 0;
-
+    size_t          buflen;
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
     ibuf += sizeof( ofrefnum );
@@ -1397,22 +1374,20 @@ int             ibuflen, *rbuflen;
     ibuf += sizeof( bitmap );
 
     *rbuflen = 0;
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
-        LOG(log_error, logtype_afpd, "afp_getforkparams: of_find");
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
+        LOG(log_error, logtype_afpd, "afp_getforkparams: of_find(%d) could not locate fork", ofrefnum );
         return( AFPERR_PARAM );
     }
-    attrbits = ((ofork->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
-    attrbits |= ((ofork->of_ad->ad_hf.adf_refcount > ofork->of_ad->ad_df.adf_refcount) ? ATTRBIT_ROPEN : 0);
 
-    if ( ad_hfileno( ofork->of_ad ) != -1 ) {
+    if ( ad_meta_fileno( ofork->of_ad ) != -1 ) { /* META */
         if ( ad_refresh( ofork->of_ad ) < 0 ) {
-            LOG(log_error, logtype_afpd, "getforkparams: ad_refresh: %s", strerror(errno) );
+            LOG(log_error, logtype_afpd, "getforkparams(%s): ad_refresh: %s", of_name(ofork), strerror(errno) );
             return( AFPERR_PARAM );
         }
     }
 
     if (AFP_OK != ( ret = getforkparams( ofork, bitmap,
-                               rbuf + sizeof( u_short ), &buflen, attrbits ))) {
+                               rbuf + sizeof( u_short ), &buflen ))) {
         return( ret );
     }