]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/directory.c
error code for dirlookup, cname.
[netatalk.git] / etc / afpd / directory.c
index 32c73ba1d590fd906e8e9e84cce8d4a2f9fd34cd..7f4b44eb1e66254aeded9af2d2ad2b169d15db53 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: directory.c,v 1.55 2003-01-08 15:01:33 didg Exp $
+ * $Id: directory.c,v 1.64 2003-03-15 01:34:35 didg Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -121,6 +121,43 @@ u_int32_t  did;
     return NULL;
 }
 
+/* ------------------- */
+#ifdef ATACC
+int path_isadir(struct path *o_path)
+{
+    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
+
+int get_afp_errno(const int param)
+{
+    if (afp_errno != AFPERR_DID1)
+        return afp_errno;
+    return param;
+}
+
+/* ------------------- */
+struct dir *
+            dirsearch_byname( cdir, name )
+            struct dir *cdir;
+            const char *name;
+{
+struct dir *dir;
+
+    if (!strcmp(name, "."))
+        return cdir;
+    dir = cdir->d_child;
+    while (dir) {
+        if ( strcmp( dir->d_u_name, name ) == 0 ) {
+            break;
+        }
+        dir = (dir == curdir->d_child->d_prev) ? NULL : dir->d_next;
+    }
+    return dir;
+}            
+
 /* -----------------------------------------
  * if did is not in the cache resolve it with cnid 
  * 
@@ -143,16 +180,19 @@ u_int32_t did;
     char *mpath;
     
     ret = dirsearch(vol, did);
-    if (ret != NULL)
+    if (ret != NULL || afp_errno == AFPERR_PARAM)
         return ret;
 
     id = did;
-    if ((upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) == NULL) {
+    if (NULL == (upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) ) {
         afp_errno = AFPERR_NOOBJ;
         return NULL;
     }
     ptr = path + MAXPATHLEN;
-    mpath = utompath(vol, upath);
+    if (NULL == ( mpath = utompath(vol, upath, utf8_encoding()) ) ) {
+        afp_errno = AFPERR_NOOBJ;
+        return NULL;
+    }
     len = strlen(mpath);
     pathlen = len;          /* no 0 in the last part */
     len++;
@@ -163,11 +203,14 @@ u_int32_t did;
         if (ret != NULL) {
             break;
         }
-        if ((upath = cnid_resolve(vol->v_db, &id, buffer, buflen)) == NULL) {
+        if ( NULL == (upath = cnid_resolve(vol->v_db, &id, buffer, buflen))
+             ||
+             NULL == (mpath = utompath(vol, upath, utf8_encoding()))
+        ) {
             afp_errno = AFPERR_NOOBJ;
             return NULL;
         }
-        mpath = utompath(vol, upath);
+
         len = strlen(mpath) + 1;
         pathlen += len;
         if (pathlen > 255) {
@@ -450,8 +493,9 @@ 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");
+               if (movecwd(vol, vol->v_root) < 0) {
+            LOG(log_error, logtype_afpd, "cname can't chdir to : %s", vol->v_root);
+        }
        }
        /* FIXME */
     dirchildremove(dir->d_parent, dir);
@@ -497,10 +541,13 @@ struct vol        *vol;
 struct dir     *dir;
 struct path *path;
 {
-    char       *p;
+    path->u_name = mtoupath(vol, path->m_name, utf8_encoding() );
 
-    path->u_name = p = mtoupath(vol, path->m_name );
-    if ( of_stat( path ) != 0 ) {
+    if ( path->u_name == NULL) {
+        afp_errno = AFPERR_PARAM;
+        return NULL;
+    }
+    if (of_stat( path ) != 0 ) {
         return( NULL );
     }
 
@@ -519,6 +566,79 @@ struct path *path;
     return( dir );
 }
 
+/* -------------------
+   system rmdir with afp error code.
+   ENOENT is not an error.
+ */
+static 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.
+*/
+static int netatalk_mkdir(const char *name)
+{
+    if (ad_mkdir(name, DIRBITS | 0777) < 0) {
+        switch ( errno ) {
+        case ENOENT :
+            return( AFPERR_NOOBJ );
+        case EROFS :
+            return( AFPERR_VLOCK );
+        case EPERM:
+        case EACCES :
+            return( AFPERR_ACCESS );
+        case EEXIST :
+            return( AFPERR_EXIST );
+        case ENOSPC :
+        case EDQUOT :
+            return( AFPERR_DFULL );
+        default :
+            return( AFPERR_PARAM );
+        }
+    }
+    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)
 {
     char path[MAXPATHLEN + 1];
@@ -526,9 +646,10 @@ static int deletedir(char *dir)
     struct dirent      *de;
     struct stat st;
     size_t len;
-    int err;
+    int err = AFP_OK;
+    size_t remain;
 
-    if ((len = strlen(dir)) > sizeof(path))
+    if ((len = strlen(dir)) +2 > sizeof(path))
         return AFPERR_PARAM;
 
     /* already gone */
@@ -538,57 +659,34 @@ static int deletedir(char *dir)
     strcpy(path, dir);
     strcat(path, "/");
     len++;
-    while ((de = readdir(dp))) {
+    remain = sizeof(path) -len -1;
+    while ((de = readdir(dp)) && err == AFP_OK) {
         /* skip this and previous directory */
         if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
             continue;
 
-        strncpy(path + len, de->d_name, sizeof(path) - len);
-        if (stat(path, &st) == 0) {
-            if (S_ISDIR(st.st_mode)) {
-                if ((err = deletedir(path)) < 0) {
-                    closedir(dp);
-                    return err;
-                }
-            } else if (unlink(path) < 0) {
-                switch (errno) {
-                case ENOENT :
-                    continue; /* somebody went and deleted it behind our backs. */
-                case EROFS:
-                    err = AFPERR_VLOCK;
-                    break;
-                case EPERM:
-                case EACCES :
-                    err = AFPERR_ACCESS;
-                    break;
-                default :
-                    err = AFPERR_PARAM;
-                }
-                closedir(dp);
-                return err;
-            }
+        if (strlen(de->d_name) > remain) {
+            err = AFPERR_PARAM;
+            break;
+        }
+        strcpy(path + len, de->d_name);
+        if (stat(path, &st)) {
+            continue;
+        }
+        if (S_ISDIR(st.st_mode)) {
+            err = deletedir(path);
+        } else {
+            err = netatalk_unlink(path);
         }
     }
     closedir(dp);
 
     /* okay. the directory is empty. delete it. note: we already got rid
        of .AppleDouble.  */
-    if (rmdir(dir) < 0) {
-        switch ( errno ) {
-        case ENOENT :
-            break;
-        case ENOTEMPTY : /* should never happen */
-            return( AFPERR_DIRNEMPT );
-        case EPERM:
-        case EACCES :
-            return( AFPERR_ACCESS );
-        case EROFS:
-            return AFPERR_VLOCK;
-        default :
-            return( AFPERR_PARAM );
-        }
+    if (err == AFP_OK) {
+        err = netatalk_rmdir(dir);
     }
-    return AFP_OK;
+    return err;
 }
 
 /* do a recursive copy. */
@@ -600,6 +698,8 @@ static int copydir(char *src, char *dst, int noadouble)
     struct stat st;
     struct utimbuf      ut;
     size_t slen, dlen;
+    size_t srem, drem;
+    
     int err;
 
     /* doesn't exist or the path is too long. */
@@ -609,47 +709,45 @@ static int copydir(char *src, char *dst, int noadouble)
         return AFPERR_PARAM;
 
     /* try to create the destination directory */
-    if (ad_mkdir(dst, DIRBITS | 0777) < 0) {
+    if (AFP_OK != (err = netatalk_mkdir(dst)) ) {
         closedir(dp);
-        switch ( errno ) {
-        case ENOENT :
-            return( AFPERR_NOOBJ );
-        case EROFS :
-            return( AFPERR_VLOCK );
-        case EPERM:
-        case EACCES :
-            return( AFPERR_ACCESS );
-        case EEXIST :
-            return( AFPERR_EXIST );
-        case ENOSPC :
-        case EDQUOT :
-            return( AFPERR_DFULL );
-        default :
-            return( AFPERR_PARAM );
-        }
+        return err;
     }
 
     /* set things up to copy */
     strcpy(spath, src);
     strcat(spath, "/");
     slen++;
+    srem = sizeof(spath) - slen -1;
+    
     strcpy(dpath, dst);
     strcat(dpath, "/");
     dlen++;
+    drem = sizeof(dpath) - dlen -1;
+
     err = AFP_OK;
     while ((de = readdir(dp))) {
         /* skip this and previous directory */
         if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
             continue;
 
-        strncpy(spath + slen, de->d_name, sizeof(spath) - slen);
+        if (strlen(de->d_name) > srem) {
+            err = AFPERR_PARAM;
+            break;
+        }
+        strcpy(spath + slen, de->d_name);
+
         if (stat(spath, &st) == 0) {
-            strncpy(dpath + dlen, de->d_name, sizeof(dpath) - dlen);
+            if (strlen(de->d_name) > drem) {
+                err = AFPERR_PARAM;
+                break;
+            }
+            strcpy(dpath + dlen, de->d_name);
 
             if (S_ISDIR(st.st_mode)) {
-                if ((err = copydir(spath, dpath, noadouble)) < 0)
+                if (AFP_OK != (err = copydir(spath, dpath, noadouble)))
                     goto copydir_done;
-            } else if ((err = copyfile(spath, dpath, NULL, noadouble)) < 0) {
+            } else if (AFP_OK != (err = copyfile(spath, dpath, NULL, noadouble))) {
                 goto copydir_done;
 
             } else {
@@ -735,6 +833,14 @@ struct dir *dir;
 
 /* free everything down. we don't bother to recolor as this is only
  * called to free the entire tree */
+void dirfreename(struct dir *dir)
+{
+    if (dir->d_u_name != dir->d_m_name) {
+        free(dir->d_u_name);
+    }
+    free(dir->d_m_name);
+}
+
 void dirfree( dir )
 struct dir     *dir;
 {
@@ -749,10 +855,7 @@ struct dir *dir;
     }
 
     if (dir != SENTINEL) {
-        if (dir->d_u_name != dir->d_m_name) {
-            free(dir->d_u_name);
-        }
-        free(dir->d_m_name);
+        dirfreename(dir);
         free( dir );
     }
 }
@@ -788,24 +891,37 @@ struct dir *dirnew(const char *m_name, const char *u_name)
 }
 
 /* -------------------------------------------------- */
-/* XXX: this needs to be changed to handle path types 
+/* cname 
  return
  if it's a filename:
       in extenddir:
          compute unix name
-         stat the file
-      return mac name
+         stat the file or errno 
+      return 
+         filename
+         curdir: filename parent directory
+         
  if it's a dirname:
       not in the cache
           in extenddir
               compute unix name
-              stat the dir
+              stat the dir or errno
+          return
+              if chdir error 
+                 dirname 
+                 curdir: dir parent directory
+              sinon
+                 dirname: ""
+                 curdir: dir   
       in the cache 
-
-  u_name can be
-  XXXX u_name can be an alias on m_name if the m_name is
-  a valid unix name.
-  
+          return
+              if chdir error
+                 dirname
+                 curdir: dir parent directory 
+              else
+                 dirname: ""
+                 curdir: dir   
+                 
 */
 struct path *
 cname( vol, dir, cpath )
@@ -861,16 +977,22 @@ char      **cpath;
     ret.st_valid = 0;
     for ( ;; ) {
         if ( len == 0 ) {
-            if ( !extend && movecwd( vol, dir ) < 0 ) {
+            if (movecwd( vol, dir ) < 0 ) {
                /* it's tricky:
                   movecwd failed some of dir path are not there anymore.
                   FIXME Is it true with other errors?
                   so we remove dir from the cache 
                */
-               if (dir->d_did == DIRDID_ROOT_PARENT) 
-                   return NULL;
-               if (afp_errno == AFPERR_ACCESS)
-                   return NULL;                
+               if (dir->d_did == DIRDID_ROOT_PARENT)
+                   return NULL;
+               if (afp_errno == AFPERR_ACCESS) {
+                    if ( movecwd( vol, dir->d_parent ) < 0 ) {
+                        return NULL;                   
+                   }
+                   ret.m_name = dir->d_m_name;
+                   ret.u_name = dir->d_u_name;
+                   return &ret;
+               }
 
                dir_invalidate(vol, dir);
                return NULL;
@@ -929,10 +1051,13 @@ char     **cpath;
                        /* dir is not valid anymore 
                           we delete dir from the cache and abort.
                        */
-                       if ( dir->d_did != DIRDID_ROOT_PARENT && 
-                             (afp_errno != AFPERR_ACCESS)) {
-                           dir_invalidate(vol, dir);
+                       if ( dir->d_did == DIRDID_ROOT_PARENT) {
+                           afp_errno = AFPERR_NOOBJ;
+                           return NULL;
                        }
+                       if (afp_errno == AFPERR_ACCESS)
+                           return NULL;
+                       dir_invalidate(vol, dir);
                         return NULL;
                     }
                     cdir = extenddir( vol, dir, &ret );
@@ -944,7 +1069,7 @@ char       **cpath;
 
             if ( cdir == NULL ) {
 
-                if ( len > 0 ) {
+                if ( len > 0 || !ret.u_name) {
                     return NULL;
                 }
 
@@ -972,7 +1097,7 @@ struct dir *dir;
         return( 0 );
     }
     if ( dir->d_did == DIRDID_ROOT_PARENT) {
-        afp_errno = AFPERR_PARAM;
+        afp_errno = AFPERR_DID1; /* AFPERR_PARAM;*/
         return( -1 );
     }
 
@@ -1241,12 +1366,12 @@ int getdirparams(const struct vol *vol,
     if ( l_nameoff ) {
         ashort = htons( data - buf );
         memcpy( l_nameoff, &ashort, sizeof( ashort ));
-        data = set_name(data, dir->d_m_name, 0);
+        data = set_name(vol, data, dir->d_m_name, 0);
     }
     if ( utf_nameoff ) {
         ashort = htons( data - buf );
         memcpy( utf_nameoff, &ashort, sizeof( ashort ));
-        data = set_name(data, dir->d_m_name, utf8);
+        data = set_name(vol, data, dir->d_m_name, utf8);
     }
     if ( isad ) {
         ad_close( &ad, ADFLAGS_HF );
@@ -1273,7 +1398,7 @@ int               ibuflen, *rbuflen;
     memcpy( &vid, ibuf, sizeof( vid ));
     ibuf += sizeof( vid );
 
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
@@ -1283,7 +1408,7 @@ int               ibuflen, *rbuflen;
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( int );
 
-    if (( dir = dirlookup( vol, did )) == NULL ) {
+    if (NULL == ( dir = dirlookup( vol, did )) ) {
         return afp_errno;
     }
 
@@ -1291,12 +1416,13 @@ int             ibuflen, *rbuflen;
     bitmap = ntohs( bitmap );
     ibuf += sizeof( bitmap );
 
-    if (( path = cname( vol, dir, &ibuf )) == NULL ) {
-        return afp_errno;
+    if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
+        return get_afp_errno(AFPERR_NOOBJ); 
     }
 
+    /* FIXME access error or not a file */
     if ( *path->m_name != '\0' ) {
-        return( AFPERR_BADTYPE ); /* not a directory */
+        return (path_isadir( path))? afp_errno:AFPERR_BADTYPE ;
     }
 
     /*
@@ -1306,7 +1432,7 @@ int               ibuflen, *rbuflen;
         ibuf++;
     }
 
-    if (( rc = setdirparams(vol, path, bitmap, ibuf )) == AFP_OK ) {
+    if (AFP_OK == ( rc = setdirparams(vol, path, bitmap, ibuf )) ) {
         setvoltime(obj, vol );
     }
     return( rc );
@@ -1367,7 +1493,7 @@ int setdirparams(const struct vol *vol,
          * Check to see if a create was necessary. If it was, we'll want
          * to set our name, etc.
          */
-        if ( ad_getoflags( &ad, ADFLAGS_HF ) & O_CREAT ) {
+        if ( ad_get_HF_flags( &ad ) & O_CREAT ) {
             ad_setentrylen( &ad, ADEID_NAME, strlen( curdir->d_m_name ));
             memcpy( ad_entry( &ad, ADEID_NAME ), curdir->d_m_name,
                     ad_getentrylen( &ad, ADEID_NAME ));
@@ -1639,13 +1765,14 @@ int             ibuflen, *rbuflen;
     struct path         *s_path;
     u_int32_t          did;
     u_int16_t          vid;
-
+    int                 err;
+    
     *rbuflen = 0;
     ibuf += 2;
 
     memcpy( &vid, ibuf, sizeof( vid ));
     ibuf += sizeof( vid );
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
@@ -1654,41 +1781,24 @@ int             ibuflen, *rbuflen;
 
     memcpy( &did, ibuf, sizeof( did ));
     ibuf += sizeof( did );
-    if (( dir = dirlookup( vol, did )) == NULL ) {
-        return( AFPERR_NOOBJ );
+    if (NULL == ( dir = dirlookup( vol, did )) ) {
+        return afp_errno; /* was AFPERR_NOOBJ */
     }
 
-    if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
-        return afp_errno;
+    if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
+        return get_afp_errno(AFPERR_PARAM);
     }
-    /* FIXME check done elswhere? cname was able to move curdir to it! */
+    /* cname was able to move curdir to it! */
     if (*s_path->m_name == '\0')
         return AFPERR_EXIST;
 
     upath = s_path->u_name;
-    {
-    int ret;
-        if (0 != (ret = check_name(vol, upath))) {
-            return  ret;
-        }
+    if (0 != (err = check_name(vol, upath))) {
+       return err;
     }
 
-    if ( ad_mkdir( upath, DIRBITS | 0777 ) < 0 ) {
-        switch ( errno ) {
-        case ENOENT :
-            return( AFPERR_NOOBJ );
-        case EROFS :
-            return( AFPERR_VLOCK );
-        case EACCES :
-            return( AFPERR_ACCESS );
-        case EEXIST :
-            return( AFPERR_EXIST );
-        case ENOSPC :
-        case EDQUOT :
-            return( AFPERR_DFULL );
-        default :
-            return( AFPERR_PARAM );
-        }
+    if (AFP_OK != (err = netatalk_mkdir( upath))) {
+        return err;
     }
 
     if (of_stat(s_path) < 0) {
@@ -1830,15 +1940,12 @@ int pathlen;
     DIR *dp;
     struct adouble     ad;
     u_int16_t          ashort;
+    int err;
 
     if ( curdir->d_parent == NULL ) {
         return( AFPERR_ACCESS );
     }
 
-    if ( curdir->d_child != NULL ) {
-        return( AFPERR_DIRNEMPT );
-    }
-
     fdir = curdir;
 
     memset(&ad, 0, sizeof(ad));
@@ -1869,38 +1976,16 @@ int pathlen;
             }
 
             strcpy(path + DOT_APPLEDOUBLE_LEN, de->d_name);
-            if (unlink(path) < 0) {
+            if ((err = netatalk_unlink(path))) {
                 closedir(dp);
-                switch (errno) {
-                case EPERM:
-                case EACCES :
-                    return( AFPERR_ACCESS );
-                case EROFS:
-                    return AFPERR_VLOCK;
-                case ENOENT :
-                    continue;
-                default :
-                    return( AFPERR_PARAM );
-                }
+                return err;
             }
         }
         closedir(dp);
     }
 
-    if ( rmdir( ".AppleDouble" ) < 0 ) {
-        switch ( errno ) {
-        case ENOENT :
-            break;
-        case ENOTEMPTY :
-            return( AFPERR_DIRNEMPT );
-        case EROFS:
-            return AFPERR_VLOCK;
-        case EPERM:
-        case EACCES :
-            return( AFPERR_ACCESS );
-        default :
-            return( AFPERR_PARAM );
-        }
+    if ( (err = netatalk_rmdir( ".AppleDouble" ))  ) {
+       return err;
     }
 
     /* now get rid of dangling symlinks */
@@ -1912,53 +1997,39 @@ int pathlen;
 
             /* bail if it's not a symlink */
             if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) {
+               closedir(dp);
                 return AFPERR_DIRNEMPT;
             }
 
-            if (unlink(de->d_name) < 0) {
-                switch (errno) {
-                case EPERM:
-                case EACCES :
-                    return( AFPERR_ACCESS );
-                case EROFS:
-                    return AFPERR_VLOCK;
-                case ENOENT :
-                    continue;
-                default :
-                    return( AFPERR_PARAM );
-                }
+            if ((err = netatalk_unlink(de->d_name))) {
+               closedir(dp);
+               return err;
             }
         }
-        closedir(dp);
     }
 
     if ( movecwd( vol, curdir->d_parent ) < 0 ) {
-        return afp_errno;
+        err = afp_errno;
+        goto delete_done;
     }
 
-    if ( rmdir(fdir->d_u_name) < 0 ) {
-        switch ( errno ) {
-        case ENOENT :
-            return( AFPERR_NOOBJ );
-        case ENOTEMPTY :
-            return( AFPERR_DIRNEMPT );
-        case EPERM:
-        case EACCES :
-            return( AFPERR_ACCESS );
-        case EROFS:
-            return AFPERR_VLOCK;
-        default :
-            return( AFPERR_PARAM );
-        }
-    }
-
-    dirchildremove(curdir, fdir);
+    if ( !(err = netatalk_rmdir(fdir->d_u_name))) {
+        dirchildremove(curdir, fdir);
 #ifdef CNID_DB
-    cnid_delete(vol->v_db, fdir->d_did);
+        cnid_delete(vol->v_db, fdir->d_did);
 #endif /* CNID_DB */
-    dir_remove( vol, fdir );
-
-    return( AFP_OK );
+        dir_remove( vol, fdir );
+        err = AFP_OK;
+    }
+delete_done:
+    if (dp) {
+        /* inode is used as key for cnid.
+         * Close the descriptor only after cnid_delete
+         * has been called. 
+        */
+        closedir(dp);
+    }
+    return err;
 }
 
 int afp_mapid(obj, ibuf, ibuflen, rbuf, rbuflen )
@@ -2153,23 +2224,23 @@ int             ibuflen, *rbuflen;
     memcpy(&vid, ibuf, sizeof(vid));
     ibuf += sizeof( vid );
 
-    if (( vol = getvolbyvid( vid )) == NULL ) {
+    if (NULL == ( vol = getvolbyvid( vid )) ) {
         return( AFPERR_PARAM );
     }
 
     memcpy(&did, ibuf, sizeof(did));
     ibuf += sizeof(did);
 
-    if (( parentdir = dirlookup( vol, did )) == NULL ) {
+    if (NULL == ( parentdir = dirlookup( vol, did )) ) {
         return afp_errno;
     }
 
-    if (( path = cname( vol, parentdir, &ibuf )) == NULL ) {
-        return afp_errno;
+    if (NULL == ( path = cname( vol, parentdir, &ibuf )) ) {
+        return get_afp_errno(AFPERR_PARAM);
     }
 
     if ( *path->m_name != '\0' ) {
-        return( AFPERR_BADTYPE ); /* not a directory */
+        return (path_isadir(path))? afp_errno:AFPERR_BADTYPE ;
     }
 
     if ( !path->st_valid && of_stat(path ) < 0 ) {