s3: VFS: Change SMB_VFS_SYMLINK to use const struct smb_filename * instead of const...
authorJeremy Allison <jra@samba.org>
Thu, 8 Jun 2017 23:25:58 +0000 (16:25 -0700)
committerJeremy Allison <jra@samba.org>
Sun, 18 Jun 2017 05:03:18 +0000 (07:03 +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>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Sun Jun 18 07:03:18 CEST 2017 on sn-devel-144

18 files changed:
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source3/include/vfs.h
source3/modules/vfs_cap.c
source3/modules/vfs_ceph.c
source3/modules/vfs_default.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_syncops.c
source3/modules/vfs_time_audit.c
source3/modules/vfs_unityed_media.c
source3/smbd/msdfs.c
source3/smbd/trans2.c
source3/smbd/vfs.c
source3/torture/cmd_vfs.c

index 792f728..d5c468e 100644 (file)
@@ -476,8 +476,9 @@ static bool skel_getlock(vfs_handle_struct *handle, files_struct *fsp,
        return false;
 }
 
-static int skel_symlink(vfs_handle_struct *handle, const char *oldpath,
-                       const char *newpath)
+static int skel_symlink(vfs_handle_struct *handle,
+                       const char *link_contents,
+                       const struct smb_filename *new_smb_fname)
 {
        errno = ENOSYS;
        return -1;
index 11512e3..9387276 100644 (file)
@@ -570,10 +570,11 @@ static bool skel_getlock(vfs_handle_struct *handle, files_struct *fsp,
        return SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype, ppid);
 }
 
-static int skel_symlink(vfs_handle_struct *handle, const char *oldpath,
-                       const char *newpath)
+static int skel_symlink(vfs_handle_struct *handle,
+                       const char *link_contents,
+                       const struct smb_filename *new_smb_fname)
 {
-       return SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
+       return SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
 }
 
 static int skel_vfs_readlink(vfs_handle_struct *handle,
index 115a9dc..db555f2 100644 (file)
                to const struct smb_filename * */
 /* Version 37 - Change readlink from const char *
                to const struct smb_filename * */
+/* Version 37 - Change symlink from const char *
+               to const struct smb_filename * */
 
 #define SMB_VFS_INTERFACE_VERSION 37
 
@@ -745,7 +747,9 @@ struct vfs_fn_pointers {
                               uint32_t share_mode, uint32_t access_mask);
        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 (*symlink_fn)(struct vfs_handle_struct *handle,
+                               const char *link_contents,
+                               const struct smb_filename *new_smb_fname);
        int (*readlink_fn)(struct vfs_handle_struct *handle,
                                const struct smb_filename *smb_fname,
                                char *buf,
@@ -1251,8 +1255,9 @@ int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
 bool smb_vfs_call_getlock(struct vfs_handle_struct *handle,
                          struct files_struct *fsp, off_t *poffset,
                          off_t *pcount, int *ptype, pid_t *ppid);
-int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
-                        const char *newpath);
+int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
+                       const char *link_contents,
+                       const struct smb_filename *new_smb_fname);
 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
                        const struct smb_filename *smb_fname,
                        char *buf,
index 2c21ab1..c07a059 100644 (file)
@@ -479,17 +479,44 @@ static int cap_ntimes(vfs_handle_struct *handle,
 }
 
 
-static int cap_symlink(vfs_handle_struct *handle, const char *oldpath,
-                      const char *newpath)
+static int cap_symlink(vfs_handle_struct *handle,
+                       const char *link_contents,
+                       const struct smb_filename *new_smb_fname)
 {
-       char *capold = capencode(talloc_tos(), oldpath);
-       char *capnew = capencode(talloc_tos(), newpath);
+       char *capold = capencode(talloc_tos(), link_contents);
+       char *capnew = capencode(talloc_tos(), new_smb_fname->base_name);
+       struct smb_filename *new_cap_smb_fname = NULL;
+       int saved_errno = 0;
+       int ret;
 
        if (!capold || !capnew) {
                errno = ENOMEM;
                return -1;
        }
-       return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew);
+       new_cap_smb_fname = synthetic_smb_fname(talloc_tos(),
+                                       capnew,
+                                       NULL,
+                                       NULL,
+                                       new_smb_fname->flags);
+       if (new_cap_smb_fname == NULL) {
+               TALLOC_FREE(capold);
+               TALLOC_FREE(capnew);
+               errno = ENOMEM;
+               return -1;
+       }
+       ret = SMB_VFS_NEXT_SYMLINK(handle,
+                       capold,
+                       new_cap_smb_fname);
+       if (ret == -1) {
+               saved_errno = errno;
+       }
+       TALLOC_FREE(capold);
+       TALLOC_FREE(capnew);
+       TALLOC_FREE(new_cap_smb_fname);
+       if (saved_errno != 0) {
+               errno = saved_errno;
+       }
+       return ret;
 }
 
 static int cap_readlink(vfs_handle_struct *handle,
index 3c38165..7e2bd0e 100644 (file)
@@ -1125,11 +1125,17 @@ static int cephwrap_linux_setlease(struct vfs_handle_struct *handle, files_struc
        return result;
 }
 
-static int cephwrap_symlink(struct vfs_handle_struct *handle,  const char *oldpath, const char *newpath)
+static int cephwrap_symlink(struct vfs_handle_struct *handle,
+               const char *link_target,
+               const struct smb_filename *new_smb_fname)
 {
        int result = -1;
-       DBG_DEBUG("[CEPH] symlink(%p, %s, %s)\n", handle, oldpath, newpath);
-       result = ceph_symlink(handle->data, oldpath, newpath);
+       DBG_DEBUG("[CEPH] symlink(%p, %s, %s)\n", handle,
+                       link_target,
+                       new_smb_fname->base_name);
+       result = ceph_symlink(handle->data,
+                       link_target,
+                       new_smb_fname->base_name);
        DBG_DEBUG("[CEPH] symlink(...) = %d\n", result);
        WRAP_RETURN(result);
 }
index 93ff657..d339f39 100644 (file)
@@ -2418,12 +2418,14 @@ static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
        return result;
 }
 
-static int vfswrap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
+static int vfswrap_symlink(vfs_handle_struct *handle,
+                       const char *link_target,
+                       const struct smb_filename *new_smb_fname)
 {
        int result;
 
        START_PROFILE(syscall_symlink);
-       result = symlink(oldpath, newpath);
+       result = symlink(link_target, new_smb_fname->base_name);
        END_PROFILE(syscall_symlink);
        return result;
 }
index 408f834..1267ef3 100644 (file)
@@ -1626,14 +1626,15 @@ static bool smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp,
 }
 
 static int smb_full_audit_symlink(vfs_handle_struct *handle,
-                        const char *oldpath, const char *newpath)
+                       const char *link_contents,
+                       const struct smb_filename *new_smb_fname)
 {
        int result;
 
-       result = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
+       result = SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
 
        do_log(SMB_VFS_OP_SYMLINK, (result >= 0), handle,
-              "%s|%s", oldpath, newpath);
+              "%s|%s", link_contents, new_smb_fname->base_name);
 
        return result;
 }
index bf19dd7..2528959 100644 (file)
@@ -1234,9 +1234,12 @@ static bool vfs_gluster_getlock(struct vfs_handle_struct *handle,
 }
 
 static int vfs_gluster_symlink(struct vfs_handle_struct *handle,
-                              const char *oldpath, const char *newpath)
+                               const char *link_target,
+                               const struct smb_filename *new_smb_fname)
 {
-       return glfs_symlink(handle->data, oldpath, newpath);
+       return glfs_symlink(handle->data,
+                       link_target,
+                       new_smb_fname->base_name);
 }
 
 static int vfs_gluster_readlink(struct vfs_handle_struct *handle,
index 13604b3..ca8d6ce 100644 (file)
@@ -1719,47 +1719,41 @@ out:
  * Success: return 0
  * Failure: set errno, return -1
  */
+
 static int mh_symlink(vfs_handle_struct *handle,
-               const char *oldpath,
-               const char *newpath)
+               const char *link_contents,
+               const struct smb_filename *new_smb_fname)
 {
-       int status;
-       char *oldClientPath;
-       char *newClientPath;
-       TALLOC_CTX *ctx;
+       int status = -1;
+       char *client_link_contents = NULL;
+       struct smb_filename *newclientFname = NULL;
 
        DEBUG(MH_INFO_DEBUG, ("Entering mh_symlink\n"));
-       if (!is_in_media_files(oldpath) && !is_in_media_files(newpath))
-       {
-               status = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
+       if (!is_in_media_files(link_contents) &&
+                       !is_in_media_files(new_smb_fname->base_name)) {
+               status = SMB_VFS_NEXT_SYMLINK(handle,
+                               link_contents,
+                               new_smb_fname);
                goto out;
        }
 
-       oldClientPath = NULL;
-       newClientPath = NULL;
-       ctx = talloc_tos();
-
-       if ((status = alloc_get_client_path(handle, ctx,
-                               oldpath,
-                               &oldClientPath)))
-       {
+       if ((status = alloc_get_client_path(handle, talloc_tos(),
+                               link_contents,
+                               &client_link_contents))) {
                goto err;
        }
-
-       if ((status = alloc_get_client_path(handle, ctx,
-                               newpath,
-                               &newClientPath)))
-       {
+       if ((status = alloc_get_client_smb_fname(handle, talloc_tos(),
+                               new_smb_fname,
+                               &newclientFname))) {
                goto err;
        }
 
        status = SMB_VFS_NEXT_SYMLINK(handle,
-                       oldClientPath,
-                       newClientPath);
-
+                               client_link_contents,
+                               newclientFname);
 err:
-       TALLOC_FREE(newClientPath);
-       TALLOC_FREE(oldClientPath);
+       TALLOC_FREE(client_link_contents);
+       TALLOC_FREE(newclientFname);
 out:
        return status;
 }
index 2c7fcaa..31ef499 100644 (file)
@@ -1150,19 +1150,28 @@ static int shadow_copy2_rename(vfs_handle_struct *handle,
 }
 
 static int shadow_copy2_symlink(vfs_handle_struct *handle,
-                               const char *oldname, const char *newname)
+                       const char *link_contents,
+                       const struct smb_filename *new_smb_fname)
 {
        time_t timestamp_old = 0;
        time_t timestamp_new = 0;
        char *snappath_old = NULL;
        char *snappath_new = NULL;
 
-       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, oldname,
-                                        &timestamp_old, NULL, &snappath_old)) {
+       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
+                               handle,
+                               link_contents,
+                               &timestamp_old,
+                               NULL,
+                               &snappath_old)) {
                return -1;
        }
-       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, newname,
-                                        &timestamp_new, NULL, &snappath_new)) {
+       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(),
+                               handle,
+                               new_smb_fname->base_name,
+                               &timestamp_new,
+                               NULL,
+                               &snappath_new)) {
                return -1;
        }
        if ((timestamp_old != 0) || (timestamp_new != 0)) {
@@ -1176,7 +1185,7 @@ static int shadow_copy2_symlink(vfs_handle_struct *handle,
                errno = EROFS;
                return -1;
        }
-       return SMB_VFS_NEXT_SYMLINK(handle, oldname, newname);
+       return SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
 }
 
 static int shadow_copy2_link(vfs_handle_struct *handle,
index a413974..4c81432 100644 (file)
@@ -2037,23 +2037,31 @@ static int snapper_gmt_rename(vfs_handle_struct *handle,
 }
 
 static int snapper_gmt_symlink(vfs_handle_struct *handle,
-                              const char *oldname, const char *newname)
+                               const char *link_contents,
+                               const struct smb_filename *new_smb_fname)
 {
-       time_t timestamp_old, timestamp_new;
+       time_t timestamp_old = 0;
+       time_t timestamp_new = 0;
 
-       if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, oldname,
-                                       &timestamp_old, NULL)) {
+       if (!snapper_gmt_strip_snapshot(talloc_tos(),
+                               handle,
+                               link_contents,
+                               &timestamp_old,
+                               NULL)) {
                return -1;
        }
-       if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, newname,
-                                       &timestamp_new, NULL)) {
+       if (!snapper_gmt_strip_snapshot(talloc_tos(),
+                               handle,
+                               new_smb_fname->base_name,
+                               &timestamp_new,
+                               NULL)) {
                return -1;
        }
        if ((timestamp_old != 0) || (timestamp_new != 0)) {
                errno = EROFS;
                return -1;
        }
-       return SMB_VFS_NEXT_SYMLINK(handle, oldname, newname);
+       return SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
 }
 
 static int snapper_gmt_link(vfs_handle_struct *handle,
index 725bd10..f94588c 100644 (file)
@@ -108,19 +108,6 @@ static void syncops_two_names(const char *name1, const char *name2)
        talloc_free(tmp_ctx);
 }
 
-/*
-  sync two meta data changes for 1 names
- */
-static void syncops_name(const char *name)
-{
-       char *parent;
-       parent = parent_dir(NULL, name);
-       if (parent) {
-               syncops_sync_directory(parent);
-               talloc_free(parent);
-       }
-}
-
 /*
   sync two meta data changes for 1 names
  */
@@ -158,20 +145,6 @@ static int syncops_rename(vfs_handle_struct *handle,
        return ret;
 }
 
-/* handle the rest with a macro */
-#define SYNCOPS_NEXT(op, fname, args) do {   \
-       int ret; \
-       struct syncops_config_data *config; \
-       SMB_VFS_HANDLE_GET_DATA(handle, config, \
-                               struct syncops_config_data, \
-                               return -1); \
-       ret = SMB_VFS_NEXT_ ## op args; \
-       if (ret == 0 \
-               && config->onmeta && !config->disable  \
-               && fname) syncops_name(fname); \
-       return ret; \
-} while (0)
-
 #define SYNCOPS_NEXT_SMB_FNAME(op, fname, args) do {   \
        int ret; \
        struct syncops_config_data *config; \
@@ -186,9 +159,22 @@ static int syncops_rename(vfs_handle_struct *handle,
 } while (0)
 
 static int syncops_symlink(vfs_handle_struct *handle,
-                          const char *oldname, const char *newname)
+                       const char *link_contents,
+                       const struct smb_filename *new_smb_fname)
 {
-       SYNCOPS_NEXT(SYMLINK, newname, (handle, oldname, newname));
+       int ret;
+       struct syncops_config_data *config;
+
+       SMB_VFS_HANDLE_GET_DATA(handle, config,
+                               struct syncops_config_data,
+                               return -1);
+
+       ret = SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
+       if (ret == 0 && config->onmeta && !config->disable) {
+               syncops_two_names(link_contents,
+                                 new_smb_fname->base_name);
+       }
+       return ret;
 }
 
 static int syncops_link(vfs_handle_struct *handle,
index 58c0f79..d399201 100644 (file)
@@ -1424,19 +1424,21 @@ static bool smb_time_audit_getlock(vfs_handle_struct *handle,
 }
 
 static int smb_time_audit_symlink(vfs_handle_struct *handle,
-                                 const char *oldpath, const char *newpath)
+                               const char *link_contents,
+                               const struct smb_filename *new_smb_fname)
 {
        int result;
        struct timespec ts1,ts2;
        double timediff;
 
        clock_gettime_mono(&ts1);
-       result = SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
+       result = SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
        clock_gettime_mono(&ts2);
        timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
 
        if (timediff > audit_timeout) {
-               smb_time_audit_log_fname("symlink", timediff, newpath);
+               smb_time_audit_log_fname("symlink", timediff,
+                       new_smb_fname->base_name);
        }
 
        return result;
index c9ecc27..45232e1 100644 (file)
@@ -1318,38 +1318,40 @@ err:
 }
 
 static int um_symlink(vfs_handle_struct *handle,
-                     const char *oldpath,
-                     const char *newpath)
+                       const char *link_contents,
+                       const struct smb_filename *new_smb_fname)
 {
        int status;
-       char *old_client_path = NULL;
-       char *new_client_path = NULL;
+       char *client_link_contents = NULL;
+       struct smb_filename *new_client_fname = NULL;
 
        DEBUG(10, ("Entering um_symlink\n"));
 
-       if (!is_in_media_files(oldpath) && !is_in_media_files(newpath)) {
-               return SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath);
+       if (!is_in_media_files(link_contents) &&
+                       !is_in_media_files(new_smb_fname->base_name)) {
+               return SMB_VFS_NEXT_SYMLINK(handle,
+                               link_contents,
+                               new_smb_fname);
        }
 
        status = alloc_get_client_path(handle, talloc_tos(),
-                                      oldpath, &old_client_path);
+                               link_contents, &client_link_contents);
        if (status != 0) {
                goto err;
        }
-
-       status = alloc_get_client_path(handle, talloc_tos(),
-                                      newpath, &new_client_path);
+       status = alloc_get_client_smb_fname(handle, talloc_tos(),
+                                           new_smb_fname, &new_client_fname);
        if (status != 0) {
                goto err;
        }
 
        status = SMB_VFS_NEXT_SYMLINK(handle,
-                                     old_client_path,
-                                     new_client_path);
+                                       client_link_contents,
+                                       new_client_fname);
 
 err:
-       TALLOC_FREE(new_client_path);
-       TALLOC_FREE(old_client_path);
+       TALLOC_FREE(client_link_contents);
+       TALLOC_FREE(new_client_fname);
        return status;
 }
 
index b88538c..9c25d8b 100644 (file)
@@ -1297,6 +1297,7 @@ bool create_msdfs_link(const struct junction_map *jucn)
        int i=0;
        bool insert_comma = False;
        bool ret = False;
+       struct smb_filename *smb_fname = NULL;
 
        if(!junction_to_local_path(jucn, &path, &conn, &cwd)) {
                return False;
@@ -1339,27 +1340,24 @@ bool create_msdfs_link(const struct junction_map *jucn)
        DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n",
                path, msdfs_link));
 
-       if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) {
-               if (errno == EEXIST) {
-                       struct smb_filename *smb_fname;
-
-                       smb_fname = synthetic_smb_fname(talloc_tos(),
-                                               path,
-                                               NULL,
-                                               NULL,
-                                               0);
-                       if (smb_fname == NULL) {
-                               errno = ENOMEM;
-                               goto out;
-                       }
+       smb_fname = synthetic_smb_fname(talloc_tos(),
+                               path,
+                               NULL,
+                               NULL,
+                               0);
+       if (smb_fname == NULL) {
+               errno = ENOMEM;
+               goto out;
+       }
 
+       if(SMB_VFS_SYMLINK(conn, msdfs_link, smb_fname) < 0) {
+               if (errno == EEXIST) {
                        if(SMB_VFS_UNLINK(conn, smb_fname)!=0) {
                                TALLOC_FREE(smb_fname);
                                goto out;
                        }
-                       TALLOC_FREE(smb_fname);
                }
-               if (SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) {
+               if (SMB_VFS_SYMLINK(conn, msdfs_link, smb_fname) < 0) {
                        DEBUG(1,("create_msdfs_link: symlink failed "
                                 "%s -> %s\nError: %s\n",
                                 path, msdfs_link, strerror(errno)));
@@ -1370,6 +1368,7 @@ bool create_msdfs_link(const struct junction_map *jucn)
        ret = True;
 
 out:
+       TALLOC_FREE(smb_fname);
        vfs_ChDir(conn, cwd);
        SMB_VFS_DISCONNECT(conn);
        conn_free(conn);
index 8615a78..de6073a 100644 (file)
@@ -6607,10 +6607,9 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
                                       struct smb_request *req,
                                       const char *pdata,
                                       int total_data,
-                                      const struct smb_filename *smb_fname)
+                                      const struct smb_filename *new_smb_fname)
 {
        char *link_target = NULL;
-       const char *newname = smb_fname->base_name;
        TALLOC_CTX *ctx = talloc_tos();
 
        /* Set a symbolic link. */
@@ -6632,9 +6631,9 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
        }
 
        DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
-                       newname, link_target ));
+                       new_smb_fname->base_name, link_target ));
 
-       if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
+       if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
                return map_nt_error_from_unix(errno);
        }
 
index bed3d2c..5acfb9a 100644 (file)
@@ -2152,11 +2152,12 @@ int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
        return handle->fns->linux_setlease_fn(handle, fsp, leasetype);
 }
 
-int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
-                        const char *newpath)
+int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
+                       const char *link_target,
+                       const struct smb_filename *new_smb_fname)
 {
        VFS_FIND(symlink);
-       return handle->fns->symlink_fn(handle, oldpath, newpath);
+       return handle->fns->symlink_fn(handle, link_target, new_smb_fname);
 }
 
 int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
index 47e365a..65a8e25 100644 (file)
@@ -1213,12 +1213,20 @@ static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c
 
 static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
 {
+       struct smb_filename *new_smb_fname = NULL;
+
        if (argc != 3) {
                printf("Usage: symlink <path> <link>\n");
                return NT_STATUS_OK;
        }
 
-       if (SMB_VFS_SYMLINK(vfs->conn, argv[1], argv[2]) == -1) {
+       new_smb_fname = synthetic_smb_fname_split(mem_ctx,
+                                       argv[2],
+                                       lp_posix_pathnames());
+       if (new_smb_fname == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       if (SMB_VFS_SYMLINK(vfs->conn, argv[1], new_smb_fname) == -1) {
                printf("symlink: error=%d (%s)\n", errno, strerror(errno));
                return NT_STATUS_UNSUCCESSFUL;
        }