Fix bug 7104 - "wide links" and "unix extensions" are incompatible.
[samba.git] / source3 / smbd / vfs.c
index 668defa5701c5373c500b56199f4be5d2db56ecb..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);
 }
 
 /*******************************************************************
@@ -859,7 +843,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                                DEBUG(3,("check_reduced_name: Component not a "
                                         "directory in getting realpath for "
                                         "%s\n", fname));
-                               return map_nt_error_from_unix(errno);
+                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
                        case ENOENT:
                        {
                                TALLOC_CTX *ctx = talloc_tos();
@@ -890,10 +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) {
+                                       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\n", fname));
-                                       return map_nt_error_from_unix(errno);
+                                                "%s (%s)\n",
+                                               fname,
+                                               nt_errstr(status)));
+                                       return status;
                                }
                                tmp_fname = talloc_asprintf(ctx,
                                                "%s/%s",
@@ -953,7 +945,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                                strlen(conn_rootdir)) != 0) {
                            DEBUG(2, ("check_reduced_name: Bad access "
                                      "attempt: %s is a symlink outside the "
-                                     "share path", fname));
+                                     "share path\n", fname));
                            if (free_resolved_name) {
                                    SAFE_FREE(resolved_name);
                            }
@@ -1550,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,