]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/fork.c
MFH sleep and unix priv functionalities.
[netatalk.git] / etc / afpd / fork.c
index 8330220f379ca5d4207c85ba4a37e45aa5ef4c57..7a60db017fa5b8f7f0210e718ac1102b7126796b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.38 2002-10-11 14:18:32 didg Exp $
+ * $Id: fork.c,v 1.51.2.1 2003-07-21 05:50:54 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
 #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 );
+                 struct path *path, struct dir *dir, char *buf, 
+                 int *buflen, struct adouble *adp, int attrbits );
 
 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
 struct ofork   *ofork;
@@ -63,8 +60,8 @@ char          *buf;
 int                    *buflen;
 const u_int16_t     attrbits;
 {
-    struct stat                st;
-    char               *upath;
+    struct path         path;
+    struct stat                *st;
 
     struct adouble     *adp;
     struct dir         *dir;
@@ -89,71 +86,116 @@ const u_int16_t     attrbits;
     vol = ofork->of_vol;
     dir = ofork->of_dir;
 
+    if (NULL == (path.u_name = mtoupath(vol, ofork->of_name, utf8_encoding()))) {
+        return( AFPERR_MISC );
+    }
+    path.m_name = ofork->of_name;
+    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 (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_dfileno( 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, attrbits );    
 }
 
-/* -------------------------
+/* ---------------------------- */
+static off_t get_off_t(ibuf, is64)
+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(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;
+}
+
+/* ------------------------ 
 */
-#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 __inline__ 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)
 {
     return ad_testlock(adp, eid,  what);
 }
 
-/* -------------------------- 
-   a lot of races, some can be remove. but I try first to get the semantic right
-*/
-#ifdef USE_FLOCK_LOCKS 
-#error sorry, for now configure --with-flock-locks is broken...
-#endif
-
-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))) {
@@ -173,14 +215,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;
         }
@@ -200,22 +241,26 @@ 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;
@@ -225,7 +270,7 @@ int         ibuflen, *rbuflen;
     struct dir         *dir;
     struct ofork       *ofork, *opened;
     struct adouble      *adsame = NULL;
-    int                        buflen, ret, adflags, eid, lockop;
+    int                        buflen, ret, adflags, eid;
     u_int32_t           did;
     u_int16_t          vid, bitmap, access, ofrefnum, attrbits = 0;
     char               fork, *path, *upath;
@@ -239,15 +284,15 @@ int               ibuflen, *rbuflen;
     ibuf += sizeof(vid);
 
     *rbuflen = 0;
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid ))) {
         return( AFPERR_PARAM );
     }
 
     memcpy(&did, ibuf, sizeof( did ));
     ibuf += sizeof( int );
 
-    if (( dir = dirlookup( vol, did )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( dir = dirlookup( vol, did ))) {
+       return afp_errno;    
     }
 
     memcpy(&bitmap, ibuf, sizeof( bitmap ));
@@ -261,8 +306,8 @@ int         ibuflen, *rbuflen;
         return AFPERR_VLOCK;
     }
 
-    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
-        return AFPERR_NOOBJ;
+    if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
+       return get_afp_errno(AFPERR_PARAM);    
     }
 
     if (*s_path->m_name == '\0') {
@@ -282,10 +327,17 @@ int               ibuflen, *rbuflen;
         LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
         return AFPERR_PARAM;
     }
-    /* FIXME should we check first ? */
+    /* 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;
@@ -329,15 +381,18 @@ int               ibuflen, *rbuflen;
                 break;
             case ENOENT:
                 if (fork == OPENFORK_DATA) {
+                    /* try to open only the data fork */
                     if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
                         goto openfork_err;
                     }
                     adflags = ADFLAGS_DF;
-
+                }
+                else {
                     /* here's the deal. we only try to create the resource
                     * 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 :
@@ -356,6 +411,10 @@ int                ibuflen, *rbuflen;
                 break;
             }
         }
+        else {
+            /* the ressource fork is open too */
+            ofork->of_flags |= AFPFORK_OPEN;
+        }
     } else {
         /* try opening in read-only mode */
         ret = AFPERR_NOOBJ;
@@ -364,21 +423,24 @@ int               ibuflen, *rbuflen;
             case EROFS:
                 ret = AFPERR_VLOCK;
             case EACCES:
-                /* check for a read-only data fork */
-                if ((adflags != ADFLAGS_HF) &&
-                        (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
-                    goto openfork_err;
-
-                adflags = ADFLAGS_DF;
+                goto openfork_err;
                 break;
             case ENOENT:
-                /* see if client asked for the data fork */
+                /* see if client asked for a read only data fork */
                 if (fork == OPENFORK_DATA) {
                     if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
                         goto openfork_err;
                     }
                     adflags = ADFLAGS_DF;
                 }
+                /* 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 :
             case ENFILE :
@@ -395,10 +457,13 @@ int               ibuflen, *rbuflen;
                 break;
             }
         }
+        else {
+            /* the ressource fork is open too */
+            ofork->of_flags |= AFPFORK_OPEN;
+        }
     }
 
-    if ((adflags & ADFLAGS_HF) &&
-            (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
+    if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & 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 ));
@@ -416,14 +481,18 @@ int               ibuflen, *rbuflen;
     memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
     rbuf += sizeof( u_int16_t );
 
-    /* check  WriteInhibit bit, the test is done here, after some Mac trafic capture */
-    ad_getattr(ofork->of_ad, &bshort);
-    if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
-        ad_close( ofork->of_ad, adflags );
-        of_dealloc( ofork );
-        ofrefnum = 0;
-        memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
-        return(AFPERR_OLOCK);
+    /* 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) {
+        ad_getattr(ofork->of_ad, &bshort);
+        if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
+            ad_close( ofork->of_ad, adflags );
+            of_dealloc( ofork );
+            ofrefnum = 0;
+            memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
+            return(AFPERR_OLOCK);
+        }
     }
 
     /*
@@ -433,7 +502,7 @@ int         ibuflen, *rbuflen;
     /* don't try to lock non-existent rforks. */
     if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
 
-        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;
@@ -449,15 +518,16 @@ 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: ad_lock: %s", strerror(ret) );
                 return( AFPERR_PARAM );
             }
         }
         if ((access & OPENACC_WR))
             ofork->of_flags |= AFPFORK_ACCWR;
-        if ((access & OPENACC_RD))
-            ofork->of_flags |= AFPFORK_ACCRD;
     }
+    /* the file may be open read only without ressource fork */
+    if ((access & OPENACC_RD))
+        ofork->of_flags |= AFPFORK_ACCRD;
 
     memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
     return( AFP_OK );
@@ -475,21 +545,24 @@ char      *ibuf, *rbuf;
 int            ibuflen, *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 ) {
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
         LOG(log_error, logtype_afpd, "afp_setforkparams: of_find could not locate open fork refnum: %u", ofrefnum );
         return( AFPERR_PARAM );
     }
@@ -500,24 +573,69 @@ 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 );
+            LOG(log_error, logtype_afpd, "afp_setforkparams: ad_flush: %s",strerror(errno) );
+            return AFPERR_PARAM;
         }
     } else
         return AFPERR_BITMAP;
@@ -559,47 +677,6 @@ 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 ));
-        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 )
@@ -613,7 +690,8 @@ int     is64;
     int                 eid;
     u_int16_t          ofrefnum;
     u_int8_t            flags;
-
+    int                 lockop;
+    
     *rbuflen = 0;
 
     /* figure out parameters */
@@ -623,7 +701,7 @@ int     is64;
     memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
     ibuf += sizeof(ofrefnum);
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
         LOG(log_error, logtype_afpd, "afp_bytelock: of_find");
         return( AFPERR_PARAM );
     }
@@ -638,39 +716,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_hfileno(ofork->of_ad))) {
+        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:
@@ -722,7 +790,7 @@ struct ofork        *of;
     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 ||
+        if (NULL == ( em = getextmap( of->of_name )) ||
                 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
             return( 1 );
         } else {
@@ -740,7 +808,7 @@ struct ofork        *of;
 
 
 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
-                                    int offset, u_char nlmask,
+                                    off_t offset, u_char nlmask,
                                     u_char nlchar, char *rbuf,
                                     int *rbuflen, const int xlate)
 {
@@ -824,7 +892,7 @@ int is64;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
     ibuf += sizeof( u_short );
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
         LOG(log_error, logtype_afpd, "afp_read: of_find");
         err = AFPERR_PARAM;
         goto afp_read_err;
@@ -878,7 +946,7 @@ int is64;
 
     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;
     }
@@ -961,12 +1029,12 @@ afp_read_loop:
 afp_read_exit:
         LOG(log_error, logtype_afpd, "afp_read: %s", strerror(errno));
         dsi_readdone(dsi);
-        ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
+        ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
         obj->exit(1);
     }
 
 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:
@@ -1005,7 +1073,7 @@ int               ibuflen, *rbuflen;
     ibuf += 2;
 
     memcpy(&vid, ibuf, sizeof(vid));
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
@@ -1025,7 +1093,7 @@ int               ibuflen, *rbuflen;
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
         LOG(log_error, logtype_afpd, "afp_flushfork: of_find");
         return( AFPERR_PARAM );
     }
@@ -1094,31 +1162,28 @@ int             ibuflen, *rbuflen;
     ibuf += 2;
     memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
         LOG(log_error, logtype_afpd, "afp_closefork: of_find");
         return( AFPERR_PARAM );
     }
 
     adflags = 0;
-    if ((ofork->of_flags & AFPFORK_DATA) &&
-            (ad_dfileno( ofork->of_ad ) != -1)) {
-        adflags |= ADFLAGS_DF;
+    if ((ofork->of_flags & AFPFORK_DATA) && (ad_dfileno( ofork->of_ad ) != -1)) {
+            adflags |= ADFLAGS_DF;
     }
-
-    if ( ad_hfileno( ofork->of_ad ) != -1 ) {
+    if ( (ofork->of_flags & AFPFORK_OPEN) && 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)) {
+            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 );
+                 ad_flush( ofork->of_ad, adflags );
             }
         }
     }
@@ -1169,6 +1234,7 @@ 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. */
@@ -1194,7 +1260,7 @@ int                 is64;
     offset   = get_off_t(&ibuf, is64);
     reqcount = get_off_t(&ibuf, is64);
 
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
         LOG(log_error, logtype_afpd, "afp_write: of_find");
         err = AFPERR_PARAM;
         goto afp_write_err;
@@ -1230,7 +1296,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;
     }
@@ -1243,7 +1309,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;
     }
@@ -1266,7 +1332,7 @@ int                 is64;
         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;
@@ -1283,7 +1349,7 @@ int                 is64;
                     (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;
@@ -1305,7 +1371,7 @@ int                 is64;
                     dsi_writeflush(dsi);
                     *rbuflen = 0;
                     ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
-                               reqcount);
+                               reqcount,  ofork->of_refnum);
                     return cc;
                 }
 
@@ -1326,7 +1392,7 @@ int                 is64;
                     dsi_writeflush(dsi);
                     *rbuflen = 0;
                     ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
-                               reqcount);
+                               reqcount,  ofork->of_refnum);
                     return cc;
                 }
                 offset += cc;
@@ -1335,7 +1401,7 @@ int                 is64;
         break;
     }
 
-    ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
+    ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount,  ofork->of_refnum);
     if ( ad_hfileno( ofork->of_ad ) != -1 )
         ofork->of_flags |= AFPFORK_DIRTY;
 
@@ -1361,7 +1427,9 @@ int                 ibuflen, *rbuflen;
     return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
 }
 
-/* ---------------------------- */
+/* ---------------------------- 
+ * FIXME need to deal with SIGXFSZ signal
+*/
 int afp_write_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
 AFPObj              *obj;
 char                *ibuf, *rbuf;
@@ -1389,7 +1457,7 @@ int               ibuflen, *rbuflen;
     ibuf += sizeof( bitmap );
 
     *rbuflen = 0;
-    if (( ofork = of_find( ofrefnum )) == NULL ) {
+    if (NULL == ( ofork = of_find( ofrefnum )) ) {
         LOG(log_error, logtype_afpd, "afp_getforkparams: of_find");
         return( AFPERR_PARAM );
     }
@@ -1403,8 +1471,8 @@ int               ibuflen, *rbuflen;
         }
     }
 
-    if (( ret = getforkparams( ofork, bitmap,
-                               rbuf + sizeof( u_short ), &buflen, attrbits )) != AFP_OK ) {
+    if (AFP_OK != ( ret = getforkparams( ofork, bitmap,
+                               rbuf + sizeof( u_short ), &buflen, attrbits ))) {
         return( ret );
     }