]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/directory.c
more bits set in files/folders attributes. Fix error -51 in inspiration
[netatalk.git] / etc / afpd / directory.c
index 414ca4358093a56f239c394a618aec8a1aacfb11..40f78e4a191064d9035423959828be5c2ffbb980 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.28 2002-03-24 01:23:40 sibaz Exp $
+ * $Id: directory.c,v 1.34 2002-06-17 18:23:02 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -120,7 +120,67 @@ u_int32_t  did;
     return NULL;
 }
 
+/* -----------------------------------------
+ * if did is not in the cache resolve it with cnid 
+ * 
+ */
+struct dir *
+            dirlookup( vol, did )
+            const struct vol   *vol;
+u_int32_t      did;
+{
+#ifdef CNID_DB
+    struct dir *ret;
+    char               *upath;
+    u_int32_t  id;
+    static char                path[MAXPATHLEN + 1];
+    int len;
+    int pathlen;
+    char *ptr;
+    static char buffer[12 + MAXPATHLEN + 1];
+    int buflen = 12 + MAXPATHLEN + 1;
+
+    ret = dirsearch(vol, did);
+    if (ret != NULL)
+        return ret;
+
+    id = did;
+    if ((upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) == NULL) {
+        return NULL;
+    }
+    ptr = path + MAXPATHLEN;
+    len = strlen(upath);
+    pathlen = len;          /* no 0 in the last part */
+    len++;
+    strcpy(ptr - len, upath);
+    ptr -= len;
+    while (1) {
+        ret = dirsearch(vol,id);
+        if (ret != NULL) {
+            break;
+        }
+        if ((upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) == NULL)
+            return NULL;
+        len = strlen(upath) + 1;
+        pathlen += len;
+        if (pathlen > 255)
+            return NULL;
+        strcpy(ptr - len, upath);
+        ptr -= len;
+    }
+    /* fill the cache */
+    ptr--;
+    *ptr = (unsigned char)pathlen;
+    ptr--;
+    *ptr = 2;
+    /* cname is not efficient */
+    if (cname( vol, ret, &ptr ) == NULL )
+        return NULL;
+#endif
+    return dirsearch(vol, did);
+}
 
+/* --------------------------- */
 /* rotate the tree to the left */
 static void dir_leftrotate(vol, dir)
 struct vol *vol;
@@ -357,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;
@@ -683,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 );
@@ -693,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 );
         }
@@ -706,6 +818,7 @@ char        **cpath;
             data++;
             len--;
         }
+       u = NULL;
 
         while ( *data == '\0' && len > 0 ) {
             if ( dir->d_parent == NULL ) {
@@ -718,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--;
@@ -757,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 );
@@ -773,7 +898,7 @@ char        **cpath;
                 }
 
             } else {
-                dir = cdir;
+                dir = cdir;    
                 *path = '\0';
             }
         }
@@ -868,6 +993,7 @@ int getdirparams(const struct vol *vol,
                 ashort = htons(ATTRBIT_INVISIBLE);
             } else
                 ashort = 0;
+            ashort |= htons(ATTRBIT_SHARED);
             memcpy( data, &ashort, sizeof( ashort ));
             data += sizeof( ashort );
             break;
@@ -1417,28 +1543,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 );
@@ -1607,6 +1727,8 @@ int pathlen;
     struct stat st;
     struct dir *fdir;
     DIR *dp;
+    struct adouble     ad;
+    u_int16_t          ashort;
 #ifdef FORCE_UIDGID
     uidgidset          *uidgid;
 
@@ -1628,6 +1750,20 @@ int pathlen;
     set_uidgid  ( vol );
 #endif /* FORCE_UIDGID */
 
+    memset(&ad, 0, sizeof(ad));
+    if ( ad_open( ".", ADFLAGS_HF|ADFLAGS_DIR, O_RDONLY,
+                  DIRBITS | 0777, &ad) == 0 ) {
+
+        ad_getattr(&ad, &ashort);
+        ad_close( &ad, ADFLAGS_HF );
+        if ((ashort & htons(ATTRBIT_NODELETE))) {
+#ifdef FORCE_UIDGID
+            restore_uidgid ( &uidgid );
+#endif /* FORCE_UIDGID */
+            return  AFPERR_OLOCK;
+        }
+    }
+
     /* delete stray .AppleDouble files. this happens to get .Parent files
        as well. */
     if ((dp = opendir(".AppleDouble"))) {