s4-dsdb Add ability to force a particular SID in the upgrade case
[idra/samba.git] / source3 / libsmb / smb2cli_write.c
1 /*
2    Unix SMB/CIFS implementation.
3    smb2 lib
4    Copyright (C) Volker Lendecke 2011
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "client.h"
22 #include "async_smb.h"
23 #include "smb2cli_base.h"
24 #include "smb2cli.h"
25 #include "libsmb/proto.h"
26 #include "lib/util/tevent_ntstatus.h"
27
28 struct smb2cli_write_state {
29         uint8_t fixed[48];
30 };
31
32 static void smb2cli_write_done(struct tevent_req *subreq);
33
34 struct tevent_req *smb2cli_write_send(TALLOC_CTX *mem_ctx,
35                                       struct tevent_context *ev,
36                                       struct cli_state *cli,
37                                       uint32_t length,
38                                       uint64_t offset,
39                                       uint64_t fid_persistent,
40                                       uint64_t fid_volatile,
41                                       uint32_t remaining_bytes,
42                                       uint32_t flags,
43                                       const uint8_t *data)
44 {
45         struct tevent_req *req, *subreq;
46         struct smb2cli_write_state *state;
47         uint8_t *fixed;
48
49         req = tevent_req_create(mem_ctx, &state,
50                                 struct smb2cli_write_state);
51         if (req == NULL) {
52                 return NULL;
53         }
54
55         fixed = state->fixed;
56
57         SSVAL(fixed, 0, 49);
58         SSVAL(fixed, 2, SMB2_HDR_BODY + 48);
59         SIVAL(fixed, 4, length);
60         SBVAL(fixed, 8, offset);
61         SBVAL(fixed, 16, fid_persistent);
62         SBVAL(fixed, 24, fid_volatile);
63         SIVAL(fixed, 36, remaining_bytes);
64         SIVAL(fixed, 44, flags);
65
66         subreq = smb2cli_req_send(state, ev, cli, SMB2_OP_WRITE,
67                                   0, 0, /* flags */
68                                   cli->smb2.pid,
69                                   cli->smb2.tid,
70                                   cli->smb2.uid,
71                                   state->fixed, sizeof(state->fixed),
72                                   data, length);
73         if (tevent_req_nomem(subreq, req)) {
74                 return tevent_req_post(req, ev);
75         }
76         tevent_req_set_callback(subreq, smb2cli_write_done, req);
77         return req;
78 }
79
80 static void smb2cli_write_done(struct tevent_req *subreq)
81 {
82         struct tevent_req *req =
83                 tevent_req_callback_data(subreq,
84                 struct tevent_req);
85         NTSTATUS status;
86         struct iovec *iov;
87
88         status = smb2cli_req_recv(subreq, talloc_tos(), &iov, 17);
89         if (tevent_req_nterror(req, status)) {
90                 return;
91         }
92         tevent_req_done(req);
93 }
94
95 NTSTATUS smb2cli_write_recv(struct tevent_req *req)
96 {
97         return tevent_req_simple_recv_ntstatus(req);
98 }
99
100 NTSTATUS smb2cli_write(struct cli_state *cli,
101                        uint32_t length,
102                        uint64_t offset,
103                        uint64_t fid_persistent,
104                        uint64_t fid_volatile,
105                        uint32_t remaining_bytes,
106                        uint32_t flags,
107                        const uint8_t *data)
108 {
109         TALLOC_CTX *frame = talloc_stackframe();
110         struct event_context *ev;
111         struct tevent_req *req;
112         NTSTATUS status = NT_STATUS_NO_MEMORY;
113
114         if (cli_has_async_calls(cli)) {
115                 /*
116                  * Can't use sync call while an async call is in flight
117                  */
118                 status = NT_STATUS_INVALID_PARAMETER;
119                 goto fail;
120         }
121         ev = event_context_init(frame);
122         if (ev == NULL) {
123                 goto fail;
124         }
125         req = smb2cli_write_send(frame, ev, cli, length, offset,
126                                  fid_persistent, fid_volatile,
127                                  remaining_bytes, flags, data);
128         if (req == NULL) {
129                 goto fail;
130         }
131         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
132                 goto fail;
133         }
134         status = smb2cli_write_recv(req);
135  fail:
136         TALLOC_FREE(frame);
137         return status;
138 }