mirror of
https://github.com/samba-team/samba.git
synced 2025-01-03 01:18:10 +03:00
s4:libcli: allow smb2_composite_unlink* to truncate the file before close
This is needed to delete streams... BUG: https://bugzilla.samba.org/show_bug.cgi?id=15656 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Volker Lendecke <vl@samba.org>
This commit is contained in:
parent
41df9e1c74
commit
b1b1f2ea6b
@ -139,6 +139,12 @@ union smb_unlink {
|
|||||||
struct {
|
struct {
|
||||||
const char *pattern;
|
const char *pattern;
|
||||||
uint16_t attrib;
|
uint16_t attrib;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* only used by
|
||||||
|
* smb2_composite_unlink*
|
||||||
|
*/
|
||||||
|
bool truncate_if_needed;
|
||||||
} in;
|
} in;
|
||||||
} unlink;
|
} unlink;
|
||||||
};
|
};
|
||||||
|
@ -47,6 +47,38 @@ static void continue_close(struct smb2_request *req)
|
|||||||
composite_error(ctx, status);
|
composite_error(ctx, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct smb2_composite_unlink_state {
|
||||||
|
bool truncate_if_needed;
|
||||||
|
struct smb2_handle handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
continue after the truncate in a composite unlink
|
||||||
|
*/
|
||||||
|
static void continue_truncate(struct smb2_request *req)
|
||||||
|
{
|
||||||
|
struct composite_context *ctx = talloc_get_type(req->async.private_data,
|
||||||
|
struct composite_context);
|
||||||
|
struct smb2_composite_unlink_state *state =
|
||||||
|
talloc_get_type_abort(ctx->private_data,
|
||||||
|
struct smb2_composite_unlink_state);
|
||||||
|
struct smb2_tree *tree = req->tree;
|
||||||
|
struct smb2_close close_parm;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
status = smb2_setinfo_recv(req);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
/* we ignore errors as we should not leak the handle */
|
||||||
|
}
|
||||||
|
|
||||||
|
ZERO_STRUCT(close_parm);
|
||||||
|
close_parm.in.file.handle = state->handle;
|
||||||
|
close_parm.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
|
||||||
|
|
||||||
|
req = smb2_close_send(tree, &close_parm);
|
||||||
|
composite_continue_smb2(ctx, req, continue_close, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
continue after the create in a composite unlink
|
continue after the create in a composite unlink
|
||||||
*/
|
*/
|
||||||
@ -54,6 +86,9 @@ static void continue_unlink(struct smb2_request *req)
|
|||||||
{
|
{
|
||||||
struct composite_context *ctx = talloc_get_type(req->async.private_data,
|
struct composite_context *ctx = talloc_get_type(req->async.private_data,
|
||||||
struct composite_context);
|
struct composite_context);
|
||||||
|
struct smb2_composite_unlink_state *state =
|
||||||
|
talloc_get_type_abort(ctx->private_data,
|
||||||
|
struct smb2_composite_unlink_state);
|
||||||
struct smb2_tree *tree = req->tree;
|
struct smb2_tree *tree = req->tree;
|
||||||
struct smb2_create create_parm;
|
struct smb2_create create_parm;
|
||||||
struct smb2_close close_parm;
|
struct smb2_close close_parm;
|
||||||
@ -65,6 +100,23 @@ static void continue_unlink(struct smb2_request *req)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (create_parm.out.size != 0 &&
|
||||||
|
state->truncate_if_needed)
|
||||||
|
{
|
||||||
|
union smb_setfileinfo sinfo;
|
||||||
|
|
||||||
|
state->handle = create_parm.out.file.handle;
|
||||||
|
|
||||||
|
ZERO_STRUCT(sinfo);
|
||||||
|
sinfo.end_of_file_info.level =
|
||||||
|
RAW_SFILEINFO_END_OF_FILE_INFORMATION;
|
||||||
|
sinfo.end_of_file_info.in.file.handle = state->handle;
|
||||||
|
sinfo.end_of_file_info.in.size = 0;
|
||||||
|
req = smb2_setinfo_file_send(tree, &sinfo);
|
||||||
|
composite_continue_smb2(ctx, req, continue_truncate, ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ZERO_STRUCT(close_parm);
|
ZERO_STRUCT(close_parm);
|
||||||
close_parm.in.file.handle = create_parm.out.file.handle;
|
close_parm.in.file.handle = create_parm.out.file.handle;
|
||||||
|
|
||||||
@ -79,12 +131,20 @@ struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree,
|
|||||||
union smb_unlink *io)
|
union smb_unlink *io)
|
||||||
{
|
{
|
||||||
struct composite_context *ctx;
|
struct composite_context *ctx;
|
||||||
|
struct smb2_composite_unlink_state *state = NULL;
|
||||||
struct smb2_create create_parm;
|
struct smb2_create create_parm;
|
||||||
struct smb2_request *req;
|
struct smb2_request *req;
|
||||||
|
|
||||||
ctx = composite_create(tree, tree->session->transport->ev);
|
ctx = composite_create(tree, tree->session->transport->ev);
|
||||||
if (ctx == NULL) return NULL;
|
if (ctx == NULL) return NULL;
|
||||||
|
|
||||||
|
state = talloc_zero(ctx, struct smb2_composite_unlink_state);
|
||||||
|
if (composite_nomem(state, ctx)) {
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
ctx->private_data = state;
|
||||||
|
state->truncate_if_needed = io->unlink.in.truncate_if_needed;
|
||||||
|
|
||||||
/* check for wildcards - we could support these with a
|
/* check for wildcards - we could support these with a
|
||||||
search, but for now they aren't necessary */
|
search, but for now they aren't necessary */
|
||||||
if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) {
|
if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) {
|
||||||
@ -94,6 +154,9 @@ struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree,
|
|||||||
|
|
||||||
ZERO_STRUCT(create_parm);
|
ZERO_STRUCT(create_parm);
|
||||||
create_parm.in.desired_access = SEC_STD_DELETE;
|
create_parm.in.desired_access = SEC_STD_DELETE;
|
||||||
|
if (state->truncate_if_needed) {
|
||||||
|
create_parm.in.desired_access |= SEC_FILE_WRITE_DATA;
|
||||||
|
}
|
||||||
create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
|
create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
|
||||||
create_parm.in.share_access =
|
create_parm.in.share_access =
|
||||||
NTCREATEX_SHARE_ACCESS_DELETE|
|
NTCREATEX_SHARE_ACCESS_DELETE|
|
||||||
|
Loading…
Reference in New Issue
Block a user