Fix bug 7104 - "wide links" and "unix extensions" are incompatible.
[samba.git] / source3 / smbd / vfs.c
index 35e4f3f9868466e8c9894ba05e65809cd891d498..94bdb1f495c423ce3eb0c252ec3e0c6b3f0308b1 100644 (file)
@@ -659,11 +659,13 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
  A vfs_readdir wrapper which just returns the file name.
 ********************************************************************/
 
-char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
+const char *vfs_readdirname(connection_struct *conn, void *p,
+                           SMB_STRUCT_STAT *sbuf, char **talloced)
 {
        SMB_STRUCT_DIRENT *ptr= NULL;
-       char *dname = NULL;
-       NTSTATUS result;
+       const char *dname;
+       char *translated;
+       NTSTATUS status;
 
        if (!p)
                return(NULL);
@@ -672,17 +674,8 @@ char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
        if (!ptr)
                return(NULL);
 
-       dname = talloc_strdup(talloc_tos(), ptr->d_name);
-       if (dname == NULL) {
-               errno = ENOMEM;
-               return NULL;
-       }
-       result = SMB_VFS_TRANSLATE_NAME(conn, &dname,
-                                       vfs_translate_to_windows);
-       if (!NT_STATUS_IS_OK(result)) {
-               TALLOC_FREE(dname);
-               return NULL;
-       }
+       dname = ptr->d_name;
+
 
 #ifdef NEXT2
        if (telldir(p) < 0)
@@ -694,7 +687,17 @@ char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
        dname = dname - 2;
 #endif
 
-       return(dname);
+       status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
+                                       talloc_tos(), &translated);
+       if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
+               *talloced = NULL;
+               return dname;
+       }
+       *talloced = translated;
+       if (!NT_STATUS_IS_OK(status)) {
+               return NULL;
+       }
+       return translated;
 }
 
 /*******************************************************************
@@ -703,26 +706,7 @@ char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
 
 int vfs_ChDir(connection_struct *conn, const char *path)
 {
-       int res;
-
-       if (!LastDir) {
-               LastDir = SMB_STRDUP("");
-       }
-
-       if (strcsequal(path,"."))
-               return(0);
-
-       if (*path == '/' && strcsequal(LastDir,path))
-               return(0);
-
-       DEBUG(4,("vfs_ChDir to %s\n",path));
-
-       res = SMB_VFS_CHDIR(conn,path);
-       if (!res) {
-               SAFE_FREE(LastDir);
-               LastDir = SMB_STRDUP(path);
-       }
-       return(res);
+       return SMB_VFS_CHDIR(conn,path);
 }
 
 /*******************************************************************
@@ -845,7 +829,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
        char *resolved_name = NULL;
        char *p = NULL;
 
-       DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
+       DEBUG(3,("check_reduced_name [%s] [%s]\n", fname, conn->connectpath));
 
 #ifdef REALPATH_TAKES_NULL
        resolved_name = SMB_VFS_REALPATH(conn,fname,NULL);
@@ -856,8 +840,10 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
        if (!resolved_name) {
                switch (errno) {
                        case ENOTDIR:
-                               DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname));
-                               return map_nt_error_from_unix(errno);
+                               DEBUG(3,("check_reduced_name: Component not a "
+                                        "directory in getting realpath for "
+                                        "%s\n", fname));
+                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
                        case ENOENT:
                        {
                                TALLOC_CTX *ctx = talloc_tos();
@@ -888,8 +874,18 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                                resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,resolved_name_buf);
 #endif
                                if (!resolved_name) {
-                                       DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
-                                       return map_nt_error_from_unix(errno);
+                                       NTSTATUS status = map_nt_error_from_unix(errno);
+
+                                       if (errno == ENOENT || errno == ENOTDIR) {
+                                               status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+                                       }
+
+                                       DEBUG(3,("check_reduce_named: "
+                                                "couldn't get realpath for "
+                                                "%s (%s)\n",
+                                               fname,
+                                               nt_errstr(status)));
+                                       return status;
                                }
                                tmp_fname = talloc_asprintf(ctx,
                                                "%s/%s",
@@ -902,7 +898,8 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                                SAFE_FREE(resolved_name);
                                resolved_name = SMB_STRDUP(tmp_fname);
                                if (!resolved_name) {
-                                       DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname));
+                                       DEBUG(0, ("check_reduced_name: malloc "
+                                                 "fail for %s\n", tmp_fname));
                                        return NT_STATUS_NO_MEMORY;
                                }
 #else
@@ -912,15 +909,18 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                                break;
                        }
                        default:
-                               DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname));
+                               DEBUG(1,("check_reduced_name: couldn't get "
+                                        "realpath for %s\n", fname));
                                return map_nt_error_from_unix(errno);
                }
        }
 
-       DEBUG(10,("reduce_name realpath [%s] -> [%s]\n", fname, resolved_name));
+       DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
+                 resolved_name));
 
        if (*resolved_name != '/') {
-               DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n"));
+               DEBUG(0,("check_reduced_name: realpath doesn't return "
+                        "absolute paths !\n"));
                if (free_resolved_name) {
                        SAFE_FREE(resolved_name);
                }
@@ -933,7 +933,8 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
 
                    conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
                    if (conn_rootdir == NULL) {
-                           DEBUG(2, ("check_reduced_name: Could not get conn_rootdir\n"));
+                           DEBUG(2, ("check_reduced_name: Could not get "
+                                     "conn_rootdir\n"));
                            if (free_resolved_name) {
                                    SAFE_FREE(resolved_name);
                            }
@@ -942,9 +943,9 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
 
                    if (strncmp(conn_rootdir, resolved_name,
                                strlen(conn_rootdir)) != 0) {
-                           DEBUG(2, ("reduce_name: Bad access attempt: %s is "
-                                     "a symlink outside the share path",
-                                     fname));
+                           DEBUG(2, ("check_reduced_name: Bad access "
+                                     "attempt: %s is a symlink outside the "
+                                     "share path\n", fname));
                            if (free_resolved_name) {
                                    SAFE_FREE(resolved_name);
                            }
@@ -975,7 +976,8 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                        if (free_resolved_name) {
                                SAFE_FREE(resolved_name);
                        }
-                        DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name));
+                        DEBUG(3,("check_reduced_name: denied: file path name "
+                                "%s is a symlink\n",resolved_name));
                        TALLOC_FREE(smb_fname);
                        return NT_STATUS_ACCESS_DENIED;
                 }
@@ -983,7 +985,8 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
         }
 #endif
 
-       DEBUG(3,("reduce_name: %s reduced to %s\n", fname, resolved_name));
+       DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname,
+                resolved_name));
        if (free_resolved_name) {
                SAFE_FREE(resolved_name);
        }
@@ -1539,11 +1542,14 @@ void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
 }
 
 NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
-                                    char **mapped_name,
-                                    enum vfs_translate_direction direction)
+                                    const char *name,
+                                    enum vfs_translate_direction direction,
+                                    TALLOC_CTX *mem_ctx,
+                                    char **mapped_name)
 {
        VFS_FIND(translate_name);
-       return handle->fns->translate_name(handle, mapped_name, direction);
+       return handle->fns->translate_name(handle, name, direction, mem_ctx,
+                                          mapped_name);
 }
 
 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,