summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2019-08-09 15:31:03 -0700
committerJeremy Allison <jra@samba.org>2019-08-16 19:52:34 +0000
commit251bb56d1b064cbc90729cc58d0549e8f561b4bd (patch)
treee546482b3ee21a2c39b56051b4ddc0eec3fa3766
parent7ec34e6ab86c53e51896b717ede24bf1a9c0a14a (diff)
downloadsamba-251bb56d1b064cbc90729cc58d0549e8f561b4bd.tar.gz
s3: VFS: vfs_streams_xattr. Implement renameat().
Currently identical to rename(). Signed-off-by: Jeremy Allison <jra@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org>
-rw-r--r--source3/modules/vfs_streams_xattr.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
index 3e840d9535e..7f53a3c167c 100644
--- a/source3/modules/vfs_streams_xattr.c
+++ b/source3/modules/vfs_streams_xattr.c
@@ -682,6 +682,99 @@ static int streams_xattr_rename(vfs_handle_struct *handle,
return ret;
}
+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)
+{
+ NTSTATUS status;
+ int ret = -1;
+ char *src_xattr_name = NULL;
+ char *dst_xattr_name = NULL;
+ bool src_is_stream, dst_is_stream;
+ ssize_t oret;
+ ssize_t nret;
+ struct ea_struct ea;
+
+ src_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
+ dst_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
+
+ if (!src_is_stream && !dst_is_stream) {
+ return SMB_VFS_NEXT_RENAMEAT(handle,
+ srcfsp,
+ smb_fname_src,
+ dstfsp,
+ smb_fname_dst);
+ }
+
+ /* For now don't allow renames from or to the default stream. */
+ if (is_ntfs_default_stream_smb_fname(smb_fname_src) ||
+ is_ntfs_default_stream_smb_fname(smb_fname_dst)) {
+ errno = ENOSYS;
+ goto done;
+ }
+
+ /* Don't rename if the streams are identical. */
+ if (strcasecmp_m(smb_fname_src->stream_name,
+ smb_fname_dst->stream_name) == 0) {
+ goto done;
+ }
+
+ /* Get the xattr names. */
+ status = streams_xattr_get_name(handle, talloc_tos(),
+ smb_fname_src->stream_name,
+ &src_xattr_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ goto fail;
+ }
+ status = streams_xattr_get_name(handle, talloc_tos(),
+ smb_fname_dst->stream_name,
+ &dst_xattr_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
+ goto fail;
+ }
+
+ /* read the old stream */
+ status = get_ea_value(talloc_tos(), handle->conn, NULL,
+ smb_fname_src, src_xattr_name, &ea);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = ENOENT;
+ goto fail;
+ }
+
+ /* (over)write the new stream */
+ nret = SMB_VFS_SETXATTR(handle->conn, smb_fname_src,
+ dst_xattr_name, ea.value.data, ea.value.length,
+ 0);
+ if (nret < 0) {
+ if (errno == ENOATTR) {
+ errno = ENOENT;
+ }
+ goto fail;
+ }
+
+ /* remove the old stream */
+ oret = SMB_VFS_REMOVEXATTR(handle->conn, smb_fname_src,
+ src_xattr_name);
+ if (oret < 0) {
+ if (errno == ENOATTR) {
+ errno = ENOENT;
+ }
+ goto fail;
+ }
+
+ done:
+ errno = 0;
+ ret = 0;
+ fail:
+ TALLOC_FREE(src_xattr_name);
+ TALLOC_FREE(dst_xattr_name);
+ return ret;
+}
+
static NTSTATUS walk_xattr_streams(vfs_handle_struct *handle,
files_struct *fsp,
const struct smb_filename *smb_fname,
@@ -1657,6 +1750,7 @@ static struct vfs_fn_pointers vfs_streams_xattr_fns = {
.pwrite_recv_fn = streams_xattr_pwrite_recv,
.unlink_fn = streams_xattr_unlink,
.rename_fn = streams_xattr_rename,
+ .renameat_fn = streams_xattr_renameat,
.ftruncate_fn = streams_xattr_ftruncate,
.fallocate_fn = streams_xattr_fallocate,
.streaminfo_fn = streams_xattr_streaminfo,