librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/gebeck_regimport.git] / source4 / libcli / smb_composite / savefile.c
blob2f004430837a8f4dba543e88cd340a90e5f709e2
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2005
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.
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.
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/>.
20 a composite API for saving a whole file from memory
23 #include "includes.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/raw/raw_proto.h"
26 #include "libcli/composite/composite.h"
27 #include "libcli/smb_composite/smb_composite.h"
29 /* the stages of this call */
30 enum savefile_stage {SAVEFILE_OPEN, SAVEFILE_WRITE, SAVEFILE_CLOSE};
32 static void savefile_handler(struct smbcli_request *req);
34 struct savefile_state {
35 enum savefile_stage stage;
36 off_t total_written;
37 struct smb_composite_savefile *io;
38 union smb_open *io_open;
39 union smb_write *io_write;
40 struct smbcli_request *req;
45 setup for the close
47 static NTSTATUS setup_close(struct composite_context *c,
48 struct smbcli_tree *tree, uint16_t fnum)
50 struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state);
51 union smb_close *io_close;
53 /* nothing to write, setup the close */
54 io_close = talloc(c, union smb_close);
55 NT_STATUS_HAVE_NO_MEMORY(io_close);
57 io_close->close.level = RAW_CLOSE_CLOSE;
58 io_close->close.in.file.fnum = fnum;
59 io_close->close.in.write_time = 0;
61 state->req = smb_raw_close_send(tree, io_close);
62 NT_STATUS_HAVE_NO_MEMORY(state->req);
64 /* call the handler again when the close is done */
65 state->stage = SAVEFILE_CLOSE;
66 state->req->async.fn = savefile_handler;
67 state->req->async.private_data = c;
69 return NT_STATUS_OK;
73 called when the open is done - pull the results and setup for the
74 first writex, or close if the file is zero size
76 static NTSTATUS savefile_open(struct composite_context *c,
77 struct smb_composite_savefile *io)
79 struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state);
80 union smb_write *io_write;
81 struct smbcli_tree *tree = state->req->tree;
82 NTSTATUS status;
83 uint32_t max_xmit = tree->session->transport->negotiate.max_xmit;
85 status = smb_raw_open_recv(state->req, c, state->io_open);
86 NT_STATUS_NOT_OK_RETURN(status);
88 if (io->in.size == 0) {
89 return setup_close(c, tree, state->io_open->ntcreatex.out.file.fnum);
92 /* setup for the first write */
93 io_write = talloc(c, union smb_write);
94 NT_STATUS_HAVE_NO_MEMORY(io_write);
96 io_write->writex.level = RAW_WRITE_WRITEX;
97 io_write->writex.in.file.fnum = state->io_open->ntcreatex.out.file.fnum;
98 io_write->writex.in.offset = 0;
99 io_write->writex.in.wmode = 0;
100 io_write->writex.in.remaining = 0;
101 io_write->writex.in.count = MIN(max_xmit - 100, io->in.size);
102 io_write->writex.in.data = io->in.data;
103 state->io_write = io_write;
105 state->req = smb_raw_write_send(tree, io_write);
106 NT_STATUS_HAVE_NO_MEMORY(state->req);
108 /* call the handler again when the first write is done */
109 state->stage = SAVEFILE_WRITE;
110 state->req->async.fn = savefile_handler;
111 state->req->async.private_data = c;
112 talloc_free(state->io_open);
114 return NT_STATUS_OK;
119 called when a write is done - pull the results and setup for the
120 next write, or close if the file is all done
122 static NTSTATUS savefile_write(struct composite_context *c,
123 struct smb_composite_savefile *io)
125 struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state);
126 struct smbcli_tree *tree = state->req->tree;
127 NTSTATUS status;
128 uint32_t max_xmit = tree->session->transport->negotiate.max_xmit;
130 status = smb_raw_write_recv(state->req, state->io_write);
131 NT_STATUS_NOT_OK_RETURN(status);
133 state->total_written += state->io_write->writex.out.nwritten;
135 /* we might be done */
136 if (state->io_write->writex.out.nwritten != state->io_write->writex.in.count ||
137 state->total_written == io->in.size) {
138 return setup_close(c, tree, state->io_write->writex.in.file.fnum);
141 /* setup for the next write */
142 state->io_write->writex.in.offset = state->total_written;
143 state->io_write->writex.in.count = MIN(max_xmit - 100,
144 io->in.size - state->total_written);
145 state->io_write->writex.in.data = io->in.data + state->total_written;
147 state->req = smb_raw_write_send(tree, state->io_write);
148 NT_STATUS_HAVE_NO_MEMORY(state->req);
150 /* call the handler again when the write is done */
151 state->req->async.fn = savefile_handler;
152 state->req->async.private_data = c;
154 return NT_STATUS_OK;
158 called when the close is done, check the status and cleanup
160 static NTSTATUS savefile_close(struct composite_context *c,
161 struct smb_composite_savefile *io)
163 struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state);
164 NTSTATUS status;
166 status = smbcli_request_simple_recv(state->req);
167 NT_STATUS_NOT_OK_RETURN(status);
169 if (state->total_written != io->in.size) {
170 return NT_STATUS_DISK_FULL;
173 c->state = COMPOSITE_STATE_DONE;
175 return NT_STATUS_OK;
180 handler for completion of a sub-request in savefile
182 static void savefile_handler(struct smbcli_request *req)
184 struct composite_context *c = (struct composite_context *)req->async.private_data;
185 struct savefile_state *state = talloc_get_type(c->private_data, struct savefile_state);
187 /* when this handler is called, the stage indicates what
188 call has just finished */
189 switch (state->stage) {
190 case SAVEFILE_OPEN:
191 c->status = savefile_open(c, state->io);
192 break;
194 case SAVEFILE_WRITE:
195 c->status = savefile_write(c, state->io);
196 break;
198 case SAVEFILE_CLOSE:
199 c->status = savefile_close(c, state->io);
200 break;
203 if (!NT_STATUS_IS_OK(c->status)) {
204 c->state = COMPOSITE_STATE_ERROR;
207 if (c->state >= COMPOSITE_STATE_DONE &&
208 c->async.fn) {
209 c->async.fn(c);
214 composite savefile call - does an openx followed by a number of writex calls,
215 followed by a close
217 struct composite_context *smb_composite_savefile_send(struct smbcli_tree *tree,
218 struct smb_composite_savefile *io)
220 struct composite_context *c;
221 struct savefile_state *state;
222 union smb_open *io_open;
224 c = talloc_zero(tree, struct composite_context);
225 if (c == NULL) goto failed;
227 c->state = COMPOSITE_STATE_IN_PROGRESS;
228 c->event_ctx = tree->session->transport->ev;
230 state = talloc(c, struct savefile_state);
231 if (state == NULL) goto failed;
233 state->stage = SAVEFILE_OPEN;
234 state->total_written = 0;
235 state->io = io;
237 /* setup for the open */
238 io_open = talloc_zero(c, union smb_open);
239 if (io_open == NULL) goto failed;
241 io_open->ntcreatex.level = RAW_OPEN_NTCREATEX;
242 io_open->ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
243 io_open->ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
244 io_open->ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
245 io_open->ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
246 io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
247 io_open->ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
248 io_open->ntcreatex.in.fname = io->in.fname;
249 state->io_open = io_open;
251 /* send the open on its way */
252 state->req = smb_raw_open_send(tree, io_open);
253 if (state->req == NULL) goto failed;
255 /* setup the callback handler */
256 state->req->async.fn = savefile_handler;
257 state->req->async.private_data = c;
258 c->private_data = state;
260 return c;
262 failed:
263 talloc_free(c);
264 return NULL;
269 composite savefile call - recv side
271 NTSTATUS smb_composite_savefile_recv(struct composite_context *c)
273 NTSTATUS status;
274 status = composite_wait(c);
275 talloc_free(c);
276 return status;
281 composite savefile call - sync interface
283 NTSTATUS smb_composite_savefile(struct smbcli_tree *tree,
284 struct smb_composite_savefile *io)
286 struct composite_context *c = smb_composite_savefile_send(tree, io);
287 return smb_composite_savefile_recv(c);