s3: Do not talloc in readdir
authorVolker Lendecke <vl@samba.org>
Mon, 16 Nov 2009 08:49:23 +0000 (09:49 +0100)
committerVolker Lendecke <vl@samba.org>
Wed, 18 Nov 2009 22:16:13 +0000 (23:16 +0100)
This is a hot codepath (called from the stat cache)

12 files changed:
source3/include/proto.h
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_catia.c
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 6f971c3a07efe841ff35548efa7986c50eed8490..9450140b9074c834ec8a23f33f9e5b28065100b8 100644 (file)
@@ -6219,8 +6219,8 @@ 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);
-char *ReadDirName(struct smb_Dir *dirp, long *poffset,
-                       SMB_STRUCT_STAT *sbuf);
+const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
+                       SMB_STRUCT_STAT *sbuf, char **talloced);
 void RewindDir(struct smb_Dir *dirp, long *poffset);
 void SeekDir(struct smb_Dir *dirp, long offset);
 long TellDir(struct smb_Dir *dirp);
@@ -7145,7 +7145,8 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len);
 int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len);
 int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len);
 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);
+const char *vfs_readdirname(connection_struct *conn, void *p,
+                           SMB_STRUCT_STAT *sbuf, char **talloced);
 int vfs_ChDir(connection_struct *conn, const char *path);
 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
 NTSTATUS check_reduced_name(connection_struct *conn, const char *fname);
index f9c1f0a54f20840b39a12e17a40bc1f4decf2c83..aee84a70b7d9c48554d175d1a84fce56ad4a6966 100644 (file)
@@ -308,8 +308,10 @@ struct vfs_fn_pointers {
                              struct lock_struct *plock);
 
        NTSTATUS (*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);
 
        /* NT ACL operations. */
 
@@ -658,8 +660,10 @@ 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,
-                                    enum vfs_translate_direction direction);
+                                    const char *name,
+                                    enum vfs_translate_direction direction,
+                                    TALLOC_CTX *mem_ctx,
+                                    char **mapped_name);
 NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
                                  struct files_struct *fsp,
                                  uint32 security_info,
index 7206bf41bb700799af7ba220058e16b2a5b2154d..c6f83bda07a9efacecfe1031d2ad9174c199c20b 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, direction)                   \
-       smb_vfs_call_translate_name((conn)->vfs_handles, (mapped_name), (direction))
-#define SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction)            \
-       smb_vfs_call_translate_name((handle)->next, (mapped_name), (direction))
+#define SMB_VFS_TRANSLATE_NAME(conn, name, direction, mem_ctx, mapped_name) \
+       smb_vfs_call_translate_name((conn)->vfs_handles, (name), (direction), (mem_ctx), (mapped_name))
+#define SMB_VFS_NEXT_TRANSLATE_NAME(handle, name, direction, mem_ctx, mapped_name) \
+       smb_vfs_call_translate_name((handle)->next, (name), (direction), (mem_ctx), (mapped_name))
 
 #define SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock) \
        smb_vfs_call_strict_unlock((handle)->next, (fsp), (plock))
index 14e404f9f5c09678adfb2e768778fab61c7ebb16..f1d0cadee75de969956ea9258997ed0e598181b6 100644 (file)
@@ -286,11 +286,14 @@ static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle,
  * TRANSLATE_NAME call which converts the given name to
  * "WINDOWS displayable" name
  */
-static NTSTATUS catia_translate_name(vfs_handle_struct *handle,
-                                    char **mapped_name,
-                                    enum vfs_translate_direction direction)
+static NTSTATUS catia_translate_name(struct vfs_handle_struct *handle,
+                                    const char *orig_name,
+                                    enum vfs_translate_direction direction,
+                                    TALLOC_CTX *mem_ctx,
+                                    char **pmapped_name)
 {
        char *name = NULL;
+       char *mapped_name;
        NTSTATUS ret;
 
        /*
@@ -299,21 +302,27 @@ static NTSTATUS catia_translate_name(vfs_handle_struct *handle,
         * We will be allocating new memory for mapped_name in
         * catia_string_replace_allocate
         */
-       name = talloc_strdup(talloc_tos(), *mapped_name);
+       name = talloc_strdup(talloc_tos(), orig_name);
        if (!name) {
                errno = ENOMEM;
                return NT_STATUS_NO_MEMORY;
        }
-       TALLOC_FREE(*mapped_name);
        ret = catia_string_replace_allocate(handle->conn, name,
-                       mapped_name, direction);
+                       &mapped_name, direction);
 
        TALLOC_FREE(name);
        if (!NT_STATUS_IS_OK(ret)) {
                return ret;
        }
 
-       ret = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction);
+       ret = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction,
+                                         mem_ctx, pmapped_name);
+
+       if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
+               *pmapped_name = talloc_move(mem_ctx, &mapped_name);
+       } else {
+               TALLOC_FREE(mapped_name);
+       }
 
        return ret;
 }
index 8fbea0c4f333623430dad759afc2e8d1b4455e21..848440809c4ff2129ccd6e3fb1cfc670eed62728 100644 (file)
@@ -649,17 +649,15 @@ static int vfswrap_lstat(vfs_handle_struct *handle,
        return result;
 }
 
-static NTSTATUS vfswrap_translate_name(vfs_handle_struct *handle,
-                                      char **mapped_name,
-                                      enum vfs_translate_direction direction)
+static NTSTATUS vfswrap_translate_name(struct vfs_handle_struct *handle,
+                                      const char *name,
+                                      enum vfs_translate_direction direction,
+                                      TALLOC_CTX *mem_ctx,
+                                      char **mapped_name)
 {
-       /* Default behavior is a NOOP */
-
-       if (*mapped_name != NULL)
-               return NT_STATUS_OK;
-
-       return NT_STATUS_INVALID_PARAMETER;
+       return NT_STATUS_NONE_MAPPED;
 }
+
 /********************************************************************
  Given a stat buffer return the allocated size on disk, taking into
  account sparse files.
index 5305af48324418da5d4e5d285209a65b699dacb9..d9d12a1d285257fc6318c2bb2093900b46ea5fcd 100644 (file)
@@ -1517,13 +1517,16 @@ 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,
-                                             enum vfs_translate_direction direction)
+static NTSTATUS smb_full_audit_translate_name(struct vfs_handle_struct *handle,
+                                             const char *name,
+                                             enum vfs_translate_direction direction,
+                                             TALLOC_CTX *mem_ctx,
+                                             char **mapped_name)
 {
        NTSTATUS result;
 
-       result = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name, direction);
+       result = SMB_VFS_NEXT_TRANSLATE_NAME(handle, name, direction, mem_ctx,
+                                            mapped_name);
 
        do_log(SMB_VFS_OP_TRANSLATE_NAME, NT_STATUS_IS_OK(result), handle, "");
 
index d7b878b882a9900da632bbcead719725d7c8d28b..853d7b4d98c4ca9959568a9bdc0e37f6745cd816 100644 (file)
@@ -382,7 +382,8 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
 {
        char *dirname;
        SMB_STRUCT_DIR *dirhandle = NULL;
-       char *dirent = NULL;
+       const char *dirent = NULL;
+       char *talloced = NULL;
 
        dirname = stream_dir(handle, smb_fname_base, &smb_fname_base->st,
                             false);
@@ -406,20 +407,21 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle,
                return map_nt_error_from_unix(errno);
        }
 
-       while ((dirent = vfs_readdirname(handle->conn, dirhandle, NULL)) != NULL) {
+       while ((dirent = vfs_readdirname(handle->conn, dirhandle, NULL,
+                                        &talloced)) != NULL) {
 
                if (ISDOT(dirent) || ISDOTDOT(dirent)) {
-                       TALLOC_FREE(dirent);
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
                DEBUG(10, ("walk_streams: dirent=%s\n", dirent));
 
                if (!fn(dirname, dirent, private_data)) {
-                       TALLOC_FREE(dirent);
+                       TALLOC_FREE(talloced);
                        break;
                }
-               TALLOC_FREE(dirent);
+               TALLOC_FREE(talloced);
        }
 
        SMB_VFS_NEXT_CLOSEDIR(handle, dirhandle);
index 60fa0306b9265df60b298cae35e61bce21f83dd2..5d18d452f83a0fa38436257212887321d8ce8b2d 100644 (file)
@@ -585,16 +585,21 @@ int dptr_dnum(struct dptr_struct *dptr)
  Return the next visible file name, skipping veto'd and invisible files.
 ****************************************************************************/
 
-static char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
-                                          long *poffset, SMB_STRUCT_STAT *pst)
+static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
+                                          long *poffset, SMB_STRUCT_STAT *pst,
+                                          char **ptalloced)
 {
        /* Normal search for the next file. */
-       char *name;
-       while ((name = ReadDirName(dptr->dir_hnd, poffset, pst)) != NULL) {
+       const char *name;
+       char *talloced = NULL;
+
+       while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
+              != NULL) {
                if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
+                       *ptalloced = talloced;
                        return name;
                }
-               TALLOC_FREE(name);
+               TALLOC_FREE(talloced);
        }
        return NULL;
 }
@@ -610,6 +615,8 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
 {
        struct smb_filename *smb_fname_base = NULL;
        char *name = NULL;
+       const char *name_temp = NULL;
+       char *talloced = NULL;
        char *pathreal = NULL;
        char *found_name = NULL;
        int ret;
@@ -618,8 +625,15 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
        SET_STAT_INVALID(*pst);
 
        if (dptr->has_wild || dptr->did_stat) {
-               name = dptr_normal_ReadDirName(dptr, poffset, pst);
-               return name;
+               name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
+                                                   &talloced);
+               if (name_temp == NULL) {
+                       return NULL;
+               }
+               if (talloced != NULL) {
+                       return talloc_move(ctx, &talloced);
+               }
+               return talloc_strdup(ctx, name_temp);
        }
 
        /* If poffset is -1 then we know we returned this name before and we
@@ -706,9 +720,14 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
 
        TALLOC_FREE(pathreal);
 
-       name = dptr_normal_ReadDirName(dptr, poffset, pst);
-
-       return name;
+       name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
+       if (name_temp == NULL) {
+               return NULL;
+       }
+       if (talloced != NULL) {
+               return talloc_move(ctx, &talloced);
+       }
+       return talloc_strdup(ctx, name_temp);
 
 clean:
        TALLOC_FREE(pathreal);
@@ -1336,10 +1355,11 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
  Don't check for veto or invisible files.
 ********************************************************************/
 
-char *ReadDirName(struct smb_Dir *dirp, long *poffset,
-                       SMB_STRUCT_STAT *sbuf)
+const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
+                       SMB_STRUCT_STAT *sbuf, char **ptalloced)
 {
-       char *n;
+       const char *n;
+       char *talloced = NULL;
        connection_struct *conn = dirp->conn;
 
        /* Cheat to allow . and .. to be the first entries returned. */
@@ -1347,17 +1367,14 @@ char *ReadDirName(struct smb_Dir *dirp, long *poffset,
             (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
        {
                if (dirp->file_number == 0) {
-                       n = talloc_strdup(talloc_tos(), ".");
-                       if (n == NULL)
-                               return NULL;
+                       n = ".";
                        *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
                } else {
+                       n = "..";
                        *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
-                       n = talloc_strdup(talloc_tos(), "..");
-                       if (n == NULL)
-                               return NULL;
                }
                dirp->file_number++;
+               *ptalloced = NULL;
                return n;
        } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
                *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
@@ -1367,19 +1384,21 @@ char *ReadDirName(struct smb_Dir *dirp, long *poffset,
                SeekDir(dirp, *poffset);
        }
 
-       while ((n = vfs_readdirname(conn, dirp->dir, sbuf))) {
+       while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
                /* Ignore . and .. - we've already returned them. */
                if (*n == '.') {
                        if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
-                               TALLOC_FREE(n);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                }
                *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
+               *ptalloced = talloced;
                dirp->file_number++;
                return n;
        }
        *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
+       *ptalloced = NULL;
        return NULL;
 }
 
@@ -1474,7 +1493,8 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
 {
        int i;
-       char *entry = NULL;
+       const char *entry = NULL;
+       char *talloced = NULL;
        connection_struct *conn = dirp->conn;
 
        /* Search back in the name cache. */
@@ -1501,12 +1521,12 @@ bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
        SMB_VFS_REWINDDIR(conn, dirp->dir);
        dirp->file_number = 0;
        *poffset = START_OF_DIRECTORY_OFFSET;
-       while ((entry = ReadDirName(dirp, poffset, NULL))) {
+       while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
                if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
-                       TALLOC_FREE(entry);
+                       TALLOC_FREE(talloced);
                        return True;
                }
-               TALLOC_FREE(entry);
+               TALLOC_FREE(talloced);
        }
        return False;
 }
@@ -1520,7 +1540,8 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
 {
        NTSTATUS status = NT_STATUS_OK;
        long dirpos = 0;
-       char *dname = NULL;
+       const char *dname = NULL;
+       char *talloced = NULL;
        SMB_STRUCT_STAT st;
        struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname,
                                          NULL, 0);
@@ -1529,17 +1550,17 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
                return map_nt_error_from_unix(errno);
        }
 
-       while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
+       while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
                /* Quick check for "." and ".." */
                if (dname[0] == '.') {
                        if (!dname[1] || (dname[1] == '.' && !dname[2])) {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                }
 
                if (!is_visible_file(conn, dirname, dname, &st, True)) {
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
@@ -1548,7 +1569,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
                status = NT_STATUS_DIRECTORY_NOT_EMPTY;
                break;
        }
-       TALLOC_FREE(dname);
+       TALLOC_FREE(talloced);
        TALLOC_FREE(dir_hnd);
 
        return status;
index a64ca271144896c9e37743e31c0ade4b748c97c9..5d6661df2a13d1fad1b16e42ed3c6085b55c446b 100644 (file)
@@ -829,7 +829,8 @@ static int get_real_filename_full_scan(connection_struct *conn,
                                       TALLOC_CTX *mem_ctx, char **found_name)
 {
        struct smb_Dir *cur_dir;
-       char *dname = NULL;
+       const char *dname = NULL;
+       char *talloced = NULL;
        char *unmangled_name = NULL;
        long curpos;
 
@@ -881,11 +882,11 @@ static int get_real_filename_full_scan(connection_struct *conn,
 
        /* now scan for matching names */
        curpos = 0;
-       while ((dname = ReadDirName(cur_dir, &curpos, NULL))) {
+       while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
 
                /* Is it dot or dot dot. */
                if (ISDOT(dname) || ISDOTDOT(dname)) {
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
@@ -908,13 +909,13 @@ static int get_real_filename_full_scan(connection_struct *conn,
                        TALLOC_FREE(cur_dir);
                        if (!*found_name) {
                                errno = ENOMEM;
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                return -1;
                        }
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        return 0;
                }
-               TALLOC_FREE(dname);
+               TALLOC_FREE(talloced);
        }
 
        TALLOC_FREE(unmangled_name);
index 4a338fa5904707c1eb7ae2fbbe5ff29610081c26..fce84170454f215dadaa9f6de236dd302078cea9 100644 (file)
@@ -1505,7 +1505,8 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
 {
        size_t cnt = 0;
        SMB_STRUCT_DIR *dirp = NULL;
-       char *dname = NULL;
+       const char *dname = NULL;
+       char *talloced = NULL;
        const char *connect_path = lp_pathname(snum);
        const char *msdfs_proxy = lp_msdfs_proxy(snum);
        connection_struct *conn;
@@ -1542,13 +1543,14 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
                goto out;
        }
 
-       while ((dname = vfs_readdirname(conn, dirp, NULL)) != NULL) {
+       while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced))
+              != NULL) {
                if (is_msdfs_link(conn,
                                dname,
                                NULL)) {
                        cnt++;
                }
-               TALLOC_FREE(dname);
+               TALLOC_FREE(talloced);
        }
 
        SMB_VFS_CLOSEDIR(conn,dirp);
@@ -1569,7 +1571,8 @@ static int form_junctions(TALLOC_CTX *ctx,
 {
        size_t cnt = 0;
        SMB_STRUCT_DIR *dirp = NULL;
-       char *dname = NULL;
+       const char *dname = NULL;
+       char *talloced = NULL;
        const char *connect_path = lp_pathname(snum);
        char *service_name = lp_servicename(snum);
        const char *msdfs_proxy = lp_msdfs_proxy(snum);
@@ -1643,12 +1646,13 @@ static int form_junctions(TALLOC_CTX *ctx,
                goto out;
        }
 
-       while ((dname = vfs_readdirname(conn, dirp, NULL)) != NULL) {
+       while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced))
+              != NULL) {
                char *link_target = NULL;
                if (cnt >= jn_remain) {
                        DEBUG(2, ("form_junctions: ran out of MSDFS "
                                "junction slots"));
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        goto out;
                }
                if (is_msdfs_link_internal(ctx,
@@ -1666,7 +1670,7 @@ static int form_junctions(TALLOC_CTX *ctx,
                                                                dname);
                                if (!jucn[cnt].service_name ||
                                                !jucn[cnt].volume_name) {
-                                       TALLOC_FREE(dname);
+                                       TALLOC_FREE(talloced);
                                        goto out;
                                }
                                jucn[cnt].comment = "";
@@ -1674,7 +1678,7 @@ static int form_junctions(TALLOC_CTX *ctx,
                        }
                        TALLOC_FREE(link_target);
                }
-               TALLOC_FREE(dname);
+               TALLOC_FREE(talloced);
        }
 
 out:
index b4e0f574004571ec6eed19277767480b52f27128..ae88db7562fd595af28d663a8ee124ad0ce049f0 100644 (file)
@@ -2584,7 +2584,8 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
        } else {
                struct smb_Dir *dir_hnd = NULL;
                long offset = 0;
-               char *dname = NULL;
+               const char *dname = NULL;
+               char *talloced = NULL;
 
                if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
                        status = NT_STATUS_OBJECT_NAME_INVALID;
@@ -2620,27 +2621,27 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                status = NT_STATUS_NO_SUCH_FILE;
 
                while ((dname = ReadDirName(dir_hnd, &offset,
-                                           &smb_fname->st))) {
+                                           &smb_fname->st, &talloced))) {
                        TALLOC_CTX *frame = talloc_stackframe();
 
                        if (!is_visible_file(conn, fname_dir, dname,
                                             &smb_fname->st, true)) {
                                TALLOC_FREE(frame);
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
                        /* Quick check for "." and ".." */
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
                                TALLOC_FREE(frame);
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
                        if(!mask_match(dname, fname_mask,
                                       conn->case_sensitive)) {
                                TALLOC_FREE(frame);
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
@@ -2653,7 +2654,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);
+                               TALLOC_FREE(talloced);
                                goto out;
                        }
 
@@ -2661,14 +2662,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);
+                               TALLOC_FREE(talloced);
                                goto out;
                        }
 
                        status = do_unlink(conn, req, smb_fname, dirtype);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(frame);
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
@@ -2677,7 +2678,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                                 smb_fname->base_name));
 
                        TALLOC_FREE(frame);
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                }
                TALLOC_FREE(dir_hnd);
        }
@@ -5298,7 +5299,8 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
                        connection_struct *conn,
                        struct smb_filename *smb_dname)
 {
-       char *dname = NULL;
+       const char *dname = NULL;
+       char *talloced = NULL;
        bool ret = True;
        long offset = 0;
        SMB_STRUCT_STAT st;
@@ -5310,20 +5312,20 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
        if(dir_hnd == NULL)
                return False;
 
-       while((dname = ReadDirName(dir_hnd, &offset, &st))) {
+       while((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
                struct smb_filename *smb_dname_full = NULL;
                char *fullname = NULL;
                bool do_break = true;
                NTSTATUS status;
 
                if (ISDOT(dname) || ISDOTDOT(dname)) {
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
                if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
                                     false)) {
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
@@ -5366,7 +5368,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx,
         err_break:
                TALLOC_FREE(smb_dname_full);
                TALLOC_FREE(fullname);
-               TALLOC_FREE(dname);
+               TALLOC_FREE(talloced);
                if (do_break) {
                        ret = false;
                        break;
@@ -5420,7 +5422,8 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                 * do a recursive delete) then fail the rmdir.
                 */
                SMB_STRUCT_STAT st;
-               char *dname = NULL;
+               const char *dname = NULL;
+               char *talloced = NULL;
                long dirpos = 0;
                struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
                                                  smb_dname->base_name, NULL,
@@ -5431,23 +5434,24 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                        goto err;
                }
 
-               while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
+               while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
+                                           &talloced)) != NULL) {
                        if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                        if (!is_visible_file(conn, smb_dname->base_name, dname,
                                             &st, false)) {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                        if(!IS_VETO_PATH(conn, dname)) {
                                TALLOC_FREE(dir_hnd);
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                errno = ENOTEMPTY;
                                goto err;
                        }
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                }
 
                /* We only have veto files/directories.
@@ -5461,19 +5465,20 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
 
                /* Do a recursive delete. */
                RewindDir(dir_hnd,&dirpos);
-               while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
+               while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
+                                           &talloced)) != NULL) {
                        struct smb_filename *smb_dname_full = NULL;
                        char *fullname = NULL;
                        bool do_break = true;
                        NTSTATUS status;
 
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                        if (!is_visible_file(conn, smb_dname->base_name, dname,
                                             &st, false)) {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
@@ -5518,7 +5523,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
                 err_break:
                        TALLOC_FREE(fullname);
                        TALLOC_FREE(smb_dname_full);
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        if (do_break)
                                break;
                }
@@ -6131,7 +6136,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
        int count=0;
        NTSTATUS status = NT_STATUS_OK;
        struct smb_Dir *dir_hnd = NULL;
-       char *dname = NULL;
+       const char *dname = NULL;
+       char *talloced = NULL;
        long offset = 0;
        int create_options = 0;
        bool posix_pathnames = lp_posix_pathnames();
@@ -6309,7 +6315,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
         * - gentest fix. JRA
         */
 
-       while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
+       while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
+                                   &talloced))) {
                files_struct *fsp = NULL;
                char *destname = NULL;
                bool sysdir_entry = False;
@@ -6319,19 +6326,19 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                        if (attrs & aDIR) {
                                sysdir_entry = True;
                        } else {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                }
 
                if (!is_visible_file(conn, fname_src_dir, dname,
                                     &smb_fname_src->st, false)) {
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
                if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                        continue;
                }
 
@@ -6355,7 +6362,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);
+                       TALLOC_FREE(talloced);
                        continue;
                }
                if (!destname) {
@@ -6431,7 +6438,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(talloced);
        }
        TALLOC_FREE(dir_hnd);
 
@@ -6440,7 +6447,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
        }
 
  out:
-       TALLOC_FREE(dname);
+       TALLOC_FREE(talloced);
        TALLOC_FREE(fname_src_dir);
        TALLOC_FREE(fname_src_mask);
        return status;
@@ -6905,7 +6912,8 @@ void reply_copy(struct smb_request *req)
                }
        } else {
                struct smb_Dir *dir_hnd = NULL;
-               char *dname = NULL;
+               const char *dname = NULL;
+               char *talloced = NULL;
                long offset = 0;
 
                /*
@@ -6946,23 +6954,23 @@ void reply_copy(struct smb_request *req)
 
                /* Iterate over the src dir copying each entry to the dst. */
                while ((dname = ReadDirName(dir_hnd, &offset,
-                                           &smb_fname_src->st))) {
+                                           &smb_fname_src->st, &talloced))) {
                        char *destname = NULL;
 
                        if (ISDOT(dname) || ISDOTDOT(dname)) {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
                        if (!is_visible_file(conn, fname_src_dir, dname,
                                             &smb_fname_src->st, false)) {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
                        if(!mask_match(dname, fname_src_mask,
                                       conn->case_sensitive)) {
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
 
@@ -6976,7 +6984,7 @@ void reply_copy(struct smb_request *req)
 
                        if (!smb_fname_src->base_name) {
                                TALLOC_FREE(dir_hnd);
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
                        }
@@ -6984,12 +6992,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);
+                               TALLOC_FREE(talloced);
                                continue;
                        }
                        if (!destname) {
                                TALLOC_FREE(dir_hnd);
-                               TALLOC_FREE(dname);
+                               TALLOC_FREE(talloced);
                                reply_nterror(req, NT_STATUS_NO_MEMORY);
                                goto out;
                        }
@@ -7000,7 +7008,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);
+                               TALLOC_FREE(talloced);
                                reply_nterror(req, status);
                                goto out;
                        }
@@ -7008,7 +7016,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);
+                               TALLOC_FREE(talloced);
                                reply_nterror(req, status);
                                goto out;
                        }
@@ -7024,7 +7032,7 @@ void reply_copy(struct smb_request *req)
                                count++;
                        }
 
-                       TALLOC_FREE(dname);
+                       TALLOC_FREE(talloced);
                }
                TALLOC_FREE(dir_hnd);
        }
index 668defa5701c5373c500b56199f4be5d2db56ecb..1510bfcdd537440298f319a1619475ef5355829a 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;
 }
 
 /*******************************************************************
@@ -1550,11 +1553,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,