mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
s3:streams_xattr: add support for renaming streams
metze
This commit is contained in:
parent
787b0536b7
commit
9ae1a17c95
@ -94,7 +94,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
|
||||
|
||||
DEBUG(10, ("streams_xattr_fstat called for %d\n", fsp->fh->fd));
|
||||
|
||||
if (io == NULL) {
|
||||
if (io == NULL || fsp->base_fsp == NULL) {
|
||||
return SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
|
||||
}
|
||||
|
||||
@ -136,6 +136,10 @@ static int streams_xattr_stat(vfs_handle_struct *handle, const char *fname,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sname == NULL){
|
||||
return SMB_VFS_NEXT_STAT(handle, base, sbuf);
|
||||
}
|
||||
|
||||
if (SMB_VFS_STAT(handle->conn, base, sbuf) == -1) {
|
||||
goto fail;
|
||||
}
|
||||
@ -183,6 +187,10 @@ static int streams_xattr_lstat(vfs_handle_struct *handle, const char *fname,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sname == NULL){
|
||||
return SMB_VFS_NEXT_LSTAT(handle, base, sbuf);
|
||||
}
|
||||
|
||||
if (SMB_VFS_LSTAT(handle->conn, base, sbuf) == -1) {
|
||||
goto fail;
|
||||
}
|
||||
@ -239,6 +247,12 @@ static int streams_xattr_open(vfs_handle_struct *handle, const char *fname,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sname == NULL) {
|
||||
hostfd = SMB_VFS_NEXT_OPEN(handle, base, fsp, flags, mode);
|
||||
talloc_free(frame);
|
||||
return hostfd;
|
||||
}
|
||||
|
||||
xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
|
||||
SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
|
||||
if (xattr_name == NULL) {
|
||||
@ -391,6 +405,10 @@ static int streams_xattr_unlink(vfs_handle_struct *handle, const char *fname)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (sname == NULL){
|
||||
return SMB_VFS_NEXT_UNLINK(handle, base);
|
||||
}
|
||||
|
||||
xattr_name = talloc_asprintf(talloc_tos(), "%s%s",
|
||||
SAMBA_XATTR_DOSSTREAM_PREFIX, sname);
|
||||
if (xattr_name == NULL) {
|
||||
@ -413,6 +431,127 @@ static int streams_xattr_unlink(vfs_handle_struct *handle, const char *fname)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int streams_xattr_rename(vfs_handle_struct *handle,
|
||||
const char *oldname,
|
||||
const char *newname)
|
||||
{
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *frame = NULL;
|
||||
char *obase;
|
||||
char *ostream;
|
||||
char *nbase;
|
||||
char *nstream;
|
||||
const char *base;
|
||||
int ret = -1;
|
||||
char *oxattr_name;
|
||||
char *nxattr_name;
|
||||
bool o_is_stream;
|
||||
bool n_is_stream;
|
||||
ssize_t oret;
|
||||
ssize_t nret;
|
||||
struct ea_struct ea;
|
||||
|
||||
o_is_stream = is_ntfs_stream_name(oldname);
|
||||
n_is_stream = is_ntfs_stream_name(newname);
|
||||
|
||||
if (!o_is_stream && !n_is_stream) {
|
||||
return SMB_VFS_NEXT_RENAME(handle, oldname, newname);
|
||||
}
|
||||
|
||||
if (!(o_is_stream && n_is_stream)) {
|
||||
errno = ENOSYS;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
frame = talloc_stackframe();
|
||||
if (!frame) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = split_ntfs_stream_name(talloc_tos(), oldname, &obase, &ostream);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = split_ntfs_stream_name(talloc_tos(), newname, &nbase, &nstream);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*TODO: maybe call SMB_VFS_NEXT_RENAME() both streams are NULL (::$DATA) */
|
||||
if (ostream == NULL) {
|
||||
errno = ENOSYS;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (nstream == NULL) {
|
||||
errno = ENOSYS;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* the new base should be empty */
|
||||
if (StrCaseCmp(obase, nbase) != 0) {
|
||||
errno = ENOSYS;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (StrCaseCmp(ostream, nstream) == 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
base = obase;
|
||||
|
||||
oxattr_name = talloc_asprintf(talloc_tos(), "%s%s",
|
||||
SAMBA_XATTR_DOSSTREAM_PREFIX, ostream);
|
||||
if (oxattr_name == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nxattr_name = talloc_asprintf(talloc_tos(), "%s%s",
|
||||
SAMBA_XATTR_DOSSTREAM_PREFIX, nstream);
|
||||
if (nxattr_name == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* read the old stream */
|
||||
status = get_ea_value(talloc_tos(), handle->conn, NULL,
|
||||
base, oxattr_name, &ea);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
errno = ENOENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* (over)write the new stream */
|
||||
nret = SMB_VFS_SETXATTR(handle->conn, base, nxattr_name,
|
||||
ea.value.data, ea.value.length, 0);
|
||||
if (nret < 0) {
|
||||
if (errno == ENOATTR) {
|
||||
errno = ENOENT;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* remove the old stream */
|
||||
oret = SMB_VFS_REMOVEXATTR(handle->conn, base, oxattr_name);
|
||||
if (oret < 0) {
|
||||
if (errno == ENOATTR) {
|
||||
errno = ENOENT;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
||||
done:
|
||||
errno = 0;
|
||||
ret = 0;
|
||||
fail:
|
||||
TALLOC_FREE(frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static NTSTATUS walk_xattr_streams(connection_struct *conn, files_struct *fsp,
|
||||
const char *fname,
|
||||
bool (*fn)(struct ea_struct *ea,
|
||||
@ -761,6 +900,8 @@ static vfs_op_tuple streams_xattr_ops[] = {
|
||||
SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(streams_xattr_unlink), SMB_VFS_OP_UNLINK,
|
||||
SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(streams_xattr_rename), SMB_VFS_OP_RENAME,
|
||||
SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(streams_xattr_ftruncate), SMB_VFS_OP_FTRUNCATE,
|
||||
SMB_VFS_LAYER_TRANSPARENT},
|
||||
{SMB_VFS_OP(streams_xattr_streaminfo), SMB_VFS_OP_STREAMINFO,
|
||||
|
Loading…
Reference in New Issue
Block a user