s3: Add a new VFS op called SMB_VFS_TRANSLATE_NAME
authorAravind Srinivasan <aravind.srinivasan@isilon.com>
Wed, 26 Aug 2009 21:56:09 +0000 (14:56 -0700)
committerTim Prouty <tprouty@samba.org>
Fri, 28 Aug 2009 23:38:57 +0000 (16:38 -0700)
This vop is designed to work in tandem with SMB_VFS_READDIR to allow
vfs modules to make modifications to arbitrary filenames before
they're consumed by callers.  Subsequently the core directory
enumeration code in smbd is now changed to free the memory that may be
allocated in a module.  This vop enables the new version of catia in
the following patch.

Signed-off-by: Tim Prouty <tprouty@samba.org>
source3/include/proto.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_streams_depot.c
source3/smbd/dir.c
source3/smbd/filename.c
source3/smbd/msdfs.c
source3/smbd/reply.c
source3/smbd/vfs.c

index ac0eed2b5b9012061437f6b68e43c6c6d2305baf..9314e57cc244391ae8b948e39f6418b3a1359ee6 100644 (file)
@@ -6216,7 +6216,7 @@ bool get_dir_entry(TALLOC_CTX *ctx,
 bool is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, bool use_veto);
 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
                        const char *name, const char *mask, uint32 attr);
-const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
+char *ReadDirName(struct smb_Dir *dirp, long *poffset,
                        SMB_STRUCT_STAT *sbuf);
 void RewindDir(struct smb_Dir *dirp, long *poffset);
 void SeekDir(struct smb_Dir *dirp, long offset);
index 38a972f04c9899b7072302398b0e75b8c334fd44..38d60a0aecc24735c7a5f4447c516799b65412b5 100644 (file)
                           SMB_VFS_RENAME, SMB_VFS_UNLINK, SMB_VFS_NTIMES.  */
 /* Changed to version 27 - not yet released. Added enum timestamp_set_resolution
  *                        return to fs_capabilities call. JRA. */
+/* Leave at 27 - not yet released. Add translate_name VFS call to convert
+                UNIX names to Windows supported names -- asrinivasan. */
 #define SMB_VFS_INTERFACE_VERSION 27
 
 
@@ -299,6 +301,9 @@ struct vfs_fn_pointers {
                              struct files_struct *fsp,
                              struct lock_struct *plock);
 
+       NTSTATUS (*translate_name)(struct vfs_handle_struct *handle,
+                                  char **mapped_name);
+
        /* NT ACL operations. */
 
        NTSTATUS (*fget_nt_acl)(struct vfs_handle_struct *handle,
@@ -644,6 +649,8 @@ bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
 void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
                                struct files_struct *fsp,
                                struct lock_struct *plock);
+NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
+                                    char **mapped_name);
 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
                                  struct files_struct *fsp,
                                  uint32 security_info,
index e271cdee6197312fc0ad4e10e1a2c670628ea2bb..7cc5579e25bb8a4ae1f28a6d05cec79d10b3d286 100644 (file)
 #define SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock) \
        smb_vfs_call_strict_unlock((handle)->next, (fsp), (plock))
 
+#define SMB_VFS_TRANSLATE_NAME(conn, mapped_name) \
+       smb_vfs_call_translate_name((conn)->vfs_handles, (mapped_name))
+#define SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name) \
+       smb_vfs_call_translate_name((handle)->next, (mapped_name))
+
+#define SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock) \
+       smb_vfs_call_strict_unlock((handle)->next, (fsp), (plock))
+
 #define SMB_VFS_FGET_NT_ACL(fsp, security_info, ppdesc) \
        smb_vfs_call_fget_nt_acl((fsp)->conn->vfs_handles, (fsp), (security_info), (ppdesc))
 #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc) \
index b70868eb9f87bda9ff906b491249b9e1ef738b08..e78ddf242c0fd8c439c9f710ff449c454c103bcd 100644 (file)
@@ -651,6 +651,16 @@ static int vfswrap_lstat(vfs_handle_struct *handle,
        return result;
 }
 
+static NTSTATUS vfswrap_translate_name(vfs_handle_struct *handle,
+                                      char **mapped_name)
+{
+       /* Default behavior is a NOOP */
+
+       if (*mapped_name != NULL)
+               return NT_STATUS_OK;
+
+       return NT_STATUS_INVALID_PARAMETER;
+}
 /********************************************************************
  Given a stat buffer return the allocated size on disk, taking into
  account sparse files.
@@ -1725,6 +1735,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .brl_cancel_windows = vfswrap_brl_cancel_windows,
        .strict_lock = vfswrap_strict_lock,
        .strict_unlock = vfswrap_strict_unlock,
+       .translate_name = vfswrap_translate_name,
 
        /* NT ACL operations. */
 
index 0f6de79bcfa1cdbc7dd995b348585630f39e4763..b5c9e6bd9c85ed4a17ba2cadef77e853f565828d 100644 (file)
@@ -143,6 +143,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_BRL_CANCEL_WINDOWS,
        SMB_VFS_OP_STRICT_LOCK,
        SMB_VFS_OP_STRICT_UNLOCK,
+       SMB_VFS_OP_TRANSLATE_NAME,
 
        /* NT ACL operations. */
 
@@ -280,6 +281,7 @@ static struct {
        { SMB_VFS_OP_BRL_CANCEL_WINDOWS, "brl_cancel_windows" },
        { SMB_VFS_OP_STRICT_LOCK, "strict_lock" },
        { SMB_VFS_OP_STRICT_UNLOCK, "strict_unlock" },
+       { SMB_VFS_OP_TRANSLATE_NAME,    "translate_name" },
        { SMB_VFS_OP_FGET_NT_ACL,       "fget_nt_acl" },
        { SMB_VFS_OP_GET_NT_ACL,        "get_nt_acl" },
        { SMB_VFS_OP_FSET_NT_ACL,       "fset_nt_acl" },
@@ -1515,6 +1517,18 @@ static void smb_full_audit_strict_unlock(struct vfs_handle_struct *handle,
        return;
 }
 
+static NTSTATUS smb_full_audit_translate_name(vfs_handle_struct *handle,
+                                             char **mapped_name)
+{
+       NTSTATUS result;
+
+       result = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name);
+
+       do_log(SMB_VFS_OP_TRANSLATE_NAME, NT_STATUS_IS_OK(result), handle, "");
+
+       return result;
+}
+
 static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                uint32 security_info,
                                SEC_DESC **ppdesc)
@@ -2229,6 +2243,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
        .brl_cancel_windows = smb_full_audit_brl_cancel_windows,
        .strict_lock = smb_full_audit_strict_lock,
        .strict_unlock = smb_full_audit_strict_unlock,
+       .translate_name = smb_full_audit_translate_name,
        .fget_nt_acl = smb_full_audit_fget_nt_acl,
        .get_nt_acl = smb_full_audit_get_nt_acl,
        .fset_nt_acl = smb_full_audit_fset_nt_acl,
index aa0189123bbf4bbac973c1df334cf60be66ebb06..51cd56e8fb49a55b0e0715a1fa1277f81b08c0ed 100644 (file)
@@ -384,7 +384,7 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
 {
        char *dirname;
        SMB_STRUCT_DIR *dirhandle = NULL;
-       char *dirent;
+       char *dirent = NULL;
 
        dirname = stream_dir(handle, smb_fname_base, &smb_fname_base->st,
                             false);
@@ -411,14 +411,17 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
        while ((dirent = vfs_readdirname(handle->conn, dirhandle, NULL)) != NULL) {
 
                if (ISDOT(dirent) || ISDOTDOT(dirent)) {
+                       TALLOC_FREE(dirent);
                        continue;
                }
 
                DEBUG(10, ("walk_streams: dirent=%s\n", dirent));
 
                if (!fn(dirname, dirent, private_data)) {
+                       TALLOC_FREE(dirent);
                        break;
                }
+               TALLOC_FREE(dirent);
        }
 
        SMB_VFS_NEXT_CLOSEDIR(handle, dirhandle);
index 73c4cbb3e7c0792498e1025680c13f76b08d9f5b..60fa0306b9265df60b298cae35e61bce21f83dd2 100644 (file)
@@ -585,15 +585,16 @@ int dptr_dnum(struct dptr_struct *dptr)
  Return the next visible file name, skipping veto'd and invisible files.
 ****************************************************************************/
 
-static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
+static char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
                                           long *poffset, SMB_STRUCT_STAT *pst)
 {
        /* Normal search for the next file. */
-       const char *name;
+       char *name;
        while ((name = ReadDirName(dptr->dir_hnd, poffset, pst)) != NULL) {
                if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
                        return name;
                }
+               TALLOC_FREE(name);
        }
        return NULL;
 }
@@ -612,14 +613,12 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
        char *pathreal = NULL;
        char *found_name = NULL;
        int ret;
-       const char *name_temp = NULL;
        NTSTATUS status;
 
        SET_STAT_INVALID(*pst);
 
        if (dptr->has_wild || dptr->did_stat) {
-               name_temp = dptr_normal_ReadDirName(dptr, poffset, pst);
-               name = talloc_strdup(ctx, name_temp);
+               name = dptr_normal_ReadDirName(dptr, poffset, pst);
                return name;
        }
 
@@ -707,8 +706,8 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
 
        TALLOC_FREE(pathreal);
 
-       name_temp = dptr_normal_ReadDirName(dptr, poffset, pst);
-       name = talloc_strdup(ctx, name_temp);
+       name = dptr_normal_ReadDirName(dptr, poffset, pst);
+
        return name;
 
 clean:
@@ -1337,10 +1336,10 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
  Don't check for veto or invisible files.
 ********************************************************************/
 
-const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
+char *ReadDirName(struct smb_Dir *dirp, long *poffset,
                        SMB_STRUCT_STAT *sbuf)
 {
-       const char *n;
+       char *n;
        connection_struct *conn = dirp->conn;
 
        /* Cheat to allow . and .. to be the first entries returned. */
@@ -1348,11 +1347,15 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
             (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
        {
                if (dirp->file_number == 0) {
-                       n = ".";
+                       n = talloc_strdup(talloc_tos(), ".");
+                       if (n == NULL)
+                               return NULL;
                        *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
                } else {
                        *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
-                       n = "..";
+                       n = talloc_strdup(talloc_tos(), "..");
+                       if (n == NULL)
+                               return NULL;
                }
                dirp->file_number++;
                return n;
@@ -1368,6 +1371,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
                /* Ignore . and .. - we've already returned them. */
                if (*n == '.') {
                        if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
+                               TALLOC_FREE(n);
                                continue;
                        }
                }
@@ -1470,7 +1474,7 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
 {
        int i;
-       const char *entry;
+       char *entry = NULL;
        connection_struct *conn = dirp->conn;
 
        /* Search back in the name cache. */
@@ -1499,8 +1503,10 @@ bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
        *poffset = START_OF_DIRECTORY_OFFSET;
        while ((entry = ReadDirName(dirp, poffset, NULL))) {
                if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
+                       TALLOC_FREE(entry);
                        return True;
                }
+               TALLOC_FREE(entry);
        }
        return False;
 }
@@ -1514,7 +1520,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
 {
        NTSTATUS status = NT_STATUS_OK;
        long dirpos = 0;
-       const char *dname;
+       char *dname = NULL;
        SMB_STRUCT_STAT st;
        struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname,
                                          NULL, 0);
@@ -1527,11 +1533,13 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
                /* Quick check for "." and ".." */
                if (dname[0] == '.') {
                        if (!dname[1] || (dname[1] == '.' && !dname[2])) {
+                               TALLOC_FREE(dname);
                                continue;
                        }
                }
 
                if (!is_visible_file(conn, dirname, dname, &st, True)) {
+                       TALLOC_FREE(dname);
                        continue;
                }
 
@@ -1540,6 +1548,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
                status = NT_STATUS_DIRECTORY_NOT_EMPTY;
                break;
        }
+       TALLOC_FREE(dname);
        TALLOC_FREE(dir_hnd);
 
        return status;
index 2538bc1ea63c32ec529391bf437cbb5a2e15e0e7..ee97388da28c925e1b66b923765308c9734fcf0e 100644 (file)
@@ -829,7 +829,7 @@ static int get_real_filename_full_scan(connection_struct *conn,
                                       TALLOC_CTX *mem_ctx, char **found_name)
 {
        struct smb_Dir *cur_dir;
-       const char *dname;
+       char *dname = NULL;
        char *unmangled_name = NULL;
        long curpos;
 
@@ -885,6 +885,7 @@ static int get_real_filename_full_scan(connection_struct *conn,
 
                /* Is it dot or dot dot. */
                if (ISDOT(dname) || ISDOTDOT(dname)) {
+                       TALLOC_FREE(dname);
                        continue;
                }
 
@@ -907,10 +908,13 @@ static int get_real_filename_full_scan(connection_struct *conn,
                        TALLOC_FREE(cur_dir);
                        if (!*found_name) {
                                errno = ENOMEM;
+                               TALLOC_FREE(dname);
                                return -1;
                        }
+                       TALLOC_FREE(dname);
                        return 0;
                }
+               TALLOC_FREE(dname);
        }
 
        TALLOC_FREE(unmangled_name);
index 74e46527bcb336c1c099192ba92af5cb2fdf96a1..4a338fa5904707c1eb7ae2fbbe5ff29610081c26 100644 (file)
@@ -1548,6 +1548,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
                                NULL)) {
                        cnt++;
                }
+               TALLOC_FREE(dname);
        }
 
        SMB_VFS_CLOSEDIR(conn,dirp);
@@ -1647,6 +1648,7 @@ static int form_junctions(TALLOC_CTX *ctx,
                if (cnt >= jn_remain) {
                        DEBUG(2, ("form_junctions: ran out of MSDFS "
                                "junction slots"));
+                       TALLOC_FREE(dname);
                        goto out;
                }
                if (is_msdfs_link_internal(ctx,
@@ -1664,6 +1666,7 @@ static int form_junctions(TALLOC_CTX *ctx,
                                                                dname);
                                if (!jucn[cnt].service_name ||
                                                !jucn[cnt].volume_name) {
+                                       TALLOC_FREE(dname);
                                        goto out;
                                }
                                jucn[cnt].comment = "";
@@ -1671,6 +1674,7 @@ static int form_junctions(TALLOC_CTX *ctx,
                        }
                        TALLOC_FREE(link_target);
                }
+               TALLOC_FREE(dname);
        }
 
 out:
index bdc71c240432d8afb306feaf8c73a95cb0e60346..a3280cb9d4ae36910098cdbae9cdce41bfc09588 100644 (file)
@@ -2577,7 +2577,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
        } else {
                struct smb_Dir *dir_hnd = NULL;
                long offset = 0;
-               const char *dname;
+               char *dname = NULL;
 
                if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
                        status = NT_STATUS_OBJECT_NAME_INVALID;
@@ -2619,18 +2619,21 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        if (!is_visible_file(conn, fname_dir, dname,
                                             &smb_fname->st, true)) {
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(dname);
                                continue;
                        }
 
                        /* Quick check for "." and ".." */
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(dname);
                                continue;
                        }
 
                        if(!mask_match(dname, fname_mask,
                                       conn->case_sensitive)) {
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(dname);
                                continue;
                        }
 
@@ -2643,6 +2646,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                                TALLOC_FREE(dir_hnd);
                                status = NT_STATUS_NO_MEMORY;
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(dname);
                                goto out;
                        }
 
@@ -2650,12 +2654,14 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(dname);
                                goto out;
                        }
 
                        status = do_unlink(conn, req, smb_fname, dirtype);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(frame);
+                               TALLOC_FREE(dname);
                                continue;
                        }
 
@@ -2664,6 +2670,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                                 smb_fname->base_name));
 
                        TALLOC_FREE(frame);
+                       TALLOC_FREE(dname);
                }
                TALLOC_FREE(dir_hnd);
        }
@@ -5287,7 +5294,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
                        connection_struct *conn,
                        struct smb_filename *smb_dname)
 {
-       const char *dname = NULL;
+       char *dname = NULL;
        bool ret = True;
        long offset = 0;
        SMB_STRUCT_STAT st;
@@ -5306,11 +5313,13 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
                NTSTATUS status;
 
                if (ISDOT(dname) || ISDOTDOT(dname)) {
+                       TALLOC_FREE(dname);
                        continue;
                }
 
                if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
                                     false)) {
+                       TALLOC_FREE(dname);
                        continue;
                }
 
@@ -5353,6 +5362,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
         err_break:
                TALLOC_FREE(smb_dname_full);
                TALLOC_FREE(fullname);
+               TALLOC_FREE(dname);
                if (do_break) {
                        ret = false;
                        break;
@@ -5406,7 +5416,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                 * retry. If we fail to delete any of them (and we *don't*
                 * do a recursive delete) then fail the rmdir.
                 */
-               const char *dname;
+               char *dname = NULL;
                long dirpos = 0;
                struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
                                                  smb_dname->base_name, NULL,
@@ -5418,16 +5428,22 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                }
 
                while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
-                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+                       if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
+                               TALLOC_FREE(dname);
                                continue;
+                       }
                        if (!is_visible_file(conn, smb_dname->base_name, dname,
-                                            &st, false))
+                                            &st, false)) {
+                               TALLOC_FREE(dname);
                                continue;
+                       }
                        if(!IS_VETO_PATH(conn, dname)) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(dname);
                                errno = ENOTEMPTY;
                                goto err;
                        }
+                       TALLOC_FREE(dname);
                }
 
                /* We only have veto files/directories.
@@ -5448,10 +5464,12 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                        NTSTATUS status;
 
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
+                               TALLOC_FREE(dname);
                                continue;
                        }
                        if (!is_visible_file(conn, smb_dname->base_name, dname,
                                             &st, false)) {
+                               TALLOC_FREE(dname);
                                continue;
                        }
 
@@ -5496,6 +5514,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                 err_break:
                        TALLOC_FREE(fullname);
                        TALLOC_FREE(smb_dname_full);
+                       TALLOC_FREE(dname);
                        if (do_break)
                                break;
                }
@@ -6132,7 +6151,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
        struct smb_Dir *dir_hnd = NULL;
-       const char *dname;
+       char *dname = NULL;
        long offset = 0;
        int create_options = 0;
        bool posix_pathnames = lp_posix_pathnames();
@@ -6320,16 +6339,19 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        if (attrs & aDIR) {
                                sysdir_entry = True;
                        } else {
+                               TALLOC_FREE(dname);
                                continue;
                        }
                }
 
                if (!is_visible_file(conn, fname_src_dir, dname,
                                     &smb_fname_src->st, false)) {
+                       TALLOC_FREE(dname);
                        continue;
                }
 
                if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
+                       TALLOC_FREE(dname);
                        continue;
                }
 
@@ -6353,6 +6375,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                                       &destname)) {
                        DEBUG(6, ("resolve_wildcards %s %s failed\n",
                                  smb_fname_src->base_name, destname));
+                       TALLOC_FREE(dname);
                        continue;
                }
                if (!destname) {
@@ -6428,7 +6451,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                DEBUG(3,("rename_internals: doing rename on %s -> "
                         "%s\n", smb_fname_str_dbg(smb_fname_src),
                         smb_fname_str_dbg(smb_fname_src)));
-
+               TALLOC_FREE(dname);
        }
        TALLOC_FREE(dir_hnd);
 
@@ -6437,6 +6460,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
        }
 
  out:
+       TALLOC_FREE(dname);
        TALLOC_FREE(fname_src_dir);
        TALLOC_FREE(fname_src_mask);
        return status;
@@ -6901,7 +6925,7 @@ void reply_copy(struct smb_request *req)
                }
        } else {
                struct smb_Dir *dir_hnd = NULL;
-               const char *dname = NULL;
+               char *dname = NULL;
                long offset = 0;
 
                /*
@@ -6946,16 +6970,19 @@ void reply_copy(struct smb_request *req)
                        char *destname = NULL;
 
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
+                               TALLOC_FREE(dname);
                                continue;
                        }
 
                        if (!is_visible_file(conn, fname_src_dir, dname,
                                             &smb_fname_src->st, false)) {
+                               TALLOC_FREE(dname);
                                continue;
                        }
 
                        if(!mask_match(dname, fname_src_mask,
                                       conn->case_sensitive)) {
+                               TALLOC_FREE(dname);
                                continue;
                        }
 
@@ -6969,6 +6996,7 @@ void reply_copy(struct smb_request *req)
 
                        if (!smb_fname_src->base_name) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(dname);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
                        }
@@ -6976,10 +7004,12 @@ void reply_copy(struct smb_request *req)
                        if (!resolve_wildcards(ctx, smb_fname_src->base_name,
                                               smb_fname_dst->base_name,
                                               &destname)) {
+                               TALLOC_FREE(dname);
                                continue;
                        }
                        if (!destname) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(dname);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
                        }
@@ -6990,6 +7020,7 @@ void reply_copy(struct smb_request *req)
                        status = check_name(conn, smb_fname_src->base_name);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(dname);
                                reply_nterror(req, status);
                                goto out;
                        }
@@ -6997,6 +7028,7 @@ void reply_copy(struct smb_request *req)
                        status = check_name(conn, smb_fname_dst->base_name);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
+                               TALLOC_FREE(dname);
                                reply_nterror(req, status);
                                goto out;
                        }
@@ -7011,6 +7043,8 @@ void reply_copy(struct smb_request *req)
                        if (NT_STATUS_IS_OK(status)) {
                                count++;
                        }
+
+                       TALLOC_FREE(dname);
                }
                TALLOC_FREE(dir_hnd);
        }
index 5425c55198ec0215f8649204faa909b7a836fef8..42ff8b19cda5afb630c5013ed7faf7819c5e4c3e 100644 (file)
@@ -662,7 +662,8 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
 char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
 {
        SMB_STRUCT_DIRENT *ptr= NULL;
-       char *dname;
+       char *dname = NULL;
+       NTSTATUS result;
 
        if (!p)
                return(NULL);
@@ -671,7 +672,16 @@ char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
        if (!ptr)
                return(NULL);
 
-       dname = ptr->d_name;
+       dname = talloc_strdup(talloc_tos(), ptr->d_name);
+       if (dname == NULL) {
+               errno = ENOMEM;
+               return NULL;
+       }
+       result = SMB_VFS_TRANSLATE_NAME(conn, &dname);
+       if (!NT_STATUS_IS_OK(result)) {
+               TALLOC_FREE(dname);
+               return NULL;
+       }
 
 #ifdef NEXT2
        if (telldir(p) < 0)
@@ -1495,6 +1505,13 @@ void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
        handle->fns->strict_unlock(handle, fsp, plock);
 }
 
+NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
+                                    char **mapped_name)
+{
+       VFS_FIND(translate_name);
+       return handle->fns->translate_name(handle, mapped_name);
+}
+
 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
                                  struct files_struct *fsp,
                                  uint32 security_info,