diff options
Diffstat (limited to 'net/samba422/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch')
| -rw-r--r-- | net/samba422/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch | 335 | 
1 files changed, 335 insertions, 0 deletions
| diff --git a/net/samba422/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch b/net/samba422/files/0026-vfs-add-a-compatibility-option-to-the-vfs_streams_xa.patch new file mode 100644 index 000000000000..38a7f0295b90 --- /dev/null +++ b/net/samba422/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, | 
