summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2017-06-29 14:32:47 -0700
committerJeremy Allison <jra@samba.org>2017-07-01 03:07:11 +0200
commitbd9285b19741128bae501b721d9e63dd9a9bd833 (patch)
tree7fd477f84fc8d1e072e3acb550157ab2da68b597 /source3
parent6acb0d6ca08d72f776d3ba9dc934261a481aa737 (diff)
downloadsamba-bd9285b19741128bae501b721d9e63dd9a9bd833.tar.gz
s3: VFS: Change SMB_VFS_GETWD to return struct smb_filename * instead of char *.
We need to migrate all pathname based VFS calls to use a struct to finish modernising the VFS with extra timestamp and flags parameters. Signed-off-by: Jeremy Allison <jra@samba.org> Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com>
Diffstat (limited to 'source3')
-rw-r--r--source3/include/vfs.h12
-rw-r--r--source3/include/vfs_macros.h8
-rw-r--r--source3/modules/vfs_acl_common.c13
-rw-r--r--source3/modules/vfs_ceph.c9
-rw-r--r--source3/modules/vfs_default.c14
-rw-r--r--source3/modules/vfs_dirsort.c10
-rw-r--r--source3/modules/vfs_full_audit.c9
-rw-r--r--source3/modules/vfs_glusterfs.c12
-rw-r--r--source3/modules/vfs_netatalk.c25
-rw-r--r--source3/modules/vfs_preopen.c3
-rw-r--r--source3/modules/vfs_shadow_copy2.c12
-rw-r--r--source3/modules/vfs_time_audit.c7
-rw-r--r--source3/smbd/dir.c22
-rw-r--r--source3/smbd/msdfs.c22
-rw-r--r--source3/smbd/open.c43
-rw-r--r--source3/smbd/proto.h2
-rw-r--r--source3/smbd/service.c15
-rw-r--r--source3/smbd/vfs.c120
-rw-r--r--source3/torture/cmd_vfs.c8
-rw-r--r--source3/torture/torture.c82
20 files changed, 259 insertions, 189 deletions
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index f5ac5b5c82e..716e194a4ee 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -230,6 +230,10 @@
to const struct smb_filename * */
/* Version 37 - Change chdir from const char *
to const struct smb_filename * */
+/* Version 37 - Change getwd from char *
+ to const struct smb_filename * */
+/* Version 37 - Change conn->cwd from char *
+ to struct smb_filename * */
#define SMB_VFS_INTERFACE_VERSION 37
@@ -419,7 +423,7 @@ typedef struct connection_struct {
enum timestamp_set_resolution ts_res;
char *connectpath;
char *origpath;
- char *cwd; /* Working directory. */
+ struct smb_filename *cwd_fname; /* Working directory. */
struct vfs_handle_struct *vfs_handles; /* for the new plugins */
@@ -735,7 +739,8 @@ struct vfs_fn_pointers {
gid_t gid);
int (*chdir_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname);
- char *(*getwd_fn)(struct vfs_handle_struct *handle);
+ struct smb_filename *(*getwd_fn)(struct vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx);
int (*ntimes_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
struct smb_file_time *ft);
@@ -1237,7 +1242,8 @@ int smb_vfs_call_lchown(struct vfs_handle_struct *handle,
gid_t gid);
int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname);
-char *smb_vfs_call_getwd(struct vfs_handle_struct *handle);
+struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx);
int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
struct smb_file_time *ft);
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 367009bad07..29f03389cce 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -271,10 +271,10 @@
#define SMB_VFS_NEXT_CHDIR(handle, smb_fname) \
smb_vfs_call_chdir((handle)->next, (smb_fname))
-#define SMB_VFS_GETWD(conn) \
- smb_vfs_call_getwd((conn)->vfs_handles)
-#define SMB_VFS_NEXT_GETWD(handle) \
- smb_vfs_call_getwd((handle)->next)
+#define SMB_VFS_GETWD(conn, ctx) \
+ smb_vfs_call_getwd((conn)->vfs_handles, (ctx))
+#define SMB_VFS_NEXT_GETWD(handle, ctx) \
+ smb_vfs_call_getwd((handle)->next, (ctx))
#define SMB_VFS_NTIMES(conn, path, ts) \
smb_vfs_call_ntimes((conn)->vfs_handles, (path), (ts))
diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c
index 3b054df2b7d..6abf1e312fb 100644
--- a/source3/modules/vfs_acl_common.c
+++ b/source3/modules/vfs_acl_common.c
@@ -1300,15 +1300,13 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
struct smb_filename local_fname = {0};
struct smb_filename parent_dir_fname = {0};
int saved_errno = 0;
- char *saved_dir = NULL;
- struct smb_filename saved_dir_fname = {0};
+ struct smb_filename *saved_dir_fname = NULL;
- saved_dir = vfs_GetWd(talloc_tos(),conn);
- if (!saved_dir) {
+ saved_dir_fname = vfs_GetWd(talloc_tos(),conn);
+ if (saved_dir_fname == NULL) {
saved_errno = errno;
goto out;
}
- saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
if (!parent_dirname(talloc_tos(), smb_fname->base_name,
&parent_dir, &final_component)) {
@@ -1374,8 +1372,9 @@ static int acl_common_remove_object(vfs_handle_struct *handle,
TALLOC_FREE(parent_dir);
- if (saved_dir) {
- vfs_ChDir(conn, &saved_dir_fname);
+ if (saved_dir_fname) {
+ vfs_ChDir(conn, saved_dir_fname);
+ TALLOC_FREE(saved_dir_fname);
}
if (saved_errno) {
errno = saved_errno;
diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c
index 6b298a2e38f..7d3f4a7bbaa 100644
--- a/source3/modules/vfs_ceph.c
+++ b/source3/modules/vfs_ceph.c
@@ -949,11 +949,16 @@ static int cephwrap_chdir(struct vfs_handle_struct *handle,
WRAP_RETURN(result);
}
-static char *cephwrap_getwd(struct vfs_handle_struct *handle)
+static struct smb_filename *cephwrap_getwd(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx)
{
const char *cwd = ceph_getcwd(handle->data);
DBG_DEBUG("[CEPH] getwd(%p) = %s\n", handle, cwd);
- return SMB_STRDUP(cwd);
+ return synthetic_smb_fname(ctx,
+ cwd,
+ NULL,
+ NULL,
+ 0);
}
static int strict_allocate_ftruncate(struct vfs_handle_struct *handle, files_struct *fsp, off_t len)
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 7a2fae2156d..b01a0078180 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2099,14 +2099,24 @@ static int vfswrap_chdir(vfs_handle_struct *handle,
return result;
}
-static char *vfswrap_getwd(vfs_handle_struct *handle)
+static struct smb_filename *vfswrap_getwd(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx)
{
char *result;
+ struct smb_filename *smb_fname = NULL;
START_PROFILE(syscall_getwd);
result = sys_getwd();
END_PROFILE(syscall_getwd);
- return result;
+ smb_fname = synthetic_smb_fname(ctx,
+ result,
+ NULL,
+ NULL,
+ 0);
+ if (smb_fname == NULL) {
+ SAFE_FREE(result);
+ }
+ return smb_fname;
}
/*********************************************************************
diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c
index fc35186a402..c23f6f0152d 100644
--- a/source3/modules/vfs_dirsort.c
+++ b/source3/modules/vfs_dirsort.c
@@ -154,7 +154,15 @@ static DIR *dirsort_opendir(vfs_handle_struct *handle,
}
if (ISDOT(data->smb_fname->base_name)) {
- data->smb_fname->base_name = vfs_GetWd(data, handle->conn);
+ struct smb_filename *cwd_fname = vfs_GetWd(data, handle->conn);
+ if (cwd_fname == NULL) {
+ TALLOC_FREE(data);
+ return NULL;
+ }
+ TALLOC_FREE(data->smb_fname->base_name);
+ data->smb_fname->base_name = talloc_move(data->smb_fname,
+ &cwd_fname->base_name);
+ TALLOC_FREE(cwd_fname);
}
/* Open the underlying directory and count the number of entries */
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 5d35c340371..51783245566 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -1521,14 +1521,15 @@ static int smb_full_audit_chdir(vfs_handle_struct *handle,
return result;
}
-static char *smb_full_audit_getwd(vfs_handle_struct *handle)
+static struct smb_filename *smb_full_audit_getwd(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx)
{
- char *result;
+ struct smb_filename *result;
- result = SMB_VFS_NEXT_GETWD(handle);
+ result = SMB_VFS_NEXT_GETWD(handle, ctx);
do_log(SMB_VFS_OP_GETWD, (result != NULL), handle, "%s",
- result == NULL? "" : result);
+ result == NULL? "" : result->base_name);
return result;
}
diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index 833f093ac42..52539b36fd9 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -1076,10 +1076,12 @@ static int vfs_gluster_chdir(struct vfs_handle_struct *handle,
return glfs_chdir(handle->data, smb_fname->base_name);
}
-static char *vfs_gluster_getwd(struct vfs_handle_struct *handle)
+static struct smb_filename *vfs_gluster_getwd(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx)
{
char *cwd;
char *ret;
+ struct smb_filename *smb_fname = NULL;
cwd = SMB_CALLOC_ARRAY(char, PATH_MAX);
if (cwd == NULL) {
@@ -1090,7 +1092,13 @@ static char *vfs_gluster_getwd(struct vfs_handle_struct *handle)
if (ret == 0) {
free(cwd);
}
- return ret;
+ smb_fname = synthetic_smb_fname(ctx,
+ ret,
+ NULL,
+ NULL,
+ 0);
+ free(cwd);
+ return smb_fname;
}
static int vfs_gluster_ntimes(struct vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c
index 5715c6dd6ac..16c129de995 100644
--- a/source3/modules/vfs_netatalk.c
+++ b/source3/modules/vfs_netatalk.c
@@ -234,7 +234,7 @@ static int atalk_rmdir(struct vfs_handle_struct *handle,
const char *path = smb_fname->base_name;
char *dpath;
- if (!handle->conn->cwd || !path) goto exit_rmdir;
+ if (!handle->conn->cwd_fname->base_name || !path) goto exit_rmdir;
/* due to there is no way to change bDeleteVetoFiles variable
* from this module, gotta use talloc stuff..
@@ -246,7 +246,7 @@ static int atalk_rmdir(struct vfs_handle_struct *handle,
goto exit_rmdir;
if (!(dpath = talloc_asprintf(ctx, "%s/%s%s",
- handle->conn->cwd, path, add ? "/"APPLEDOUBLE : "")))
+ handle->conn->cwd_fname->base_name, path, add ? "/"APPLEDOUBLE : "")))
goto exit_rmdir;
atalk_rrmdir(ctx, dpath);
@@ -277,7 +277,7 @@ static int atalk_rename(struct vfs_handle_struct *handle,
return ret;
}
- if (atalk_build_paths(talloc_tos(), handle->conn->cwd, oldname,
+ if (atalk_build_paths(talloc_tos(), handle->conn->cwd_fname->base_name, oldname,
&adbl_path, &orig_path, &adbl_info,
&orig_info) != 0)
goto exit_rename;
@@ -338,7 +338,8 @@ static int atalk_unlink(struct vfs_handle_struct *handle,
}
}
- if (atalk_build_paths(talloc_tos(), handle->conn->cwd, path,
+ if (atalk_build_paths(talloc_tos(),
+ handle->conn->cwd_fname->base_name, path,
&adbl_path, &orig_path,
&adbl_info, &orig_info) != 0)
goto exit_unlink;
@@ -375,7 +376,7 @@ static int atalk_chmod(struct vfs_handle_struct *handle,
return ret;
ret1 = atalk_build_paths(ctx,
- handle->conn->cwd,
+ handle->conn->cwd_fname->base_name,
smb_fname->base_name,
&adbl_path,
&orig_path,
@@ -414,9 +415,10 @@ static int atalk_chown(struct vfs_handle_struct *handle,
if (!(ctx = talloc_init("chown_file")))
return ret;
- if (atalk_build_paths(ctx, handle->conn->cwd, smb_fname->base_name,
- &adbl_path, &orig_path,
- &adbl_info, &orig_info) != 0)
+ if (atalk_build_paths(ctx, handle->conn->cwd_fname->base_name,
+ smb_fname->base_name,
+ &adbl_path, &orig_path,
+ &adbl_info, &orig_info) != 0)
goto exit_chown;
if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) {
@@ -450,9 +452,10 @@ static int atalk_lchown(struct vfs_handle_struct *handle,
if (!(ctx = talloc_init("lchown_file")))
return ret;
- if (atalk_build_paths(ctx, handle->conn->cwd, smb_fname->base_name,
- &adbl_path, &orig_path,
- &adbl_info, &orig_info) != 0)
+ if (atalk_build_paths(ctx, handle->conn->cwd_fname->base_name,
+ smb_fname->base_name,
+ &adbl_path, &orig_path,
+ &adbl_info, &orig_info) != 0)
goto exit_lchown;
if (!S_ISDIR(orig_info.st_ex_mode) && !S_ISREG(orig_info.st_ex_mode)) {
diff --git a/source3/modules/vfs_preopen.c b/source3/modules/vfs_preopen.c
index 12ec4763a62..18b01e6c05e 100644
--- a/source3/modules/vfs_preopen.c
+++ b/source3/modules/vfs_preopen.c
@@ -408,7 +408,8 @@ static int preopen_open(vfs_handle_struct *handle,
TALLOC_FREE(state->template_fname);
state->template_fname = talloc_asprintf(
- state, "%s/%s", fsp->conn->cwd, smb_fname->base_name);
+ state, "%s/%s",
+ fsp->conn->cwd_fname->base_name, smb_fname->base_name);
if (state->template_fname == NULL) {
return res;
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index 4b5a7bccc97..b20213a698c 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -1523,19 +1523,19 @@ static void store_cwd_data(vfs_handle_struct *handle,
const char *connectpath)
{
struct shadow_copy2_private *priv = NULL;
- char *cwd = NULL;
+ struct smb_filename *cwd_fname = NULL;
SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
return);
TALLOC_FREE(priv->shadow_cwd);
- cwd = SMB_VFS_NEXT_GETWD(handle);
- if (cwd == NULL) {
+ cwd_fname = SMB_VFS_NEXT_GETWD(handle, talloc_tos());
+ if (cwd_fname == NULL) {
smb_panic("getwd failed\n");
}
- DBG_DEBUG("shadow cwd = %s\n", cwd);
- priv->shadow_cwd = talloc_strdup(priv, cwd);
- SAFE_FREE(cwd);
+ DBG_DEBUG("shadow cwd = %s\n", cwd_fname->base_name);
+ priv->shadow_cwd = talloc_strdup(priv, cwd_fname->base_name);
+ TALLOC_FREE(cwd_fname);
if (priv->shadow_cwd == NULL) {
smb_panic("talloc failed\n");
}
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index 820de3ffa2c..22075e7ac16 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -1257,14 +1257,15 @@ static int smb_time_audit_chdir(vfs_handle_struct *handle,
return result;
}
-static char *smb_time_audit_getwd(vfs_handle_struct *handle)
+static struct smb_filename *smb_time_audit_getwd(vfs_handle_struct *handle,
+ TALLOC_CTX *mem_ctx)
{
- char *result;
+ struct smb_filename *result;
struct timespec ts1,ts2;
double timediff;
clock_gettime_mono(&ts1);
- result = SMB_VFS_NEXT_GETWD(handle);
+ result = SMB_VFS_NEXT_GETWD(handle, mem_ctx);
clock_gettime_mono(&ts2);
timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 9391e3c827c..6b77409c73f 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -400,17 +400,14 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
{
struct smb_Dir *dir_hnd = NULL;
struct smb_filename *smb_fname_cwd = NULL;
- struct smb_filename saved_dir_fname = {0};
- char *saved_dir = vfs_GetWd(talloc_tos(), conn);
+ struct smb_filename *saved_dir_fname = vfs_GetWd(talloc_tos(), conn);
struct privilege_paths *priv_paths = req->priv_paths;
int ret;
- if (saved_dir == NULL) {
+ if (saved_dir_fname == NULL) {
return NULL;
}
- saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
-
if (vfs_ChDir(conn, smb_dname) == -1) {
return NULL;
}
@@ -441,8 +438,8 @@ static struct smb_Dir *open_dir_with_privilege(connection_struct *conn,
out:
- vfs_ChDir(conn, &saved_dir_fname);
- TALLOC_FREE(saved_dir);
+ vfs_ChDir(conn, saved_dir_fname);
+ TALLOC_FREE(saved_dir_fname);
return dir_hnd;
}
@@ -1683,16 +1680,13 @@ static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
{
struct smb_Dir *dir_hnd = NULL;
struct smb_filename *smb_fname_cwd = NULL;
- struct smb_filename saved_dir_fname = {0};
- char *saved_dir = vfs_GetWd(ctx, conn);
+ struct smb_filename *saved_dir_fname = vfs_GetWd(ctx, conn);
NTSTATUS status;
- if (saved_dir == NULL) {
+ if (saved_dir_fname == NULL) {
return NULL;
}
- saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
-
if (vfs_ChDir(conn, smb_dname) == -1) {
goto out;
}
@@ -1738,8 +1732,8 @@ static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
out:
- vfs_ChDir(conn, &saved_dir_fname);
- TALLOC_FREE(saved_dir);
+ vfs_ChDir(conn, saved_dir_fname);
+ TALLOC_FREE(saved_dir_fname);
return dir_hnd;
}
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index d87b9b9bace..3c23d745eee 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -403,8 +403,7 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
struct smb_filename **poldcwd_fname)
{
connection_struct *conn;
- char *oldcwd = NULL;
- struct smb_filename *smb_fname_oldcwd = NULL;
+ struct smb_filename *oldcwd_fname = NULL;
struct smb_filename smb_fname_connectpath = {0};
NTSTATUS status = create_conn_struct(ctx, ev,
@@ -421,25 +420,14 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
* user we will fail.... WTF ? JRA.
*/
- oldcwd = vfs_GetWd(ctx, conn);
- if (oldcwd == NULL) {
+ oldcwd_fname = vfs_GetWd(ctx, conn);
+ if (oldcwd_fname == NULL) {
status = map_nt_error_from_unix(errno);
DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno)));
conn_free(conn);
return status;
}
- smb_fname_oldcwd = synthetic_smb_fname(ctx,
- oldcwd,
- NULL,
- NULL,
- 0);
- if (smb_fname_oldcwd == NULL) {
- status = NT_STATUS_NO_MEMORY;
- conn_free(conn);
- return status;
- }
-
smb_fname_connectpath = (struct smb_filename) {
.base_name = conn->connectpath
};
@@ -449,13 +437,13 @@ NTSTATUS create_conn_struct_cwd(TALLOC_CTX *ctx,
DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. "
"Error was %s\n",
conn->connectpath, strerror(errno) ));
- TALLOC_FREE(smb_fname_oldcwd);
+ TALLOC_FREE(oldcwd_fname);
conn_free(conn);
return status;
}
*pconn = conn;
- *poldcwd_fname = smb_fname_oldcwd;
+ *poldcwd_fname = oldcwd_fname;
return NT_STATUS_OK;
}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 031ba11f1d2..ac637ba7834 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -411,8 +411,7 @@ static int process_symlink_open(struct connection_struct *conn,
int fd = -1;
char *link_target = NULL;
int link_len = -1;
- char *oldwd = NULL;
- struct smb_filename oldwd_fname = {0};
+ struct smb_filename *oldwd_fname = NULL;
size_t rootdir_len = 0;
char *resolved_name = NULL;
bool matched = false;
@@ -484,13 +483,11 @@ static int process_symlink_open(struct connection_struct *conn,
goto out;
}
- oldwd = vfs_GetWd(talloc_tos(), conn);
- if (oldwd == NULL) {
+ oldwd_fname = vfs_GetWd(talloc_tos(), conn);
+ if (oldwd_fname == NULL) {
goto out;
}
- oldwd_fname = (struct smb_filename) { .base_name = oldwd };
-
/* Ensure we operate from the root of the share. */
if (vfs_ChDir(conn, conn_rootdir_fname) == -1) {
goto out;
@@ -512,12 +509,12 @@ static int process_symlink_open(struct connection_struct *conn,
SAFE_FREE(resolved_name);
TALLOC_FREE(link_target);
- if (oldwd != NULL) {
- int ret = vfs_ChDir(conn, &oldwd_fname);
+ if (oldwd_fname != NULL) {
+ int ret = vfs_ChDir(conn, oldwd_fname);
if (ret == -1) {
smb_panic("unable to get back to old directory\n");
}
- TALLOC_FREE(oldwd);
+ TALLOC_FREE(oldwd_fname);
}
if (saved_errno != 0) {
errno = saved_errno;
@@ -541,8 +538,7 @@ static int non_widelink_open(struct connection_struct *conn,
int fd = -1;
struct smb_filename *smb_fname_rel = NULL;
int saved_errno = 0;
- char *oldwd = NULL;
- struct smb_filename oldwd_fname = {0};
+ struct smb_filename *oldwd_fname = NULL;
char *parent_dir = NULL;
struct smb_filename parent_dir_fname = {0};
const char *final_component = NULL;
@@ -556,13 +552,11 @@ static int non_widelink_open(struct connection_struct *conn,
parent_dir_fname = (struct smb_filename) { .base_name = parent_dir };
- oldwd = vfs_GetWd(talloc_tos(), conn);
- if (oldwd == NULL) {
+ oldwd_fname = vfs_GetWd(talloc_tos(), conn);
+ if (oldwd_fname == NULL) {
goto out;
}
- oldwd_fname = (struct smb_filename) { .base_name = oldwd };
-
/* Pin parent directory in place. */
if (vfs_ChDir(conn, &parent_dir_fname) == -1) {
goto out;
@@ -644,12 +638,12 @@ static int non_widelink_open(struct connection_struct *conn,
TALLOC_FREE(parent_dir);
TALLOC_FREE(smb_fname_rel);
- if (oldwd != NULL) {
- int ret = vfs_ChDir(conn, &oldwd_fname);
+ if (oldwd_fname != NULL) {
+ int ret = vfs_ChDir(conn, oldwd_fname);
if (ret == -1) {
smb_panic("unable to get back to old directory\n");
}
- TALLOC_FREE(oldwd);
+ TALLOC_FREE(oldwd_fname);
}
if (saved_errno != 0) {
errno = saved_errno;
@@ -837,8 +831,7 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
{
struct smb_filename *smb_fname_parent;
struct smb_filename *smb_fname_cwd = NULL;
- char *saved_dir = NULL;
- struct smb_filename smb_fname_saved_dir = {0};
+ struct smb_filename *saved_dir_fname = NULL;
TALLOC_CTX *ctx = talloc_tos();
NTSTATUS status = NT_STATUS_OK;
int ret;
@@ -869,8 +862,8 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
should work on any UNIX (thanks tridge :-). JRA.
*/
- saved_dir = vfs_GetWd(ctx,conn);
- if (!saved_dir) {
+ saved_dir_fname = vfs_GetWd(ctx,conn);
+ if (!saved_dir_fname) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to get "
"current working directory. Error was %s\n",
@@ -878,8 +871,6 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
goto out;
}
- smb_fname_saved_dir = (struct smb_filename) { .base_name = saved_dir };
-
/* Chdir into the new path. */
if (vfs_ChDir(conn, smb_dname) == -1) {
status = map_nt_error_from_unix(errno);
@@ -949,9 +940,9 @@ static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
}
chdir:
- vfs_ChDir(conn, &smb_fname_saved_dir);
+ vfs_ChDir(conn, saved_dir_fname);
out:
- TALLOC_FREE(saved_dir);
+ TALLOC_FREE(saved_dir_fname);
TALLOC_FREE(smb_fname_parent);
TALLOC_FREE(smb_fname_cwd);
return status;
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 4823e1170fc..7d641bdab19 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -1232,7 +1232,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p,
SMB_STRUCT_STAT *sbuf, char **talloced);
int vfs_ChDir(connection_struct *conn,
const struct smb_filename *smb_fname);
-char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
+struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
NTSTATUS check_reduced_name(connection_struct *conn,
const char *cwd_name,
const char *fname);
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 47cd0fa19d5..ed739c9baf1 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -68,10 +68,17 @@ bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
talloc_free(conn->connectpath);
conn->connectpath = destname;
- /* Ensure conn->cwd is initialized - start as conn->connectpath. */
- TALLOC_FREE(conn->cwd);
- conn->cwd = talloc_strdup(conn, conn->connectpath);
- if (!conn->cwd) {
+ /*
+ * Ensure conn->cwd_fname is initialized.
+ * start as conn->connectpath.
+ */
+ TALLOC_FREE(conn->cwd_fname);
+ conn->cwd_fname = synthetic_smb_fname(conn,
+ conn->connectpath,
+ NULL,
+ NULL,
+ 0);
+ if (conn->cwd_fname == NULL) {
return false;
}
return true;
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 40c41ed27fc..5c4e9c37b30 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -881,9 +881,14 @@ int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
LastDir = SMB_STRDUP(smb_fname->base_name);
/* conn cache. */
- TALLOC_FREE(conn->cwd);
- conn->cwd = vfs_GetWd(conn, conn);
- DEBUG(4,("vfs_ChDir got %s\n",conn->cwd));
+ TALLOC_FREE(conn->cwd_fname);
+ conn->cwd_fname = vfs_GetWd(conn, conn);
+ if (conn->cwd_fname == NULL) {
+ smb_panic("con->cwd getwd failed\n");
+ /* NOTREACHED */
+ return -1;
+ }
+ DEBUG(4,("vfs_ChDir got %s\n",conn->cwd_fname->base_name));
}
return ret;
}
@@ -894,14 +899,13 @@ int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
format. Note this can be called with conn == NULL.
********************************************************************/
-char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
+struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
{
- char *current_dir = NULL;
- char *result = NULL;
- DATA_BLOB cache_value;
+ struct smb_filename *current_dir_fname = NULL;
struct file_id key;
struct smb_filename *smb_fname_dot = NULL;
struct smb_filename *smb_fname_full = NULL;
+ struct smb_filename *result = NULL;
if (!lp_getwd_cache()) {
goto nocache;
@@ -925,20 +929,13 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
- if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
- data_blob_const(&key, sizeof(key)),
- &cache_value)) {
- goto nocache;
- }
-
- SMB_ASSERT((cache_value.length > 0)
- && (cache_value.data[cache_value.length-1] == '\0'));
+ smb_fname_full = (struct smb_filename *)memcache_lookup_talloc(
+ smbd_memcache(),
+ GETWD_CACHE,
+ data_blob_const(&key, sizeof(key)));
- smb_fname_full = synthetic_smb_fname(ctx, (char *)cache_value.data,
- NULL, NULL, 0);
if (smb_fname_full == NULL) {
- errno = ENOMEM;
- goto out;
+ goto nocache;
}
if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
@@ -947,8 +944,10 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
(S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
/*
* Ok, we're done
+ * Note: smb_fname_full is owned by smbd_memcache()
+ * so we must make a copy to return.
*/
- result = talloc_strdup(ctx, smb_fname_full->base_name);
+ result = cp_smb_filename(ctx, smb_fname_full);
if (result == NULL) {
errno = ENOMEM;
}
@@ -963,8 +962,8 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
* systems, or the not quite so bad getwd.
*/
- current_dir = SMB_VFS_GETWD(conn);
- if (current_dir == NULL) {
+ current_dir_fname = SMB_VFS_GETWD(conn, ctx);
+ if (current_dir_fname == NULL) {
DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
strerror(errno)));
goto out;
@@ -973,21 +972,39 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
- memcache_add(smbd_memcache(), GETWD_CACHE,
- data_blob_const(&key, sizeof(key)),
- data_blob_const(current_dir,
- strlen(current_dir)+1));
- }
+ /*
+ * smbd_memcache() will own current_dir_fname after the
+ * memcache_add_talloc call, so we must make
+ * a copy on ctx to return.
+ */
+ result = cp_smb_filename(ctx, current_dir_fname);
+ if (result == NULL) {
+ errno = ENOMEM;
+ }
- result = talloc_strdup(ctx, current_dir);
- if (result == NULL) {
- errno = ENOMEM;
+ /*
+ * Ensure the memory going into the cache
+ * doesn't have a destructor so it can be
+ * cleanly freed.
+ */
+ talloc_set_destructor(current_dir_fname, NULL);
+
+ memcache_add_talloc(smbd_memcache(),
+ GETWD_CACHE,
+ data_blob_const(&key, sizeof(key)),
+ &current_dir_fname);
+ /* current_dir_fname is now == NULL here. */
+ } else {
+ /* current_dir_fname is already allocated on ctx. */
+ result = current_dir_fname;
}
out:
TALLOC_FREE(smb_fname_dot);
- TALLOC_FREE(smb_fname_full);
- SAFE_FREE(current_dir);
+ /*
+ * Don't free current_dir_fname here. It's either been moved
+ * to the memcache or is being returned in result.
+ */
return result;
}
@@ -1009,7 +1026,6 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
char *dir_name = NULL;
const char *last_component = NULL;
char *resolved_name = NULL;
- char *saved_dir = NULL;
struct smb_filename *saved_dir_fname = NULL;
struct smb_filename *smb_fname_cwd = NULL;
struct privilege_paths *priv_paths = NULL;
@@ -1045,23 +1061,12 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
goto err;
}
/* Remember where we were. */
- saved_dir = vfs_GetWd(ctx, conn);
- if (!saved_dir) {
+ saved_dir_fname = vfs_GetWd(ctx, conn);
+ if (!saved_dir_fname) {
status = map_nt_error_from_unix(errno);
goto err;
}
- saved_dir_fname = synthetic_smb_fname(ctx,
- saved_dir,
- NULL,
- NULL,
- 0);
- if (saved_dir_fname == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto err;
- }
-
- /* Go to the parent directory to lock in memory. */
if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
status = map_nt_error_from_unix(errno);
goto err;
@@ -1177,9 +1182,8 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
err:
- if (saved_dir_fname) {
+ if (saved_dir_fname != NULL) {
vfs_ChDir(conn, saved_dir_fname);
- TALLOC_FREE(saved_dir);
TALLOC_FREE(saved_dir_fname);
}
SAFE_FREE(resolved_name);
@@ -2024,15 +2028,14 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
* and always act using lchown to ensure we
* don't deref any symbolic links.
*/
- char *saved_dir = NULL;
char *parent_dir = NULL;
const char *final_component = NULL;
struct smb_filename *local_smb_fname = NULL;
struct smb_filename parent_dir_fname = {0};
- struct smb_filename saved_dir_fname = {0};
+ struct smb_filename *saved_dir_fname = NULL;
- saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
- if (!saved_dir) {
+ saved_dir_fname = vfs_GetWd(talloc_tos(),fsp->conn);
+ if (!saved_dir_fname) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("vfs_chown_fsp: failed to get "
"current working directory. Error was %s\n",
@@ -2040,10 +2043,6 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
return status;
}
- saved_dir_fname = (struct smb_filename) {
- .base_name = saved_dir
- };
-
if (!parent_dirname(talloc_tos(),
fsp->fsp_name->base_name,
&parent_dir,
@@ -2098,9 +2097,9 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
out:
- vfs_ChDir(fsp->conn, &saved_dir_fname);
+ vfs_ChDir(fsp->conn, saved_dir_fname);
TALLOC_FREE(local_smb_fname);
- TALLOC_FREE(saved_dir);
+ TALLOC_FREE(saved_dir_fname);
TALLOC_FREE(parent_dir);
return status;
@@ -2131,10 +2130,11 @@ int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
return handle->fns->chdir_fn(handle, smb_fname);
}
-char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
+struct smb_filename *smb_vfs_call_getwd(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx)
{
VFS_FIND(getwd);
- return handle->fns->getwd_fn(handle);
+ return handle->fns->getwd_fn(handle, ctx);
}
int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c
index f6d9d5b6be7..fd09df9bcd6 100644
--- a/source3/torture/cmd_vfs.c
+++ b/source3/torture/cmd_vfs.c
@@ -1057,14 +1057,14 @@ static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc,
static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
- char *buf = SMB_VFS_GETWD(vfs->conn);
- if (buf == NULL) {
+ struct smb_filename *smb_fname = SMB_VFS_GETWD(vfs->conn, talloc_tos());
+ if (smb_fname == NULL) {
printf("getwd: error=%d (%s)\n", errno, strerror(errno));
return NT_STATUS_UNSUCCESSFUL;
}
- printf("getwd: %s\n", buf);
- SAFE_FREE(buf);
+ printf("getwd: %s\n", smb_fname->base_name);
+ TALLOC_FREE(smb_fname);
return NT_STATUS_OK;
}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 10e450ee4a7..6959b715b00 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -10580,15 +10580,25 @@ static bool data_blob_equal(DATA_BLOB a, DATA_BLOB b)
static bool run_local_memcache(int dummy)
{
struct memcache *cache;
- DATA_BLOB k1, k2;
- DATA_BLOB d1, d2, d3;
- DATA_BLOB v1, v2, v3;
+ DATA_BLOB k1, k2, k3;
+ DATA_BLOB d1, d3;
+ DATA_BLOB v1, v3;
TALLOC_CTX *mem_ctx;
+ char *ptr1 = NULL;
+ char *ptr2 = NULL;
+
char *str1, *str2;
size_t size1, size2;
bool ret = false;
+ mem_ctx = talloc_init("foo");
+ if (mem_ctx == NULL) {
+ return false;
+ }
+
+ /* STAT_CACHE TESTS */
+
cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
if (cache == NULL) {
@@ -10597,14 +10607,13 @@ static bool run_local_memcache(int dummy)
}
d1 = data_blob_const("d1", 2);
- d2 = data_blob_const("d2", 2);
d3 = data_blob_const("d3", 2);
k1 = data_blob_const("d1", 2);
k2 = data_blob_const("d2", 2);
+ k3 = data_blob_const("d3", 2);
memcache_add(cache, STAT_CACHE, k1, d1);
- memcache_add(cache, GETWD_CACHE, k2, d2);
if (!memcache_lookup(cache, STAT_CACHE, k1, &v1)) {
printf("could not find k1\n");
@@ -10614,40 +10623,79 @@ static bool run_local_memcache(int dummy)
return false;
}
- if (!memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
- printf("could not find k2\n");
+ memcache_add(cache, STAT_CACHE, k1, d3);
+
+ if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
+ printf("could not find replaced k1\n");
return false;
}
- if (!data_blob_equal(d2, v2)) {
+ if (!data_blob_equal(d3, v3)) {
return false;
}
- memcache_add(cache, STAT_CACHE, k1, d3);
+ TALLOC_FREE(cache);
- if (!memcache_lookup(cache, STAT_CACHE, k1, &v3)) {
- printf("could not find replaced k1\n");
+ /* GETWD_CACHE TESTS */
+ str1 = talloc_strdup(mem_ctx, "string1");
+ if (str1 == NULL) {
return false;
}
- if (!data_blob_equal(d3, v3)) {
+ ptr2 = str1; /* Keep an alias for comparison. */
+
+ str2 = talloc_strdup(mem_ctx, "string2");
+ if (str2 == NULL) {
+ return false;
+ }
+
+ cache = memcache_init(NULL, sizeof(void *) == 8 ? 200 : 100);
+ if (cache == NULL) {
+ printf("memcache_init failed\n");
+ return false;
+ }
+
+ memcache_add_talloc(cache, GETWD_CACHE, k2, &str1);
+ /* str1 == NULL now. */
+ ptr1 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
+ if (ptr1 == NULL) {
+ printf("could not find k2\n");
+ return false;
+ }
+ if (ptr1 != ptr2) {
+ printf("fetch of k2 got wrong string\n");
return false;
}
- memcache_add(cache, GETWD_CACHE, k1, d1);
+ /* Add a blob to ensure k2 gets purged. */
+ d3 = data_blob_talloc_zero(mem_ctx, 180);
+ memcache_add(cache, STAT_CACHE, k3, d3);
- if (memcache_lookup(cache, GETWD_CACHE, k2, &v2)) {
+ ptr2 = memcache_lookup_talloc(cache, GETWD_CACHE, k2);
+ if (ptr2 != NULL) {
printf("Did find k2, should have been purged\n");
return false;
}
TALLOC_FREE(cache);
-
- cache = memcache_init(NULL, 0);
+ TALLOC_FREE(mem_ctx);
mem_ctx = talloc_init("foo");
+ if (mem_ctx == NULL) {
+ return false;
+ }
+
+ cache = memcache_init(NULL, 0);
+ if (cache == NULL) {
+ return false;
+ }
str1 = talloc_strdup(mem_ctx, "string1");
+ if (str1 == NULL) {
+ return false;
+ }
str2 = talloc_strdup(mem_ctx, "string2");
-
+ if (str2 == NULL) {
+ return false;
+ }
memcache_add_talloc(cache, SINGLETON_CACHE_TALLOC,
data_blob_string_const("torture"), &str1);
size1 = talloc_total_size(cache);