]> arthur.barton.de Git - netatalk.git/commitdiff
A big patch to correct many afpd problems. For one, the trash will
authorjmarcus <jmarcus>
Mon, 13 May 2002 04:59:36 +0000 (04:59 +0000)
committerjmarcus <jmarcus>
Mon, 13 May 2002 04:59:36 +0000 (04:59 +0000)
work in multi-user environments.  This should also correct the
read-write/read-only lock issues.

This is a bug patch, and should be thoroughly tested.

Submitted by: didier <dgautheron@magic.fr>

etc/afpd/directory.c
etc/afpd/file.c
etc/afpd/file.h
etc/afpd/filedir.c
etc/afpd/filedir.h
etc/afpd/fork.c
etc/afpd/ofork.c

index 007540f06c3d709f5cd376011fc6a05e33a53769..7060a828ca0d3cb9edaeaffb64cec26ed00f5795 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.31 2002-04-29 06:56:02 morgana Exp $
+ * $Id: directory.c,v 1.32 2002-05-13 04:59:36 jmarcus Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -417,7 +417,31 @@ struct dir *dir;
 #endif /* ! REMOVE_NODES */
 }
 
+/* ---------------------------------------
+ * remove the node and its childs from the tree
+ *
+ * FIXME what about opened forks with refs to it?
+ * it's an afp specs violation because you can't delete
+ * an opened forks. Now afpd doesn't care about forks opened by other 
+ * process. It's fixable within afpd if fnctl_lock, doable with smb and
+ * next to impossible for nfs and local filesystem access.
+ */
+static void dir_invalidate( vol, dir )
+const struct vol *vol;
+struct dir *dir;
+{
+       if (curdir == dir) {
+           /* v_root can't be deleted */
+               if (movecwd(vol, vol->v_root) < 0) 
+                       printf("Yuup cant change dir to v_root\n");
+       }
+       /* FIXME */
+    dirchildremove(dir->d_parent, dir);
+       dir_remove( vol, dir );
+}
 
+/* ------------------------------------ */
 static struct dir *dir_insert(vol, dir)
             const struct vol *vol;
 struct dir *dir;
@@ -743,9 +767,11 @@ char       **cpath;
     struct dir         *cdir;
     static char                path[ MAXPATHLEN + 1];
     char               *data, *p;
+    char        *u;
     int                        extend = 0;
     int                        len;
-
+       int                     olen = 0;
+       
     data = *cpath;
     if ( *data++ != 2 ) {                      /* path type */
         return( NULL );
@@ -753,11 +779,37 @@ char      **cpath;
     len = (unsigned char) *data++;
     *cpath += len + 2;
     *path = '\0';
+    u = NULL;
 
     for ( ;; ) {
         if ( len == 0 ) {
             if ( !extend && movecwd( vol, dir ) < 0 ) {
-                return( NULL );
+               /* it's tricky:
+                  movecwd failed so dir is not there anymore.
+                  FIXME Is it true with other errors?
+                  if path == '\0' ==> the cpath parameter is that dir,
+                  and maybe we are trying to recreate it! So we can't 
+                  fail here.
+                  
+               */
+                   if ( dir->d_did == DIRDID_ROOT_PARENT) 
+                               return NULL;                    
+               cdir = dir->d_parent;
+               dir_invalidate(vol, dir);
+               if (*path != '\0' || u == NULL) {
+                       /* FIXME: if path != '\0' then extend != 0 ?
+                        * u == NUL ==> cpath is something like:
+                        * toto\0\0\0
+                       */
+                       return NULL;
+               }
+               if (movecwd(vol, cdir) < 0) {
+                       printf("can't change to parent\n");
+                       return NULL; /* give up the whole tree is out of synch*/
+               }
+                               /* restore the previous token */
+                       strncpy(path, u, olen);
+                       path[olen] = '\0';
             }
             return( path );
         }
@@ -766,6 +818,7 @@ char        **cpath;
             data++;
             len--;
         }
+       u = NULL;
 
         while ( *data == '\0' && len > 0 ) {
             if ( dir->d_parent == NULL ) {
@@ -778,6 +831,10 @@ char       **cpath;
 
         /* would this be faster with strlen + strncpy? */
         p = path;
+        if (len > 0) {
+               u = data;
+               olen = len;
+               }        
         while ( *data != '\0' && len > 0 ) {
             *p++ = *data++;
             len--;
@@ -817,7 +874,15 @@ char       **cpath;
                 }
                 if ( cdir == NULL ) {
                     ++extend;
+                    /* if dir == curdir it always succeed,
+                       even if curdir is deleted. 
+                       it's not a pb because it will failed in extenddir
+                    */
                     if ( movecwd( vol, dir ) < 0 ) {
+                       /* dir is not valid anymore 
+                          we delete dir from the cache and abort.
+                       */
+                       dir_invalidate(vol, dir);
                         return( NULL );
                     }
                     cdir = extenddir( vol, dir, path );
@@ -833,7 +898,7 @@ char        **cpath;
                 }
 
             } else {
-                dir = cdir;
+                dir = cdir;    
                 *path = '\0';
             }
         }
@@ -1477,28 +1542,22 @@ int             ibuflen, *rbuflen;
         switch( errno ) {
         case EACCES:
             return( AFPERR_ACCESS );
-        case EEXIST:
+        case EEXIST:                           /* FIXME this on is impossible? */
             return( AFPERR_EXIST );
         default:
             return( AFPERR_NOOBJ );
         }
     }
-
+    /* FIXME check done elswhere? cname was able to move curdir to it! */
+       if (*path == '\0')
+               return AFPERR_EXIST;
     upath = mtoupath(vol, path);
-
-    /* check for illegal bits in the unix filename */
-    if (!wincheck(vol, upath))
-        return AFPERR_PARAM;
-
-    if ((vol->v_flags & AFPVOL_NOHEX) && strchr(upath, '/'))
-        return AFPERR_PARAM;
-
-    if (!validupath(vol, upath))
-        return AFPERR_EXIST;
-
-    /* check for vetoed filenames */
-    if (veto_file(vol->v_veto, upath))
-        return AFPERR_EXIST;
+    {
+    int ret;
+        if (0 != (ret = check_name(vol, upath))) {
+            return  ret;
+        }
+    }
 
 #ifdef FORCE_UIDGID
     save_uidgid ( &uidgid );
index 5341b687379754faa3e1c3e7ec2bbb417fe4efb4..6b4406a564fc6bf1c3256cecb1b83843396cbe8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.c,v 1.43 2002-03-24 17:43:39 jmarcus Exp $
+ * $Id: file.c,v 1.44 2002-05-13 04:59:36 jmarcus Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -95,42 +95,27 @@ const u_char ufinderi[] = {
                               0, 0, 0, 0, 0, 0, 0, 0
                           };
 
-int getfilparams(struct vol *vol,
+int getmetadata(struct vol *vol,
                  u_int16_t bitmap,
                  char *path, struct dir *dir, struct stat *st,
-                 char *buf, int *buflen )
+                 char *buf, int *buflen, struct adouble *adp, int attrbits )
 {
 #ifndef USE_LASTDID
-    struct stat                hst, lst, *lstp;
-#else /* USE_LASTDID */
-    struct stat                hst;
+    struct stat                lst, *lstp;
 #endif /* USE_LASTDID */
-    struct adouble     ad, *adp;
-    struct ofork        *of;
+    struct stat                hst;
     struct extmap      *em;
     char               *data, *nameoff = NULL, *upath;
-    int                        bit = 0, isad = 1;
+    int                        bit = 0;
     u_int32_t          aint;
     u_int16_t          ashort;
     u_char              achar, fdType[4];
 
 #ifdef DEBUG
-    LOG(log_info, logtype_afpd, "begin getfilparams:");
+    LOG(log_info, logtype_afpd, "begin getmetadata:");
 #endif /* DEBUG */
 
     upath = mtoupath(vol, path);
-    if ((of = of_findname(vol, curdir, path))) {
-        adp = of->of_ad;
-    } else {
-        memset(&ad, 0, sizeof(ad));
-        adp = &ad;
-    }
-
-    if ( ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, adp) < 0 ) {
-        isad = 0;
-    } else if ( fstat( ad_hfileno( adp ), &hst ) < 0 ) {
-        LOG(log_error, logtype_afpd, "getfilparams fstat: %s", strerror(errno) );
-    }
 
     data = buf;
     while ( bitmap != 0 ) {
@@ -141,14 +126,16 @@ int getfilparams(struct vol *vol,
 
         switch ( bit ) {
         case FILPBIT_ATTR :
-            if ( isad ) {
+            if ( adp ) {
                 ad_getattr(adp, &ashort);
             } else if (*upath == '.') {
                 ashort = htons(ATTRBIT_INVISIBLE);
             } else
                 ashort = 0;
+            if (attrbits)
+                ashort = htons(ntohs(ashort) | attrbits);
             memcpy(data, &ashort, sizeof( ashort ));
-            data += sizeof( u_short );
+            data += sizeof( ashort );
             break;
 
         case FILPBIT_PDID :
@@ -157,17 +144,22 @@ int getfilparams(struct vol *vol,
             break;
 
         case FILPBIT_CDATE :
-            if (!isad || (ad_getdate(adp, AD_DATE_CREATE, &aint) < 0))
+            if (!adp || (ad_getdate(adp, AD_DATE_CREATE, &aint) < 0))
                 aint = AD_DATE_FROM_UNIX(st->st_mtime);
             memcpy(data, &aint, sizeof( aint ));
             data += sizeof( aint );
             break;
 
         case FILPBIT_MDATE :
-            if ( isad && (ad_getdate(adp, AD_DATE_MODIFY, &aint) == 0)) {
-                if ((st->st_mtime > AD_DATE_TO_UNIX(aint)) &&
-                        (hst.st_mtime < st->st_mtime)) {
-                    aint = AD_DATE_FROM_UNIX(st->st_mtime);
+            if ( adp && (ad_getdate(adp, AD_DATE_MODIFY, &aint) == 0)) {
+                if ((st->st_mtime > AD_DATE_TO_UNIX(aint))) {
+                        if ( fstat( ad_hfileno( adp ), &hst ) < 0 ) {
+                            LOG(log_error, logtype_default, "getfilparams fstat: %s", strerror(errno) );
+                        }
+                        else if (hst.st_mtime < st->st_mtime) 
+                            aint = AD_DATE_FROM_UNIX(st->st_mtime);
+                        else 
+                            aint = AD_DATE_FROM_UNIX(hst.st_mtime);
                 }
             } else {
                 aint = AD_DATE_FROM_UNIX(st->st_mtime);
@@ -177,14 +169,14 @@ int getfilparams(struct vol *vol,
             break;
 
         case FILPBIT_BDATE :
-            if (!isad || (ad_getdate(adp, AD_DATE_BACKUP, &aint) < 0))
+            if (!adp || (ad_getdate(adp, AD_DATE_BACKUP, &aint) < 0))
                 aint = AD_DATE_START;
             memcpy(data, &aint, sizeof( int ));
             data += sizeof( int );
             break;
 
         case FILPBIT_FINFO :
-            if (isad)
+            if (adp)
                 memcpy(data, ad_entry(adp, ADEID_FINDERI), 32);
             else {
                 memcpy(data, ufinderi, 32);
@@ -194,7 +186,7 @@ int getfilparams(struct vol *vol,
                 }
             }
 
-            if ((!isad || (memcmp(ad_entry(adp, ADEID_FINDERI),
+            if ((!adp || (memcmp(ad_entry(adp, ADEID_FINDERI),
                                   ufinderi, 8 ) == 0)) &&
                     (em = getextmap( path ))) {
                 memcpy(data, em->em_type, sizeof( em->em_type ));
@@ -217,7 +209,7 @@ int getfilparams(struct vol *vol,
             aint = 0;
 #if AD_VERSION > AD_VERSION1
             /* look in AD v2 header */
-            if (isad)
+            if (adp)
                 memcpy(&aint, ad_entry(adp, ADEID_DID), sizeof(aint));
 #endif /* AD_VERSION > AD_VERSION1 */
 
@@ -289,7 +281,7 @@ int getfilparams(struct vol *vol,
             break;
 
         case FILPBIT_RFLEN :
-            if ( isad ) {
+            if ( adp ) {
                 aint = htonl( ad_getentrylen( adp, ADEID_RFORK ));
             } else {
                 aint = 0;
@@ -305,7 +297,7 @@ int getfilparams(struct vol *vol,
                to "pXYZ" when we created it.  See IA, Ver 2.
                <shirsch@ibm.net> */
         case FILPBIT_PDINFO :
-            if ( isad ) {
+            if ( adp ) {
                 memcpy(fdType, ad_entry( adp, ADEID_FINDERI ), 4 );
 
                 if ( memcmp( fdType, "TEXT", 4 ) == 0 ) {
@@ -347,9 +339,6 @@ int getfilparams(struct vol *vol,
             break;
 
         default :
-            if ( isad ) {
-                ad_close( adp, ADFLAGS_HF );
-            }
             return( AFPERR_BITMAP );
         }
         bitmap = bitmap>>1;
@@ -364,18 +353,47 @@ int getfilparams(struct vol *vol,
         memcpy(data, path, aint );
         data += aint;
     }
-    if ( isad ) {
-        ad_close( adp, ADFLAGS_HF );
-    }
     *buflen = data - buf;
+    return (AFP_OK);
+}
+                
+/* ----------------------- */
+int getfilparams(struct vol *vol,
+                 u_int16_t bitmap,
+                 char *path, struct dir *dir, struct stat *st,
+                 char *buf, int *buflen )
+{
+    struct adouble     ad, *adp;
+    struct ofork        *of;
+    char                   *upath;
+    int rc;    
+#ifdef DEBUG
+    LOG(log_info, logtype_default, "begin getfilparams:");
+#endif /* DEBUG */
 
+    upath = mtoupath(vol, path);
+    if ((of = of_findname(vol, dir, path))) {
+        adp = of->of_ad;
+    } else {
+        memset(&ad, 0, sizeof(ad));
+        adp = &ad;
+    }
+
+    if ( ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, adp) < 0 ) {
+        adp = NULL;
+    }
+    rc = getmetadata(vol, bitmap, path, dir, st, buf, buflen, adp, 0);    
+    if ( adp ) {
+        ad_close( adp, ADFLAGS_HF );
+    }
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "end getfilparams:");
 #endif /* DEBUG */
 
-    return( AFP_OK );
+    return( rc );
 }
 
+/* ----------------------------- */
 int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -423,20 +441,11 @@ int               ibuflen, *rbuflen;
     }
 
     upath = mtoupath(vol, path);
-
-    /* check for illegal bits in the unix filename */
-    if (!wincheck(vol, upath))
-        return AFPERR_PARAM;
-
-    if ((vol->v_flags & AFPVOL_NOHEX) && strchr(upath, '/'))
-        return AFPERR_PARAM;
-
-    if (!validupath(vol, upath))
-        return AFPERR_EXIST;
-
-    /* check for vetoed filenames */
-    if (veto_file(vol->v_veto, upath))
-        return AFPERR_EXIST;
+    {
+    int ret;
+        if (0 != (ret = check_name(vol, upath))) 
+            return  ret;
+    }
 
     if ((of = of_findname(vol, curdir, path))) {
         adp = of->of_ad;
@@ -756,12 +765,20 @@ setfilparam_done:
  * and the new mac name.
  * NOTE: if we have to copy a file instead of renaming it, locks
  *       will break.
+ * FIXME: locks on ressource fork will always break thanks to ad_close, done ?
+ *
+ * src         the full source absolute path 
+ * dst         the dest filename in current dir
+ * newname     the dest mac name
+ * adp         adouble struct of src file, if open, or & zeroed one
+ *
  */
-int renamefile(src, dst, newname, noadouble )
+int renamefile(src, dst, newname, noadouble, adp )
 char   *src, *dst, *newname;
 const int         noadouble;
+struct adouble    *adp;
 {
-    struct adouble     ad;
+    struct ofork       *opened;
     char               adsrc[ MAXPATHLEN + 1];
     int                        len, rc;
 
@@ -808,12 +825,11 @@ rename_retry:
         case ENOENT :
             /* check for a source appledouble header. if it exists, make
              * a dest appledouble directory and do the rename again. */
-            memset(&ad, 0, sizeof(ad));
             if (rc || stat(adsrc, &st) ||
-                    (ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad) < 0))
+                    (ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, adp) < 0))
                 return AFP_OK;
             rc++;
-            ad_close(&ad, ADFLAGS_HF);
+            ad_close(adp, ADFLAGS_HF);
             goto rename_retry;
         case EPERM:
         case EACCES :
@@ -825,8 +841,7 @@ rename_retry:
         }
     }
 
-    memset(&ad, 0, sizeof(ad));
-    if ( ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, &ad) < 0 ) {
+    if ( ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp) < 0 ) {
         switch ( errno ) {
         case ENOENT :
             return( AFPERR_NOOBJ );
@@ -840,10 +855,10 @@ rename_retry:
     }
 
     len = strlen( newname );
-    ad_setentrylen( &ad, ADEID_NAME, len );
-    memcpy(ad_entry( &ad, ADEID_NAME ), newname, len );
-    ad_flush( &ad, ADFLAGS_HF );
-    ad_close( &ad, ADFLAGS_HF );
+    ad_setentrylen( adp, ADEID_NAME, len );
+    memcpy(ad_entry( adp, ADEID_NAME ), newname, len );
+    ad_flush( adp, ADFLAGS_HF );
+    ad_close( adp, ADFLAGS_HF );
 
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "end renamefile:");
@@ -1173,8 +1188,9 @@ copydata_done:
 
 /* -----------------------------------
    checkAttrib:   1 check kFPDeleteInhibitBit 
-   ie deletfile called from afp_delete
-   
+   ie deletfile called by afp_delete
+
+   when deletefile is called we don't have lock on it, file is closed (for us)
 */
 int deletefile( file, checkAttrib )
 char           *file;
@@ -1251,11 +1267,21 @@ int         checkAttrib;
             return(AFPERR_OLOCK);
         }
     }
-
-    if ((adflags & ADFLAGS_HF) &&
-            (ad_tmplock(&ad, ADEID_RFORK, locktype, 0, 0) < 0 )) {
-        ad_close( &ad, adflags );
-        return( AFPERR_BUSY );
+    
+    if ((adflags & ADFLAGS_HF) ) {
+        /* FIXME we have a pb here because we want to know if a file is open 
+         * there's a 'priority inversion' if you can't open the ressource fork RW
+         * you can delete it if it's open because you can't get a write lock.
+         * 
+         * ADLOCK_FILELOCK means the whole ressource fork, not only after the 
+         * metadatas
+         *
+         * FIXME it doesn't for RFORK open read only and fork open without deny mode
+         */
+        if (ad_tmplock(&ad, ADEID_RFORK, locktype |ADLOCK_FILELOCK, 0, 0) < 0 ) {
+            ad_close( &ad, adflags );
+            return( AFPERR_BUSY );
+        }
     }
 
     if (ad_tmplock( &ad, ADEID_DFORK, locktype, 0, 0 ) < 0) {
@@ -1299,7 +1325,7 @@ int         checkAttrib;
 
 delete_unlock:
     if (adflags & ADFLAGS_HF)
-        ad_tmplock(&ad, ADEID_RFORK, ADLOCK_CLR, 0, 0);
+        ad_tmplock(&ad, ADEID_RFORK, ADLOCK_CLR |ADLOCK_FILELOCK, 0, 0);
     ad_tmplock(&ad, ADEID_DFORK, ADLOCK_CLR, 0, 0);
     ad_close( &ad, adflags );
 
@@ -1582,6 +1608,12 @@ int              ibuflen, *rbuflen;
     char               *spath, temp[17], *path, *p;
     char                *supath, *upath;
     int                 err;
+    struct adouble     ads;
+    struct adouble     add;
+    struct adouble     *adsp;
+    struct adouble     *addp;
+    struct ofork       *opened;
+    
 #ifdef CNID_DB
     int                 slen, dlen;
 #endif /* CNID_DB */
@@ -1621,7 +1653,7 @@ int               ibuflen, *rbuflen;
     }
 
     if ( *path == '\0' ) {
-        return( AFPERR_BADTYPE );
+        return( AFPERR_BADTYPE );   /* it's a dir */
     }
 
     upath = mtoupath(vol, path);
@@ -1636,7 +1668,12 @@ int              ibuflen, *rbuflen;
             return AFPERR_PARAM;
         }
     }
-
+    memset(&ads, 0, sizeof(ads));
+    adsp = &ads;
+    if ((opened = of_findname(vol, curdir, path))) {
+            /* reuse struct adouble so it won't break locks */
+            adsp = opened->of_ad;
+    }
     /* save some stuff */
     sdir = curdir;
     spath = obj->oldtmp;
@@ -1681,7 +1718,12 @@ int              ibuflen, *rbuflen;
             return AFPERR_PARAM;
         }
     }
-
+    memset(&add, 0, sizeof(add));
+    addp = &add;
+    if ((opened = of_findname(vol, curdir, path))) {
+            /* reuse struct adouble so it won't break locks */
+            addp = opened->of_ad;
+    }
 #ifdef CNID_DB
     /* look for destination id. */
     did = cnid_lookup(vol->v_db, &destst, curdir->d_did, upath,
@@ -1696,17 +1738,17 @@ int             ibuflen, *rbuflen;
         return AFPERR_MISC;
 
     /* now, quickly rename the file. we error if we can't. */
-    if ((err = renamefile(p, temp, temp, vol_noadouble(vol))) < 0)
+    if ((err = renamefile(p, temp, temp, vol_noadouble(vol), adsp)) < 0)
         goto err_exchangefile;
     of_rename(vol, sdir, spath, curdir, temp);
 
     /* rename destination to source */
-    if ((err = renamefile(path, p, spath, vol_noadouble(vol))) < 0)
+    if ((err = renamefile(path, p, spath, vol_noadouble(vol), addp)) < 0)
         goto err_src_to_tmp;
     of_rename(vol, curdir, path, sdir, spath);
 
     /* rename temp to destination */
-    if ((err = renamefile(temp, upath, path, vol_noadouble(vol))) < 0)
+    if ((err = renamefile(temp, upath, path, vol_noadouble(vol), adsp)) < 0)
         goto err_dest_to_src;
     of_rename(vol, curdir, temp, curdir, path);
 
@@ -1753,17 +1795,17 @@ int             ibuflen, *rbuflen;
      * properly. */
 err_temp_to_dest:
     /* rename dest to temp */
-    renamefile(upath, temp, temp, vol_noadouble(vol));
+    renamefile(upath, temp, temp, vol_noadouble(vol), adsp);
     of_rename(vol, curdir, upath, curdir, temp);
 
 err_dest_to_src:
     /* rename source back to dest */
-    renamefile(p, upath, path, vol_noadouble(vol));
+    renamefile(p, upath, path, vol_noadouble(vol), addp);
     of_rename(vol, sdir, spath, curdir, path);
 
 err_src_to_tmp:
     /* rename temp back to source */
-    renamefile(temp, p, spath, vol_noadouble(vol));
+    renamefile(temp, p, spath, vol_noadouble(vol), adsp);
     of_rename(vol, curdir, temp, sdir, spath);
 
 err_exchangefile:
index 738682b85b3fb4b7bf9cc9b193325951bbca1fb4..0c970fe137c1f75c6f28490f36aca27a7911943f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: file.h,v 1.6 2002-03-24 17:43:39 jmarcus Exp $
+ * $Id: file.h,v 1.7 2002-05-13 04:59:36 jmarcus Exp $
  *
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
@@ -77,7 +77,7 @@ extern int getfilparams __P((struct vol *, u_int16_t, char *,
                                  struct dir *, struct stat *, char *buf,
                                  int *));
 extern int setfilparams __P((struct vol *, char *, u_int16_t, char *));
-extern int renamefile   __P((char *, char *, char *, const int));
+extern int renamefile   __P((char *, char *, char *, const int, struct adouble *));
 extern int copyfile     __P((char *, char *, char *, const int));
 extern int deletefile   __P((char *, int));
 
index 230802bcbf89359ea796bc38d3ee216608a0e65b..b4e616676553bdf2d50b259d59d101d3daeca2f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: filedir.c,v 1.26 2002-03-24 17:43:39 jmarcus Exp $
+ * $Id: filedir.c,v 1.27 2002-05-13 04:59:36 jmarcus Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -302,24 +302,145 @@ int              ibuflen, *rbuflen;
     return( rc );
 }
 
+/* -------------------------------------------- 
+   Factorise some check on a pathname
+*/
+int check_name(const struct vol *vol, char *name)
+{
+    /* check for illegal characters in the unix filename */
+    if (!wincheck(vol, name))
+        return AFPERR_PARAM;
+
+    if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/'))
+        return AFPERR_PARAM;
+
+    if (!validupath(vol, name))
+        return AFPERR_EXIST;
+
+    /* check for vetoed filenames */
+    if (veto_file(vol->v_veto, name))
+        return AFPERR_EXIST;
+    return 0;
+}
+
+/* ------------------------- 
+    move and rename sdir:oldname to curdir:newname in volume vol
+   
+    special care is needed for lock   
+*/
+static int moveandrename(vol, sdir, oldname, newname, isdir)
+const struct vol       *vol;
+struct dir     *sdir;
+char        *oldname;
+char        *newname;
+int         isdir;
+{
+    char            *p;
+    char            *upath;
+    int             rc;
+    struct stat     st;
+    int             adflags;
+    struct adouble     ad;
+    struct adouble     *adp;
+    struct ofork       *opened;
+
+#ifdef CNID_DB
+    cnid_t      id;
+#endif /* CNID_DB */
+
+    memset(&ad, 0, sizeof(ad));
+    adp = &ad;
+    adflags = 0;
+    
+    if (!isdir) {
+#ifdef CNID_DB
+        p = mtoupath(vol, oldname);
+        id = cnid_get(vol->v_db, sdir->d_did, p, strlen(p));
+#endif /* CNID_DB */
+        p = ctoupath( vol, sdir, oldname );
+        if ((opened = of_findname(vol, sdir, oldname))) {
+            /* reuse struct adouble so it won't break locks */
+            adp = opened->of_ad;
+        }
+    }
+    else {
+#ifdef CNID_DB
+        id = sdir->d_did; /* we already have the CNID */
+#endif /* CNID_DB */
+        p = ctoupath( vol, sdir->d_parent, oldname );
+        adflags = ADFLAGS_DIR;
+    }
+    /*
+     * p now points to the full pathname of the source fs object.
+     * 
+     * we are in the dest folder so we need to use p for ad_open
+    */
+    
+    if (!ad_open(p, ADFLAGS_HF |adflags, O_RDONLY, 0666, adp)) {
+    u_int16_t bshort;
+
+        ad_getattr(adp, &bshort);
+        ad_close( adp, ADFLAGS_HF );
+        if ((bshort & htons(ATTRBIT_NORENAME))) 
+            return(AFPERR_OLOCK);
+    }
+
+    upath = mtoupath(vol, newname);
+    if (0 != (rc = check_name(vol, upath))) {
+            return  rc;
+    }
+
+    /* source == destination. we just silently accept this. */
+    if (curdir == sdir) {
+        if (strcmp(oldname, newname) == 0)
+            return AFP_OK;
+
+        /* deal with case insensitive, case-preserving filesystems. */
+        if ((stat(upath, &st) == 0) && strdiacasecmp(oldname, newname))
+            return AFPERR_EXIST;
+
+    } else if (stat(upath, &st ) == 0)
+        return AFPERR_EXIST;
+
+    if ( !isdir ) {
+        if (of_findname(vol, curdir, newname)) {
+            rc = AFPERR_EXIST; /* was AFPERR_BUSY; */
+        } else if ((rc = renamefile( p, upath, newname,
+                                     vol_noadouble(vol), adp )) == AFP_OK) {
+            /* if it's still open, rename the ofork as well. */
+            rc = of_rename(vol, sdir, oldname, curdir, newname);
+        }
+    } else {
+        rc = renamedir(p, upath, sdir, curdir, newname, vol_noadouble(vol));
+    }
+    if ( rc == AFP_OK ) {
+#ifdef CNID_DB
+        /* renaming may have moved the file/dir across a filesystem */
+        if (stat(upath, &st) < 0)
+            return AFPERR_MISC;
+
+        /* fix up the catalog entry */
+        cnid_update(vol->v_db, id, &st, curdir->d_did, upath, strlen(upath));
+#endif /* CNID_DB */
+    }
+
+    return rc;
+}
+
+/* -------------------------------------------- */
 int afp_rename(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
-    struct adouble     ad;
-    struct stat                st;
-    struct vol         *vol;
-    struct dir         *dir, *odir = NULL;
-    char               *path, *buf, *upath, *newpath;
-    char               *newadpath;
-    u_int32_t          did;
+    struct vol *vol;
+    struct dir *sdir;
+    char               *path, *oldname, *newname;
+    u_int32_t  did;
     int                        plen;
-    u_int16_t          vid;
-#ifdef CNID_DB
-    cnid_t              id;
-#endif /* CNID_DB */
-
+    u_int16_t  vid;
+    int         isdir = 0;
+    int         rc;
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "begin afp_rename:");
 #endif /* DEBUG */
@@ -338,153 +459,60 @@ int              ibuflen, *rbuflen;
 
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( did );
-    if (( dir = dirsearch( vol, did )) == NULL ) {
+    if (( sdir = dirsearch( vol, did )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+    /* source pathname */
+    if (( path = cname( vol, sdir, &ibuf )) == NULL ) {
         return( AFPERR_NOOBJ );
     }
 
-    /* another place where we know about the path type */
-    if ( *ibuf++ != 2 ) {
-        return( AFPERR_PARAM );
+    sdir = curdir;
+    newname = obj->newtmp;
+    oldname = obj->oldtmp;
+    if ( *path != '\0' ) {
+        strcpy(oldname, path); /* an extra copy for of_rename */
     }
-    plen = (unsigned char) *ibuf++;
-    *( ibuf + plen ) = '\0';
-
-    if ( *path == '\0' ) {
-        if ( curdir->d_parent == NULL ) { /* root directory */
+    else {
+        if ( sdir->d_parent == NULL ) { /* root directory */
             return( AFPERR_NORENAME );
         }
-        odir = curdir;
-        path = curdir->d_name;
-        if ( movecwd( vol, curdir->d_parent ) < 0 ) {
+        /* move to destination dir */
+        if ( movecwd( vol, sdir->d_parent ) < 0 ) {
             return( AFPERR_NOOBJ );
         }
+        isdir = 1;
+        strcpy(oldname, sdir->d_name);
     }
 
-#ifdef notdef
-    if ( strcasecmp( path, ibuf ) == 0 ) {
-        return( AFP_OK );
+    /* another place where we know about the path type */
+    if ( *ibuf++ != 2 ) {
+        return( AFPERR_PARAM );
     }
-#endif /* notdef */
-
-    /* if a curdir/newname ofork exists, return busy */
-    if (of_findname(vol, curdir, ibuf))
-        return AFPERR_BUSY;
-
-    /* source == destination. just say okay. */
-    if (strcmp(path, ibuf) == 0)
-        return AFP_OK;
 
-    newpath = obj->oldtmp;
-    strcpy( newpath, mtoupath(vol, ibuf ));
-
-    /* check for illegal characters in the unix filename */
-    if (!wincheck(vol, newpath))
-        return AFPERR_PARAM;
-
-    if ((vol->v_flags & AFPVOL_NOHEX) && strchr(newpath, '/'))
-        return AFPERR_PARAM;
-
-    if (!validupath(vol, newpath))
-        return AFPERR_EXIST;
-
-    /* check for vetoed filenames */
-    if (veto_file(vol->v_veto, newpath))
-        return AFPERR_EXIST;
-
-    /* the strdiacasecmp deals with case-insensitive, case preserving
-       filesystems */
-    if (stat( newpath, &st ) == 0 && strdiacasecmp(path, ibuf))
-        return( AFPERR_EXIST );
-
-    upath = mtoupath(vol, path);
-
-#ifdef CNID_DB
-    id = cnid_get(vol->v_db, curdir->d_did, upath, strlen(upath));
-#endif /* CNID_DB */
-
-    if ( rename( upath, newpath ) < 0 ) {
-        switch ( errno ) {
-        case ENOENT :
-            return( AFPERR_NOOBJ );
-        case EACCES :
-            return( AFPERR_ACCESS );
-        default :
-            return( AFPERR_PARAM );
-        }
+    if (( plen = (unsigned char)*ibuf++ ) != 0 ) {
+        strncpy( newname, ibuf, plen );
+        newname[ plen ] = '\0';
     }
-
-#ifdef CNID_DB
-    if (stat(newpath, &st) < 0) /* this shouldn't fail */
-        return AFPERR_MISC;
-    cnid_update(vol->v_db, id, &st, curdir->d_did, newpath, strlen(newpath));
-#endif /* CNID_DB */
-
-    if ( !odir ) {
-        newadpath = obj->newtmp;
-        strcpy( newadpath, ad_path( newpath, 0 ));
-        if ( rename( ad_path( upath, 0 ), newadpath ) < 0 ) {
-            if ( errno == ENOENT ) {   /* no adouble header file */
-                if (( unlink( newadpath ) < 0 ) && ( errno != ENOENT )) {
-                    return( AFPERR_PARAM );
-                }
-                goto out;
-            }
-            return( AFPERR_PARAM );
-        }
-
-        memset(&ad, 0, sizeof(ad));
-        if ( ad_open( newpath, ADFLAGS_HF, O_RDWR|O_CREAT, 0666,
-                      &ad) < 0 ) {
-            return( AFPERR_PARAM );
-        }
-    } else {
-        int isad = 1;
-
-        memset(&ad, 0, sizeof(ad));
-        if ( ad_open( newpath, vol_noadouble(vol)|ADFLAGS_HF|ADFLAGS_DIR,
-                      O_RDWR|O_CREAT, 0666, &ad) < 0 ) {
-            if (!((errno == ENOENT) && vol_noadouble(vol)))
-                return( AFPERR_PARAM );
-            isad = 0;
-        }
-        if ((buf = realloc( odir->d_name, plen + 1 )) == NULL ) {
-            LOG(log_error, logtype_afpd, "afp_rename: realloc: %s", strerror(errno) );
-            if (isad) {
-                ad_flush(&ad, ADFLAGS_HF); /* in case of create */
-                ad_close(&ad, ADFLAGS_HF);
-            }
-            return AFPERR_MISC;
-        }
-        odir->d_name = buf;
-        strcpy( odir->d_name, ibuf );
-        if (!isad)
-            goto out;
+    else {
+        return AFP_OK; /* newname == oldname same dir */
     }
+    
+    rc = moveandrename(vol, sdir, oldname, newname, isdir);
 
-    ad_setentrylen( &ad, ADEID_NAME, plen );
-    memcpy( ad_entry( &ad, ADEID_NAME ), ibuf, plen );
-    ad_flush( &ad, ADFLAGS_HF );
-    ad_close( &ad, ADFLAGS_HF );
-
-out:
-    setvoltime(obj, vol );
-
-    /* if it's still open, rename the ofork as well. */
-    if (of_rename(vol, curdir, path, curdir, ibuf) < 0)
-        return AFPERR_MISC;
+    if ( rc == AFP_OK ) {
+        setvoltime(obj, vol );
+    }
 
 #ifdef DEBUG
     LOG(log_info, logtype_afpd, "end afp_rename:");
 #endif /* DEBUG */
 
-    return( AFP_OK );
+    return( rc );
 }
 
-
+/* ------------------------------- */
 int afp_delete(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -574,23 +602,21 @@ char      *name;
     return( p );
 }
 
-
+/* ------------------------- */
 int afp_moveandrename(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
 int            ibuflen, *rbuflen;
 {
     struct vol *vol;
-    struct dir *sdir, *ddir, *odir = NULL;
-    struct stat st;
-    char       *oldname, *newname;
-    char        *path, *p, *upath;
-    int                did, rc;
+    struct dir *sdir, *ddir;
+    int         isdir = 0;
+    char           *oldname, *newname;
+    char        *path;
+    int                did;
     int                plen;
     u_int16_t  vid;
-#ifdef CNID_DB
-    cnid_t      id;
-#endif /* CNID_DB */
+    int         rc;
 #ifdef DROPKLUDGE
     int                retvalue;
 #endif /* DROPKLUDGE */
@@ -631,25 +657,11 @@ int               ibuflen, *rbuflen;
     oldname = obj->oldtmp;
     if ( *path != '\0' ) {
         /* not a directory */
-        strcpy(newname, path);
         strcpy(oldname, path); /* an extra copy for of_rename */
-#ifdef CNID_DB
-        p = mtoupath(vol, path);
-        id = cnid_get(vol->v_db, sdir->d_did, p, strlen(p));
-#endif /* CNID_DB */
-        p = ctoupath( vol, sdir, newname );
     } else {
-        odir = curdir;
-        strcpy( newname, odir->d_name );
-        strcpy(oldname, odir->d_name);
-        p = ctoupath( vol, odir->d_parent, newname );
-#ifdef CNID_DB
-        id = curdir->d_did; /* we already have the CNID */
-#endif /* CNID_DB */
+        isdir = 1;
+        strcpy(oldname, sdir->d_name);
     }
-    /*
-     * p now points to the full pathname of the source fs object.
-     */
 
     /* get the destination directory */
     if (( ddir = dirsearch( vol, did )) == NULL ) {
@@ -671,64 +683,20 @@ int               ibuflen, *rbuflen;
         strncpy( newname, ibuf, plen );
         newname[ plen ] = '\0';
     }
-
-    upath = mtoupath(vol, newname);
-
-    /* check for illegal characters in the unix filename */
-    if (!wincheck(vol, upath))
-        return AFPERR_PARAM;
-
-    if ((vol->v_flags & AFPVOL_NOHEX) && strchr(upath, '/'))
-        return AFPERR_PARAM;
-
-    if (!validupath(vol, upath))
-        return AFPERR_EXIST;
-
-    /* check for vetoed filenames */
-    if (veto_file(vol->v_veto, upath))
-        return AFPERR_EXIST;
-
-    /* source == destination. we just silently accept this. */
-    if (curdir == sdir) {
-        if (strcmp(oldname, newname) == 0)
-            return AFP_OK;
-
-        /* deal with case insensitive, case-preserving filesystems. */
-        if ((stat(upath, &st) == 0) && strdiacasecmp(oldname, newname))
-            return AFPERR_EXIST;
-
-    } else if (stat(upath, &st ) == 0)
-        return( AFPERR_EXIST );
-
-    if ( !odir ) {
-        if (of_findname(vol, curdir, newname)) {
-            rc = AFPERR_BUSY;
-        } else if ((rc = renamefile( p, upath, newname,
-                                     vol_noadouble(vol) )) == AFP_OK) {
-            /* if it's still open, rename the ofork as well. */
-            rc = of_rename(vol, sdir, oldname, curdir, newname);
-        }
-    } else {
-        rc = renamedir(p, upath, odir, curdir, newname, vol_noadouble(vol));
+    else {
+        strcpy(newname, oldname);
     }
+    
+    rc = moveandrename(vol, sdir, oldname, newname, isdir);
 
+    if ( rc == AFP_OK ) {
 #ifdef DROPKLUDGE
-    if (vol->v_flags & AFPVOL_DROPBOX) {
-        if (retvalue=matchfile2dirperms (newname, vol, did) != AFP_OK) {
-            return retvalue;
+        if (vol->v_flags & AFPVOL_DROPBOX) {
+            if (retvalue=matchfile2dirperms (newname, vol, did) != AFP_OK) {
+                return retvalue;
+            }
         }
-    }
 #endif /* DROPKLUDGE */
-
-    if ( rc == AFP_OK ) {
-#ifdef CNID_DB
-        /* renaming may have moved the file/dir across a filesystem */
-        if (stat(upath, &st) < 0)
-            return AFPERR_MISC;
-
-        /* fix up the catalog entry */
-        cnid_update(vol->v_db, id, &st, curdir->d_did, upath, strlen(upath));
-#endif /* CNID_DB */
         setvoltime(obj, vol );
     }
 
index a182631a896deb9bef6de50af6a78e966e766e1f..f1ef1f6cb16d21a0f37a2711ca0ccef688df3f27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: filedir.h,v 1.6 2001-12-03 05:03:38 jmarcus Exp $
+ * $Id: filedir.h,v 1.7 2002-05-13 04:59:36 jmarcus Exp $
  */
 
 #ifndef AFPD_FILEDIR_H
@@ -15,6 +15,7 @@ extern struct afp_options default_options;
 extern char            *ctoupath __P((const struct vol *, struct dir *,
                                 char *));
 extern int             veto_file __P((const char *veto_str, const char *path));
+extern int             check_name __P((const struct vol *vol, char *name));
 
 /* FP functions */
 extern int     matchfile2dirperms __P((char *, struct vol *, int));
index e6b438066dd28593b3f44d2d8aa4adea15adb502..0108508daa7599534a99344ac6ffc22ec5632d7a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: fork.c,v 1.26 2002-03-24 01:23:40 sibaz Exp $
+ * $Id: fork.c,v 1.27 2002-05-13 04:59:36 jmarcus Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
 #define BYTELOCK_MAX 0x7FFFFFFFU
 
 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;
@@ -63,13 +67,17 @@ const u_int16_t     attrbits;
 #endif /* !USE_LASTDID */
     struct stat                st;
     struct extmap      *em;
-    char               *data, *nameoff = NULL, *upath;
-    int                        bit = 0, isad = 1;
-    u_int32_t           aint;
+    char                   *data, *nameoff = NULL, *upath;
+    int                            bit = 0;
+    u_int32_t       aint;
     u_int16_t          ashort;
 
+    struct adouble     *adp;
+    struct dir      *dir;
+    struct vol      *vol;
+    
     if ( ad_hfileno( ofork->of_ad ) == -1 ) {
-        isad = 0;
+        adp = NULL;
     } else {
         aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
         if ( ad_refresh( ofork->of_ad ) < 0 ) {
@@ -78,6 +86,7 @@ const u_int16_t     attrbits;
         }
         /* See afp_closefork() for why this is bad */
         ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
+        adp = ofork->of_ad;
     }
 
     /* can only get the length of the opened fork */
@@ -99,164 +108,117 @@ const u_int16_t     attrbits;
             }
         }
     }
+    dir = ofork->of_dir;
+    vol = ofork->of_vol;
+    return getmetadata(vol, bitmap, ofork->of_name, dir, &st, buf, buflen, adp, attrbits );    
+}
 
-    data = buf;
-    while ( bitmap != 0 ) {
-        while (( bitmap & 1 ) == 0 ) {
-            bitmap = bitmap>>1;
-            bit++;
-        }
-
-        switch ( bit ) {
-        case FILPBIT_ATTR :
-            if ( isad ) {
-                ad_getattr(ofork->of_ad, &ashort);
-            } else {
-                ashort = 0;
-            }
-            if (attrbits)
-                ashort = htons(ntohs(ashort) | attrbits);
-            memcpy(data, &ashort, sizeof( ashort ));
-            data += sizeof( ashort );
-            break;
-
-        case FILPBIT_PDID :
-            memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
-            data += sizeof( aint );
-            break;
-
-        case FILPBIT_CDATE :
-            if (!isad ||
-                    (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
-                aint = AD_DATE_FROM_UNIX(st.st_mtime);
-            memcpy(data, &aint, sizeof( aint ));
-            data += sizeof( aint );
-            break;
-
-        case FILPBIT_MDATE :
-            if (!isad ||
-                    (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
-                    (AD_DATE_TO_UNIX(aint) < st.st_mtime))
-                aint = AD_DATE_FROM_UNIX(st.st_mtime);
-            memcpy(data, &aint, sizeof( aint ));
-            data += sizeof( aint );
-            break;
-
-        case FILPBIT_BDATE :
-            if (!isad ||
-                    (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
-                aint = AD_DATE_START;
-            memcpy(data, &aint, sizeof( aint ));
-            data += sizeof( aint );
-            break;
-
-        case FILPBIT_FINFO :
-            memcpy(data, isad ?
-                   (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
-                   (void *) ufinderi, 32);
-            if ( !isad ||
-                    memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
-                            ufinderi, 8 ) == 0 ) {
-                memcpy(data, ufinderi, 8 );
-                if (( em = getextmap( ofork->of_name )) != NULL ) {
-                    memcpy(data, em->em_type, sizeof( em->em_type ));
-                    memcpy(data + 4, em->em_creator,
-                           sizeof( em->em_creator ));
-                }
-            }
-            data += 32;
-            break;
-
-        case FILPBIT_LNAME :
-            nameoff = data;
-            data += sizeof(u_int16_t);
-            break;
-
-        case FILPBIT_SNAME :
-            memset(data, 0, sizeof(u_int16_t));
-            data += sizeof(u_int16_t);
-            break;
+/* -------------------------
+*/
+#define SHARE 0
+#define EXCL  1
+static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what, int mode)
+{
+    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);
+}
 
-        case FILPBIT_FNUM :
-            aint = 0;
-#if AD_VERSION > AD_VERSION1
-            /* look in AD v2 header */
-            if (isad)
-                memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
-#endif /* AD_VERSION > AD_VERSION1 */
+/* -------------------------
+*/
+extern int ad_testlock(struct adouble *adp, int eid, int off);
 
-#ifdef CNID_DB
-            aint = cnid_add(ofork->of_vol->v_db, &st,
-                            ofork->of_dir->d_did,
-                            upath, strlen(upath), aint);
-            if (aint == CNID_INVALID) {
-                switch (errno) {
-                case CNID_ERR_PARAM:
-                    LOG(log_error, logtype_afpd, "getforkparams: Incorrect parameters passed to cnid_add");
-                    return(AFPERR_PARAM);
-                case CNID_ERR_PATH:
-                    return(AFPERR_PARAM);
-                case CNID_ERR_DB:
-                case CNID_ERR_MAX:
-                    return(AFPERR_MISC);
-                }
-            }
-#endif /* CNID_DB */
-
-            if (aint == 0) {
-#ifdef USE_LASTDID
-                aint = htonl(( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff ));
-#else /* USE_LASTDID */
-                lstp = lstat(upath, &lst) < 0 ? &st : &lst;
-#ifdef DID_MTAB
-                aint = htonl( afpd_st_cnid ( lstp ) );
-#else /* DID_MTAB */
-                aint = htonl(CNID(lstp, 1));
-#endif /* DID_MTAB */
-#endif /* USE_LASTDID */
-            }
+static int getforkmode(struct adouble *adp, int eid, int what)
+{
+    return ad_testlock(adp, eid,  what);
+}
 
-            memcpy(data, &aint, sizeof( aint ));
-            data += sizeof( aint );
-            break;
+/* -------------------------- 
+   a lot of races, some can be remove. but I try first to get the semantic right
+*/
 
-        case FILPBIT_DFLEN :
-            aint = htonl( st.st_size );
-            memcpy(data, &aint, sizeof( aint ));
-            data += sizeof( aint );
-            break;
+static int 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);
+    }
 
-        case FILPBIT_RFLEN :
-            if ( isad ) {
-                aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
-            } else {
-                aint = 0;
-            }
-            memcpy(data, &aint, sizeof( aint ));
-            data += sizeof( aint );
-            break;
+    if ((access & (OPENACC_RD | OPENACC_DRD))) {
+        if ((readset = getforkmode(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
+            return readset;
+        if ((denyreadset = getforkmode(adp, eid, AD_FILELOCK_DENY_RD)) <0)
+            return denyreadset;
 
-        default :
-            return( AFPERR_BITMAP );
+        if ((access & OPENACC_RD) && denyreadset) {
+            errno = EACCES;
+            return -1;
+        }
+        if ((access & OPENACC_DRD) && readset) {
+            errno = EACCES;
+            return -1;
+        }   
+        /* 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);
+            if (ret)
+                return ret;
+        }
+        if ((access & OPENACC_DRD)) {
+            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD, SHARE);
+            if (ret)
+                return ret;
         }
-        bitmap = bitmap>>1;
-        bit++;
     }
-
-    if ( nameoff ) {
-        ashort = htons( data - buf );
-        memcpy(nameoff, &ashort, sizeof( ashort ));
-        aint = strlen( ofork->of_name );
-        aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
-        *data++ = aint;
-        memcpy(data, ofork->of_name, aint );
-        data += aint;
+    /* ------------same for writing -------------- */
+    if ((access & (OPENACC_WR | OPENACC_DWR))) {
+        if ((writeset = getforkmode(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
+            return writeset;
+        if ((denywriteset = getforkmode(adp, eid, AD_FILELOCK_DENY_WR)) <0)
+            return denywriteset;
+
+        if ((access & OPENACC_WR) && denywriteset) {
+            errno = EACCES;
+            return -1;
+        }
+        if ((access & OPENACC_DWR) && writeset) {
+            errno = EACCES;
+            return -1;
+        }   
+        mode = ((access & OPENACC_DWR))?EXCL: SHARE;
+        if ((access & OPENACC_WR)) {
+            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR, mode);
+            if (ret)
+                return ret;
+        }
+        if ((access & OPENACC_DWR)) {
+            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR, SHARE);
+            if (ret)
+                return ret;
+        }
     }
-
-    *buflen = data - buf;
-    return( AFP_OK );
+    return 0;
 }
 
+/* ----------------------- */    
 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
 AFPObj      *obj;
 char   *ibuf, *rbuf;
@@ -444,59 +406,13 @@ int               ibuflen, *rbuflen;
 
     /*
      * synchronization locks:
-     *
-     * here's the ritual:
-     *  1) attempt a read lock to see if we have read or write
-     *     privileges.
-     *  2) if that succeeds, set a write lock to correspond to the
-     *     deny mode requested.
-     *  3) whenever a file is read/written, locks get set which
-     *     prevent conflicts.
      */
 
     /* don't try to lock non-existent rforks. */
     if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
 
-        /* try to see if we have access. */
-        ret = 0;
-        if (access & OPENACC_WR) {
-            ofork->of_flags |= AFPFORK_ACCWR;
-            ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
-                          AD_FILELOCK_WR, 1, ofrefnum);
-        }
-
-        if (!ret && (access & OPENACC_RD)) {
-            ofork->of_flags |= AFPFORK_ACCRD;
-            ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
-                          AD_FILELOCK_RD, 1, ofrefnum);
-        }
-
+        ret = setmode(ofork->of_ad, eid, access, ofrefnum);
         /* can we access the fork? */
-        if (ret < 0) {
-            ad_close( ofork->of_ad, adflags );
-            of_dealloc( ofork );
-            ofrefnum = 0;
-            memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
-            return (AFPERR_DENYCONF);
-        }
-
-        /* now try to set the deny lock. if the fork is open for read or
-         * write, a read lock will already have been set. otherwise, we upgrade
-         * our lock to a write lock. 
-         *
-         * 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. */
-        lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
-                 ADLOCK_WR : ADLOCK_RD;
-        ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
-                                               lockop | ADLOCK_FILELOCK |
-                                               ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
-                                               ofrefnum) : 0;
-        if (!ret && (access & OPENACC_DRD))
-            ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
-                          ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
-
         if (ret < 0) {
             ret = errno;
             ad_close( ofork->of_ad, adflags );
@@ -515,6 +431,10 @@ int                ibuflen, *rbuflen;
                 return( AFPERR_PARAM );
             }
         }
+        if ((access & OPENACC_WR))
+            ofork->of_flags |= AFPFORK_ACCWR;
+        if ((access & OPENACC_RD))
+            ofork->of_flags |= AFPFORK_ACCRD;
     }
 
     memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
index 1209fcc28ee8f4e2f75e5779575c91f75bb215b2..d30d1af90104436c291aab28261400af58685987 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ofork.c,v 1.13 2002-04-22 07:46:00 rlewczuk Exp $
+ * $Id: ofork.c,v 1.14 2002-05-13 04:59:36 jmarcus Exp $
  *
  * Copyright (c) 1996 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -260,6 +260,15 @@ struct ofork *of_find(const u_int16_t ofrefnum )
     return( oforks[ ofrefnum % nforks ] );
 }
 
+/* --------------------------
+   it doesn't work :-(
+   mac1 open file "test" with simple text 
+   mac2 rename "test" ==> "test1"
+   
+   now of_findname return NULL 
+   
+   
+*/
 struct ofork *
             of_findname(const struct vol *vol, const struct dir *dir, const char *name)
 {