summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2017-06-30 11:32:59 -0700
committerJeremy Allison <jra@samba.org>2017-07-01 03:07:11 +0200
commitc29438f8238c3cf436e126c99f6f9f6bcca4efaf (patch)
treecff5f451fe83b9189eca4ca8f2c9530a8bfc2fa9
parentbd9285b19741128bae501b721d9e63dd9a9bd833 (diff)
downloadsamba-c29438f8238c3cf436e126c99f6f9f6bcca4efaf.tar.gz
s3: VFS: Change SMB_VFS_REALPATH to take and 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>
-rw-r--r--examples/VFS/skel_opaque.c4
-rw-r--r--examples/VFS/skel_transparent.c6
-rw-r--r--source3/include/vfs.h10
-rw-r--r--source3/include/vfs_macros.h8
-rw-r--r--source3/modules/vfs_cap.c30
-rw-r--r--source3/modules/vfs_catia.c28
-rw-r--r--source3/modules/vfs_ceph.c14
-rw-r--r--source3/modules/vfs_default.c13
-rw-r--r--source3/modules/vfs_fake_dfq.c57
-rw-r--r--source3/modules/vfs_full_audit.c14
-rw-r--r--source3/modules/vfs_glusterfs.c17
-rw-r--r--source3/modules/vfs_media_harmony.c34
-rw-r--r--source3/modules/vfs_shadow_copy2.c60
-rw-r--r--source3/modules/vfs_snapper.c42
-rw-r--r--source3/modules/vfs_time_audit.c14
-rw-r--r--source3/modules/vfs_unityed_media.c23
-rw-r--r--source3/smbd/open.c26
-rw-r--r--source3/smbd/service.c10
-rw-r--r--source3/smbd/vfs.c75
-rw-r--r--source3/torture/cmd_vfs.c10
20 files changed, 308 insertions, 187 deletions
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index 8bfc520c8eb..f8f98575f62 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -512,7 +512,9 @@ static int skel_mknod(vfs_handle_struct *handle,
return -1;
}
-static char *skel_realpath(vfs_handle_struct *handle, const char *path)
+static struct smb_filename *skel_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
errno = ENOSYS;
return NULL;
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index a5ba6a9c4d8..29a97852974 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -602,9 +602,11 @@ static int skel_mknod(vfs_handle_struct *handle,
return SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev);
}
-static char *skel_realpath(vfs_handle_struct *handle, const char *path)
+static struct smb_filename *skel_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
- return SMB_VFS_NEXT_REALPATH(handle, path);
+ return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
static int skel_chflags(vfs_handle_struct *handle,
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 716e194a4ee..1aa44ee14e1 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -234,6 +234,8 @@
to const struct smb_filename * */
/* Version 37 - Change conn->cwd from char *
to struct smb_filename * */
+/* Version 37 - Change realpath from char *
+ to struct smb_filename * */
#define SMB_VFS_INTERFACE_VERSION 37
@@ -769,7 +771,9 @@ struct vfs_fn_pointers {
const struct smb_filename *smb_fname,
mode_t mode,
SMB_DEV_T dev);
- char *(*realpath_fn)(struct vfs_handle_struct *handle, const char *path);
+ struct smb_filename *(*realpath_fn)(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname);
int (*chflags_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
unsigned int flags);
@@ -1279,7 +1283,9 @@ int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,
SMB_DEV_T dev);
-char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path);
+struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname);
int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
unsigned int flags);
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 29f03389cce..0e8245e752d 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -331,10 +331,10 @@
#define SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev) \
smb_vfs_call_mknod((handle)->next, (smb_fname), (mode), (dev))
-#define SMB_VFS_REALPATH(conn, path) \
- smb_vfs_call_realpath((conn)->vfs_handles, (path))
-#define SMB_VFS_NEXT_REALPATH(handle, path) \
- smb_vfs_call_realpath((handle)->next, (path))
+#define SMB_VFS_REALPATH(conn, ctx, smb_fname) \
+ smb_vfs_call_realpath((conn)->vfs_handles, (ctx), (smb_fname))
+#define SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname) \
+ smb_vfs_call_realpath((handle)->next, (ctx), (smb_fname))
#define SMB_VFS_CHFLAGS(conn, smb_fname, flags) \
smb_vfs_call_chflags((conn)->vfs_handles, (smb_fname), (flags))
diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c
index 44a81bbcefb..e4d30cb4e5a 100644
--- a/source3/modules/vfs_cap.c
+++ b/source3/modules/vfs_cap.c
@@ -667,16 +667,40 @@ static int cap_mknod(vfs_handle_struct *handle,
return ret;
}
-static char *cap_realpath(vfs_handle_struct *handle, const char *path)
+static struct smb_filename *cap_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
/* monyo need capencode'ed and capdecode'ed? */
- char *cappath = capencode(talloc_tos(), path);
+ struct smb_filename *cap_smb_fname = NULL;
+ struct smb_filename *return_fname = NULL;
+ char *cappath = capencode(talloc_tos(), smb_fname->base_name);
+ int saved_errno = 0;
if (!cappath) {
errno = ENOMEM;
return NULL;
}
- return SMB_VFS_NEXT_REALPATH(handle, cappath);
+ cap_smb_fname = synthetic_smb_fname(ctx,
+ cappath,
+ NULL,
+ NULL,
+ smb_fname->flags);
+ if (cap_smb_fname == NULL) {
+ TALLOC_FREE(cappath);
+ errno = ENOMEM;
+ return NULL;
+ }
+ return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, cap_smb_fname);
+ if (return_fname == NULL) {
+ saved_errno = errno;
+ }
+ TALLOC_FREE(cappath);
+ TALLOC_FREE(cap_smb_fname);
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
+ return return_fname;
}
static int cap_chmod_acl(vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c
index 7db50a26206..6adf4414af6 100644
--- a/source3/modules/vfs_catia.c
+++ b/source3/modules/vfs_catia.c
@@ -1055,24 +1055,38 @@ static int catia_ntimes(vfs_handle_struct *handle,
return ret;
}
-static char *
-catia_realpath(vfs_handle_struct *handle, const char *path)
+static struct smb_filename *
+catia_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
char *mapped_name = NULL;
+ struct smb_filename *catia_smb_fname = NULL;
+ struct smb_filename *return_fname = NULL;
NTSTATUS status;
- char *ret = NULL;
- status = catia_string_replace_allocate(handle->conn, path,
+ status = catia_string_replace_allocate(handle->conn,
+ smb_fname->base_name,
&mapped_name, vfs_translate_to_unix);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
return NULL;
}
- ret = SMB_VFS_NEXT_REALPATH(handle, mapped_name);
+ catia_smb_fname = synthetic_smb_fname(talloc_tos(),
+ mapped_name,
+ NULL,
+ NULL,
+ smb_fname->flags);
+ if (catia_smb_fname == NULL) {
+ TALLOC_FREE(mapped_name);
+ errno = ENOMEM;
+ return NULL;
+ }
+ return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, catia_smb_fname);
TALLOC_FREE(mapped_name);
-
- return ret;
+ TALLOC_FREE(catia_smb_fname);
+ return return_fname;
}
static int catia_chflags(struct vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c
index 7d3f4a7bbaa..488ebc7795d 100644
--- a/source3/modules/vfs_ceph.c
+++ b/source3/modules/vfs_ceph.c
@@ -1191,10 +1191,14 @@ static int cephwrap_mknod(struct vfs_handle_struct *handle,
* This is a simple version of real-path ... a better version is needed to
* ask libceph about symbolic links.
*/
-static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *path)
+static struct smb_filename *cephwrap_realpath(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
char *result;
+ const char *path = smb_fname->base_name;
size_t len = strlen(path);
+ struct smb_filename *result_fname = NULL;
result = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
if (len && (path[0] == '/')) {
@@ -1216,7 +1220,13 @@ static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *pa
if (r < 0) return NULL;
}
DBG_DEBUG("[CEPH] realpath(%p, %s) = %s\n", handle, path, result);
- return result;
+ result_fname = synthetic_smb_fname(ctx,
+ result,
+ NULL,
+ NULL,
+ 0);
+ SAFE_FREE(result);
+ return result_fname;
}
static int cephwrap_chflags(struct vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index b01a0078180..3336232e3d6 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2487,14 +2487,21 @@ static int vfswrap_mknod(vfs_handle_struct *handle,
return result;
}
-static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path)
+static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
char *result;
+ struct smb_filename *result_fname = NULL;
START_PROFILE(syscall_realpath);
- result = sys_realpath(path);
+ result = sys_realpath(smb_fname->base_name);
END_PROFILE(syscall_realpath);
- return result;
+ if (result) {
+ result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
+ SAFE_FREE(result);
+ }
+ return result_fname;
}
static int vfswrap_chflags(vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_fake_dfq.c b/source3/modules/vfs_fake_dfq.c
index 971db68bc55..019b2e8891d 100644
--- a/source3/modules/vfs_fake_dfq.c
+++ b/source3/modules/vfs_fake_dfq.c
@@ -61,24 +61,27 @@ static uint64_t dfq_disk_free(vfs_handle_struct *handle,
uint64_t free_1k;
int snum = SNUM(handle->conn);
uint64_t dfq_bsize = 0;
- char *rpath = NULL;
+ struct smb_filename *rpath_fname = NULL;
/* look up the params based on real path to be resilient
* to refactoring of path<->realpath
*/
- rpath = SMB_VFS_NEXT_REALPATH(handle, smb_fname->base_name);
- if (rpath != NULL) {
- dfq_bsize = dfq_load_param(snum, rpath, "df", "block size", 0);
+ rpath_fname = SMB_VFS_NEXT_REALPATH(handle, talloc_tos(), smb_fname);
+ if (rpath_fname != NULL) {
+ dfq_bsize = dfq_load_param(snum, rpath_fname->base_name,
+ "df", "block size", 0);
}
if (dfq_bsize == 0) {
- SAFE_FREE(rpath);
+ TALLOC_FREE(rpath_fname);
return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname, bsize, dfree,
dsize);
}
*bsize = dfq_bsize;
- *dfree = dfq_load_param(snum, rpath, "df", "disk free", 0);
- *dsize = dfq_load_param(snum, rpath, "df", "disk size", 0);
+ *dfree = dfq_load_param(snum, rpath_fname->base_name,
+ "df", "disk free", 0);
+ *dsize = dfq_load_param(snum, rpath_fname->base_name,
+ "df", "disk size", 0);
if ((*bsize) < 1024) {
free_1k = (*dfree) / (1024 / (*bsize));
@@ -86,7 +89,7 @@ static uint64_t dfq_disk_free(vfs_handle_struct *handle,
free_1k = ((*bsize) / 1024) * (*dfree);
}
- SAFE_FREE(rpath);
+ TALLOC_FREE(rpath_fname);
return free_1k;
}
@@ -101,10 +104,10 @@ static int dfq_get_quota(struct vfs_handle_struct *handle,
char *section = NULL;
int snum = SNUM(handle->conn);
uint64_t bsize = 0;
- char *rpath = NULL;
+ struct smb_filename *rpath_fname = NULL;
- rpath = SMB_VFS_NEXT_REALPATH(handle, smb_fname->base_name);
- if (rpath == NULL) {
+ rpath_fname = SMB_VFS_NEXT_REALPATH(handle, talloc_tos(), smb_fname);
+ if (rpath_fname == NULL) {
goto dflt;
}
@@ -131,18 +134,21 @@ static int dfq_get_quota(struct vfs_handle_struct *handle,
goto dflt;
}
- bsize = dfq_load_param(snum, rpath, section, "block size", 4096);
+ bsize = dfq_load_param(snum, rpath_fname->base_name,
+ section, "block size", 4096);
if (bsize == 0) {
goto dflt;
}
- if (dfq_load_param(snum, rpath, section, "err", 0) != 0) {
+ if (dfq_load_param(snum, rpath_fname->base_name,
+ section, "err", 0) != 0) {
errno = ENOTSUP;
rc = -1;
goto out;
}
- if (dfq_load_param(snum, rpath, section, "nosys", 0) != 0) {
+ if (dfq_load_param(snum, rpath_fname->base_name,
+ section, "nosys", 0) != 0) {
errno = ENOSYS;
rc = -1;
goto out;
@@ -151,15 +157,22 @@ static int dfq_get_quota(struct vfs_handle_struct *handle,
ZERO_STRUCTP(qt);
qt->bsize = bsize;
- qt->hardlimit = dfq_load_param(snum, rpath, section, "hard limit", 0);
- qt->softlimit = dfq_load_param(snum, rpath, section, "soft limit", 0);
- qt->curblocks = dfq_load_param(snum, rpath, section, "cur blocks", 0);
+ qt->hardlimit = dfq_load_param(snum, rpath_fname->base_name,
+ section, "hard limit", 0);
+ qt->softlimit = dfq_load_param(snum, rpath_fname->base_name,
+ section, "soft limit", 0);
+ qt->curblocks = dfq_load_param(snum, rpath_fname->base_name,
+ section, "cur blocks", 0);
qt->ihardlimit =
- dfq_load_param(snum, rpath, section, "inode hard limit", 0);
+ dfq_load_param(snum, rpath_fname->base_name,
+ section, "inode hard limit", 0);
qt->isoftlimit =
- dfq_load_param(snum, rpath, section, "inode soft limit", 0);
- qt->curinodes = dfq_load_param(snum, rpath, section, "cur inodes", 0);
- qt->qflags = dfq_load_param(snum, rpath, section, "qflags", QUOTAS_DENY_DISK);
+ dfq_load_param(snum, rpath_fname->base_name,
+ section, "inode soft limit", 0);
+ qt->curinodes = dfq_load_param(snum, rpath_fname->base_name,
+ section, "cur inodes", 0);
+ qt->qflags = dfq_load_param(snum, rpath_fname->base_name,
+ section, "qflags", QUOTAS_DENY_DISK);
goto out;
@@ -169,7 +182,7 @@ dflt:
out:
save_errno = errno;
TALLOC_FREE(section);
- SAFE_FREE(rpath);
+ TALLOC_FREE(rpath_fname);
errno = save_errno;
return rc;
}
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 51783245566..e66ad9ebe43 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -1685,16 +1685,18 @@ static int smb_full_audit_mknod(vfs_handle_struct *handle,
return result;
}
-static char *smb_full_audit_realpath(vfs_handle_struct *handle,
- const char *path)
+static struct smb_filename *smb_full_audit_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
- char *result;
+ struct smb_filename *result_fname = NULL;
- result = SMB_VFS_NEXT_REALPATH(handle, path);
+ result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
- do_log(SMB_VFS_OP_REALPATH, (result != NULL), handle, "%s", path);
+ do_log(SMB_VFS_OP_REALPATH, (result_fname != NULL), handle, "%s",
+ smb_fname->base_name);
- return result;
+ return result_fname;
}
static int smb_full_audit_chflags(vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index 52539b36fd9..188463f6d51 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -1149,10 +1149,12 @@ static int vfs_gluster_fallocate(struct vfs_handle_struct *handle,
return -1;
}
-static char *vfs_gluster_realpath(struct vfs_handle_struct *handle,
- const char *path)
+static struct smb_filename *vfs_gluster_realpath(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
char *result = NULL;
+ struct smb_filename *result_fname = NULL;
char *resolved_path = SMB_MALLOC_ARRAY(char, PATH_MAX+1);
if (resolved_path == NULL) {
@@ -1160,12 +1162,15 @@ static char *vfs_gluster_realpath(struct vfs_handle_struct *handle,
return NULL;
}
- result = glfs_realpath(handle->data, path, resolved_path);
- if (result == NULL) {
- SAFE_FREE(resolved_path);
+ result = glfs_realpath(handle->data,
+ smb_fname->base_name,
+ resolved_path);
+ if (result != NULL) {
+ result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0);
}
- return result;
+ SAFE_FREE(resolved_path);
+ return result_fname;
}
static bool vfs_gluster_lock(struct vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c
index bd774b83909..e39a4447bc9 100644
--- a/source3/modules/vfs_media_harmony.c
+++ b/source3/modules/vfs_media_harmony.c
@@ -1863,36 +1863,28 @@ out:
* Success: return path pointer
* Failure: set errno, return NULL pointer
*/
-static char *mh_realpath(vfs_handle_struct *handle,
- const char *path)
+static struct smb_filename *mh_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
- char *buf;
- char *clientPath;
- TALLOC_CTX *ctx;
+ struct smb_filename *result_fname = NULL;
+ struct smb_filename *clientFname = NULL;
DEBUG(MH_INFO_DEBUG, ("Entering mh_realpath\n"));
- if (!is_in_media_files(path))
- {
- buf = SMB_VFS_NEXT_REALPATH(handle, path);
- goto out;
+ if (!is_in_media_files(smb_fname->base_name)) {
+ return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
- clientPath = NULL;
- ctx = talloc_tos();
-
- if (alloc_get_client_path(handle, ctx,
- path,
- &clientPath))
- {
- buf = NULL;
+ if (alloc_get_client_smb_fname(handle, ctx,
+ smb_fname,
+ &clientFname) != 0) {
goto err;
}
- buf = SMB_VFS_NEXT_REALPATH(handle, clientPath);
+ result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, clientFname);
err:
- TALLOC_FREE(clientPath);
-out:
- return buf;
+ TALLOC_FREE(clientFname);
+ return result_fname;
}
/*
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index b20213a698c..2977d7bdc3f 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -78,8 +78,8 @@ struct shadow_copy2_private {
char *shadow_cwd; /* Absolute $cwd path. */
/* Absolute connectpath - can vary depending on $cwd. */
char *shadow_connectpath;
- /* malloc'ed realpath return. */
- char *shadow_realpath;
+ /* talloc'ed realpath return. */
+ struct smb_filename *shadow_realpath;
};
static int shadow_copy2_get_shadow_copy_data(
@@ -1742,40 +1742,47 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle,
return ret;
}
-static char *shadow_copy2_realpath(vfs_handle_struct *handle,
- const char *fname)
+static struct smb_filename *shadow_copy2_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
time_t timestamp = 0;
char *stripped = NULL;
- char *tmp = NULL;
- char *result = NULL;
+ struct smb_filename *result_fname = NULL;
+ struct smb_filename *conv_fname = NULL;
int saved_errno = 0;
- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
- &timestamp, &stripped)) {
+ if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
+ smb_fname->base_name,
+ &timestamp, &stripped)) {
goto done;
}
if (timestamp == 0) {
- return SMB_VFS_NEXT_REALPATH(handle, fname);
+ return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
- tmp = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
- if (tmp == NULL) {
+ conv_fname = cp_smb_filename(talloc_tos(), smb_fname);
+ if (conv_fname == NULL) {
+ goto done;
+ }
+ conv_fname->base_name = shadow_copy2_convert(
+ conv_fname, handle, stripped, timestamp);
+ if (conv_fname->base_name == NULL) {
goto done;
}
- result = SMB_VFS_NEXT_REALPATH(handle, tmp);
+ result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, conv_fname);
done:
- if (result == NULL) {
+ if (result_fname == NULL) {
saved_errno = errno;
}
- TALLOC_FREE(tmp);
+ TALLOC_FREE(conv_fname);
TALLOC_FREE(stripped);
if (saved_errno != 0) {
errno = saved_errno;
}
- return result;
+ return result_fname;
}
/**
@@ -2698,6 +2705,8 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
time_t timestamp = 0;
char *stripped = NULL;
char *tmp = NULL;
+ struct smb_filename smb_fname = {0};
+ struct smb_filename *result_fname = NULL;
char *result = NULL;
char *parent_dir = NULL;
int saved_errno = 0;
@@ -2760,17 +2769,20 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
(int)rootpath_len, tmp);
tmp[rootpath_len] = '\0';
- result = SMB_VFS_NEXT_REALPATH(handle, tmp);
- if (result == NULL) {
+ smb_fname = (struct smb_filename) { .base_name = tmp };
+
+ result_fname = SMB_VFS_NEXT_REALPATH(handle, priv, &smb_fname);
+ if (result_fname == NULL) {
goto done;
}
/*
- * SMB_VFS_NEXT_REALPATH returns a malloc'ed string.
+ * SMB_VFS_NEXT_REALPATH returns a talloc'ed string.
* Don't leak memory.
*/
- SAFE_FREE(priv->shadow_realpath);
- priv->shadow_realpath = result;
+ TALLOC_FREE(priv->shadow_realpath);
+ priv->shadow_realpath = result_fname;
+ result = priv->shadow_realpath->base_name;
DBG_DEBUG("connect path is [%s]\n", result);
@@ -2890,12 +2902,6 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle,
return ret;
}
-static int shadow_copy2_private_destructor(struct shadow_copy2_private *priv)
-{
- SAFE_FREE(priv->shadow_realpath);
- return 0;
-}
-
static int shadow_copy2_connect(struct vfs_handle_struct *handle,
const char *service, const char *user)
{
@@ -2927,8 +2933,6 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle,
return -1;
}
- talloc_set_destructor(priv, shadow_copy2_private_destructor);
-
priv->snaps = talloc_zero(priv, struct shadow_copy2_snaplist_info);
if (priv->snaps == NULL) {
DBG_ERR("talloc_zero() failed\n");
diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c
index 05d57671db7..9dbb74f8fe9 100644
--- a/source3/modules/vfs_snapper.c
+++ b/source3/modules/vfs_snapper.c
@@ -2507,39 +2507,47 @@ static int snapper_gmt_mknod(vfs_handle_struct *handle,
return ret;
}
-static char *snapper_gmt_realpath(vfs_handle_struct *handle,
- const char *fname)
+static struct smb_filename *snapper_gmt_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
- time_t timestamp;
+ time_t timestamp = 0;
char *stripped = NULL;
- char *tmp = NULL;
- char *result = NULL;
- int saved_errno;
+ struct smb_filename *result_fname = NULL;
+ struct smb_filename *conv_smb_fname = NULL;
+ int saved_errno = 0;
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname,
+ if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
+ smb_fname->base_name,
&timestamp, &stripped)) {
goto done;
}
if (timestamp == 0) {
- return SMB_VFS_NEXT_REALPATH(handle, fname);
+ return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
}
- tmp = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- if (tmp == NULL) {
+ conv_smb_fname = cp_smb_filename(talloc_tos(), smb_fname);
+ if (conv_smb_fname == NULL) {
goto done;
}
-
- result = SMB_VFS_NEXT_REALPATH(handle, tmp);
- if (result == NULL) {
+ conv_smb_fname->base_name = snapper_gmt_convert(conv_smb_fname, handle,
+ stripped, timestamp);
+ if (conv_smb_fname->base_name == NULL) {
goto done;
}
+ result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, conv_smb_fname);
+
done:
- saved_errno = errno;
- TALLOC_FREE(tmp);
+ if (result_fname == NULL) {
+ saved_errno = errno;
+ }
+ TALLOC_FREE(conv_smb_fname);
TALLOC_FREE(stripped);
- errno = saved_errno;
- return result;
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
+ return result_fname;
}
static NTSTATUS snapper_gmt_fget_nt_acl(vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index 22075e7ac16..905ad22fa6c 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -1513,23 +1513,25 @@ static int smb_time_audit_mknod(vfs_handle_struct *handle,
return result;
}
-static char *smb_time_audit_realpath(vfs_handle_struct *handle,
- const char *path)
+static struct smb_filename *smb_time_audit_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
- char *result;
+ struct smb_filename *result_fname;
struct timespec ts1,ts2;
double timediff;
clock_gettime_mono(&ts1);
- result = SMB_VFS_NEXT_REALPATH(handle, path);
+ result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname);
clock_gettime_mono(&ts2);
timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
if (timediff > audit_timeout) {
- smb_time_audit_log_fname("realpath", timediff, path);
+ smb_time_audit_log_fname("realpath", timediff,
+ smb_fname->base_name);
}
- return result;
+ return result_fname;
}
static int smb_time_audit_chflags(vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c
index 435deeb0579..34881bc50b7 100644
--- a/source3/modules/vfs_unityed_media.c
+++ b/source3/modules/vfs_unityed_media.c
@@ -1444,30 +1444,31 @@ err:
return status;
}
-static char *um_realpath(vfs_handle_struct *handle,
- const char *path)
+static struct smb_filename *um_realpath(vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
- char *buf = NULL;
- char *client_path = NULL;
+ struct smb_filename *client_fname = NULL;
+ struct smb_filename *result_fname = NULL;
int status;
DEBUG(10, ("Entering um_realpath\n"));
- if (!is_in_media_files(path)) {
- return SMB_VFS_NEXT_REALPATH(handle, path);
+ if (!is_in_media_files(smb_fname->base_name)) {
+ return SMB_VFS_NEXT_REALPATH(handle, ctx, 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;
}
- buf = SMB_VFS_NEXT_REALPATH(handle, client_path);
+ result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, client_fname);
err:
- TALLOC_FREE(client_path);
- return buf;
+ TALLOC_FREE(client_fname);
+ return result_fname;
}
static int um_chflags(vfs_handle_struct *handle,
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index ac637ba7834..d7f471ed671 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -410,9 +410,11 @@ static int process_symlink_open(struct connection_struct *conn,
{
int fd = -1;
char *link_target = NULL;
+ struct smb_filename target_fname = {0};
int link_len = -1;
struct smb_filename *oldwd_fname = NULL;
size_t rootdir_len = 0;
+ struct smb_filename *resolved_fname = NULL;
char *resolved_name = NULL;
bool matched = false;
int saved_errno = 0;
@@ -444,12 +446,14 @@ static int process_symlink_open(struct connection_struct *conn,
/* Ensure it's at least null terminated. */
link_target[link_len] = '\0';
+ target_fname = (struct smb_filename){ .base_name = link_target };
/* Convert to an absolute path. */
- resolved_name = SMB_VFS_REALPATH(conn, link_target);
- if (resolved_name == NULL) {
+ resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(), &target_fname);
+ if (resolved_fname == NULL) {
goto out;
}
+ resolved_name = resolved_fname->base_name;
/*
* We know conn_rootdir starts with '/' and
@@ -471,18 +475,22 @@ static int process_symlink_open(struct connection_struct *conn,
*/
if (resolved_name[rootdir_len] == '\0') {
/* Link to the root of the share. */
- smb_fname->base_name = talloc_strdup(talloc_tos(), ".");
- if (smb_fname->base_name == NULL) {
- errno = ENOMEM;
- goto out;
- }
+ TALLOC_FREE(smb_fname->base_name);
+ smb_fname->base_name = talloc_strdup(smb_fname, ".");
} else if (resolved_name[rootdir_len] == '/') {
- smb_fname->base_name = &resolved_name[rootdir_len+1];
+ TALLOC_FREE(smb_fname->base_name);
+ smb_fname->base_name = talloc_strdup(smb_fname,
+ &resolved_name[rootdir_len+1]);
} else {
errno = EACCES;
goto out;
}
+ if (smb_fname->base_name == NULL) {
+ errno = ENOMEM;
+ goto out;
+ }
+
oldwd_fname = vfs_GetWd(talloc_tos(), conn);
if (oldwd_fname == NULL) {
goto out;
@@ -507,7 +515,7 @@ static int process_symlink_open(struct connection_struct *conn,
out:
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
TALLOC_FREE(link_target);
if (oldwd_fname != NULL) {
int ret = vfs_ChDir(conn, oldwd_fname);
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index ed739c9baf1..75a47dee0ca 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -36,12 +36,14 @@
static bool canonicalize_connect_path(connection_struct *conn)
{
bool ret;
- char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
- if (!resolved_name) {
+ struct smb_filename con_fname = { .base_name = conn->connectpath };
+ struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
+ &con_fname);
+ if (resolved_fname == NULL) {
return false;
}
- ret = set_conn_connectpath(conn,resolved_name);
- SAFE_FREE(resolved_name);
+ ret = set_conn_connectpath(conn,resolved_fname->base_name);
+ TALLOC_FREE(resolved_fname);
return ret;
}
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 5c4e9c37b30..7607bcb0537 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -1024,8 +1024,9 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
const char *conn_rootdir;
size_t rootdir_len;
char *dir_name = NULL;
- const char *last_component = NULL;
char *resolved_name = NULL;
+ const char *last_component = NULL;
+ struct smb_filename *resolved_fname = NULL;
struct smb_filename *saved_dir_fname = NULL;
struct smb_filename *smb_fname_cwd = NULL;
struct privilege_paths *priv_paths = NULL;
@@ -1072,12 +1073,19 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
goto err;
}
+ smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
+ if (smb_fname_cwd == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto err;
+ }
+
/* Get the absolute path of the parent directory. */
- resolved_name = SMB_VFS_REALPATH(conn,".");
- if (!resolved_name) {
+ resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd);
+ if (resolved_fname == NULL) {
status = map_nt_error_from_unix(errno);
goto err;
}
+ resolved_name = resolved_fname->base_name;
if (*resolved_name != '/') {
DEBUG(0,("check_reduced_name_with_privilege: realpath "
@@ -1091,12 +1099,6 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
resolved_name));
/* Now check the stat value is the same. */
- smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0);
- if (smb_fname_cwd == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto err;
- }
-
if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) {
status = map_nt_error_from_unix(errno);
goto err;
@@ -1186,7 +1188,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
vfs_ChDir(conn, saved_dir_fname);
TALLOC_FREE(saved_dir_fname);
}
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(priv_paths);
}
@@ -1209,6 +1211,9 @@ NTSTATUS check_reduced_name(connection_struct *conn,
const char *cwd_name,
const char *fname)
{
+ TALLOC_CTX *ctx = talloc_tos();
+ struct smb_filename smb_fname = { .base_name = discard_const(fname) };
+ struct smb_filename *resolved_fname;
char *resolved_name = NULL;
char *new_fname = NULL;
bool allow_symlinks = true;
@@ -1216,9 +1221,9 @@ NTSTATUS check_reduced_name(connection_struct *conn,
DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
- resolved_name = SMB_VFS_REALPATH(conn,fname);
+ resolved_fname = SMB_VFS_REALPATH(conn, ctx, &smb_fname);
- if (!resolved_name) {
+ if (resolved_fname == NULL) {
switch (errno) {
case ENOTDIR:
DEBUG(3,("check_reduced_name: Component not a "
@@ -1227,11 +1232,9 @@ NTSTATUS check_reduced_name(connection_struct *conn,
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
case ENOENT:
{
- TALLOC_CTX *ctx = talloc_tos();
char *dir_name = NULL;
+ struct smb_filename dir_fname = {0};
const char *last_component = NULL;
- char *new_name = NULL;
- int ret;
/* Last component didn't exist.
Remove it and try and canonicalise
@@ -1242,8 +1245,12 @@ NTSTATUS check_reduced_name(connection_struct *conn,
return NT_STATUS_NO_MEMORY;
}
- resolved_name = SMB_VFS_REALPATH(conn,dir_name);
- if (!resolved_name) {
+ dir_fname = (struct smb_filename)
+ { .base_name = dir_name };
+ resolved_fname = SMB_VFS_REALPATH(conn,
+ ctx,
+ &dir_fname);
+ if (resolved_fname == NULL) {
NTSTATUS status = map_nt_error_from_unix(errno);
if (errno == ENOENT || errno == ENOTDIR) {
@@ -1257,13 +1264,13 @@ NTSTATUS check_reduced_name(connection_struct *conn,
nt_errstr(status)));
return status;
}
- ret = asprintf(&new_name, "%s/%s",
- resolved_name, last_component);
- SAFE_FREE(resolved_name);
- if (ret == -1) {
+ resolved_name = talloc_asprintf(ctx,
+ "%s/%s",
+ resolved_fname->base_name,
+ last_component);
+ if (resolved_name == NULL) {
return NT_STATUS_NO_MEMORY;
}
- resolved_name = new_name;
break;
}
default:
@@ -1271,6 +1278,8 @@ NTSTATUS check_reduced_name(connection_struct *conn,
"realpath for %s\n", fname));
return map_nt_error_from_unix(errno);
}
+ } else {
+ resolved_name = resolved_fname->base_name;
}
DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
@@ -1279,7 +1288,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
if (*resolved_name != '/') {
DEBUG(0,("check_reduced_name: realpath doesn't return "
"absolute paths !\n"));
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
return NT_STATUS_OBJECT_NAME_INVALID;
}
@@ -1295,7 +1304,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
if (conn_rootdir == NULL) {
DEBUG(2, ("check_reduced_name: Could not get "
"conn_rootdir\n"));
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
return NT_STATUS_ACCESS_DENIED;
}
@@ -1324,7 +1333,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
conn_rootdir));
DEBUGADD(2, ("resolved_name=%s\n",
resolved_name));
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
return NT_STATUS_ACCESS_DENIED;
}
}
@@ -1347,7 +1356,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
"in resolved_name: %s\n",
*p,
fname));
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
return NT_STATUS_ACCESS_DENIED;
}
@@ -1361,12 +1370,12 @@ NTSTATUS check_reduced_name(connection_struct *conn,
* sent (cwd_name+fname).
*/
if (cwd_name != NULL && !ISDOT(cwd_name)) {
- new_fname = talloc_asprintf(talloc_tos(),
+ new_fname = talloc_asprintf(ctx,
"%s/%s",
cwd_name,
fname);
if (new_fname == NULL) {
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
return NT_STATUS_NO_MEMORY;
}
fname = new_fname;
@@ -1376,7 +1385,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
DEBUG(2, ("check_reduced_name: Bad access "
"attempt: %s is a symlink to %s\n",
fname, p));
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
TALLOC_FREE(new_fname);
return NT_STATUS_ACCESS_DENIED;
}
@@ -1386,7 +1395,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
out:
DBG_INFO("%s reduced to %s\n", fname, resolved_name);
- SAFE_FREE(resolved_name);
+ TALLOC_FREE(resolved_fname);
TALLOC_FREE(new_fname);
return NT_STATUS_OK;
}
@@ -2212,10 +2221,12 @@ int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
return handle->fns->mknod_fn(handle, smb_fname, mode, dev);
}
-char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path)
+struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
+ TALLOC_CTX *ctx,
+ const struct smb_filename *smb_fname)
{
VFS_FIND(realpath);
- return handle->fns->realpath_fn(handle, path);
+ return handle->fns->realpath_fn(handle, ctx, smb_fname);
}
int smb_vfs_call_chflags(struct vfs_handle_struct *handle,
diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c
index fd09df9bcd6..034136f3d23 100644
--- a/source3/torture/cmd_vfs.c
+++ b/source3/torture/cmd_vfs.c
@@ -1340,12 +1340,20 @@ static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc,
static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
{
+ struct smb_filename *smb_fname = NULL;
+
if (argc != 2) {
printf("Usage: realpath <path>\n");
return NT_STATUS_OK;
}
- if (SMB_VFS_REALPATH(vfs->conn, argv[1]) == NULL) {
+ smb_fname = synthetic_smb_fname_split(mem_ctx,
+ argv[1],
+ lp_posix_pathnames());
+ if (smb_fname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (SMB_VFS_REALPATH(vfs->conn, mem_ctx, smb_fname) == NULL) {
printf("realpath: error=%d (%s)\n", errno, strerror(errno));
return NT_STATUS_UNSUCCESSFUL;
}