]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
vfs: Add streams_xattr implementation of rename_stream()
authorVolker Lendecke <vl@samba.org>
Fri, 19 Sep 2025 18:02:25 +0000 (11:02 -0700)
committerRalph Boehme <slow@samba.org>
Tue, 21 Oct 2025 17:33:29 +0000 (17:33 +0000)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
source3/modules/vfs_streams_xattr.c

index 3b870f579bebcbeb9b8647c69e2c36828b326f73..d121bc6bf5fc37ac00d690fbfe34b3d4ec915c55 100644 (file)
@@ -1308,8 +1308,93 @@ static int streams_xattr_rename_stream(struct vfs_handle_struct *handle,
                                       const char *dst_name,
                                       bool replace_if_exists)
 {
-       errno = ENOSYS;
-       return -1;
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct files_struct *base_fsp = src_fsp->base_fsp;
+       struct streams_xattr_config *config = NULL;
+       char *src_raw_stream_name = NULL;
+       char *src_xattr_name = NULL;
+       char *dst_raw_stream_name = NULL;
+       char *dst_xattr_name = NULL;
+       char *val = NULL;
+       bool is_default = false;
+       int ret = -1;
+
+       SMB_VFS_HANDLE_GET_DATA(handle,
+                               config,
+                               struct streams_xattr_config,
+                               goto fail;);
+
+       ret = streams_xattr_get_name(handle,
+                                    talloc_tos(),
+                                    src_fsp->fsp_name->stream_name,
+                                    &src_raw_stream_name,
+                                    &is_default,
+                                    &src_xattr_name);
+       if (ret != 0) {
+               errno = ret;
+               goto fail;
+       }
+       if (is_default) {
+               errno = ENOSYS;
+               goto done;
+       }
+
+       ret = streams_xattr_get_name(handle,
+                                    talloc_tos(),
+                                    dst_name,
+                                    &dst_raw_stream_name,
+                                    &is_default,
+                                    &dst_xattr_name);
+       if (ret != 0) {
+               errno = ret;
+               goto fail;
+       }
+       if (is_default) {
+               errno = ENOSYS;
+               goto done;
+       }
+
+       ret = streams_xattr_get_ea_value_fsp(
+               talloc_tos(), config, base_fsp, src_raw_stream_name, &val);
+       if (ret != 0) {
+               errno = ret;
+               goto fail;
+       }
+
+       ret = fsetxattr_multi(config,
+                             base_fsp,
+                             dst_raw_stream_name,
+                             val,
+                             talloc_get_size(val),
+                             replace_if_exists ? 0 : XATTR_CREATE);
+       if (ret < 0) {
+               if (errno == ENOATTR) {
+                       errno = ENOENT;
+               }
+               goto fail;
+       }
+
+       /*
+        * Remove the old stream from the base file fsp.
+        */
+       ret = fremovexattr_multi(config, base_fsp, src_raw_stream_name);
+       if (ret < 0) {
+               if (errno == ENOATTR) {
+                       errno = ENOENT;
+               }
+               goto fail;
+       }
+
+done:
+       errno = 0;
+       ret = 0;
+fail:
+       {
+               int err = errno;
+               TALLOC_FREE(frame);
+               errno = err;
+       }
+       return ret;
 }
 
 static NTSTATUS walk_xattr_streams(vfs_handle_struct *handle,