diff options
Diffstat (limited to 'source3/modules/vfs_streams_xattr.c')
-rw-r--r-- | source3/modules/vfs_streams_xattr.c | 122 |
1 files changed, 92 insertions, 30 deletions
diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 5e9bd3e864c..735db2b9204 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -29,6 +29,12 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS +struct streams_xattr_config { + const char *prefix; + size_t prefix_len; + bool store_stream_type; +}; + struct stream_io { char *base; char *xattr_name; @@ -95,33 +101,41 @@ static ssize_t get_xattr_size(connection_struct *conn, * Given a stream name, populate xattr_name with the xattr name to use for * accessing the stream. */ -static NTSTATUS streams_xattr_get_name(TALLOC_CTX *ctx, +static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle, + TALLOC_CTX *ctx, const char *stream_name, char **xattr_name) { char *stype; + struct streams_xattr_config *config; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config, + return NT_STATUS_UNSUCCESSFUL); stype = strchr_m(stream_name + 1, ':'); *xattr_name = talloc_asprintf(ctx, "%s%s", - SAMBA_XATTR_DOSSTREAM_PREFIX, + config->prefix, stream_name + 1); if (*xattr_name == NULL) { return NT_STATUS_NO_MEMORY; } - if (stype == NULL) { - /* Append an explicit stream type if one wasn't specified. */ - *xattr_name = talloc_asprintf(ctx, "%s:$DATA", - *xattr_name); - if (*xattr_name == NULL) { - return NT_STATUS_NO_MEMORY; - } - } else { + if (stype != NULL) { /* Normalize the stream type to upercase. */ if (!strupper_m(strrchr_m(*xattr_name, ':') + 1)) { return NT_STATUS_INVALID_PARAMETER; } + } else if (config->store_stream_type) { + /* + * Append an explicit stream type if one wasn't + * specified. + */ + *xattr_name = talloc_asprintf(ctx, "%s%s", + *xattr_name, ":$DATA"); + if (*xattr_name == NULL) { + return NT_STATUS_NO_MEMORY; + } } DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name, @@ -145,7 +159,7 @@ static bool streams_xattr_recheck(struct stream_io *sio) return false; } - status = streams_xattr_get_name(talloc_tos(), + status = streams_xattr_get_name(sio->handle, talloc_tos(), sio->fsp->fsp_name->stream_name, &xattr_name); if (!NT_STATUS_IS_OK(status)) { @@ -271,8 +285,8 @@ static int streams_xattr_stat(vfs_handle_struct *handle, } /* Derive the xattr name to lookup. */ - status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, - &xattr_name); + status = streams_xattr_get_name(handle, talloc_tos(), + smb_fname->stream_name, &xattr_name); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); return -1; @@ -322,8 +336,8 @@ static int streams_xattr_lstat(vfs_handle_struct *handle, } /* Derive the xattr name to lookup. */ - status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, - &xattr_name); + status = streams_xattr_get_name(handle, talloc_tos(), + smb_fname->stream_name, &xattr_name); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); return -1; @@ -386,8 +400,8 @@ static int streams_xattr_open(vfs_handle_struct *handle, return ret; } - status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, - &xattr_name); + status = streams_xattr_get_name(handle, talloc_tos(), + smb_fname->stream_name, &xattr_name); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); goto fail; @@ -541,8 +555,8 @@ static int streams_xattr_unlink(vfs_handle_struct *handle, return ret; } - status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, - &xattr_name); + status = streams_xattr_get_name(handle, talloc_tos(), + smb_fname->stream_name, &xattr_name); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); goto fail; @@ -597,14 +611,14 @@ static int streams_xattr_rename(vfs_handle_struct *handle, } /* Get the xattr names. */ - status = streams_xattr_get_name(talloc_tos(), + 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(talloc_tos(), + status = streams_xattr_get_name(handle, talloc_tos(), smb_fname_dst->stream_name, &dst_xattr_name); if (!NT_STATUS_IS_OK(status)) { @@ -650,7 +664,7 @@ static int streams_xattr_rename(vfs_handle_struct *handle, return ret; } -static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp, +static NTSTATUS walk_xattr_streams(vfs_handle_struct *handle, files_struct *fsp, const char *fname, bool (*fn)(struct ea_struct *ea, void *private_data), @@ -659,9 +673,12 @@ static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp, NTSTATUS status; char **names; size_t i, num_names; - size_t prefix_len = strlen(SAMBA_XATTR_DOSSTREAM_PREFIX); + struct streams_xattr_config *config; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config, + return NT_STATUS_UNSUCCESSFUL); - status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname, + status = get_ea_names_from_file(talloc_tos(), handle->conn, fsp, fname, &names, &num_names); if (!NT_STATUS_IS_OK(status)) { return status; @@ -670,20 +687,26 @@ static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp, for (i=0; i<num_names; i++) { struct ea_struct ea; - if (strncmp(names[i], SAMBA_XATTR_DOSSTREAM_PREFIX, - prefix_len) != 0) { + if (strncmp(names[i], config->prefix, + config->prefix_len) != 0) { + continue; + } + if (samba_private_attr_name(names[i])) { continue; } - status = get_ea_value(names, conn, fsp, fname, names[i], &ea); + status = get_ea_value(names, handle->conn, fsp, fname, + names[i], &ea); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("Could not get ea %s for file %s: %s\n", names[i], fname, nt_errstr(status))); continue; } - ea.name = talloc_asprintf(ea.value.data, ":%s", - names[i] + prefix_len); + ea.name = talloc_asprintf( + ea.value.data, ":%s%s", + names[i] + config->prefix_len, + config->store_stream_type ? "" : ":$DATA"); if (ea.name == NULL) { DEBUG(0, ("talloc failed\n")); continue; @@ -803,7 +826,7 @@ static NTSTATUS streams_xattr_streaminfo(vfs_handle_struct *handle, */ status = NT_STATUS_OK; } else { - status = walk_xattr_streams(handle->conn, fsp, fname, + status = walk_xattr_streams(handle, fsp, fname, collect_one_stream, &state); } @@ -829,6 +852,44 @@ static uint32_t streams_xattr_fs_capabilities(struct vfs_handle_struct *handle, return SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res) | FILE_NAMED_STREAMS; } +static int streams_xattr_connect(vfs_handle_struct *handle, + const char *service, const char *user) +{ + struct streams_xattr_config *config; + const char *default_prefix = SAMBA_XATTR_DOSSTREAM_PREFIX; + const char *prefix; + + config = talloc_zero(handle->conn, struct streams_xattr_config); + if (config == NULL) { + DEBUG(1, ("talloc_zero() failed\n")); + errno = ENOMEM; + return -1; + } + + prefix = lp_parm_const_string(SNUM(handle->conn), + "streams_xattr", "prefix", + default_prefix); + config->prefix = talloc_strdup(config, prefix); + if (config->prefix == NULL) { + DEBUG(1, ("talloc_strdup() failed\n")); + errno = ENOMEM; + return -1; + } + config->prefix_len = strlen(config->prefix); + DEBUG(10, ("streams_xattr using stream prefix: %s\n", config->prefix)); + + config->store_stream_type = lp_parm_bool(SNUM(handle->conn), + "streams_xattr", + "store_stream_type", + true); + + SMB_VFS_HANDLE_SET_DATA(handle, config, + NULL, struct stream_xattr_config, + return -1); + + return 0; +} + static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n, off_t offset) @@ -1031,6 +1092,7 @@ static int streams_xattr_fallocate(struct vfs_handle_struct *handle, static struct vfs_fn_pointers vfs_streams_xattr_fns = { .fs_capabilities_fn = streams_xattr_fs_capabilities, + .connect_fn = streams_xattr_connect, .open_fn = streams_xattr_open, .stat_fn = streams_xattr_stat, .fstat_fn = streams_xattr_fstat, |