Commit bd9285b1 authored by Jeremy Allison's avatar Jeremy Allison

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's avatarJeremy Allison <jra@samba.org>
Reviewed-by: Richard Sharpe's avatarRichard Sharpe <realrichardsharpe@gmail.com>
parent 6acb0d6c
......@@ -419,7 +419,8 @@ static int skel_chdir(vfs_handle_struct *handle,
return -1;
}
static char *skel_getwd(vfs_handle_struct *handle)
static struct smb_filename *skel_getwd(vfs_handle_struct *handle,
TALLOC_CTX *ctx)
{
errno = ENOSYS;
return NULL;
......
......@@ -521,9 +521,10 @@ static int skel_chdir(vfs_handle_struct *handle,
return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
}
static char *skel_getwd(vfs_handle_struct *handle)
static struct smb_filename *skel_getwd(vfs_handle_struct *handle,
TALLOC_CTX *ctx)
{
return SMB_VFS_NEXT_GETWD(handle);
return SMB_VFS_NEXT_GETWD(handle, ctx);
}
static int skel_ntimes(vfs_handle_struct *handle,
......
......@@ -54,6 +54,7 @@ static bool memcache_is_talloc(enum memcache_number n)
case PDB_GETPWSID_CACHE:
case SINGLETON_CACHE_TALLOC:
case SHARE_MODE_LOCK_CACHE:
case GETWD_CACHE:
result = true;
break;
default:
......
......@@ -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);
......
......@@ -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))
......
......@@ -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;
......
......@@ -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)
......
......@@ -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;
}
/*********************************************************************
......
......@@ -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 */
......
......@@ -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;
}
......
......@@ -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,
......
......@@ -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)) {
......
......@@ -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;
......
......@@ -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");
}
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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));
}
/*