mirror of
https://github.com/samba-team/samba.git
synced 2025-01-27 14:04:05 +03:00
vfs_streams_xattr: implement SMB_VFS_OPENAT()
Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
dcddc45c4c
commit
35765b8fa4
@ -498,6 +498,158 @@ static int streams_xattr_open(vfs_handle_struct *handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int streams_xattr_openat(struct vfs_handle_struct *handle,
|
||||
const struct files_struct *dirfsp,
|
||||
const struct smb_filename *smb_fname,
|
||||
files_struct *fsp,
|
||||
int flags,
|
||||
mode_t mode)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct streams_xattr_config *config = NULL;
|
||||
struct stream_io *sio = NULL;
|
||||
struct ea_struct ea;
|
||||
char *xattr_name = NULL;
|
||||
int pipe_fds[2];
|
||||
int fakefd = -1;
|
||||
bool set_empty_xattr = false;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* For now assert this, so the below SMB_VFS_SETXATTR() works.
|
||||
*/
|
||||
SMB_ASSERT(dirfsp->fh->fd == AT_FDCWD);
|
||||
|
||||
SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
|
||||
return -1);
|
||||
|
||||
DEBUG(10, ("streams_xattr_open called for %s with flags 0x%x\n",
|
||||
smb_fname_str_dbg(smb_fname), flags));
|
||||
|
||||
if (!is_named_stream(smb_fname)) {
|
||||
return SMB_VFS_NEXT_OPENAT(handle,
|
||||
dirfsp,
|
||||
smb_fname,
|
||||
fsp,
|
||||
flags,
|
||||
mode);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
status = get_ea_value(talloc_tos(), handle->conn, NULL,
|
||||
smb_fname, xattr_name, &ea);
|
||||
|
||||
DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
|
||||
/*
|
||||
* The base file is not there. This is an error even if
|
||||
* we got O_CREAT, the higher levels should have created
|
||||
* the base file for us.
|
||||
*/
|
||||
DBG_DEBUG("streams_xattr_open: base file %s not around, "
|
||||
"returning ENOENT\n", smb_fname->base_name);
|
||||
errno = ENOENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!(flags & O_CREAT)) {
|
||||
errno = ENOATTR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
set_empty_xattr = true;
|
||||
}
|
||||
|
||||
if (flags & O_TRUNC) {
|
||||
set_empty_xattr = true;
|
||||
}
|
||||
|
||||
if (set_empty_xattr) {
|
||||
/*
|
||||
* The attribute does not exist or needs to be truncated
|
||||
*/
|
||||
|
||||
/*
|
||||
* Darn, xattrs need at least 1 byte
|
||||
*/
|
||||
char null = '\0';
|
||||
|
||||
DEBUG(10, ("creating or truncating attribute %s on file %s\n",
|
||||
xattr_name, smb_fname->base_name));
|
||||
|
||||
ret = SMB_VFS_SETXATTR(fsp->conn,
|
||||
smb_fname,
|
||||
xattr_name,
|
||||
&null, sizeof(null),
|
||||
flags & O_EXCL ? XATTR_CREATE : 0);
|
||||
if (ret != 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a valid fd, but ensure any attempt to use it returns an error
|
||||
* (EPIPE).
|
||||
*/
|
||||
ret = pipe(pipe_fds);
|
||||
if (ret != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close(pipe_fds[1]);
|
||||
pipe_fds[1] = -1;
|
||||
fakefd = pipe_fds[0];
|
||||
|
||||
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),
|
||||
xattr_name);
|
||||
if (sio->xattr_name == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* so->base needs to be a copy of fsp->fsp_name->base_name,
|
||||
* making it identical to streams_xattr_recheck(). If the
|
||||
* open is changing directories, fsp->fsp_name->base_name
|
||||
* will be the full path from the share root, whilst
|
||||
* smb_fname will be relative to the $cwd.
|
||||
*/
|
||||
sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
|
||||
fsp->fsp_name->base_name);
|
||||
if (sio->base == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sio->fsp_name_ptr = fsp->fsp_name;
|
||||
sio->handle = handle;
|
||||
sio->fsp = fsp;
|
||||
|
||||
return fakefd;
|
||||
|
||||
fail:
|
||||
if (fakefd >= 0) {
|
||||
close(fakefd);
|
||||
fakefd = -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int streams_xattr_close(vfs_handle_struct *handle,
|
||||
files_struct *fsp)
|
||||
{
|
||||
@ -1639,6 +1791,7 @@ 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,
|
||||
.openat_fn = streams_xattr_openat,
|
||||
.close_fn = streams_xattr_close,
|
||||
.stat_fn = streams_xattr_stat,
|
||||
.fstat_fn = streams_xattr_fstat,
|
||||
|
Loading…
x
Reference in New Issue
Block a user