From f6650f5d19ad90b8e1f392efbe211c4ffa0e70c0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 16 Nov 2009 09:49:23 +0100 Subject: s3: Do not talloc in readdir This is a hot codepath (called from the stat cache) --- source3/include/proto.h | 7 +-- source3/include/vfs.h | 12 +++-- source3/include/vfs_macros.h | 8 ++-- source3/modules/vfs_catia.c | 23 ++++++--- source3/modules/vfs_default.c | 16 +++---- source3/modules/vfs_full_audit.c | 11 +++-- source3/modules/vfs_streams_depot.c | 12 +++-- source3/smbd/dir.c | 81 ++++++++++++++++++++------------ source3/smbd/filename.c | 13 ++--- source3/smbd/msdfs.c | 20 ++++---- source3/smbd/reply.c | 94 ++++++++++++++++++++----------------- source3/smbd/vfs.c | 42 ++++++++++------- 12 files changed, 198 insertions(+), 141 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 6f971c3a07..9450140b90 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); diff --git a/source3/include/vfs.h b/source3/include/vfs.h index f9c1f0a54f..aee84a70b7 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -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, diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 7206bf41bb..c6f83bda07 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -345,10 +345,10 @@ #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)) diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 14e404f9f5..f1d0cadee7 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -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; } diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 8fbea0c4f3..848440809c 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -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. diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 5305af4832..d9d12a1d28 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -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, ""); diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index d7b878b882..853d7b4d98 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -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); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 60fa0306b9..5d18d452f8 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -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; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index a64ca27114..5d6661df2a 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -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); diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4a338fa590..fce8417045 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -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: diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b4e0f57400..ae88db7562 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -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); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 668defa570..1510bfcdd5 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -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, -- cgit