]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/directory.c
Fix all remaining warnings from gcc -Wall that can be fixed
[netatalk.git] / etc / afpd / directory.c
index ce0dc364777a65ee641601eebb47dc599f2e3866..8c95ff50bc2a30bd749e6e5a92aec9359b2a86a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.94 2009-03-17 14:30:57 franklahm Exp $
+ * $Id: directory.c,v 1.113 2009-10-22 13:40:11 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -38,13 +38,15 @@ char *strchr (), *strrchr ();
 #include <sys/param.h>
 #include <errno.h>
 #include <utime.h>
-#include <atalk/adouble.h>
 
+#include <atalk/adouble.h>
+#include <atalk/vfs.h>
 #include <atalk/afp.h>
 #include <atalk/util.h>
 #include <atalk/cnid.h>
 #include <atalk/logger.h>
 #include <atalk/uuid.h>
+#include <atalk/unix.h>
 
 #include "directory.h"
 #include "desktop.h"
@@ -55,6 +57,7 @@ char *strchr (), *strrchr ();
 #include "globals.h"
 #include "unix.h"
 #include "mangle.h"
+#include "hash.h"
 
 #ifdef HAVE_NFSv4_ACLS
 extern void addir_inherit_acl(const struct vol *vol);
@@ -66,10 +69,10 @@ int             afp_errno;
 #define SENTINEL (&sentinel)
 static struct dir sentinel = { SENTINEL, SENTINEL, NULL, DIRTREE_COLOR_BLACK,
                                  NULL, NULL, NULL, NULL, NULL, 0, 0, 
-                                 0, 0, NULL, NULL};
+                                 0, 0, NULL, NULL, NULL};
 static struct dir rootpar  = { SENTINEL, SENTINEL, NULL, 0,
                                  NULL, NULL, NULL, NULL, NULL, 0, 0, 
-                                 0, 0, NULL, NULL};
+                                 0, 0, NULL, NULL, NULL};
 
 /* (from IM: Toolbox Essentials)
  * dirFinderInfo (DInfo) fields:
@@ -93,9 +96,7 @@ static struct dir rootpar  = { SENTINEL, SENTINEL, NULL, 0,
  * how exciting.
  */
 struct dir *
-            dirsearch( vol, did )
-            const struct vol   *vol;
-u_int32_t      did;
+            dirsearch(const struct vol *vol, u_int32_t did)
 {
     struct dir *dir;
 
@@ -132,18 +133,6 @@ u_int32_t  did;
 }
 
 /* ------------------- */
-#ifdef ATACC
-int path_isadir(struct path *o_path)
-{
-    return o_path->d_dir != NULL;
-#if 0
-    return o_path->m_name == '\0' || /* we are in a it */
-           !o_path->st_valid ||      /* in cache but we can't chdir in it */ 
-           (!o_path->st_errno && S_ISDIR(o_path->st.st_mode)); /* not in cache an can't chdir */
-#endif
-}
-#endif
-
 int get_afp_errno(const int param)
 {
     if (afp_errno != AFPERR_DID1)
@@ -179,9 +168,7 @@ struct dir *dir = NULL;
  * and we are really bad in this case.
  */
 struct dir *
-            dirlookup( vol, did )
-            const struct vol   *vol;
-u_int32_t      did;
+            dirlookup( struct vol *vol, u_int32_t did)
 {
     struct dir   *ret;
     char        *upath;
@@ -295,9 +282,7 @@ static void dirchildremove(struct dir *a,struct dir *b)
 
 /* --------------------------- */
 /* rotate the tree to the left */
-static void dir_leftrotate(vol, dir)
-struct vol *vol;
-struct dir *dir;
+static void dir_leftrotate(struct vol *vol, struct dir *dir)
 {
     struct dir *right = dir->d_right;
 
@@ -326,9 +311,7 @@ struct dir *dir;
 
 
 /* rotate the tree to the right */
-static void dir_rightrotate(vol, dir)
-struct vol *vol;
-struct dir *dir;
+static void dir_rightrotate(struct vol *vol, struct dir *dir)
 {
     struct dir *left = dir->d_left;
 
@@ -356,9 +339,7 @@ struct dir *dir;
 
 #if 0
 /* recolor after a removal */
-static struct dir *dir_rmrecolor(vol, dir)
-            struct vol *vol;
-struct dir *dir;
+static struct dir *dir_rmrecolor(struct vol *vol, struct dir *dir)
 {
     struct dir *leaf;
 
@@ -461,6 +442,7 @@ static void dir_remove( const struct vol *vol _U_, struct dir       *dir)
     dirfreename(dir);
     dir->d_m_name = NULL;
     dir->d_u_name = NULL;
+    dir->d_m_name_ucs2 = NULL;
 #else /* ! REMOVE_NODES */
 
     /* go searching for a node with at most one child */
@@ -536,11 +518,14 @@ static void dir_remove( const struct vol *vol _U_, struct dir     *dir)
         /* set the node's d_name */
         node->d_m_name = save.d_m_name;
         node->d_u_name = save.d_u_name;
+        node->d_m_name_ucs2 = save.d_m_name_ucs2;
     }
 
     if (node->d_color == DIRTREE_COLOR_BLACK)
         dir_rmrecolor(vol, leaf);
 
+    if (node->d_m_name_ucs2)
+        free(node->d_u_name_ucs2);
     if (node->d_u_name != node->d_m_name) {
         free(node->d_u_name);
     }
@@ -558,9 +543,7 @@ static void dir_remove( const struct vol *vol _U_, struct dir       *dir)
  * 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;
+static void dir_invalidate( const struct vol *vol, struct dir *dir)
 {
     if (curdir == dir) {
         /* v_root can't be deleted */
@@ -574,9 +557,7 @@ struct dir *dir;
 }
 
 /* ------------------------------------ */
-static struct dir *dir_insert(vol, dir)
-            const struct vol *vol;
-struct dir *dir;
+static struct dir *dir_insert(const struct vol *vol, struct dir *dir)
 {
     struct dir *pdir;
 
@@ -601,15 +582,95 @@ struct dir *dir;
     return pdir;
 }
 
+#define ENUMVETO "./../Network Trash Folder/TheVolumeSettingsFolder/TheFindByContentFolder/:2eDS_Store/Contents/Desktop Folder/Trash/Benutzer/"
+
+int
+caseenumerate(const struct vol *vol, struct path *path, struct dir *dir)
+{
+    DIR               *dp;
+    struct dirent     *de;
+    int               ret;
+    static u_int32_t  did = 0;
+    static char              cname[MAXPATHLEN];
+    static char              lname[MAXPATHLEN];
+    ucs2_t           u2_path[MAXPATHLEN];
+    ucs2_t           u2_dename[MAXPATHLEN];
+    char             *tmp, *savepath;
+
+    if (!(vol->v_flags & AFPVOL_CASEINSEN))
+        return -1;
+        
+    if (veto_file(ENUMVETO, path->u_name))
+       return -1;
+
+    savepath = path->u_name;
+
+    /* very simple cache */
+    if ( dir->d_did == did && strcmp(lname, path->u_name) == 0) {
+        path->u_name = cname;
+        path->d_dir = NULL;
+        if (of_stat( path ) == 0 ) {
+            return 0;
+        }
+        /* something changed, we cannot stat ... */
+        did = 0;
+    }
+
+    if (NULL == ( dp = opendir( "." )) ) {
+        LOG(log_debug, logtype_afpd, "caseenumerate: opendir failed: %s", dir->d_u_name);
+        return -1;
+    }
+
+
+    /* LOG(log_debug, logtype_afpd, "caseenumerate: for %s", path->u_name); */
+    if ((size_t) -1 == convert_string(vol->v_volcharset, CH_UCS2, path->u_name, strlen(path->u_name), u2_path, sizeof(u2_path)) ) 
+        LOG(log_debug, logtype_afpd, "caseenumerate: conversion failed for %s", path->u_name);
+
+    /*LOG(log_debug, logtype_afpd, "caseenumerate: dir: %s, path: %s", dir->d_u_name, path->u_name); */
+    ret = -1;
+    for ( de = readdir( dp ); de != NULL; de = readdir( dp )) {
+        if (NULL == check_dirent(vol, de->d_name))
+            continue;
+
+        if ((size_t) -1 == convert_string(vol->v_volcharset, CH_UCS2, de->d_name, strlen(de->d_name), u2_dename, sizeof(u2_dename)) )
+            continue;
+
+        if (strcasecmp_w( u2_path, u2_dename) == 0) {
+            tmp = path->u_name;
+            strlcpy(cname, de->d_name, sizeof(cname));
+            path->u_name = cname;
+            path->d_dir = NULL;
+            if (of_stat( path ) == 0 ) {
+                LOG(log_debug, logtype_afpd, "caseenumerate: using dir: %s, path: %s", de->d_name, path->u_name);
+                strlcpy(lname, tmp, sizeof(lname));
+                did = dir->d_did;
+                ret = 0;
+                break;
+            }
+            else 
+                path->u_name = tmp;
+        }
+
+    }
+    closedir(dp);
+
+    if (ret) {
+        /* invalidate cache */
+        cname[0] = 0;
+        did = 0;
+        path->u_name = savepath;
+    }
+    /* LOG(log_debug, logtype_afpd, "caseenumerate: path on ret: %s", path->u_name); */
+    return ret;
+}
+
+
 /*
  * attempt to extend the current dir. tree to include path
  * as a side-effect, movecwd to that point and return the new dir
  */
 static struct dir *
-            extenddir( vol, dir, path )
-struct vol     *vol;
-struct dir     *dir;
-struct path *path;
+            extenddir(struct vol *vol, struct dir *dir, struct path *path)
 {
     path->d_dir = NULL;
 
@@ -617,10 +678,22 @@ struct path *path;
         afp_errno = AFPERR_PARAM;
         return NULL;
     }
-    if (of_stat( path ) != 0 ) {
+
+    if (check_name(vol, path->u_name)) {
+        /* the name is illegal */
+        LOG(log_info, logtype_afpd, "extenddir: illegal path: '%s'", path->u_name);
+        path->u_name = NULL;
+        afp_errno = AFPERR_PARAM;
         return NULL;
     }
 
+    if (of_stat( path ) != 0 ) {
+        if (!(vol->v_flags & AFPVOL_CASEINSEN))
+            return NULL;
+       else if(caseenumerate(vol, path, dir) != 0)
+            return(NULL);
+    }
+
     if (!S_ISDIR(path->st.st_mode)) {
         return( NULL );
     }
@@ -638,30 +711,6 @@ struct path *path;
     return( dir );
 }
 
-/* -------------------
-   system rmdir with afp error code.
-   ENOENT is not an error.
- */
-int netatalk_rmdir(const char *name)
-{
-    if (rmdir(name) < 0) {
-        switch ( errno ) {
-        case ENOENT :
-            break;
-        case ENOTEMPTY : 
-            return AFPERR_DIRNEMPT;
-        case EPERM:
-        case EACCES :
-            return AFPERR_ACCESS;
-        case EROFS:
-            return AFPERR_VLOCK;
-        default :
-            return AFPERR_PARAM;
-        }
-    }
-    return AFP_OK;
-}
-
 /* -------------------------
    appledouble mkdir afp error code.
 */
@@ -688,28 +737,6 @@ static int netatalk_mkdir(const char *name)
     return AFP_OK;
 }
 
-/* -------------------
-   system unlink with afp error code.
-   ENOENT is not an error.
- */
-int netatalk_unlink(const char *name)
-{
-    if (unlink(name) < 0) {
-        switch (errno) {
-        case ENOENT :
-            break;
-        case EROFS:
-            return AFPERR_VLOCK;
-        case EPERM:
-        case EACCES :
-            return AFPERR_ACCESS;
-        default :
-            return AFPERR_PARAM;
-        }
-    }
-    return AFP_OK;
-}
-
 /* ------------------- */
 static int deletedir(char *dir)
 {
@@ -844,9 +871,7 @@ copydir_done:
 /* --- public functions follow --- */
 
 /* NOTE: we start off with at least one node (the root directory). */
-static struct dir *dirinsert( vol, dir )
-            struct vol *vol;
-struct dir     *dir;
+static struct dir *dirinsert(struct vol *vol, struct dir *dir)
 {
     struct dir *node;
 
@@ -904,10 +929,7 @@ struct dir *dir;
 
 /* ---------------------------- */
 struct dir *
-            adddir( vol, dir, path)
-struct vol     *vol;
-struct dir     *dir;
-struct path     *path;
+            adddir(struct vol *vol, struct dir *dir, struct path *path)
 {
     struct dir *cdir, *edir;
     int                upathlen;
@@ -933,6 +955,10 @@ struct path     *path;
         LOG(log_error, logtype_afpd, "adddir: malloc: %s", strerror(errno) );
         return NULL;
     }
+    if ((size_t)-1 == convert_string_allocate((utf8_encoding())?CH_UTF8_MAC:vol->v_maccharset, CH_UCS2, path->m_name, strlen(path->m_name), (char **)&cdir->d_m_name_ucs2)) {
+        LOG(log_error, logtype_afpd, "Couldn't set UCS2 name for %s", name);
+        cdir->d_m_name_ucs2 = NULL;
+    }
 
     cdir->d_did = id;
 
@@ -955,6 +981,7 @@ struct path     *path;
         dirfreename(edir);
         edir->d_m_name = cdir->d_m_name;
         edir->d_u_name = cdir->d_u_name;
+        edir->d_m_name_ucs2 = cdir->d_m_name_ucs2;
         free(cdir);
         cdir = edir;
         LOG(log_error, logtype_afpd, "adddir: insert %s", edir->d_m_name);
@@ -981,11 +1008,12 @@ void dirfreename(struct dir *dir)
     if (dir->d_u_name != dir->d_m_name) {
         free(dir->d_u_name);
     }
+    if (dir->d_m_name_ucs2)
+        free(dir->d_m_name_ucs2); 
     free(dir->d_m_name);
 }
 
-void dirfree( dir )
-struct dir     *dir;
+void dirfree(struct dir *dir)
 {
     if (!dir || (dir == SENTINEL))
         return;
@@ -1028,6 +1056,7 @@ struct dir *dirnew(const char *m_name, const char *u_name)
         return NULL;
     }
 
+    dir->d_m_name_ucs2 = NULL;
     dir->d_left = dir->d_right = SENTINEL;
     dir->d_next = dir->d_prev = dir;
     return dir;
@@ -1045,7 +1074,7 @@ const struct dir *k = key;
        0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,
     };
 
-    const unsigned char *str = (unsigned char *)k->d_u_name;
+    const unsigned char *str = (unsigned char *)(k->d_u_name);
     hash_val_t acc = 0;
 
     while (*str) {
@@ -1156,12 +1185,9 @@ static struct path *invalidate (const struct vol *vol, struct dir *dir, struct p
                  
 */
 struct path *
-cname( vol, dir, cpath )
-const struct vol       *vol;
-struct dir     *dir;
-char   **cpath;
+cname(struct vol *vol, struct dir *dir, char **cpath)
 {
-    struct dir            *cdir;
+    struct dir            *cdir, *scdir=NULL;
     static char                   path[ MAXPATHLEN + 1];
     static struct path ret;
 
@@ -1173,7 +1199,7 @@ char      **cpath;
     int         size = 0;
     char        sep;
     int         toUTF8 = 0;
-               
+
     data = *cpath;
     afp_errno = AFPERR_NOOBJ;
     memset(&ret, 0, sizeof(ret));
@@ -1305,18 +1331,50 @@ char    **cpath;
             }
         }
         if ( !extend ) {
-            if (dir->d_did == DIRDID_ROOT_PARENT) {
-                /* 
-                   root parent (did 1) has one child: the volume. Requests for did=1 with some <name>
-                   must check against the volume name.
-                */
-                if (!strcmp(vol->v_dir->d_m_name, ret.m_name))
-                    cdir = vol->v_dir;
-                else
-                    cdir = NULL;
+            ucs2_t *tmpname;
+            cdir = dir->d_child;
+            scdir = NULL;
+           if ( cdir && (vol->v_flags & AFPVOL_CASEINSEN) &&
+                    (size_t)-1 != convert_string_allocate(((ret.m_type == 3)?CH_UTF8_MAC:vol->v_maccharset), 
+                                                          CH_UCS2, path, strlen(path), (char **)&tmpname) )
+            {
+                while (cdir) {
+                    if (!cdir->d_m_name_ucs2) {
+                        LOG(log_error, logtype_afpd, "cname: no UCS2 name for %s (did %u)!!!", cdir->d_m_name, ntohl(cdir->d_did) );
+                        /* this shouldn't happen !!!! */
+                        goto noucsfallback;
+                    }
+
+                    if ( strcmp_w( cdir->d_m_name_ucs2, tmpname ) == 0 ) {
+                         break;
+                    }
+                    if ( strcasecmp_w( cdir->d_m_name_ucs2, tmpname ) == 0 ) {
+                         scdir = cdir;
+                    }
+                    cdir = (cdir == dir->d_child->d_prev) ? NULL :cdir->d_next;
+                }
+                free(tmpname);
             }
             else {
-                cdir = dirsearch_byname(vol, dir, ret.u_name);
+noucsfallback:
+                if (dir->d_did == DIRDID_ROOT_PARENT) {
+                  /* 
+                     root parent (did 1) has one child: the volume. Requests for did=1 with some <name>
+                     must check against the volume name.
+                  */
+                  if (!strcmp(vol->v_dir->d_m_name, ret.m_name))
+                      cdir = vol->v_dir;
+                  else
+                      cdir = NULL;
+                }
+                else {
+                  cdir = dirsearch_byname(vol, dir, ret.u_name);
+                }
+            }
+  
+            if (cdir == NULL && scdir != NULL) {
+                cdir = scdir;
+                /* LOG(log_debug, logtype_afpd, "cname: using casediff for %s, (%s = %s)", fullpathname(cdir->d_u_name), cdir->d_m_name, path ); */
             }
 
             if ( cdir == NULL ) {
@@ -1347,7 +1405,7 @@ char      **cpath;
 
         if ( cdir == NULL ) {
 
-            if ( len > 0) {
+            if ( len > 0 || !ret.u_name ) {
                 return NULL;
             }
 
@@ -1361,9 +1419,7 @@ char      **cpath;
 /*
  * Move curdir to dir, with a possible chdir()
  */
-int movecwd( vol, dir)
-const struct vol       *vol;
-struct dir     *dir;
+int movecwd(const struct vol *vol, struct dir *dir)
 {
     char path[MAXPATHLEN + 1];
     struct dir *d;
@@ -1475,7 +1531,7 @@ void setdiroffcnt(struct dir *dir, struct stat *st,  u_int32_t count)
  * is our cached offspring count valid?
 */
 
-int diroffcnt(struct dir *dir, struct stat *st)
+static int diroffcnt(struct dir *dir, struct stat *st)
 {
     return st->st_ctime == dir->ctime;
 }
@@ -1503,7 +1559,7 @@ static int invisible_dots(const struct vol *vol, const char *name)
 int getdirparams(const struct vol *vol,
                  u_int16_t bitmap, struct path *s_path,
                  struct dir *dir, 
-                 char *buf, int *buflen )
+                 char *buf, size_t *buflen )
 {
     struct maccess     ma;
     struct adouble     ad;
@@ -1742,10 +1798,7 @@ int path_error(struct path *path, int error)
 }
 
 /* ----------------------------- */
-int afp_setdirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj;
-char   *ibuf, *rbuf _U_;
-int    ibuflen _U_, *rbuflen;
+int afp_setdirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
     struct vol *vol;
     struct dir *dir;
@@ -2025,6 +2078,10 @@ int setdirparams(const struct vol *vol,
             break;
         case DIRPBIT_FINFO :
             if (isad) {
+                /* Fixes #2802236 */
+                u_int16_t *fflags = (u_int16_t *)(finder_buf + FINDERINFO_FRFLAGOFF);
+                *fflags &= htons(~FINDERINFO_ISHARED);
+                /* #2802236 end */
                 if (  dir->d_did == DIRDID_ROOT ) {
                     /*
                      * Alright, we admit it, this is *really* sick!
@@ -2159,13 +2216,11 @@ setdirparam_done:
     return err;
 }
 
-
-int afp_syncdir(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj _U_;
-char    *ibuf, *rbuf _U_;
-int     ibuflen _U_, *rbuflen;
+int afp_syncdir(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
+#ifdef HAVE_DIRFD
     DIR                  *dp;
+#endif
     int                  dfd;
     struct vol           *vol;
     struct dir           *dir;
@@ -2183,34 +2238,75 @@ int     ibuflen _U_, *rbuflen;
 
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( did );
-    if (NULL == ( dir = dirlookup( vol, did )) ) {
-        return afp_errno; /* was AFPERR_NOOBJ */
-    }
 
-    if (NULL == ( dp = opendir( "." )) ) {
-        switch( errno ) {
-        case ENOENT :
-            return( AFPERR_NOOBJ );
-        case EACCES :
+    /* 
+     * Here's the deal:
+     * if it's CNID 2 our only choice to meet the specs is call sync.
+     * For any other CNID just sync that dir. To my knowledge the
+     * intended use of FPSyncDir is to sync the volume so all we're
+     * ever going to see here is probably CNID 2. Anyway, we' prepared.
+    */
+
+    if ( ntohl(did) == 2 ) {
+        sync();
+    } else {
+        if (NULL == ( dir = dirlookup( vol, did )) ) {
+            return afp_errno; /* was AFPERR_NOOBJ */
+        }
+        
+        if (movecwd( vol, dir ) < 0 )
+            return ( AFPERR_NOOBJ ); 
+        
+        /*
+         * Assuming only OSens that have dirfd also may require fsyncing directories
+         * in order to flush metadata e.g. Linux.
+         */
+    
+#ifdef HAVE_DIRFD
+        if (NULL == ( dp = opendir( "." )) ) {
+            switch( errno ) {
+            case ENOENT :
+                return( AFPERR_NOOBJ );
+            case EACCES :
             return( AFPERR_ACCESS );
-        default :
-            return( AFPERR_PARAM );
+            default :
+                return( AFPERR_PARAM );
+            }
+        }
+        
+        LOG(log_debug, logtype_afpd, "afp_syncdir: dir: '%s'", dir->d_u_name);
+        
+        dfd = dirfd( dp );
+        if ( fsync ( dfd ) < 0 )
+            LOG(log_error, logtype_afpd, "afp_syncdir(%s):  %s",
+                dir->d_u_name, strerror(errno) );
+        closedir(dp); /* closes dfd too */
+#endif
+        
+        if ( -1 == (dfd = open(vol->ad_path(".", ADFLAGS_DIR), O_RDWR))) {
+            switch( errno ) {
+            case ENOENT:
+                return( AFPERR_NOOBJ );
+        case EACCES:
+            return( AFPERR_ACCESS );
+            default:
+                return( AFPERR_PARAM );
+            }        
         }
+        
+        LOG(log_debug, logtype_afpd, "afp_syncdir: ad-file: '%s'",
+            vol->ad_path(".", ADFLAGS_DIR) );
+        
+        if ( fsync(dfd) < 0 )
+            LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s",
+                vol->ad_path(dir->d_u_name, ADFLAGS_DIR), strerror(errno) );
+        close(dfd);
     }
 
-    dfd = dirfd( dp );
-    if ( fsync ( dfd ) < 0 ) {
-        LOG(log_error, logtype_afpd, "syncdir(%s): ddir(%d) %s", dir->d_u_name, dfd, strerror(errno) );
-    }
-    closedir(dp);
-    
     return ( AFP_OK );
 }
 
-int afp_createdir(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj;
-char   *ibuf, *rbuf;
-int    ibuflen _U_, *rbuflen;
+int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
     struct adouble     ad;
     struct vol         *vol;
@@ -2251,9 +2347,6 @@ int       ibuflen _U_, *rbuflen;
         return AFPERR_EXIST;
 
     upath = s_path->u_name;
-    if (0 != (err = check_name(vol, upath))) {
-       return err;
-    }
 
     if (AFP_OK != (err = netatalk_mkdir( upath))) {
         return err;
@@ -2301,10 +2394,10 @@ createdir_done:
  * newparent curdir
  *
 */
-int renamedir(vol, src, dst, dir, newparent, newname)
-const struct vol *vol;
-char   *src, *dst, *newname;
-struct dir     *dir, *newparent;
+int renamedir(const struct vol *vol, char *src, char *dst, 
+    struct dir *dir, 
+    struct dir *newparent, 
+    char *newname)
 {
     struct adouble     ad;
     struct dir         *parent;
@@ -2338,7 +2431,7 @@ struct dir        *dir, *newparent;
         }
     }
 
-    vol->vfs->rf_renamedir(vol, src, dst);
+    vol->vfs->vfs_renamedir(vol, src, dst);
 
     len = strlen( newname );
     /* rename() succeeded so we need to update our tree even if we can't open
@@ -2378,6 +2471,13 @@ struct dir       *dir, *newparent;
         strcpy( dir->d_u_name, dst );
     }
 
+    if (dir->d_m_name_ucs2)
+       free(dir->d_m_name_ucs2);
+
+    dir->d_m_name_ucs2 = NULL;
+    if ((size_t)-1 == convert_string_allocate((utf8_encoding())?CH_UTF8_MAC:vol->v_maccharset, CH_UCS2, dir->d_m_name, strlen(dir->d_m_name), (char**)&dir->d_m_name_ucs2))
+        dir->d_m_name_ucs2 = NULL;
+
     if (( parent = dir->d_parent ) == NULL ) {
         return( AFP_OK );
     }
@@ -2394,8 +2494,7 @@ struct dir        *dir, *newparent;
 }
 
 /* delete an empty directory */
-int deletecurdir( vol)
-const struct vol       *vol;
+int deletecurdir(const struct vol *vol)
 {
     struct dirent *de;
     struct stat st;
@@ -2420,7 +2519,7 @@ const struct vol  *vol;
             return  AFPERR_OLOCK;
         }
     }
-    err = vol->vfs->rf_deletecurdir(vol);
+    err = vol->vfs->vfs_deletecurdir(vol);
     if (err) {
         return err;
     }
@@ -2467,10 +2566,7 @@ delete_done:
     return err;
 }
 
-int afp_mapid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj;
-char   *ibuf, *rbuf;
-int    ibuflen _U_, *rbuflen;
+int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
     struct passwd      *pw;
     struct group       *gr;
@@ -2478,8 +2574,7 @@ int       ibuflen _U_, *rbuflen;
     u_int32_t           id;
     int                        len, sfunc;
     int         utf8 = 0;
-    uuidtype_t          type;
-
+    
     ibuf++;
     sfunc = (unsigned char) *ibuf++;
     *rbuflen = 0;
@@ -2583,10 +2678,7 @@ int      ibuflen _U_, *rbuflen;
     return( AFP_OK );
 }
 
-int afp_mapname(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj _U_;
-char   *ibuf, *rbuf;
-int    ibuflen _U_, *rbuflen;
+int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
 {
     struct passwd      *pw;
     struct group       *gr;
@@ -2678,10 +2770,7 @@ int      ibuflen _U_, *rbuflen;
 /* ------------------------------------
   variable DID support 
 */
-int afp_closedir(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj _U_;
-char   *ibuf _U_, *rbuf _U_;
-int    ibuflen _U_, *rbuflen;
+int afp_closedir(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
 #if 0
     struct vol   *vol;
@@ -2717,10 +2806,7 @@ int      ibuflen _U_, *rbuflen;
 /* did creation gets done automatically 
  * there's a pb again with case but move it to cname
 */
-int afp_opendir(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj  *obj _U_;
-char   *ibuf, *rbuf;
-int    ibuflen  _U_, *rbuflen;
+int afp_opendir(AFPObj *obj _U_, char *ibuf, size_t ibuflen  _U_, char *rbuf, size_t *rbuflen)
 {
     struct vol         *vol;
     struct dir         *parentdir;