summaryrefslogtreecommitdiff
path: root/source3/smbd
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 /source3/smbd
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)
Diffstat (limited to 'source3/smbd')
-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
5 files changed, 145 insertions, 105 deletions
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,