From 5b305d1fbb2778f8c8dd2873e79f28a27d8ce581 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 6 Aug 2024 13:21:34 +0200 Subject: [PATCH] s3:vfs: add vfs_rename_how to SMB_VFS_RENAMEAT() This will support renameat2-like operations in future. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- examples/VFS/skel_opaque.c | 3 ++- examples/VFS/skel_transparent.c | 6 ++++-- source3/include/vfs.h | 17 +++++++++++++---- source3/include/vfs_macros.h | 8 ++++---- source3/modules/vfs_audit.c | 6 ++++-- source3/modules/vfs_cap.c | 6 ++++-- source3/modules/vfs_catia.c | 6 ++++-- source3/modules/vfs_ceph.c | 8 +++++++- source3/modules/vfs_ceph_new.c | 8 +++++++- source3/modules/vfs_ceph_snapshots.c | 6 ++++-- source3/modules/vfs_crossrename.c | 6 ++++-- source3/modules/vfs_default.c | 9 ++++++++- source3/modules/vfs_extd_audit.c | 6 ++++-- source3/modules/vfs_fruit.c | 9 ++++++--- source3/modules/vfs_full_audit.c | 6 ++++-- source3/modules/vfs_glusterfs.c | 15 ++++++++++++++- source3/modules/vfs_media_harmony.c | 9 ++++++--- source3/modules/vfs_not_implemented.c | 9 +++++---- source3/modules/vfs_recycle.c | 4 +++- source3/modules/vfs_shadow_copy2.c | 6 ++++-- source3/modules/vfs_snapper.c | 6 ++++-- source3/modules/vfs_streams_depot.c | 21 ++++++++++++++++----- source3/modules/vfs_streams_xattr.c | 11 +++++++++-- source3/modules/vfs_syncops.c | 6 ++++-- source3/modules/vfs_time_audit.c | 6 ++++-- source3/modules/vfs_unityed_media.c | 9 ++++++--- source3/modules/vfs_virusfilter.c | 6 ++++-- source3/modules/vfs_virusfilter_utils.c | 4 +++- source3/modules/vfs_worm.c | 5 +++-- source3/smbd/open.c | 4 +++- source3/smbd/smb2_reply.c | 4 +++- source3/smbd/vfs.c | 6 ++++-- source3/torture/cmd_vfs.c | 4 +++- 33 files changed, 177 insertions(+), 68 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 255fa830402..a3521982f16 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -298,7 +298,8 @@ static int skel_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { errno = ENOSYS; return -1; diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index 461228f09af..4d1312414a0 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -384,13 +384,15 @@ static int skel_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { return SMB_VFS_NEXT_RENAMEAT(handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); } struct skel_fsync_state { diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 374d7e03c33..29451b081b1 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -381,9 +381,11 @@ * Change to Version 49 - will ship with 4.19 * Version 49 - remove seekdir and telldir * Version 49 - remove "sbuf" argument from readdir_fn() + * Change to Version 50 - will ship with 4.22 + * Version 50 - Change SMB_VFS_RENAMEAT() add vfs_rename_how */ -#define SMB_VFS_INTERFACE_VERSION 49 +#define SMB_VFS_INTERFACE_VERSION 50 /* All intercepted VFS operations must be declared as static functions inside module source @@ -918,6 +920,10 @@ struct vfs_open_how { uint64_t resolve; }; +struct vfs_rename_how { + int flags; +}; + /* Available VFS operations. These values must be in sync with vfs_ops struct (struct vfs_fn_pointers and struct vfs_handle_pointers inside of struct vfs_ops). @@ -1029,7 +1035,8 @@ struct vfs_fn_pointers { struct files_struct *srcdir_fsp, const struct smb_filename *smb_fname_src, struct files_struct *dstdir_fsp, - const struct smb_filename *smb_fname_dst); + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how); struct tevent_req *(*fsync_send_fn)(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -1535,7 +1542,8 @@ int smb_vfs_call_renameat(struct vfs_handle_struct *handle, struct files_struct *srcfsp, const struct smb_filename *smb_fname_src, struct files_struct *dstfsp, - const struct smb_filename *smb_fname_dst); + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how); struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, @@ -1970,7 +1978,8 @@ int vfs_not_implemented_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst); + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how); struct tevent_req *vfs_not_implemented_fsync_send(struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx, struct tevent_context *ev, diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 9196f6e5e40..723fd48635a 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -194,10 +194,10 @@ #define SMB_VFS_NEXT_RECVFILE(handle, fromfd, tofsp, offset, count) \ smb_vfs_call_recvfile((handle)->next, (fromfd), (tofsp), (offset), (count)) -#define SMB_VFS_RENAMEAT(conn, oldfsp, old, newfsp, new) \ - smb_vfs_call_renameat((conn)->vfs_handles, (oldfsp), (old), (newfsp), (new)) -#define SMB_VFS_NEXT_RENAMEAT(handle, oldfsp, old, newfsp, new) \ - smb_vfs_call_renameat((handle)->next, (oldfsp), (old), (newfsp), (new)) +#define SMB_VFS_RENAMEAT(conn, oldfsp, old, newfsp, newname, how) \ + smb_vfs_call_renameat((conn)->vfs_handles, (oldfsp), (old), (newfsp), (newname), (how)) +#define SMB_VFS_NEXT_RENAMEAT(handle, oldfsp, old, newfsp, newname, how) \ + smb_vfs_call_renameat((handle)->next, (oldfsp), (old), (newfsp), (newname), (how)) #define SMB_VFS_FSYNC_SEND(mem_ctx, ev, fsp) \ smb_vfs_call_fsync_send((fsp)->conn->vfs_handles, (mem_ctx), (ev), \ diff --git a/source3/modules/vfs_audit.c b/source3/modules/vfs_audit.c index 2b01a6a8d91..50050f8f257 100644 --- a/source3/modules/vfs_audit.c +++ b/source3/modules/vfs_audit.c @@ -246,7 +246,8 @@ static int audit_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { struct smb_filename *full_fname_src = NULL; struct smb_filename *full_fname_dst = NULL; @@ -272,7 +273,8 @@ static int audit_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); if (result == -1) { saved_errno = errno; } diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 3553e118cc2..83792d59fb5 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -192,7 +192,8 @@ static int cap_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { char *capold = NULL; char *capnew = NULL; @@ -245,7 +246,8 @@ static int cap_renameat(vfs_handle_struct *handle, srcfsp->conn->cwd_fsp, smb_fname_src_tmp, dstfsp->conn->cwd_fsp, - smb_fname_dst_tmp); + smb_fname_dst_tmp, + how); out: diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 36aa43123fd..935d978d7a3 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -541,7 +541,8 @@ static int catia_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { TALLOC_CTX *ctx = talloc_tos(); struct smb_filename *smb_fname_src_tmp = NULL; @@ -591,7 +592,8 @@ static int catia_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src_tmp, dstfsp, - smb_fname_dst_tmp); + smb_fname_dst_tmp, + how); out: TALLOC_FREE(src_name_mapped); diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 20e1c204f18..26b51ac78c5 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -713,7 +713,8 @@ static int cephwrap_renameat(struct vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { struct smb_filename *full_fname_src = NULL; struct smb_filename *full_fname_dst = NULL; @@ -725,6 +726,11 @@ static int cephwrap_renameat(struct vfs_handle_struct *handle, return result; } + if (how->flags != 0) { + errno = EINVAL; + return -1; + } + full_fname_src = full_path_from_dirfsp_atname(talloc_tos(), srcfsp, smb_fname_src); diff --git a/source3/modules/vfs_ceph_new.c b/source3/modules/vfs_ceph_new.c index 25e78444fb5..18506e68f07 100644 --- a/source3/modules/vfs_ceph_new.c +++ b/source3/modules/vfs_ceph_new.c @@ -1874,7 +1874,8 @@ static int vfs_ceph_renameat(struct vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { struct vfs_ceph_fh *src_dircfh = NULL; struct vfs_ceph_fh *dst_dircfh = NULL; @@ -1886,6 +1887,11 @@ static int vfs_ceph_renameat(struct vfs_handle_struct *handle, return result; } + if (how->flags != 0) { + errno = EINVAL; + return -1; + } + result = vfs_ceph_fetch_fh(handle, srcfsp, &src_dircfh); if (result != 0) { goto out; diff --git a/source3/modules/vfs_ceph_snapshots.c b/source3/modules/vfs_ceph_snapshots.c index 98b8f5f6b5d..9514b489237 100644 --- a/source3/modules/vfs_ceph_snapshots.c +++ b/source3/modules/vfs_ceph_snapshots.c @@ -753,7 +753,8 @@ static int ceph_snap_gmt_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int ret; time_t timestamp_src, timestamp_dst; @@ -784,7 +785,8 @@ static int ceph_snap_gmt_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); } /* block links from writeable shares to snapshots for now, like other modules */ diff --git a/source3/modules/vfs_crossrename.c b/source3/modules/vfs_crossrename.c index 042144bfc4d..79f13c28da5 100644 --- a/source3/modules/vfs_crossrename.c +++ b/source3/modules/vfs_crossrename.c @@ -144,7 +144,8 @@ static int crossrename_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int result = -1; @@ -159,7 +160,8 @@ static int crossrename_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); if ((result == -1) && (errno == EXDEV)) { /* Rename across filesystems needed. */ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index eac64f28326..ec46596ac62 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -1287,7 +1287,8 @@ static int vfswrap_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int result = -1; @@ -1296,6 +1297,12 @@ static int vfswrap_renameat(vfs_handle_struct *handle, SMB_ASSERT(!is_named_stream(smb_fname_src)); SMB_ASSERT(!is_named_stream(smb_fname_dst)); + if (how->flags != 0) { + END_PROFILE(syscall_renameat); + errno = EINVAL; + return -1; + } + result = renameat(fsp_get_pathref_fd(srcfsp), smb_fname_src->base_name, fsp_get_pathref_fd(dstfsp), diff --git a/source3/modules/vfs_extd_audit.c b/source3/modules/vfs_extd_audit.c index ea784ff6eba..c12c24adbb1 100644 --- a/source3/modules/vfs_extd_audit.c +++ b/source3/modules/vfs_extd_audit.c @@ -277,7 +277,8 @@ static int audit_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { struct smb_filename *full_fname_src = NULL; struct smb_filename *full_fname_dst = NULL; @@ -305,7 +306,8 @@ static int audit_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); if (result == -1) { saved_errno = errno; } diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index c3867f8b2f4..f8b12c09594 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -1895,7 +1895,8 @@ static int fruit_renameat(struct vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int rc = -1; struct fruit_config_data *config = NULL; @@ -1915,7 +1916,8 @@ static int fruit_renameat(struct vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); if (rc != 0) { return -1; } @@ -1944,7 +1946,8 @@ static int fruit_renameat(struct vfs_handle_struct *handle, srcfsp, src_adp_smb_fname, dstfsp, - dst_adp_smb_fname); + dst_adp_smb_fname, + how); if (errno == ENOENT) { rc = 0; } diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 9fd8a751572..187e6dd76c9 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -1402,7 +1402,8 @@ static int smb_full_audit_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int result; int saved_errno; @@ -1429,7 +1430,8 @@ static int smb_full_audit_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); if (result == -1) { saved_errno = errno; diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 5729766a8d7..2ac978eed8c 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -1231,7 +1231,8 @@ static int vfs_gluster_renameat(struct vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int ret; @@ -1241,6 +1242,12 @@ static int vfs_gluster_renameat(struct vfs_handle_struct *handle, START_PROFILE(syscall_renameat); + if (how->flags != 0) { + END_PROFILE(syscall_renameat); + errno = EINVAL; + return -1; + } + src_pglfd = vfs_gluster_fetch_glfd(handle, srcfsp); if (src_pglfd == NULL) { END_PROFILE(syscall_renameat); @@ -1263,6 +1270,12 @@ static int vfs_gluster_renameat(struct vfs_handle_struct *handle, START_PROFILE(syscall_renameat); + if (how->flags != 0) { + END_PROFILE(syscall_renameat); + errno = EINVAL; + return -1; + } + full_fname_src = full_path_from_dirfsp_atname(talloc_tos(), srcfsp, smb_fname_src); diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index a027254c6b3..10406f556fb 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -1195,7 +1195,8 @@ static int mh_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int status = -1; struct smb_filename *full_fname_src = NULL; @@ -1217,7 +1218,8 @@ static int mh_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); goto out; } @@ -1256,7 +1258,8 @@ static int mh_renameat(vfs_handle_struct *handle, srcfsp->conn->cwd_fsp, srcClientFname, dstfsp->conn->cwd_fsp, - dstClientFname); + dstClientFname, + how); err: TALLOC_FREE(full_fname_src); TALLOC_FREE(full_fname_dst); diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c index b00a4993bc5..9481e11f53e 100644 --- a/source3/modules/vfs_not_implemented.c +++ b/source3/modules/vfs_not_implemented.c @@ -318,10 +318,11 @@ ssize_t vfs_not_implemented_recvfile(vfs_handle_struct *handle, int fromfd, _PUBLIC_ int vfs_not_implemented_renameat(vfs_handle_struct *handle, - files_struct *srcfsp, - const struct smb_filename *smb_fname_src, - files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + files_struct *srcfsp, + const struct smb_filename *smb_fname_src, + files_struct *dstfsp, + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { errno = ENOSYS; return -1; diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index ea0417d9649..9c0020a8dbe 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -487,6 +487,7 @@ static int recycle_unlink_internal(vfs_handle_struct *handle, bool exist; int rc = -1; struct recycle_config_data *config = NULL; + struct vfs_rename_how rhow = { .flags = 0, }; SMB_VFS_HANDLE_GET_DATA(handle, config, @@ -706,7 +707,8 @@ static int recycle_unlink_internal(vfs_handle_struct *handle, dirfsp, smb_fname, handle->conn->cwd_fsp, - smb_fname_final); + smb_fname_final, + &rhow); if (rc != 0) { DEBUG(3, ("recycle: Move error %d (%s), purging file %s " "(%s)\n", errno, strerror(errno), diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 9d3f5843f43..b91d5c8242f 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -1027,7 +1027,8 @@ static int shadow_copy2_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { time_t timestamp_src = 0; time_t timestamp_dst = 0; @@ -1069,7 +1070,8 @@ static int shadow_copy2_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); } static int shadow_copy2_symlinkat(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c index f12a94befd6..566d574f0be 100644 --- a/source3/modules/vfs_snapper.c +++ b/source3/modules/vfs_snapper.c @@ -1905,7 +1905,8 @@ static int snapper_gmt_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { time_t timestamp_src, timestamp_dst; @@ -1931,7 +1932,8 @@ static int snapper_gmt_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); } static int snapper_gmt_symlinkat(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index 1221b2c2be2..566d34996c1 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -165,6 +165,7 @@ static char *stream_dir(vfs_handle_struct *handle, char *rootdir = NULL; struct smb_filename *rootdir_fname = NULL; struct smb_filename *tmp_fname = NULL; + struct vfs_rename_how rhow = { .flags = 0, }; int ret; check_valid = lp_parm_bool(SNUM(handle->conn), @@ -310,11 +311,13 @@ static char *stream_dir(vfs_handle_struct *handle, goto fail; } - if (SMB_VFS_NEXT_RENAMEAT(handle, + ret = SMB_VFS_NEXT_RENAMEAT(handle, handle->conn->cwd_fsp, smb_fname_hash, handle->conn->cwd_fsp, - smb_fname_new) == -1) { + smb_fname_new, + &rhow); + if (ret == -1) { TALLOC_FREE(smb_fname_new); if ((errno == EEXIST) || (errno == ENOTEMPTY)) { goto again; @@ -962,7 +965,8 @@ static int streams_depot_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { struct smb_filename *smb_fname_src_stream = NULL; struct smb_filename *smb_fname_dst_stream = NULL; @@ -984,7 +988,13 @@ static int streams_depot_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); + } + + if (how->flags != 0) { + errno = EINVAL; + goto done; } /* for now don't allow renames from or to the default stream */ @@ -1035,7 +1045,8 @@ static int streams_depot_renameat(vfs_handle_struct *handle, handle->conn->cwd_fsp, smb_fname_src_stream, handle->conn->cwd_fsp, - smb_fname_dst_stream); + smb_fname_dst_stream, + how); done: TALLOC_FREE(smb_fname_src_stream); diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 03ff6147cb0..4cc69b42a8a 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -537,7 +537,8 @@ static int streams_xattr_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { NTSTATUS status; int ret = -1; @@ -560,7 +561,13 @@ static int streams_xattr_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); + } + + if (how->flags != 0) { + errno = EINVAL; + goto done; } /* For now don't allow renames from or to the default stream. */ diff --git a/source3/modules/vfs_syncops.c b/source3/modules/vfs_syncops.c index a0d98093296..a909e2162f5 100644 --- a/source3/modules/vfs_syncops.c +++ b/source3/modules/vfs_syncops.c @@ -144,7 +144,8 @@ static int syncops_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int ret; @@ -160,7 +161,8 @@ static int syncops_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); if (ret == -1) { return ret; } diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 59bc68861b4..856486bc5c4 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -918,7 +918,8 @@ static int smb_time_audit_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *oldname, files_struct *dstfsp, - const struct smb_filename *newname) + const struct smb_filename *newname, + const struct vfs_rename_how *how) { int result; struct timespec ts1,ts2; @@ -937,7 +938,8 @@ static int smb_time_audit_renameat(vfs_handle_struct *handle, srcfsp, oldname, dstfsp, - newname); + newname, + how); clock_gettime_mono(&ts2); timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c index c848cf5f623..cf1447e8325 100644 --- a/source3/modules/vfs_unityed_media.c +++ b/source3/modules/vfs_unityed_media.c @@ -926,7 +926,8 @@ static int um_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int status; struct smb_filename *src_full_fname = NULL; @@ -965,7 +966,8 @@ static int um_renameat(vfs_handle_struct *handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); } status = alloc_get_client_smb_fname(handle, talloc_tos(), @@ -987,7 +989,8 @@ static int um_renameat(vfs_handle_struct *handle, handle->conn->cwd_fsp, src_client_fname, handle->conn->cwd_fsp, - dst_client_fname); + dst_client_fname, + how); err: TALLOC_FREE(dst_client_fname); diff --git a/source3/modules/vfs_virusfilter.c b/source3/modules/vfs_virusfilter.c index b566b628ed2..c0cf9ff78db 100644 --- a/source3/modules/vfs_virusfilter.c +++ b/source3/modules/vfs_virusfilter.c @@ -1592,13 +1592,15 @@ static int virusfilter_vfs_renameat( files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { int ret = SMB_VFS_NEXT_RENAMEAT(handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); struct virusfilter_config *config = NULL; char *fname = NULL; char *dst_fname = NULL; diff --git a/source3/modules/vfs_virusfilter_utils.c b/source3/modules/vfs_virusfilter_utils.c index b4677799c50..1ad31b8d32c 100644 --- a/source3/modules/vfs_virusfilter_utils.c +++ b/source3/modules/vfs_virusfilter_utils.c @@ -55,12 +55,14 @@ int virusfilter_vfs_next_move( const struct smb_filename *smb_fname_dst) { int result; + struct vfs_rename_how rhow = { .flags = 0, }; result = SMB_VFS_NEXT_RENAMEAT(vfs_h, vfs_h->conn->cwd_fsp, smb_fname_src, vfs_h->conn->cwd_fsp, - smb_fname_dst); + smb_fname_dst, + &rhow); if (result == 0 || errno != EXDEV) { return result; } diff --git a/source3/modules/vfs_worm.c b/source3/modules/vfs_worm.c index 5c1bc6da650..0fcda162cd7 100644 --- a/source3/modules/vfs_worm.c +++ b/source3/modules/vfs_worm.c @@ -215,7 +215,8 @@ static int vfs_worm_renameat(vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { if (is_readonly(handle, smb_fname_src)) { errno = EACCES; @@ -223,7 +224,7 @@ static int vfs_worm_renameat(vfs_handle_struct *handle, } return SMB_VFS_NEXT_RENAMEAT( - handle, srcfsp, smb_fname_src, dstfsp, smb_fname_dst); + handle, srcfsp, smb_fname_src, dstfsp, smb_fname_dst, how); } static int vfs_worm_fsetxattr(struct vfs_handle_struct *handle, diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 108a22caa44..cba43d1a1cd 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -4681,6 +4681,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn, struct server_id_buf idbuf; char *idstr = server_id_str_buf_unique_ex(id, '%', &idbuf); struct vfs_open_how how = { .flags = O_RDONLY|O_DIRECTORY, }; + struct vfs_rename_how rhow = { .flags = 0, }; int ret; if (!CAN_WRITE(conn) || (access_mask & ~(conn->share_access))) { @@ -4933,7 +4934,8 @@ mkdir_first: parent_dir_fname->fsp, tmp_atname, parent_dir_fname->fsp, - smb_fname_atname); + smb_fname_atname, + &rhow); } if (ret != 0) { diff --git a/source3/smbd/smb2_reply.c b/source3/smbd/smb2_reply.c index 1248c6f0a75..ab8b989c0a5 100644 --- a/source3/smbd/smb2_reply.c +++ b/source3/smbd/smb2_reply.c @@ -1417,6 +1417,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, true : conn->case_sensitive; bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ? true : conn->case_preserve; + struct vfs_rename_how rhow = { .flags = 0, }; status = parent_dirname_compatible_open(conn, smb_fname_dst_in); if (!NT_STATUS_IS_OK(status)) { @@ -1757,7 +1758,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, parent_dir_fname_src->fsp, parent_dir_fname_src_atname, parent_dir_fname_dst->fsp, - parent_dir_fname_dst_atname); + parent_dir_fname_dst_atname, + &rhow); if (ret == 0) { uint32_t create_options = fh_get_private_options(fsp->fh); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 13b3ba61cea..fe90d30f45f 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1721,14 +1721,16 @@ int smb_vfs_call_renameat(struct vfs_handle_struct *handle, files_struct *srcfsp, const struct smb_filename *smb_fname_src, files_struct *dstfsp, - const struct smb_filename *smb_fname_dst) + const struct smb_filename *smb_fname_dst, + const struct vfs_rename_how *how) { VFS_FIND(renameat); return handle->fns->renameat_fn(handle, srcfsp, smb_fname_src, dstfsp, - smb_fname_dst); + smb_fname_dst, + how); } struct smb_vfs_call_fsync_state { diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 95b1e21a22f..d9b921b01e8 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -675,6 +675,7 @@ static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, int ret; struct smb_filename *smb_fname_src = NULL; struct smb_filename *smb_fname_dst = NULL; + struct vfs_rename_how rhow = { .flags = 0, }; if (argc != 3) { printf("Usage: rename \n"); @@ -700,7 +701,8 @@ static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, vfs->conn->cwd_fsp, smb_fname_src, vfs->conn->cwd_fsp, - smb_fname_dst); + smb_fname_dst, + &rhow); TALLOC_FREE(smb_fname_src); TALLOC_FREE(smb_fname_dst); -- 2.47.3