return -1;
}
-static int skel_chdir(vfs_handle_struct *handle, const char *path)
+static int skel_chdir(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
errno = ENOSYS;
return -1;
return SMB_VFS_NEXT_LCHOWN(handle, smb_fname, uid, gid);
}
-static int skel_chdir(vfs_handle_struct *handle, const char *path)
+static int skel_chdir(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
- return SMB_VFS_NEXT_CHDIR(handle, path);
+ return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
}
static char *skel_getwd(vfs_handle_struct *handle)
to const struct smb_filename * */
/* Version 37 - Change symlink from const char *
to const struct smb_filename * */
+/* Version 37 - Change chdir from const char *
+ to const struct smb_filename * */
#define SMB_VFS_INTERFACE_VERSION 37
const struct smb_filename *smb_fname,
uid_t uid,
gid_t gid);
- int (*chdir_fn)(struct vfs_handle_struct *handle, const char *path);
+ int (*chdir_fn)(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname);
char *(*getwd_fn)(struct vfs_handle_struct *handle);
int (*ntimes_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
const struct smb_filename *smb_fname,
uid_t uid,
gid_t gid);
-int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path);
+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);
int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
#define SMB_VFS_NEXT_LCHOWN(handle, smb_fname, uid, gid) \
smb_vfs_call_lchown((handle)->next, (smb_fname), (uid), (gid))
-#define SMB_VFS_CHDIR(conn, path) \
- smb_vfs_call_chdir((conn)->vfs_handles, (path))
-#define SMB_VFS_NEXT_CHDIR(handle, path) \
- smb_vfs_call_chdir((handle)->next, (path))
+#define SMB_VFS_CHDIR(conn, smb_fname) \
+ smb_vfs_call_chdir((conn)->vfs_handles, (smb_fname))
+#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)
}
static int acl_common_remove_object(vfs_handle_struct *handle,
- const char *path,
+ const struct smb_filename *smb_fname,
bool is_directory)
{
connection_struct *conn = handle->conn;
int ret = 0;
char *parent_dir = NULL;
const char *final_component = NULL;
- struct smb_filename local_fname;
+ 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};
saved_dir = vfs_GetWd(talloc_tos(),conn);
if (!saved_dir) {
saved_errno = errno;
goto out;
}
+ saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
- if (!parent_dirname(talloc_tos(), path,
+ if (!parent_dirname(talloc_tos(), smb_fname->base_name,
&parent_dir, &final_component)) {
saved_errno = ENOMEM;
goto out;
DBG_DEBUG("removing %s %s/%s\n", is_directory ? "directory" : "file",
parent_dir, final_component);
+ parent_dir_fname = (struct smb_filename) { .base_name = parent_dir };
+
/* cd into the parent dir to pin it. */
- ret = vfs_ChDir(conn, parent_dir);
+ ret = vfs_ChDir(conn, &parent_dir_fname);
if (ret == -1) {
saved_errno = errno;
goto out;
}
- ZERO_STRUCT(local_fname);
local_fname.base_name = discard_const_p(char, final_component);
/* Must use lstat here. */
TALLOC_FREE(parent_dir);
if (saved_dir) {
- vfs_ChDir(conn, saved_dir);
+ vfs_ChDir(conn, &saved_dir_fname);
}
if (saved_errno) {
errno = saved_errno;
/* Failed due to access denied,
see if we need to root override. */
return acl_common_remove_object(handle,
- smb_fname->base_name,
+ smb_fname,
true);
}
return -1;
}
return acl_common_remove_object(handle,
- smb_fname->base_name,
+ smb_fname,
false);
}
return ret;
}
-static int cap_chdir(vfs_handle_struct *handle, const char *path)
+static int cap_chdir(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
- char *cappath = capencode(talloc_tos(), path);
+ struct smb_filename *cap_smb_fname = NULL;
+ char *cappath = capencode(talloc_tos(), smb_fname->base_name);
+ int ret;
+ int saved_errno = 0;
if (!cappath) {
errno = ENOMEM;
return -1;
}
- DEBUG(3,("cap: cap_chdir for %s\n", path));
- return SMB_VFS_NEXT_CHDIR(handle, cappath);
+ DEBUG(3,("cap: cap_chdir for %s\n", smb_fname->base_name));
+
+ cap_smb_fname = synthetic_smb_fname(talloc_tos(),
+ cappath,
+ NULL,
+ NULL,
+ smb_fname->flags);
+ if (cap_smb_fname == NULL) {
+ TALLOC_FREE(cappath);
+ errno = ENOMEM;
+ return -1;
+ }
+ ret = SMB_VFS_NEXT_CHDIR(handle, cap_smb_fname);
+ if (ret == -1) {
+ saved_errno = errno;
+ }
+ TALLOC_FREE(cappath);
+ TALLOC_FREE(cap_smb_fname);
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
+ return ret;
}
static int cap_ntimes(vfs_handle_struct *handle,
}
static int catia_chdir(vfs_handle_struct *handle,
- const char *path)
+ const struct smb_filename *smb_fname)
{
char *name = NULL;
+ struct smb_filename *catia_smb_fname = NULL;
NTSTATUS status;
int ret;
- status = catia_string_replace_allocate(handle->conn, path,
- &name, vfs_translate_to_unix);
+ status = catia_string_replace_allocate(handle->conn,
+ smb_fname->base_name,
+ &name,
+ vfs_translate_to_unix);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return -1;
}
- ret = SMB_VFS_NEXT_CHDIR(handle, name);
+ catia_smb_fname = synthetic_smb_fname(talloc_tos(),
+ name,
+ NULL,
+ NULL,
+ smb_fname->flags);
+ if (catia_smb_fname == NULL) {
+ TALLOC_FREE(name);
+ errno = ENOMEM;
+ return -1;
+ }
+ ret = SMB_VFS_NEXT_CHDIR(handle, catia_smb_fname);
TALLOC_FREE(name);
+ TALLOC_FREE(catia_smb_fname);
return ret;
}
WRAP_RETURN(result);
}
-static int cephwrap_chdir(struct vfs_handle_struct *handle, const char *path)
+static int cephwrap_chdir(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
int result = -1;
- DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle, path);
+ DBG_DEBUG("[CEPH] chdir(%p, %s)\n", handle, smb_fname->base_name);
/*
* If the path is just / use chdir because Ceph is below / and
* cannot deal with changing directory above its mount point
*/
- if (path && !strcmp(path, "/"))
- return chdir(path);
+ if (!strcmp(smb_fname->base_name, "/")) {
+ return chdir(smb_fname->base_name);
+ }
- result = ceph_chdir(handle->data, path);
+ result = ceph_chdir(handle->data, smb_fname->base_name);
DBG_DEBUG("[CEPH] chdir(...) = %d\n", result);
WRAP_RETURN(result);
}
!handle->conn->sconn->using_smb2,
junction, &consumedcnt, &self_referral);
if (!NT_STATUS_IS_OK(status)) {
- vfs_ChDir(handle->conn, handle->conn->connectpath);
+ struct smb_filename connectpath_fname = {
+ .base_name = handle->conn->connectpath
+ };
+ vfs_ChDir(handle->conn, &connectpath_fname);
return status;
}
- vfs_ChDir(handle->conn, handle->conn->connectpath);
+ {
+ struct smb_filename connectpath_fname = {
+ .base_name = handle->conn->connectpath
+ };
+ vfs_ChDir(handle->conn, &connectpath_fname);
+ }
if (!self_referral) {
pathnamep[consumedcnt] = '\0';
return result;
}
-static int vfswrap_chdir(vfs_handle_struct *handle, const char *path)
+static int vfswrap_chdir(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
int result;
START_PROFILE(syscall_chdir);
- result = chdir(path);
+ result = chdir(smb_fname->base_name);
END_PROFILE(syscall_chdir);
return result;
}
}
static int smb_full_audit_chdir(vfs_handle_struct *handle,
- const char *path)
+ const struct smb_filename *smb_fname)
{
int result;
- result = SMB_VFS_NEXT_CHDIR(handle, path);
+ result = SMB_VFS_NEXT_CHDIR(handle, smb_fname);
- do_log(SMB_VFS_OP_CHDIR, (result >= 0), handle, "chdir|%s", path);
+ do_log(SMB_VFS_OP_CHDIR, (result >= 0), handle, "chdir|%s",
+ smb_fname->base_name);
return result;
}
return glfs_lchown(handle->data, smb_fname->base_name, uid, gid);
}
-static int vfs_gluster_chdir(struct vfs_handle_struct *handle, const char *path)
+static int vfs_gluster_chdir(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
- return glfs_chdir(handle->data, path);
+ return glfs_chdir(handle->data, smb_fname->base_name);
}
static char *vfs_gluster_getwd(struct vfs_handle_struct *handle)
* Failure: set errno, return -1
*/
static int mh_chdir(vfs_handle_struct *handle,
- const char *path)
+ const struct smb_filename *smb_fname)
{
int status;
- char *clientPath;
- TALLOC_CTX *ctx;
+ struct smb_filename *clientFname = NULL;
DEBUG(MH_INFO_DEBUG, ("Entering mh_chdir\n"));
- if (!is_in_media_files(path))
- {
- status = SMB_VFS_NEXT_CHDIR(handle, path);
+ if (!is_in_media_files(smb_fname->base_name)) {
+ status = SMB_VFS_NEXT_CHDIR(handle, smb_fname);
goto out;
}
- clientPath = NULL;
- ctx = talloc_tos();
-
- if ((status = alloc_get_client_path(handle, ctx,
- path,
- &clientPath)))
- {
+ status = alloc_get_client_smb_fname(handle,
+ talloc_tos(),
+ smb_fname,
+ &clientFname);
+ if (status != 0) {
goto err;
}
- status = SMB_VFS_NEXT_CHDIR(handle, clientPath);
+ status = SMB_VFS_NEXT_CHDIR(handle, clientFname);
err:
- TALLOC_FREE(clientPath);
+ TALLOC_FREE(clientFname);
out:
return status;
}
}
static int shadow_copy2_chdir(vfs_handle_struct *handle,
- const char *fname)
+ const struct smb_filename *smb_fname)
{
time_t timestamp = 0;
char *stripped = NULL;
int saved_errno = 0;
char *conv = NULL;
size_t rootpath_len = 0;
+ struct smb_filename *conv_smb_fname = NULL;
- if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, fname,
- ×tamp, &stripped, &snappath)) {
+ if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
+ handle,
+ smb_fname->base_name,
+ ×tamp,
+ &stripped,
+ &snappath)) {
return -1;
}
if (stripped != NULL) {
if (conv == NULL) {
return -1;
}
- fname = conv;
+ conv_smb_fname = synthetic_smb_fname(talloc_tos(),
+ conv,
+ NULL,
+ NULL,
+ smb_fname->flags);
+ } else {
+ conv_smb_fname = cp_smb_filename(talloc_tos(), smb_fname);
}
- ret = SMB_VFS_NEXT_CHDIR(handle, fname);
+ if (conv_smb_fname == NULL) {
+ TALLOC_FREE(conv);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ret = SMB_VFS_NEXT_CHDIR(handle, conv_smb_fname);
if (ret == -1) {
saved_errno = errno;
}
TALLOC_FREE(stripped);
TALLOC_FREE(conv);
+ TALLOC_FREE(conv_smb_fname);
if (saved_errno != 0) {
errno = saved_errno;
}
static int snapper_gmt_chdir(vfs_handle_struct *handle,
- const char *fname)
+ const struct smb_filename *smb_fname)
{
- time_t timestamp;
- char *stripped;
- int ret, saved_errno;
- char *conv;
+ time_t timestamp = 0;
+ char *stripped = NULL;
+ int ret;
+ int saved_errno = 0;
+ char *conv = NULL;
+ struct smb_filename *conv_smb_fname = NULL;
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname,
- ×tamp, &stripped)) {
+ if (!snapper_gmt_strip_snapshot(talloc_tos(),
+ handle,
+ smb_fname->base_name,
+ ×tamp,
+ &stripped)) {
return -1;
}
if (timestamp == 0) {
- return SMB_VFS_NEXT_CHDIR(handle, fname);
+ return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
}
conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
TALLOC_FREE(stripped);
if (conv == NULL) {
return -1;
}
- ret = SMB_VFS_NEXT_CHDIR(handle, conv);
- saved_errno = errno;
+ conv_smb_fname = synthetic_smb_fname(talloc_tos(),
+ conv,
+ NULL,
+ NULL,
+ smb_fname->flags);
+ if (conv_smb_fname == NULL) {
+ TALLOC_FREE(conv);
+ errno = ENOMEM;
+ return -1;
+ }
+ ret = SMB_VFS_NEXT_CHDIR(handle, conv_smb_fname);
+ if (ret == -1) {
+ saved_errno = errno;
+ }
TALLOC_FREE(conv);
- errno = saved_errno;
+ TALLOC_FREE(conv_smb_fname);
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
return ret;
}
return result;
}
-static int smb_time_audit_chdir(vfs_handle_struct *handle, const char *path)
+static int smb_time_audit_chdir(vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
int result;
struct timespec ts1,ts2;
double timediff;
clock_gettime_mono(&ts1);
- result = SMB_VFS_NEXT_CHDIR(handle, path);
+ result = SMB_VFS_NEXT_CHDIR(handle, smb_fname);
clock_gettime_mono(&ts2);
timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
if (timediff > audit_timeout) {
- smb_time_audit_log_fname("chdir", timediff, path);
+ smb_time_audit_log_fname("chdir",
+ timediff,
+ smb_fname->base_name);
}
return result;
}
static int um_chdir(vfs_handle_struct *handle,
- const char *path)
+ const struct smb_filename *smb_fname)
{
int status;
- char *client_path = NULL;
+ struct smb_filename *client_fname = NULL;
DEBUG(10, ("Entering um_chdir\n"));
- if (!is_in_media_files(path)) {
- return SMB_VFS_NEXT_CHDIR(handle, path);
+ if (!is_in_media_files(smb_fname->base_name)) {
+ return SMB_VFS_NEXT_CHDIR(handle, smb_fname);
}
- status = alloc_get_client_path(handle, talloc_tos(),
- path, &client_path);
+ status = alloc_get_client_smb_fname(handle,
+ talloc_tos(),
+ smb_fname,
+ &client_fname);
if (status != 0) {
goto err;
}
- status = SMB_VFS_NEXT_CHDIR(handle, client_path);
+ status = SMB_VFS_NEXT_CHDIR(handle, client_fname);
err:
- TALLOC_FREE(client_path);
+ TALLOC_FREE(client_fname);
return status;
}
struct smb_filename *smb_fname = NULL;
files_struct *fsp = NULL;
connection_struct *conn = NULL;
- char *oldcwd;
+ struct smb_filename *oldcwd_fname = NULL;
char *printdollar = NULL;
char *printdollar_path = NULL;
char *working_dir = NULL;
&conn,
printdollar_snum,
working_dir,
- session_info, &oldcwd);
+ session_info, &oldcwd_fname);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("get_correct_cversion: create_conn_struct "
"returned %s\n", nt_errstr(nt_status)));
close_file(NULL, fsp, NORMAL_CLOSE);
}
if (conn != NULL) {
- vfs_ChDir(conn, oldcwd);
+ vfs_ChDir(conn, oldcwd_fname);
+ TALLOC_FREE(oldcwd_fname);
SMB_VFS_DISCONNECT(conn);
conn_free(conn);
}
int i;
TALLOC_CTX *ctx = talloc_tos();
int ver = 0;
- char *oldcwd;
+ struct smb_filename *oldcwd_fname = NULL;
char *printdollar = NULL;
int printdollar_snum;
WERROR err = WERR_OK;
&conn,
printdollar_snum,
lp_path(talloc_tos(), printdollar_snum),
- session_info, &oldcwd);
+ session_info, &oldcwd_fname);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("move_driver_to_download_area: create_conn_struct "
"returned %s\n", nt_errstr(nt_status)));
TALLOC_FREE(smb_dname);
if (conn != NULL) {
- vfs_ChDir(conn, oldcwd);
+ vfs_ChDir(conn, oldcwd_fname);
+ TALLOC_FREE(oldcwd_fname);
SMB_VFS_DISCONNECT(conn);
conn_free(conn);
}
const char *short_arch;
connection_struct *conn;
NTSTATUS nt_status;
- char *oldcwd;
+ struct smb_filename *oldcwd_fname = NULL;
char *printdollar = NULL;
int printdollar_snum;
bool ret = false;
&conn,
printdollar_snum,
lp_path(talloc_tos(), printdollar_snum),
- session_info, &oldcwd);
+ session_info, &oldcwd_fname);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("delete_driver_files: create_conn_struct "
"returned %s\n", nt_errstr(nt_status)));
unbecome_user();
err_free_conn:
if (conn != NULL) {
- vfs_ChDir(conn, oldcwd);
+ vfs_ChDir(conn, oldcwd_fname);
+ TALLOC_FREE(oldcwd_fname);
SMB_VFS_DISCONNECT(conn);
conn_free(conn);
}
struct sec_desc_buf *sd_buf = NULL;
files_struct *fsp = NULL;
int snum;
- char *oldcwd = NULL;
+ struct smb_filename *oldcwd_fname = NULL;
uint32_t ucf_flags = 0;
ZERO_STRUCT(st);
server_messaging_context(),
&conn,
snum, lp_path(talloc_tos(), snum),
- p->session_info, &oldcwd);
+ p->session_info, &oldcwd_fname);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(10, ("create_conn_struct failed: %s\n",
nt_errstr(nt_status)));
*r->out.sd_buf = sd_buf;
- close_file(NULL, fsp, NORMAL_CLOSE);
- vfs_ChDir(conn, oldcwd);
- SMB_VFS_DISCONNECT(conn);
- conn_free(conn);
werr = WERR_OK;
- goto done;
error_exit:
close_file(NULL, fsp, NORMAL_CLOSE);
}
- if (oldcwd) {
- vfs_ChDir(conn, oldcwd);
+ if (oldcwd_fname) {
+ vfs_ChDir(conn, oldcwd_fname);
+ TALLOC_FREE(oldcwd_fname);
}
if (conn) {
conn_free(conn);
}
- done:
-
TALLOC_FREE(smb_fname);
return werr;
WERROR werr;
connection_struct *conn = NULL;
int snum;
- char *oldcwd = NULL;
+ struct smb_filename *oldcwd_fname = NULL;
struct security_descriptor *psd = NULL;
uint32_t security_info_sent = 0;
uint32_t ucf_flags = 0;
server_messaging_context(),
&conn,
snum, lp_path(talloc_tos(), snum),
- p->session_info, &oldcwd);
+ p->session_info, &oldcwd_fname);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(10, ("create_conn_struct failed: %s\n",
nt_errstr(nt_status)));
goto error_exit;
}
- close_file(NULL, fsp, NORMAL_CLOSE);
- vfs_ChDir(conn, oldcwd);
- SMB_VFS_DISCONNECT(conn);
- conn_free(conn);
werr = WERR_OK;
- goto done;
error_exit:
close_file(NULL, fsp, NORMAL_CLOSE);
}
- if (oldcwd) {
- vfs_ChDir(conn, oldcwd);
+ if (oldcwd_fname) {
+ vfs_ChDir(conn, oldcwd_fname);
+ TALLOC_FREE(oldcwd_fname);
}
if (conn) {
conn_free(conn);
}
- done:
TALLOC_FREE(smb_fname);
return werr;
uint32_t attr)
{
struct smb_Dir *dir_hnd = NULL;
- struct smb_filename *smb_fname_cwd;
+ struct smb_filename *smb_fname_cwd = NULL;
+ struct smb_filename saved_dir_fname = {0};
char *saved_dir = vfs_GetWd(talloc_tos(), conn);
struct privilege_paths *priv_paths = req->priv_paths;
int ret;
return NULL;
}
- if (vfs_ChDir(conn, smb_dname->base_name) == -1) {
+ saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
+
+ if (vfs_ChDir(conn, smb_dname) == -1) {
return NULL;
}
out:
- vfs_ChDir(conn, saved_dir);
+ vfs_ChDir(conn, &saved_dir_fname);
+ TALLOC_FREE(saved_dir);
return dir_hnd;
}
{
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);
NTSTATUS status;
return NULL;
}
- if (vfs_ChDir(conn, smb_dname->base_name) == -1) {
+ saved_dir_fname = (struct smb_filename) { .base_name = saved_dir };
+
+ if (vfs_ChDir(conn, smb_dname) == -1) {
goto out;
}
out:
- vfs_ChDir(conn, saved_dir);
+ vfs_ChDir(conn, &saved_dir_fname);
TALLOC_FREE(saved_dir);
return dir_hnd;
}
int snum,
const char *path,
const struct auth_session_info *session_info,
- char **poldcwd)
+ struct smb_filename **poldcwd_fname)
{
connection_struct *conn;
- char *oldcwd;
+ char *oldcwd = NULL;
+ struct smb_filename *smb_fname_oldcwd = NULL;
+ struct smb_filename smb_fname_connectpath = {0};
NTSTATUS status = create_conn_struct(ctx, ev,
msg, &conn,
return status;
}
- if (vfs_ChDir(conn,conn->connectpath) != 0) {
+ 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
+ };
+
+ if (vfs_ChDir(conn, &smb_fname_connectpath) != 0) {
status = map_nt_error_from_unix(errno);
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);
conn_free(conn);
return status;
}
*pconn = conn;
- *poldcwd = oldcwd;
+ *poldcwd_fname = smb_fname_oldcwd;
return NT_STATUS_OK;
}
NTSTATUS status = NT_STATUS_NOT_FOUND;
bool dummy;
struct dfs_path *pdp = talloc(ctx, struct dfs_path);
- char *oldpath;
+ struct smb_filename *oldcwd_fname = NULL;
if (!pdp) {
return NT_STATUS_NO_MEMORY;
status = create_conn_struct_cwd(ctx,
server_event_context(),
server_messaging_context(),
- &conn, snum,
- lp_path(talloc_tos(), snum), NULL, &oldpath);
+ &conn,
+ snum,
+ lp_path(talloc_tos(), snum),
+ NULL,
+ &oldcwd_fname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(pdp);
return status;
status = NT_STATUS_OK;
err_exit:
- vfs_ChDir(conn, oldpath);
+ vfs_ChDir(conn, oldcwd_fname);
+ TALLOC_FREE(oldcwd_fname);
SMB_VFS_DISCONNECT(conn);
conn_free(conn);
TALLOC_FREE(pdp);
static bool junction_to_local_path(const struct junction_map *jucn,
char **pp_path_out,
connection_struct **conn_out,
- char **oldpath)
+ struct smb_filename **oldpath_fname)
{
int snum;
NTSTATUS status;
server_event_context(),
server_messaging_context(),
conn_out,
- snum, lp_path(talloc_tos(), snum), NULL, oldpath);
+ snum,
+ lp_path(talloc_tos(), snum),
+ NULL,
+ oldpath_fname);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
lp_path(talloc_tos(), snum),
jucn->volume_name);
if (!*pp_path_out) {
- vfs_ChDir(*conn_out, *oldpath);
+ vfs_ChDir(*conn_out, *oldpath_fname);
SMB_VFS_DISCONNECT(*conn_out);
conn_free(*conn_out);
return False;
bool create_msdfs_link(const struct junction_map *jucn)
{
char *path = NULL;
- char *cwd;
+ struct smb_filename *cwd_fname = NULL;
char *msdfs_link = NULL;
connection_struct *conn;
int i=0;
bool ret = False;
struct smb_filename *smb_fname = NULL;
- if(!junction_to_local_path(jucn, &path, &conn, &cwd)) {
+ if(!junction_to_local_path(jucn, &path, &conn, &cwd_fname)) {
return False;
}
out:
TALLOC_FREE(smb_fname);
- vfs_ChDir(conn, cwd);
+ vfs_ChDir(conn, cwd_fname);
+ TALLOC_FREE(cwd_fname);
SMB_VFS_DISCONNECT(conn);
conn_free(conn);
return ret;
bool remove_msdfs_link(const struct junction_map *jucn)
{
char *path = NULL;
- char *cwd;
+ struct smb_filename *cwd_fname = NULL;
connection_struct *conn;
bool ret = False;
struct smb_filename *smb_fname;
- if (!junction_to_local_path(jucn, &path, &conn, &cwd)) {
+ if (!junction_to_local_path(jucn, &path, &conn, &cwd_fname)) {
return false;
}
}
TALLOC_FREE(smb_fname);
- vfs_ChDir(conn, cwd);
+ vfs_ChDir(conn, cwd_fname);
+ TALLOC_FREE(cwd_fname);
SMB_VFS_DISCONNECT(conn);
conn_free(conn);
return ret;
const char *msdfs_proxy = lp_msdfs_proxy(talloc_tos(), snum);
connection_struct *conn;
NTSTATUS status;
- char *cwd;
+ struct smb_filename *cwd_fname = NULL;
struct smb_filename *smb_fname = NULL;
if(*connect_path == '\0') {
server_event_context(),
server_messaging_context(),
&conn,
- snum, connect_path, NULL, &cwd);
+ snum,
+ connect_path,
+ NULL,
+ &cwd_fname);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("create_conn_struct failed: %s\n",
nt_errstr(status)));
out:
TALLOC_FREE(smb_fname);
- vfs_ChDir(conn, cwd);
+ vfs_ChDir(conn, cwd_fname);
+ TALLOC_FREE(cwd_fname);
SMB_VFS_DISCONNECT(conn);
conn_free(conn);
return cnt;
const char *msdfs_proxy = lp_msdfs_proxy(talloc_tos(), snum);
connection_struct *conn;
struct referral *ref = NULL;
- char *cwd;
+ struct smb_filename *cwd_fname = NULL;
struct smb_filename *smb_fname = NULL;
NTSTATUS status;
status = create_conn_struct_cwd(ctx,
server_event_context(),
server_messaging_context(),
- &conn, snum, connect_path, NULL,
- &cwd);
+ &conn,
+ snum,
+ connect_path,
+ NULL,
+ &cwd_fname);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("create_conn_struct failed: %s\n",
nt_errstr(status)));
}
TALLOC_FREE(smb_fname);
- vfs_ChDir(conn, cwd);
+ vfs_ChDir(conn, cwd_fname);
+ TALLOC_FREE(cwd_fname);
conn_free(conn);
return cnt;
}
}
static int non_widelink_open(struct connection_struct *conn,
- const char *conn_rootdir,
+ const struct smb_filename *conn_rootdir_fname,
files_struct *fsp,
struct smb_filename *smb_fname,
int flags,
****************************************************************************/
static int process_symlink_open(struct connection_struct *conn,
- const char *conn_rootdir,
+ const struct smb_filename *conn_rootdir_fname,
files_struct *fsp,
struct smb_filename *smb_fname,
int flags,
char *link_target = NULL;
int link_len = -1;
char *oldwd = NULL;
+ struct smb_filename oldwd_fname = {0};
size_t rootdir_len = 0;
char *resolved_name = NULL;
bool matched = false;
* does not end in '/'. FIXME ! Should we
* smb_assert this ?
*/
- rootdir_len = strlen(conn_rootdir);
+ rootdir_len = strlen(conn_rootdir_fname->base_name);
- matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0);
+ matched = (strncmp(conn_rootdir_fname->base_name,
+ resolved_name,
+ rootdir_len) == 0);
if (!matched) {
errno = EACCES;
goto out;
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) == -1) {
+ if (vfs_ChDir(conn, conn_rootdir_fname) == -1) {
goto out;
}
/* And do it all again.. */
fd = non_widelink_open(conn,
- conn_rootdir,
+ conn_rootdir_fname,
fsp,
smb_fname,
flags,
SAFE_FREE(resolved_name);
TALLOC_FREE(link_target);
if (oldwd != NULL) {
- int ret = vfs_ChDir(conn, oldwd);
+ int ret = vfs_ChDir(conn, &oldwd_fname);
if (ret == -1) {
smb_panic("unable to get back to old directory\n");
}
****************************************************************************/
static int non_widelink_open(struct connection_struct *conn,
- const char *conn_rootdir,
+ const struct smb_filename *conn_rootdir_fname,
files_struct *fsp,
struct smb_filename *smb_fname,
int flags,
struct smb_filename *smb_fname_rel = NULL;
int saved_errno = 0;
char *oldwd = NULL;
+ struct smb_filename oldwd_fname = {0};
char *parent_dir = NULL;
+ struct smb_filename parent_dir_fname = {0};
const char *final_component = NULL;
if (!parent_dirname(talloc_tos(),
goto out;
}
+ parent_dir_fname = (struct smb_filename) { .base_name = parent_dir };
+
oldwd = vfs_GetWd(talloc_tos(), conn);
if (oldwd == NULL) {
goto out;
}
+ oldwd_fname = (struct smb_filename) { .base_name = oldwd };
+
/* Pin parent directory in place. */
- if (vfs_ChDir(conn, parent_dir) == -1) {
+ if (vfs_ChDir(conn, &parent_dir_fname) == -1) {
goto out;
}
* to ensure it's under the share definition.
*/
fd = process_symlink_open(conn,
- conn_rootdir,
+ conn_rootdir_fname,
fsp,
smb_fname_rel,
flags,
TALLOC_FREE(smb_fname_rel);
if (oldwd != NULL) {
- int ret = vfs_ChDir(conn, oldwd);
+ int ret = vfs_ChDir(conn, &oldwd_fname);
if (ret == -1) {
smb_panic("unable to get back to old directory\n");
}
/* Ensure path is below share definition. */
if (!lp_widelinks(SNUM(conn))) {
+ struct smb_filename *conn_rootdir_fname = NULL;
const char *conn_rootdir = SMB_VFS_CONNECTPATH(conn,
smb_fname->base_name);
+ int saved_errno = 0;
+
if (conn_rootdir == NULL) {
return NT_STATUS_NO_MEMORY;
}
+ conn_rootdir_fname = synthetic_smb_fname(talloc_tos(),
+ conn_rootdir,
+ NULL,
+ NULL,
+ 0);
+ if (conn_rootdir_fname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
/*
* Only follow symlinks within a share
* definition.
*/
fsp->fh->fd = non_widelink_open(conn,
- conn_rootdir,
+ conn_rootdir_fname,
fsp,
smb_fname,
flags,
mode,
0);
+ if (fsp->fh->fd == -1) {
+ saved_errno = errno;
+ }
+ TALLOC_FREE(conn_rootdir_fname);
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
} else {
fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
}
TALLOC_FREE(smb_fname_parent);
}
-NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
- const char *inherit_from_dir,
- const char *fname,
- SMB_STRUCT_STAT *psbuf)
+static NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
+ const char *inherit_from_dir,
+ struct smb_filename *smb_dname,
+ SMB_STRUCT_STAT *psbuf)
{
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};
TALLOC_CTX *ctx = talloc_tos();
NTSTATUS status = NT_STATUS_OK;
int ret;
goto out;
}
+ smb_fname_saved_dir = (struct smb_filename) { .base_name = saved_dir };
+
/* Chdir into the new path. */
- if (vfs_ChDir(conn, fname) == -1) {
+ if (vfs_ChDir(conn, smb_dname) == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to change "
"current working directory to %s. Error "
- "was %s\n", fname, strerror(errno) ));
+ "was %s\n", smb_dname->base_name, strerror(errno) ));
goto chdir;
}
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to stat "
"directory '.' (%s) Error was %s\n",
- fname, strerror(errno)));
+ smb_dname->base_name, strerror(errno)));
goto chdir;
}
smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino) {
DEBUG(0,("change_dir_owner_to_parent: "
"device/inode on directory %s changed. "
- "Refusing to chown !\n", fname ));
+ "Refusing to chown !\n",
+ smb_dname->base_name ));
status = NT_STATUS_ACCESS_DENIED;
goto chdir;
}
/* Already this uid - no need to change. */
DEBUG(10,("change_dir_owner_to_parent: directory %s "
"is already owned by uid %d\n",
- fname,
+ smb_dname->base_name,
(int)smb_fname_cwd->st.st_ex_uid ));
status = NT_STATUS_OK;
goto chdir;
status = map_nt_error_from_unix(errno);
DEBUG(10,("change_dir_owner_to_parent: failed to chown "
"directory %s to parent directory uid %u. "
- "Error was %s\n", fname,
+ "Error was %s\n",
+ smb_dname->base_name,
(unsigned int)smb_fname_parent->st.st_ex_uid,
strerror(errno) ));
} else {
DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
"directory %s to parent directory uid %u.\n",
- fname, (unsigned int)smb_fname_parent->st.st_ex_uid ));
+ smb_dname->base_name,
+ (unsigned int)smb_fname_parent->st.st_ex_uid ));
/* Ensure the uid entry is updated. */
psbuf->st_ex_uid = smb_fname_parent->st.st_ex_uid;
}
chdir:
- vfs_ChDir(conn,saved_dir);
+ vfs_ChDir(conn, &smb_fname_saved_dir);
out:
+ TALLOC_FREE(saved_dir);
TALLOC_FREE(smb_fname_parent);
TALLOC_FREE(smb_fname_cwd);
return status;
/* Change the owner if required. */
if (lp_inherit_owner(SNUM(conn)) != INHERIT_OWNER_NO) {
change_dir_owner_to_parent(conn, parent_dir,
- smb_dname->base_name,
+ smb_dname,
&smb_dname->st);
need_re_stat = true;
}
int snum,
const char *path,
const struct auth_session_info *session_info,
- char **poldcwd);
+ struct smb_filename **poldcwd_fname);
/* The following definitions come from smbd/negprot.c */
void change_file_owner_to_parent(connection_struct *conn,
const char *inherit_from_dir,
files_struct *fsp);
-NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
- const char *inherit_from_dir,
- const char *fname,
- SMB_STRUCT_STAT *psbuf);
bool is_stat_open(uint32_t access_mask);
NTSTATUS send_break_message(struct messaging_context *msg_ctx,
const struct share_mode_entry *exclusive,
off_t vfs_transfer_file(files_struct *in, files_struct *out, off_t n);
const char *vfs_readdirname(connection_struct *conn, void *p,
SMB_STRUCT_STAT *sbuf, char **talloced);
-int vfs_ChDir(connection_struct *conn, const char *path);
+int vfs_ChDir(connection_struct *conn,
+ const struct smb_filename *smb_fname);
char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
NTSTATUS check_reduced_name(connection_struct *conn,
const char *cwd_name,
snum = SNUM(conn);
- if (do_chdir &&
- vfs_ChDir(conn,conn->connectpath) != 0 &&
- vfs_ChDir(conn,conn->origpath) != 0) {
- DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
- conn->connectpath, strerror(errno)));
- return(False);
+ {
+ struct smb_filename connectpath_fname = {
+ .base_name = conn->connectpath
+ };
+ struct smb_filename origpath_fname = {
+ .base_name = conn->origpath
+ };
+
+ if (do_chdir &&
+ vfs_ChDir(conn, &connectpath_fname) != 0 &&
+ vfs_ChDir(conn, &origpath_fname) != 0) {
+ DEBUG(((errno!=EACCES)?0:3),
+ ("chdir (%s) failed, reason: %s\n",
+ conn->connectpath, strerror(errno)));
+ return(False);
+ }
}
if ((conn == last_conn) && (last_flags == flags)) {
void close_cnum(connection_struct *conn, uint64_t vuid)
{
+ char rootpath[2] = { '/', '\0'};
+ struct smb_filename root_fname = { .base_name = rootpath };
+
file_close_conn(conn);
if (!IS_IPC(conn)) {
lp_servicename(talloc_tos(), SNUM(conn))));
/* make sure we leave the directory available for unmount */
- vfs_ChDir(conn, "/");
+ vfs_ChDir(conn, &root_fname);
/* Call VFS disconnect hook */
SMB_VFS_DISCONNECT(conn);
A wrapper for vfs_chdir().
********************************************************************/
-int vfs_ChDir(connection_struct *conn, const char *path)
+int vfs_ChDir(connection_struct *conn, const struct smb_filename *smb_fname)
{
int ret;
LastDir = SMB_STRDUP("");
}
- if (ISDOT(path)) {
+ if (ISDOT(smb_fname->base_name)) {
return 0;
}
- if (*path == '/' && strcsequal(LastDir,path)) {
+ if (*smb_fname->base_name == '/' &&
+ strcsequal(LastDir,smb_fname->base_name)) {
return 0;
}
- DEBUG(4,("vfs_ChDir to %s\n",path));
+ DEBUG(4,("vfs_ChDir to %s\n", smb_fname->base_name));
- ret = SMB_VFS_CHDIR(conn,path);
+ ret = SMB_VFS_CHDIR(conn, smb_fname);
if (ret == 0) {
/* Global cache. */
SAFE_FREE(LastDir);
- LastDir = SMB_STRDUP(path);
+ LastDir = SMB_STRDUP(smb_fname->base_name);
/* conn cache. */
TALLOC_FREE(conn->cwd);
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;
int ret;
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.base_name) == -1) {
+ if (vfs_ChDir(conn, &priv_paths->parent_name) == -1) {
status = map_nt_error_from_unix(errno);
goto err;
}
err:
- if (saved_dir) {
- vfs_ChDir(conn, saved_dir);
+ if (saved_dir_fname) {
+ vfs_ChDir(conn, saved_dir_fname);
+ TALLOC_FREE(saved_dir);
+ TALLOC_FREE(saved_dir_fname);
}
SAFE_FREE(resolved_name);
if (!NT_STATUS_IS_OK(status)) {
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};
saved_dir = vfs_GetWd(talloc_tos(),fsp->conn);
if (!saved_dir) {
return status;
}
+ saved_dir_fname = (struct smb_filename) {
+ .base_name = saved_dir
+ };
+
if (!parent_dirname(talloc_tos(),
fsp->fsp_name->base_name,
&parent_dir,
return NT_STATUS_NO_MEMORY;
}
+ parent_dir_fname = (struct smb_filename) {
+ .base_name = parent_dir,
+ .flags = fsp->fsp_name->flags
+ };
+
/* cd into the parent dir to pin it. */
- ret = vfs_ChDir(fsp->conn, parent_dir);
+ ret = vfs_ChDir(fsp->conn, &parent_dir_fname);
if (ret == -1) {
return map_nt_error_from_unix(errno);
}
out:
- vfs_ChDir(fsp->conn,saved_dir);
+ vfs_ChDir(fsp->conn, &saved_dir_fname);
TALLOC_FREE(local_smb_fname);
TALLOC_FREE(saved_dir);
TALLOC_FREE(parent_dir);
return status;
}
-int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
+int smb_vfs_call_chdir(struct vfs_handle_struct *handle,
+ const struct smb_filename *smb_fname)
{
VFS_FIND(chdir);
- return handle->fns->chdir_fn(handle, path);
+ return handle->fns->chdir_fn(handle, smb_fname);
}
char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
ret = SMB_VFS_UNLINK(vfs->conn, smb_fname);
TALLOC_FREE(smb_fname);
} else if (strcmp("chdir", argv[0]) == 0 ) {
- ret = SMB_VFS_CHDIR(vfs->conn, argv[1]);
+ ret = SMB_VFS_CHDIR(vfs->conn, smb_fname);
+ TALLOC_FREE(smb_fname);
} else {
printf("%s: error=%d (invalid function name!)\n", argv[0], errno);
return NT_STATUS_UNSUCCESSFUL;