s3: VFS: Change SMB_VFS_REALPATH to take and return struct smb_filename * instead...
authorJeremy Allison <jra@samba.org>
Fri, 30 Jun 2017 18:32:59 +0000 (11:32 -0700)
committerJeremy Allison <jra@samba.org>
Sat, 1 Jul 2017 01:07:11 +0000 (03:07 +0200)
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>
20 files changed:
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_cap.c
source3/modules/vfs_catia.c
source3/modules/vfs_ceph.c
source3/modules/vfs_default.c
source3/modules/vfs_fake_dfq.c
source3/modules/vfs_full_audit.c
source3/modules/vfs_glusterfs.c
source3/modules/vfs_media_harmony.c
source3/modules/vfs_shadow_copy2.c
source3/modules/vfs_snapper.c
source3/modules/vfs_time_audit.c
source3/modules/vfs_unityed_media.c
source3/smbd/open.c
source3/smbd/service.c
source3/smbd/vfs.c
source3/torture/cmd_vfs.c

index 8bfc520..f8f9857 100644 (file)
@@ -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;
index a5ba6a9..29a9785 100644 (file)
@@ -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,
index 716e194..1aa44ee 100644 (file)
                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);
index 29f0338..0e8245e 100644 (file)
 #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))
index 44a81bb..e4d30cb 100644 (file)
@@ -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,
index 7db50a2..6adf441 100644 (file)
@@ -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,
index 7d3f4a7..488ebc7 100644 (file)
@@ -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,
index b01a007..3336232 100644 (file)
@@ -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,
index 971db68..019b2e8 100644 (file)
@@ -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;
 }
index 5178324..e66ad9e 100644 (file)
@@ -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,
index 52539b3..188463f 100644 (file)
@@ -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,
index bd774b8..e39a444 100644 (file)
@@ -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;
 }
 
 /*
index b20213a..2977d7b 100644 (file)
@@ -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");
index 05d5767..9dbb74f 100644 (file)
@@ -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,
index 22075e7..905ad22 100644 (file)
@@ -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,
index 435deeb..34881bc 100644 (file)
@@ -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,
index ac637ba..d7f471e 100644 (file)
@@ -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);
index ed739c9..75a47de 100644 (file)
 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;
 }
 
index 5c4e9c3..7607bcb 100644 (file)
@@ -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,
index fd09df9..034136f 100644 (file)
@@ -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;
        }