diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/clifile.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 3b6585b7e7..91f13a79ac 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -771,6 +771,138 @@ int cli_nt_create_full(struct cli_state *cli, const char *fname, return SVAL(cli->inbuf,smb_vwv2 + 1); } +struct async_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags) +{ + struct async_req *result; + uint8_t *bytes; + size_t converted_len; + uint16_t vwv[24]; + + SCVAL(vwv+0, 0, 0xFF); + SCVAL(vwv+0, 1, 0); + SSVAL(vwv+1, 0, 0); + SCVAL(vwv+2, 0, 0); + + if (cli->use_oplocks) { + CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK); + } + SIVAL(vwv+3, 1, CreatFlags); + SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */ + SIVAL(vwv+7, 1, DesiredAccess); + SIVAL(vwv+9, 1, 0x0); /* AllocationSize */ + SIVAL(vwv+11, 1, 0x0); /* AllocationSize */ + SIVAL(vwv+13, 1, FileAttributes); + SIVAL(vwv+15, 1, ShareAccess); + SIVAL(vwv+17, 1, CreateDisposition); + SIVAL(vwv+19, 1, CreateOptions); + SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */ + SCVAL(vwv+23, 1, SecurityFlags); + + bytes = talloc_array(talloc_tos(), uint8_t, 0); + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), + fname, strlen(fname)+1, + &converted_len); + + /* sigh. this copes with broken netapp filer behaviour */ + bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL); + + if (bytes == NULL) { + return NULL; + } + + SIVAL(vwv+2, 1, converted_len); + + result = cli_request_send(mem_ctx, ev, cli, SMBntcreateX, 0, + 24, vwv, 0, talloc_get_size(bytes), bytes); + TALLOC_FREE(bytes); + return result; +} + +NTSTATUS cli_ntcreate_recv(struct async_req *req, uint16_t *pfnum) +{ + uint8_t wct; + uint16_t *vwv; + uint16_t num_bytes; + uint8_t *bytes; + NTSTATUS status; + + if (async_req_is_error(req, &status)) { + return status; + } + + status = cli_pull_reply(req, &wct, &vwv, &num_bytes, &bytes); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (wct < 3) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } + + *pfnum = SVAL(vwv+2, 1); + + return NT_STATUS_OK; +} + +NTSTATUS cli_ntcreate(struct cli_state *cli, + const char *fname, + uint32_t CreatFlags, + uint32_t DesiredAccess, + uint32_t FileAttributes, + uint32_t ShareAccess, + uint32_t CreateDisposition, + uint32_t CreateOptions, + uint8_t SecurityFlags, + uint16_t *pfid) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct async_req *req; + NTSTATUS status; + + if (cli->fd_event != NULL) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags, + DesiredAccess, FileAttributes, ShareAccess, + CreateDisposition, CreateOptions, + SecurityFlags); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + while (req->state < ASYNC_REQ_DONE) { + event_loop_once(ev); + } + + status = cli_ntcreate_recv(req, pfid); + fail: + TALLOC_FREE(frame); + return status; +} + /**************************************************************************** Open a file. ****************************************************************************/ |