From 6ae2d86b9ccc0ebe73dc911a1d5f06bd53613acf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Jun 2017 15:03:37 -0700 Subject: [PATCH] s3: VFS: Change SMB_VFS_READLINK to use const struct smb_filename * instead of const 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 Reviewed-by: Richard Sharpe --- examples/VFS/skel_opaque.c | 6 ++- examples/VFS/skel_transparent.c | 8 ++-- source3/include/vfs.h | 11 ++++- source3/include/vfs_macros.h | 8 ++-- source3/modules/vfs_cap.c | 32 +++++++++++-- source3/modules/vfs_ceph.c | 10 +++-- source3/modules/vfs_default.c | 7 ++- source3/modules/vfs_expand_msdfs.c | 6 ++- source3/modules/vfs_full_audit.c | 9 ++-- source3/modules/vfs_glusterfs.c | 6 ++- source3/modules/vfs_media_harmony.c | 24 ++++------ source3/modules/vfs_shadow_copy2.c | 22 ++++++--- source3/modules/vfs_snapper.c | 37 ++++++++++----- source3/modules/vfs_time_audit.c | 10 +++-- source3/modules/vfs_unityed_media.c | 21 ++++----- source3/smbd/msdfs.c | 70 ++++++++++++++++------------- source3/smbd/open.c | 2 +- source3/smbd/proto.h | 3 +- source3/smbd/trans2.c | 15 +++---- source3/smbd/vfs.c | 6 ++- source3/torture/cmd_vfs.c | 10 ++++- 21 files changed, 206 insertions(+), 117 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index ec81bdc9fef..792f728f83a 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -483,8 +483,10 @@ static int skel_symlink(vfs_handle_struct *handle, const char *oldpath, return -1; } -static int skel_vfs_readlink(vfs_handle_struct *handle, const char *path, - char *buf, size_t bufsiz) +static int skel_vfs_readlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { errno = ENOSYS; return -1; diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index db3ec35bd58..11512e3815b 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -576,10 +576,12 @@ static int skel_symlink(vfs_handle_struct *handle, const char *oldpath, return SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath); } -static int skel_vfs_readlink(vfs_handle_struct *handle, const char *path, - char *buf, size_t bufsiz) +static int skel_vfs_readlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { - return SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz); + return SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz); } static int skel_link(vfs_handle_struct *handle, diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 2f434ba20dc..115a9dc01c6 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -224,6 +224,8 @@ to const struct smb_filename * */ /* Version 37 - Change statvfs from const char * to const struct smb_filename * */ +/* Version 37 - Change readlink from const char * + to const struct smb_filename * */ #define SMB_VFS_INTERFACE_VERSION 37 @@ -744,7 +746,10 @@ struct vfs_fn_pointers { int (*linux_setlease_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int leasetype); bool (*getlock_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid); int (*symlink_fn)(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath); - int (*readlink_fn)(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz); + int (*readlink_fn)(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz); int (*link_fn)(struct vfs_handle_struct *handle, const struct smb_filename *old_smb_fname, const struct smb_filename *new_smb_fname); @@ -1249,7 +1254,9 @@ bool smb_vfs_call_getlock(struct vfs_handle_struct *handle, int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath, const char *newpath); int smb_vfs_call_readlink(struct vfs_handle_struct *handle, - const char *path, char *buf, size_t bufsiz); + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz); int smb_vfs_call_link(struct vfs_handle_struct *handle, const struct smb_filename *old_smb_fname, const struct smb_filename *new_smb_fname); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 3404c8ca751..77646b45f06 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -316,10 +316,10 @@ #define SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath) \ smb_vfs_call_symlink((handle)->next, (oldpath), (newpath)) -#define SMB_VFS_READLINK(conn, path, buf, bufsiz) \ - smb_vfs_call_readlink((conn)->vfs_handles, (path), (buf), (bufsiz)) -#define SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz) \ - smb_vfs_call_readlink((handle)->next, (path), (buf), (bufsiz)) +#define SMB_VFS_READLINK(conn, smb_fname, buf, bufsiz) \ + smb_vfs_call_readlink((conn)->vfs_handles, (smb_fname), (buf), (bufsiz)) +#define SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz) \ + smb_vfs_call_readlink((handle)->next, (smb_fname), (buf), (bufsiz)) #define SMB_VFS_LINK(conn, oldpath, newpath) \ smb_vfs_call_link((conn)->vfs_handles, (oldpath), (newpath)) diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 7e89c0917f6..2c21ab18c48 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -492,16 +492,40 @@ static int cap_symlink(vfs_handle_struct *handle, const char *oldpath, return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew); } -static int cap_readlink(vfs_handle_struct *handle, const char *path, - char *buf, size_t bufsiz) +static int cap_readlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { - char *cappath = capencode(talloc_tos(), path); + char *cappath = capencode(talloc_tos(), smb_fname->base_name); + struct smb_filename *cap_smb_fname = NULL; + int saved_errno = 0; + int ret; if (!cappath) { errno = ENOMEM; return -1; } - return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz); + 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_READLINK(handle, cap_smb_fname, buf, bufsiz); + 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_link(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 638118b5c5b..3c38165b58f 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -1134,11 +1134,15 @@ static int cephwrap_symlink(struct vfs_handle_struct *handle, const char *oldpa WRAP_RETURN(result); } -static int cephwrap_readlink(struct vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz) +static int cephwrap_readlink(struct vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { int result = -1; - DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle, path, buf, llu(bufsiz)); - result = ceph_readlink(handle->data, path, buf, bufsiz); + DBG_DEBUG("[CEPH] readlink(%p, %s, %p, %llu)\n", handle, + smb_fname->base_name, buf, llu(bufsiz)); + result = ceph_readlink(handle->data, smb_fname->base_name, buf, bufsiz); DBG_DEBUG("[CEPH] readlink(...) = %d\n", result); WRAP_RETURN(result); } diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index 4f86537c031..93ff6578553 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -2428,12 +2428,15 @@ static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const return result; } -static int vfswrap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz) +static int vfswrap_readlink(vfs_handle_struct *handle, + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { int result; START_PROFILE(syscall_readlink); - result = readlink(path, buf, bufsiz); + result = readlink(smb_fname->base_name, buf, bufsiz); END_PROFILE(syscall_readlink); return result; } diff --git a/source3/modules/vfs_expand_msdfs.c b/source3/modules/vfs_expand_msdfs.c index b0e51987523..4cabc8f5508 100644 --- a/source3/modules/vfs_expand_msdfs.c +++ b/source3/modules/vfs_expand_msdfs.c @@ -181,7 +181,9 @@ static char *expand_msdfs_target(TALLOC_CTX *ctx, } static int expand_msdfs_readlink(struct vfs_handle_struct *handle, - const char *path, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { TALLOC_CTX *ctx = talloc_tos(); int result; @@ -197,7 +199,7 @@ static int expand_msdfs_readlink(struct vfs_handle_struct *handle, return -1; } - result = SMB_VFS_NEXT_READLINK(handle, path, target, + result = SMB_VFS_NEXT_READLINK(handle, smb_fname, target, PATH_MAX); if (result <= 0) diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 609ef378fdd..408f834858c 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -1639,13 +1639,16 @@ static int smb_full_audit_symlink(vfs_handle_struct *handle, } static int smb_full_audit_readlink(vfs_handle_struct *handle, - const char *path, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { int result; - result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz); + result = SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz); - do_log(SMB_VFS_OP_READLINK, (result >= 0), handle, "%s", path); + do_log(SMB_VFS_OP_READLINK, (result >= 0), handle, "%s", + smb_fname->base_name); return result; } diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 7a42d869d40..bf19dd722a8 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -1240,9 +1240,11 @@ static int vfs_gluster_symlink(struct vfs_handle_struct *handle, } static int vfs_gluster_readlink(struct vfs_handle_struct *handle, - const char *path, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { - return glfs_readlink(handle->data, path, buf, bufsiz); + return glfs_readlink(handle->data, smb_fname->base_name, buf, bufsiz); } static int vfs_gluster_link(struct vfs_handle_struct *handle, diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index 420b51f9910..13604b36dcf 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -1769,34 +1769,28 @@ out: * Failure: set errno, return -1 */ static int mh_readlink(vfs_handle_struct *handle, - const char *path, + const struct smb_filename *smb_fname, char *buf, size_t bufsiz) { int status; - char *clientPath; - TALLOC_CTX *ctx; + struct smb_filename *clientFname = NULL; DEBUG(MH_INFO_DEBUG, ("Entering mh_readlink\n")); - if (!is_in_media_files(path)) - { - status = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz); + if (!is_in_media_files(smb_fname->base_name)) { + status = SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz); goto out; } - clientPath = NULL; - ctx = talloc_tos(); - - if ((status = alloc_get_client_path(handle, ctx, - path, - &clientPath))) - { + if ((status = alloc_get_client_smb_fname(handle, talloc_tos(), + smb_fname, + &clientFname))) { goto err; } - status = SMB_VFS_NEXT_READLINK(handle, clientPath, buf, bufsiz); + status = SMB_VFS_NEXT_READLINK(handle, clientFname, buf, bufsiz); err: - TALLOC_FREE(clientPath); + TALLOC_FREE(clientFname); out: return status; } diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 5481eda0e25..2c7fcaacef7 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -1633,24 +1633,34 @@ static int shadow_copy2_ntimes(vfs_handle_struct *handle, } static int shadow_copy2_readlink(vfs_handle_struct *handle, - const char *fname, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { time_t timestamp = 0; char *stripped = NULL; int saved_errno = 0; int ret; - char *conv; + struct smb_filename *conv = NULL; - if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, + if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, + smb_fname->base_name, ×tamp, &stripped)) { return -1; } if (timestamp == 0) { - return SMB_VFS_NEXT_READLINK(handle, fname, buf, bufsiz); + return SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz); } - conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); - TALLOC_FREE(stripped); + conv = cp_smb_filename(talloc_tos(), smb_fname); if (conv == NULL) { + TALLOC_FREE(stripped); + errno = ENOMEM; + return -1; + } + conv->base_name = shadow_copy2_convert( + conv, handle, stripped, timestamp); + TALLOC_FREE(stripped); + if (conv->base_name == NULL) { return -1; } ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz); diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c index ec0c680124e..a41397427cc 100644 --- a/source3/modules/vfs_snapper.c +++ b/source3/modules/vfs_snapper.c @@ -2398,29 +2398,44 @@ static int snapper_gmt_ntimes(vfs_handle_struct *handle, } static int snapper_gmt_readlink(vfs_handle_struct *handle, - const char *fname, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { - time_t timestamp; - char *stripped; - int ret, saved_errno; - char *conv; + time_t timestamp = 0; + char *stripped = NULL; + int ret; + int saved_errno = 0; + struct smb_filename *conv = NULL; - if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname, + if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, + smb_fname->base_name, ×tamp, &stripped)) { return -1; } if (timestamp == 0) { - return SMB_VFS_NEXT_READLINK(handle, fname, buf, bufsiz); + return SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz); } - conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp); - TALLOC_FREE(stripped); + conv = cp_smb_filename(talloc_tos(), smb_fname); if (conv == NULL) { + TALLOC_FREE(stripped); + errno = ENOMEM; + return -1; + } + conv->base_name = snapper_gmt_convert(conv, handle, + stripped, timestamp); + TALLOC_FREE(stripped); + if (conv->base_name == NULL) { return -1; } ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz); - saved_errno = errno; + if (ret == -1) { + saved_errno = errno; + } TALLOC_FREE(conv); - errno = saved_errno; + if (saved_errno != 0) { + errno = saved_errno; + } return ret; } diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index b1bf59ee6a3..58c0f796a87 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -1443,19 +1443,23 @@ static int smb_time_audit_symlink(vfs_handle_struct *handle, } static int smb_time_audit_readlink(vfs_handle_struct *handle, - const char *path, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { int result; struct timespec ts1,ts2; double timediff; clock_gettime_mono(&ts1); - result = SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz); + result = SMB_VFS_NEXT_READLINK(handle, smb_fname, + buf, bufsiz); clock_gettime_mono(&ts2); timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; if (timediff > audit_timeout) { - smb_time_audit_log_fname("readlink", timediff, path); + smb_time_audit_log_fname("readlink", timediff, + smb_fname->base_name); } return result; diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c index b1c459ada4c..c9ecc277408 100644 --- a/source3/modules/vfs_unityed_media.c +++ b/source3/modules/vfs_unityed_media.c @@ -1354,29 +1354,30 @@ err: } static int um_readlink(vfs_handle_struct *handle, - const char *path, - char *buf, - size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { int status; - char *client_path = NULL; + struct smb_filename *client_fname = NULL; DEBUG(10, ("Entering um_readlink\n")); - if (!is_in_media_files(path)) { - return SMB_VFS_NEXT_READLINK(handle, path, buf, bufsiz); + if (!is_in_media_files(smb_fname->base_name)) { + return SMB_VFS_NEXT_READLINK(handle, smb_fname, + buf, bufsiz); } - 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_READLINK(handle, client_path, buf, bufsiz); + status = SMB_VFS_NEXT_READLINK(handle, client_fname, buf, bufsiz); err: - TALLOC_FREE(client_path); + TALLOC_FREE(client_fname); return status; } diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index acb45fd01c2..b88538c2ba1 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -567,9 +567,8 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, static bool is_msdfs_link_internal(TALLOC_CTX *ctx, connection_struct *conn, - const char *path, - char **pp_link_target, - SMB_STRUCT_STAT *sbufp) + struct smb_filename *smb_fname, + char **pp_link_target) { int referral_len = 0; #if defined(HAVE_BROKEN_READLINK) @@ -579,7 +578,6 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx, #endif size_t bufsize = 0; char *link_target = NULL; - struct smb_filename smb_fname; if (pp_link_target) { bufsize = 1024; @@ -593,33 +591,28 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx, link_target = link_target_buf; } - ZERO_STRUCT(smb_fname); - smb_fname.base_name = discard_const_p(char, path); - - if (SMB_VFS_LSTAT(conn, &smb_fname) != 0) { + if (SMB_VFS_LSTAT(conn, smb_fname) != 0) { DEBUG(5,("is_msdfs_link_read_target: %s does not exist.\n", - path)); + smb_fname->base_name)); goto err; } - if (!S_ISLNK(smb_fname.st.st_ex_mode)) { + if (!S_ISLNK(smb_fname->st.st_ex_mode)) { DEBUG(5,("is_msdfs_link_read_target: %s is not a link.\n", - path)); + smb_fname->base_name)); goto err; } - if (sbufp != NULL) { - *sbufp = smb_fname.st; - } - referral_len = SMB_VFS_READLINK(conn, path, link_target, bufsize - 1); + referral_len = SMB_VFS_READLINK(conn, smb_fname, + link_target, bufsize - 1); if (referral_len == -1) { DEBUG(0,("is_msdfs_link_read_target: Error reading " "msdfs link %s: %s\n", - path, strerror(errno))); + smb_fname->base_name, strerror(errno))); goto err; } link_target[referral_len] = '\0'; - DEBUG(5,("is_msdfs_link_internal: %s -> %s\n",path, + DEBUG(5,("is_msdfs_link_internal: %s -> %s\n", smb_fname->base_name, link_target)); if (!strnequal(link_target, "msdfs:", 6)) { @@ -640,14 +633,12 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx, **********************************************************************/ bool is_msdfs_link(connection_struct *conn, - const char *path, - SMB_STRUCT_STAT *sbufp) + struct smb_filename *smb_fname) { return is_msdfs_link_internal(talloc_tos(), conn, - path, - NULL, - sbufp); + smb_fname, + NULL); } /***************************************************************** @@ -706,8 +697,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, /* Optimization - check if we can redirect the whole path. */ - if (is_msdfs_link_internal(ctx, conn, smb_fname->base_name, - pp_targetpath, NULL)) { + if (is_msdfs_link_internal(ctx, conn, smb_fname, pp_targetpath)) { /* XX_ALLOW_WCARD_XXX is called from search functions. */ if (ucf_flags & (UCF_COND_ALLOW_WCARD_LCOMP| @@ -770,8 +760,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, } if (is_msdfs_link_internal(ctx, conn, - smb_fname->base_name, pp_targetpath, - NULL)) { + smb_fname, pp_targetpath)) { DEBUG(4, ("dfs_path_lookup: Redirecting %s because " "parent %s is dfs link\n", dfspath, smb_fname_str_dbg(smb_fname))); @@ -1481,12 +1470,20 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced)) != NULL) { - if (is_msdfs_link(conn, - dname, - NULL)) { + struct smb_filename *smb_dname = + synthetic_smb_fname(talloc_tos(), + dname, + NULL, + NULL, + 0); + if (smb_dname == NULL) { + goto out; + } + if (is_msdfs_link(conn, smb_dname)) { cnt++; } TALLOC_FREE(talloced); + TALLOC_FREE(smb_dname); } SMB_VFS_CLOSEDIR(conn,dirp); @@ -1600,16 +1597,26 @@ static int form_junctions(TALLOC_CTX *ctx, while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced)) != NULL) { char *link_target = NULL; + struct smb_filename *smb_dname = NULL; + if (cnt >= jn_remain) { DEBUG(2, ("form_junctions: ran out of MSDFS " "junction slots")); TALLOC_FREE(talloced); goto out; } + smb_dname = synthetic_smb_fname(talloc_tos(), + dname, + NULL, + NULL, + 0); + if (smb_dname == NULL) { + TALLOC_FREE(talloced); + goto out; + } if (is_msdfs_link_internal(ctx, conn, - dname, &link_target, - NULL)) { + smb_dname, &link_target)) { if (parse_msdfs_symlink(ctx, snum, link_target, &jucn[cnt].referral_list, @@ -1630,6 +1637,7 @@ static int form_junctions(TALLOC_CTX *ctx, TALLOC_FREE(link_target); } TALLOC_FREE(talloced); + TALLOC_FREE(smb_dname); } out: diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8fdc96376d8..e68e2ace850 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -435,7 +435,7 @@ static int process_symlink_open(struct connection_struct *conn, /* Read the link target. */ link_len = SMB_VFS_READLINK(conn, - smb_fname->base_name, + smb_fname, link_target, PATH_MAX - 1); if (link_len == -1) { diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 89797296a77..722edf3e67c 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -468,8 +468,7 @@ void reply_sendend(struct smb_request *req); /* The following definitions come from smbd/msdfs.c */ bool is_msdfs_link(connection_struct *conn, - const char *path, - SMB_STRUCT_STAT *sbufp); + struct smb_filename *smb_fname); struct junction_map; NTSTATUS get_referred_path(TALLOC_CTX *ctx, const char *dfs_path, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index ae41f199cb2..8615a782f4a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1577,18 +1577,18 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn, ****************************************************************************/ static bool check_msdfs_link(connection_struct *conn, - const char *pathname, - SMB_STRUCT_STAT *psbuf) + struct smb_filename *smb_fname) { int saved_errno = errno; if(lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - is_msdfs_link(conn, pathname, psbuf)) { + is_msdfs_link(conn, smb_fname)) { DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s " "as a directory\n", - pathname)); - psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR; + smb_fname->base_name)); + smb_fname->st.st_ex_mode = + (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR; errno = saved_errno; return true; } @@ -1729,8 +1729,7 @@ static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx, * directories */ ms_dfs_link = check_msdfs_link(state->conn, - smb_fname->base_name, - &smb_fname->st); + smb_fname); if (!ms_dfs_link) { DEBUG(5,("smbd_dirptr_lanman2_mode_fn: " "Couldn't stat [%s] (%s)\n", @@ -5483,7 +5482,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, return NT_STATUS_DOS(ERRDOS, ERRbadlink); #endif link_len = SMB_VFS_READLINK(conn, - smb_fname->base_name, + smb_fname, buffer, PATH_MAX); if (link_len == -1) { return map_nt_error_from_unix(errno); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index acfc705a401..bed3d2c1554 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -2160,10 +2160,12 @@ int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath, } int smb_vfs_call_readlink(struct vfs_handle_struct *handle, - const char *path, char *buf, size_t bufsiz) + const struct smb_filename *smb_fname, + char *buf, + size_t bufsiz) { VFS_FIND(readlink); - return handle->fns->readlink_fn(handle, path, buf, bufsiz); + return handle->fns->readlink_fn(handle, smb_fname, buf, bufsiz); } int smb_vfs_call_link(struct vfs_handle_struct *handle, diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 38d87464c42..47e365a5dac 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -1231,6 +1231,7 @@ static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { char buffer[PATH_MAX]; + struct smb_filename *smb_fname = NULL; int size; if (argc != 2) { @@ -1238,7 +1239,14 @@ static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg return NT_STATUS_OK; } - if ((size = SMB_VFS_READLINK(vfs->conn, argv[1], buffer, PATH_MAX)) == -1) { + smb_fname = synthetic_smb_fname_split(mem_ctx, + argv[1], + lp_posix_pathnames()); + if (smb_fname == NULL) { + return NT_STATUS_NO_MEMORY; + } + if ((size = SMB_VFS_READLINK(vfs->conn, smb_fname, + buffer, PATH_MAX)) == -1) { printf("readlink: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } -- 2.34.1