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 loading a whole file into memory
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/composite/composite.h"
26 #include "libcli/smb_composite/smb_composite.h"
28 /* the stages of this call */
29 enum loadfile_stage
{LOADFILE_OPEN
, LOADFILE_READ
, LOADFILE_CLOSE
};
32 static void loadfile_handler(struct smbcli_request
*req
);
34 struct loadfile_state
{
35 enum loadfile_stage stage
;
36 struct smb_composite_loadfile
*io
;
37 struct smbcli_request
*req
;
38 union smb_open
*io_open
;
39 union smb_read
*io_read
;
45 static NTSTATUS
setup_close(struct composite_context
*c
,
46 struct smbcli_tree
*tree
, uint16_t fnum
)
48 struct loadfile_state
*state
= talloc_get_type(c
->private_data
, struct loadfile_state
);
49 union smb_close
*io_close
;
51 /* nothing to read, setup the close */
52 io_close
= talloc(c
, union smb_close
);
53 NT_STATUS_HAVE_NO_MEMORY(io_close
);
55 io_close
->close
.level
= RAW_CLOSE_CLOSE
;
56 io_close
->close
.in
.file
.fnum
= fnum
;
57 io_close
->close
.in
.write_time
= 0;
59 state
->req
= smb_raw_close_send(tree
, io_close
);
60 NT_STATUS_HAVE_NO_MEMORY(state
->req
);
62 /* call the handler again when the close is done */
63 state
->req
->async
.fn
= loadfile_handler
;
64 state
->req
->async
.private_data
= c
;
65 state
->stage
= LOADFILE_CLOSE
;
71 called when the open is done - pull the results and setup for the
72 first readx, or close if the file is zero size
74 static NTSTATUS
loadfile_open(struct composite_context
*c
,
75 struct smb_composite_loadfile
*io
)
77 struct loadfile_state
*state
= talloc_get_type(c
->private_data
, struct loadfile_state
);
78 struct smbcli_tree
*tree
= state
->req
->tree
;
81 status
= smb_raw_open_recv(state
->req
, c
, state
->io_open
);
82 NT_STATUS_NOT_OK_RETURN(status
);
84 /* don't allow stupidly large loads */
85 if (state
->io_open
->ntcreatex
.out
.size
> 100*1000*1000) {
86 return NT_STATUS_INSUFFICIENT_RESOURCES
;
89 /* allocate space for the file data */
90 io
->out
.size
= state
->io_open
->ntcreatex
.out
.size
;
91 io
->out
.data
= talloc_array(c
, uint8_t, io
->out
.size
);
92 NT_STATUS_HAVE_NO_MEMORY(io
->out
.data
);
94 if (io
->out
.size
== 0) {
95 return setup_close(c
, tree
, state
->io_open
->ntcreatex
.out
.file
.fnum
);
98 /* setup for the read */
99 state
->io_read
= talloc(c
, union smb_read
);
100 NT_STATUS_HAVE_NO_MEMORY(state
->io_read
);
102 state
->io_read
->readx
.level
= RAW_READ_READX
;
103 state
->io_read
->readx
.in
.file
.fnum
= state
->io_open
->ntcreatex
.out
.file
.fnum
;
104 state
->io_read
->readx
.in
.offset
= 0;
105 state
->io_read
->readx
.in
.mincnt
= MIN(32768, io
->out
.size
);
106 state
->io_read
->readx
.in
.maxcnt
= state
->io_read
->readx
.in
.mincnt
;
107 state
->io_read
->readx
.in
.remaining
= 0;
108 state
->io_read
->readx
.in
.read_for_execute
= false;
109 state
->io_read
->readx
.out
.data
= io
->out
.data
;
111 state
->req
= smb_raw_read_send(tree
, state
->io_read
);
112 NT_STATUS_HAVE_NO_MEMORY(state
->req
);
114 /* call the handler again when the first read is done */
115 state
->req
->async
.fn
= loadfile_handler
;
116 state
->req
->async
.private_data
= c
;
117 state
->stage
= LOADFILE_READ
;
119 talloc_free(state
->io_open
);
126 called when a read is done - pull the results and setup for the
127 next read, or close if the file is all done
129 static NTSTATUS
loadfile_read(struct composite_context
*c
,
130 struct smb_composite_loadfile
*io
)
132 struct loadfile_state
*state
= talloc_get_type(c
->private_data
, struct loadfile_state
);
133 struct smbcli_tree
*tree
= state
->req
->tree
;
136 status
= smb_raw_read_recv(state
->req
, state
->io_read
);
137 NT_STATUS_NOT_OK_RETURN(status
);
139 /* we might be done */
140 if (state
->io_read
->readx
.in
.offset
+
141 state
->io_read
->readx
.out
.nread
== io
->out
.size
) {
142 return setup_close(c
, tree
, state
->io_read
->readx
.in
.file
.fnum
);
145 /* setup for the next read */
146 state
->io_read
->readx
.in
.offset
+= state
->io_read
->readx
.out
.nread
;
147 state
->io_read
->readx
.in
.mincnt
= MIN(32768, io
->out
.size
- state
->io_read
->readx
.in
.offset
);
148 state
->io_read
->readx
.out
.data
= io
->out
.data
+ state
->io_read
->readx
.in
.offset
;
150 state
->req
= smb_raw_read_send(tree
, state
->io_read
);
151 NT_STATUS_HAVE_NO_MEMORY(state
->req
);
153 /* call the handler again when the read is done */
154 state
->req
->async
.fn
= loadfile_handler
;
155 state
->req
->async
.private_data
= c
;
161 called when the close is done, check the status and cleanup
163 static NTSTATUS
loadfile_close(struct composite_context
*c
,
164 struct smb_composite_loadfile
*io
)
166 struct loadfile_state
*state
= talloc_get_type(c
->private_data
, struct loadfile_state
);
169 status
= smbcli_request_simple_recv(state
->req
);
170 NT_STATUS_NOT_OK_RETURN(status
);
172 c
->state
= COMPOSITE_STATE_DONE
;
179 handler for completion of a sub-request in loadfile
181 static void loadfile_handler(struct smbcli_request
*req
)
183 struct composite_context
*c
= (struct composite_context
*)req
->async
.private_data
;
184 struct loadfile_state
*state
= talloc_get_type(c
->private_data
, struct loadfile_state
);
186 /* when this handler is called, the stage indicates what
187 call has just finished */
188 switch (state
->stage
) {
190 c
->status
= loadfile_open(c
, state
->io
);
194 c
->status
= loadfile_read(c
, state
->io
);
198 c
->status
= loadfile_close(c
, state
->io
);
202 if (!NT_STATUS_IS_OK(c
->status
)) {
203 c
->state
= COMPOSITE_STATE_ERROR
;
206 if (c
->state
>= COMPOSITE_STATE_DONE
&&
213 composite loadfile call - does an openx followed by a number of readx calls,
216 struct composite_context
*smb_composite_loadfile_send(struct smbcli_tree
*tree
,
217 struct smb_composite_loadfile
*io
)
219 struct composite_context
*c
;
220 struct loadfile_state
*state
;
222 c
= talloc_zero(tree
, struct composite_context
);
223 if (c
== NULL
) goto failed
;
225 state
= talloc(c
, struct loadfile_state
);
226 if (state
== NULL
) goto failed
;
230 c
->private_data
= state
;
231 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
232 c
->event_ctx
= tree
->session
->transport
->ev
;
234 /* setup for the open */
235 state
->io_open
= talloc_zero(c
, union smb_open
);
236 if (state
->io_open
== NULL
) goto failed
;
238 state
->io_open
->ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
239 state
->io_open
->ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
240 state
->io_open
->ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
241 state
->io_open
->ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
242 state
->io_open
->ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
243 state
->io_open
->ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
244 state
->io_open
->ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
245 state
->io_open
->ntcreatex
.in
.fname
= io
->in
.fname
;
247 /* send the open on its way */
248 state
->req
= smb_raw_open_send(tree
, state
->io_open
);
249 if (state
->req
== NULL
) goto failed
;
251 /* setup the callback handler */
252 state
->req
->async
.fn
= loadfile_handler
;
253 state
->req
->async
.private_data
= c
;
254 state
->stage
= LOADFILE_OPEN
;
265 composite loadfile call - recv side
267 NTSTATUS
smb_composite_loadfile_recv(struct composite_context
*c
, TALLOC_CTX
*mem_ctx
)
271 status
= composite_wait(c
);
273 if (NT_STATUS_IS_OK(status
)) {
274 struct loadfile_state
*state
= talloc_get_type(c
->private_data
, struct loadfile_state
);
275 talloc_steal(mem_ctx
, state
->io
->out
.data
);
284 composite loadfile call - sync interface
286 NTSTATUS
smb_composite_loadfile(struct smbcli_tree
*tree
,
288 struct smb_composite_loadfile
*io
)
290 struct composite_context
*c
= smb_composite_loadfile_send(tree
, io
);
291 return smb_composite_loadfile_recv(c
, mem_ctx
);