summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2009-11-16 09:49:23 +0100
committerVolker Lendecke <vl@samba.org>2009-11-18 23:16:13 +0100
commitf6650f5d19ad90b8e1f392efbe211c4ffa0e70c0 (patch)
tree6091c37e17a96edaaab867094b99bfe8c5aa456d
parentaea3a8f50131744f8393d0179cd04a1b97982028 (diff)
downloadsamba-f6650f5d19ad90b8e1f392efbe211c4ffa0e70c0.tar.gz
samba-f6650f5d19ad90b8e1f392efbe211c4ffa0e70c0.tar.bz2
samba-f6650f5d19ad90b8e1f392efbe211c4ffa0e70c0.zip
s3: Do not talloc in readdir
This is a hot codepath (called from the stat cache)
-rw-r--r--source3/include/proto.h7
-rw-r--r--source3/include/vfs.h12
-rw-r--r--source3/include/vfs_macros.h8
-rw-r--r--source3/modules/vfs_catia.c23
-rw-r--r--source3/modules/vfs_default.c16
-rw-r--r--source3/modules/vfs_full_audit.c11
-rw-r--r--source3/modules/vfs_streams_depot.c12
-rw-r--r--source3/smbd/dir.c81
-rw-r--r--source3/smbd/filename.c13
-rw-r--r--source3/smbd/msdfs.c20
-rw-r--r--source3/smbd/reply.c94
-rw-r--r--source3/smbd/vfs.c42
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,