summaryrefslogtreecommitdiff
path: root/net/samba419/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch
diff options
context:
space:
mode:
Diffstat (limited to 'net/samba419/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch')
-rw-r--r--net/samba419/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch335
1 files changed, 335 insertions, 0 deletions
diff --git a/net/samba419/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch b/net/samba419/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch
new file mode 100644
index 000000000000..38a7f0295b90
--- /dev/null
+++ b/net/samba419/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch
@@ -0,0 +1,335 @@
+From 2d73ccb27ffcdf419d569260fcca6e9ee3b9538a Mon Sep 17 00:00:00 2001
+From: "Timur I. Bakeyev" <timur@FreeBSD.org>
+Date: Thu, 29 Sep 2022 03:24:26 +0200
+Subject: [PATCH 26/28] vfs: add a compatibility option to the
+ vfs_streams_xattr
+
+When enabled, the module does not append a trailing 0
+byte to the end of the extended attribute data.
+
+This is primarily a consideration when the administrator
+wishes to expose extended attributes that have been written
+by another application as alternate data streams via
+Samba.
+
+An example where this parameter may be required is when
+migrating a netatalk share to Samba. See manpage for
+vfs_fruit for additional considerations regarding
+Netatalk and Samba compatibility.
+
+Signed-off-by: Timur I. Bakeyev <timur@FreeBSD.org>
+---
+ docs-xml/manpages/vfs_streams_xattr.8.xml | 25 ++++++
+ source3/modules/vfs_streams_xattr.c | 95 +++++++++++++++++------
+ 2 files changed, 97 insertions(+), 23 deletions(-)
+
+diff --git a/docs-xml/manpages/vfs_streams_xattr.8.xml b/docs-xml/manpages/vfs_streams_xattr.8.xml
+index 6645928c016..0f38d510a82 100644
+--- a/docs-xml/manpages/vfs_streams_xattr.8.xml
++++ b/docs-xml/manpages/vfs_streams_xattr.8.xml
+@@ -71,6 +71,31 @@
+ </listitem>
+ </varlistentry>
+
++ <varlistentry>
++ <term>streams_xattr:xattr_compat = [yes|no]</term>
++ <listitem>
++ <para>When enabled, the module does not append a trailing 0
++ byte to the end of the extended attribute data. This parameter
++ must not be changed once data has been written to the share
++ since it may result in dropping the last byte from xattr data.
++
++ This is primarily a consideration when the administrator
++ wishes to expose extended attributes that have been written
++ by another application as alternate data streams via
++ Samba.
++
++ An example where this parameter may be required is when
++ migrating a netatalk share to Samba. See manpage for
++ vfs_fruit for additional considerations regarding
++ Netatalk and Samba compatibility.
++
++ WARNING: this parameter must not be changed on existing
++ Samba shares or new shares that export paths currently
++ or previously have been shared by Samba.
++ The default is <command>yes</command>.</para>
++ </listitem>
++ </varlistentry>
++
+ </variablelist>
+
+ </refsect1>
+diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
+index b69a4f342f5..070111e3ee9 100644
+--- a/source3/modules/vfs_streams_xattr.c
++++ b/source3/modules/vfs_streams_xattr.c
+@@ -35,6 +35,7 @@ struct streams_xattr_config {
+ const char *prefix;
+ size_t prefix_len;
+ bool store_stream_type;
++ int xattr_compat_bytes;
+ };
+
+ struct stream_io {
+@@ -45,22 +46,28 @@ struct stream_io {
+ vfs_handle_struct *handle;
+ };
+
+-static ssize_t get_xattr_size_fsp(struct files_struct *fsp,
++static ssize_t get_xattr_size_fsp(vfs_handle_struct *handle,
++ struct files_struct *fsp,
+ const char *xattr_name)
+ {
+ NTSTATUS status;
+ struct ea_struct ea;
+ ssize_t result;
++ struct streams_xattr_config *config = NULL;
+
++ SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
++ return -1);
++
+ status = get_ea_value_fsp(talloc_tos(),
+ fsp,
+ xattr_name,
+ &ea);
++
+ if (!NT_STATUS_IS_OK(status)) {
+ return -1;
+ }
+
+- result = ea.value.length-1;
++ result = ea.value.length - config->xattr_compat_bytes;
+ TALLOC_FREE(ea.value.data);
+ return result;
+ }
+@@ -197,7 +204,8 @@ static int streams_xattr_fstat(vfs_handle_struct *hand
+ return -1;
+ }
+
+- sbuf->st_ex_size = get_xattr_size_fsp(fsp->base_fsp,
++ sbuf->st_ex_size = get_xattr_size_fsp(handle,
++ fsp->base_fsp,
+ io->xattr_name);
+ if (sbuf->st_ex_size == -1) {
+ SET_STAT_INVALID(*sbuf);
+@@ -273,7 +281,7 @@ static int streams_xattr_stat(vfs_handle_struct *handl
+ fsp = fsp->base_fsp;
+ }
+
+- smb_fname->st.st_ex_size = get_xattr_size_fsp(fsp,
++ smb_fname->st.st_ex_size = get_xattr_size_fsp(handle, fsp,
+ xattr_name);
+ if (smb_fname->st.st_ex_size == -1) {
+ TALLOC_FREE(xattr_name);
+@@ -308,6 +316,7 @@ static int streams_xattr_lstat(vfs_handle_struct *hand
+ errno = ENOENT;
+ return -1;
+ }
++
+ return SMB_VFS_NEXT_LSTAT(handle, smb_fname);
+ }
+
+@@ -341,6 +350,12 @@ static int streams_xattr_openat(struct vfs_handle_stru
+ how);
+ }
+
++#ifdef O_EMPTY_PATH
++ if (how->flags & O_EMPTY_PATH) {
++ return vfs_fake_fd();
++ }
++#endif
++
+ if (how->resolve != 0) {
+ errno = ENOSYS;
+ return -1;
+@@ -356,6 +371,8 @@ static int streams_xattr_openat(struct vfs_handle_stru
+ goto fail;
+ }
+
++ fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
++
+ status = get_ea_value_fsp(talloc_tos(),
+ fsp->base_fsp,
+ xattr_name,
+@@ -394,7 +411,8 @@ static int streams_xattr_openat(struct vfs_handle_stru
+ */
+
+ /*
+- * Darn, xattrs need at least 1 byte
++ * If xattr_compat_bytes is set we need to
++ * provide one extra trailing byte
+ */
+ char null = '\0';
+
+@@ -403,7 +421,8 @@ static int streams_xattr_openat(struct vfs_handle_stru
+
+ ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
+ xattr_name,
+- &null, sizeof(null),
++ (config->xattr_compat_bytes) ? &null : NULL,
++ (config->xattr_compat_bytes) ? sizeof(null) : 0,
+ how->flags & O_EXCL ? XATTR_CREATE : 0);
+ if (ret != 0) {
+ goto fail;
+@@ -412,13 +431,13 @@ static int streams_xattr_openat(struct vfs_handle_stru
+
+ fakefd = vfs_fake_fd();
+
+- sio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct stream_io, NULL);
+- if (sio == NULL) {
+- errno = ENOMEM;
+- goto fail;
+- }
++ sio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct stream_io, NULL);
++ if (sio == NULL) {
++ errno = ENOMEM;
++ goto fail;
++ }
+
+- sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
++ sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
+ xattr_name);
+ if (sio->xattr_name == NULL) {
+ errno = ENOMEM;
+@@ -808,12 +827,16 @@ static bool collect_one_stream(struct ea_struct *ea, v
+ {
+ struct streaminfo_state *state =
+ (struct streaminfo_state *)private_data;
++ struct streams_xattr_config *config = NULL;
+
++ SMB_VFS_HANDLE_GET_DATA(state->handle, config, struct streams_xattr_config,
++ return false);
++
+ if (!add_one_stream(state->mem_ctx,
+ &state->num_streams, &state->streams,
+- ea->name, ea->value.length-1,
++ ea->name, ea->value.length - config->xattr_compat_bytes,
+ smb_roundup(state->handle->conn,
+- ea->value.length-1))) {
++ ea->value.length - config->xattr_compat_bytes))) {
+ state->status = NT_STATUS_NO_MEMORY;
+ return false;
+ }
+@@ -875,6 +898,7 @@ static int streams_xattr_connect(vfs_handle_struct *ha
+ const char *default_prefix = SAMBA_XATTR_DOSSTREAM_PREFIX;
+ const char *prefix;
+ int rc;
++ bool xattr_compat;
+
+ rc = SMB_VFS_NEXT_CONNECT(handle, service, user);
+ if (rc != 0) {
+@@ -905,6 +929,13 @@ static int streams_xattr_connect(vfs_handle_struct *ha
+ "store_stream_type",
+ true);
+
++ xattr_compat = lp_parm_bool(SNUM(handle->conn),
++ "streams_xattr",
++ "xattr_compat",
++ true);
++
++ config->xattr_compat_bytes = xattr_compat ? 0 : 1;
++
+ SMB_VFS_HANDLE_SET_DATA(handle, config,
+ NULL, struct stream_xattr_config,
+ return -1);
+@@ -921,6 +952,7 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct
+ struct ea_struct ea;
+ NTSTATUS status;
+ int ret;
++ struct streams_xattr_config *config = NULL;
+
+ DEBUG(10, ("streams_xattr_pwrite called for %d bytes\n", (int)n));
+
+@@ -932,6 +964,9 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct
+ return -1;
+ }
+
++ SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
++ return -1);
++
+ if ((offset + n) >= lp_smbd_max_xattr_size(SNUM(handle->conn))) {
+ /*
+ * Requested write is beyond what can be read based on
+@@ -961,11 +996,11 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct
+ return -1;
+ }
+
+- if ((offset + n) > ea.value.length-1) {
++ if ((offset + n) > ea.value.length - config->xattr_compat_bytes) {
+ uint8_t *tmp;
+
+ tmp = talloc_realloc(talloc_tos(), ea.value.data, uint8_t,
+- offset + n + 1);
++ offset + n + config->xattr_compat_bytes);
+
+ if (tmp == NULL) {
+ TALLOC_FREE(ea.value.data);
+@@ -973,8 +1008,10 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct
+ return -1;
+ }
+ ea.value.data = tmp;
+- ea.value.length = offset + n + 1;
+- ea.value.data[offset+n] = 0;
++ ea.value.length = offset + n + config->xattr_compat_bytes;
++ if (config->xattr_compat_bytes) {
++ ea.value.data[offset+n] = 0;
++ }
+ }
+
+ memcpy(ea.value.data + offset, data, n);
+@@ -1002,7 +1039,12 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *
+ struct ea_struct ea;
+ NTSTATUS status;
+ size_t length, overlap;
++ struct smb_filename *smb_fname_base = NULL;
++ struct streams_xattr_config *config = NULL;
+
++ SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
++ return -1);
++
+ DEBUG(10, ("streams_xattr_pread: offset=%d, size=%d\n",
+ (int)offset, (int)n));
+
+@@ -1022,7 +1064,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *
+ return -1;
+ }
+
+- length = ea.value.length-1;
++ length = ea.value.length - config->xattr_compat_bytes;
+
+ DBG_DEBUG("get_ea_value_fsp returned %d bytes\n",
+ (int)length);
+@@ -1210,6 +1252,12 @@ static int streams_xattr_ftruncate(struct vfs_handle_s
+ struct stream_io *sio =
+ (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+
++ struct smb_filename *smb_fname_base = NULL;
++ struct streams_xattr_config *config = NULL;
++
++ SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
++ return -1);
++
+ DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n",
+ fsp_str_dbg(fsp), (double)offset));
+
+@@ -1239,14 +1287,16 @@ static int streams_xattr_ftruncate(struct vfs_handle_s
+ }
+
+ /* Did we expand ? */
+- if (ea.value.length < offset + 1) {
++ if (ea.value.length < offset + config->xattr_compat_bytes) {
+ memset(&tmp[ea.value.length], '\0',
+- offset + 1 - ea.value.length);
++ offset + config->xattr_compat_bytes - ea.value.length);
+ }
+
+ ea.value.data = tmp;
+- ea.value.length = offset + 1;
+- ea.value.data[offset] = 0;
++ ea.value.length = offset + config->xattr_compat_bytes;
++ if (config->xattr_compat_bytes) {
++ ea.value.data[offset] = 0;
++ }
+
+ ret = SMB_VFS_FSETXATTR(fsp->base_fsp,
+ sio->xattr_name,