~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/libcli/smb_composite/loadfile.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   Copyright (C) Andrew Tridgell 2005
 
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
  a composite API for loading a whole file into memory
 
21
*/
 
22
 
 
23
#include "includes.h"
 
24
#include "libcli/raw/libcliraw.h"
 
25
#include "libcli/composite/composite.h"
 
26
#include "libcli/smb_composite/smb_composite.h"
 
27
 
 
28
/* the stages of this call */
 
29
enum loadfile_stage {LOADFILE_OPEN, LOADFILE_READ, LOADFILE_CLOSE};
 
30
 
 
31
 
 
32
static void loadfile_handler(struct smbcli_request *req);
 
33
 
 
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;
 
40
};
 
41
 
 
42
/*
 
43
  setup for the close
 
44
*/
 
45
static NTSTATUS setup_close(struct composite_context *c, 
 
46
                            struct smbcli_tree *tree, uint16_t fnum)
 
47
{
 
48
        struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state);
 
49
        union smb_close *io_close;
 
50
 
 
51
        /* nothing to read, setup the close */
 
52
        io_close = talloc(c, union smb_close);
 
53
        NT_STATUS_HAVE_NO_MEMORY(io_close);
 
54
        
 
55
        io_close->close.level = RAW_CLOSE_CLOSE;
 
56
        io_close->close.in.file.fnum = fnum;
 
57
        io_close->close.in.write_time = 0;
 
58
 
 
59
        state->req = smb_raw_close_send(tree, io_close);
 
60
        NT_STATUS_HAVE_NO_MEMORY(state->req);
 
61
 
 
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;
 
66
 
 
67
        return NT_STATUS_OK;
 
68
}
 
69
 
 
70
/*
 
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
 
73
*/
 
74
static NTSTATUS loadfile_open(struct composite_context *c, 
 
75
                              struct smb_composite_loadfile *io)
 
76
{
 
77
        struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state);
 
78
        struct smbcli_tree *tree = state->req->tree;
 
79
        NTSTATUS status;
 
80
 
 
81
        status = smb_raw_open_recv(state->req, c, state->io_open);
 
82
        NT_STATUS_NOT_OK_RETURN(status);
 
83
        
 
84
        /* don't allow stupidly large loads */
 
85
        if (state->io_open->ntcreatex.out.size > 100*1000*1000) {
 
86
                return NT_STATUS_INSUFFICIENT_RESOURCES;
 
87
        }
 
88
 
 
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);
 
93
 
 
94
        if (io->out.size == 0) {
 
95
                return setup_close(c, tree, state->io_open->ntcreatex.out.file.fnum);
 
96
        }
 
97
 
 
98
        /* setup for the read */
 
99
        state->io_read = talloc(c, union smb_read);
 
100
        NT_STATUS_HAVE_NO_MEMORY(state->io_read);
 
101
        
 
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;
 
110
 
 
111
        state->req = smb_raw_read_send(tree, state->io_read);
 
112
        NT_STATUS_HAVE_NO_MEMORY(state->req);
 
113
 
 
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;
 
118
 
 
119
        talloc_free(state->io_open);
 
120
 
 
121
        return NT_STATUS_OK;
 
122
}
 
123
 
 
124
 
 
125
/*
 
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
 
128
*/
 
129
static NTSTATUS loadfile_read(struct composite_context *c, 
 
130
                              struct smb_composite_loadfile *io)
 
131
{
 
132
        struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state);
 
133
        struct smbcli_tree *tree = state->req->tree;
 
134
        NTSTATUS status;
 
135
 
 
136
        status = smb_raw_read_recv(state->req, state->io_read);
 
137
        NT_STATUS_NOT_OK_RETURN(status);
 
138
        
 
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);
 
143
        }
 
144
 
 
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;
 
149
 
 
150
        state->req = smb_raw_read_send(tree, state->io_read);
 
151
        NT_STATUS_HAVE_NO_MEMORY(state->req);
 
152
 
 
153
        /* call the handler again when the read is done */
 
154
        state->req->async.fn = loadfile_handler;
 
155
        state->req->async.private_data = c;
 
156
 
 
157
        return NT_STATUS_OK;
 
158
}
 
159
 
 
160
/*
 
161
  called when the close is done, check the status and cleanup
 
162
*/
 
163
static NTSTATUS loadfile_close(struct composite_context *c, 
 
164
                               struct smb_composite_loadfile *io)
 
165
{
 
166
        struct loadfile_state *state = talloc_get_type(c->private_data, struct loadfile_state);
 
167
        NTSTATUS status;
 
168
 
 
169
        status = smbcli_request_simple_recv(state->req);
 
170
        NT_STATUS_NOT_OK_RETURN(status);
 
171
        
 
172
        c->state = COMPOSITE_STATE_DONE;
 
173
 
 
174
        return NT_STATUS_OK;
 
175
}
 
176
                                                     
 
177
 
 
178
/*
 
179
  handler for completion of a sub-request in loadfile
 
180
*/
 
181
static void loadfile_handler(struct smbcli_request *req)
 
182
{
 
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);
 
185
 
 
186
        /* when this handler is called, the stage indicates what
 
187
           call has just finished */
 
188
        switch (state->stage) {
 
189
        case LOADFILE_OPEN:
 
190
                c->status = loadfile_open(c, state->io);
 
191
                break;
 
192
 
 
193
        case LOADFILE_READ:
 
194
                c->status = loadfile_read(c, state->io);
 
195
                break;
 
196
 
 
197
        case LOADFILE_CLOSE:
 
198
                c->status = loadfile_close(c, state->io);
 
199
                break;
 
200
        }
 
201
 
 
202
        if (!NT_STATUS_IS_OK(c->status)) {
 
203
                c->state = COMPOSITE_STATE_ERROR;
 
204
        }
 
205
 
 
206
        if (c->state >= COMPOSITE_STATE_DONE &&
 
207
            c->async.fn) {
 
208
                c->async.fn(c);
 
209
        }
 
210
}
 
211
 
 
212
/*
 
213
  composite loadfile call - does an openx followed by a number of readx calls,
 
214
  followed by a close
 
215
*/
 
216
struct composite_context *smb_composite_loadfile_send(struct smbcli_tree *tree, 
 
217
                                                     struct smb_composite_loadfile *io)
 
218
{
 
219
        struct composite_context *c;
 
220
        struct loadfile_state *state;
 
221
 
 
222
        c = talloc_zero(tree, struct composite_context);
 
223
        if (c == NULL) goto failed;
 
224
 
 
225
        state = talloc(c, struct loadfile_state);
 
226
        if (state == NULL) goto failed;
 
227
 
 
228
        state->io = io;
 
229
 
 
230
        c->private_data = state;
 
231
        c->state = COMPOSITE_STATE_IN_PROGRESS;
 
232
        c->event_ctx = tree->session->transport->socket->event.ctx;
 
233
 
 
234
        /* setup for the open */
 
235
        state->io_open = talloc_zero(c, union smb_open);
 
236
        if (state->io_open == NULL) goto failed;
 
237
        
 
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;
 
246
 
 
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;
 
250
 
 
251
        /* setup the callback handler */
 
252
        state->req->async.fn = loadfile_handler;
 
253
        state->req->async.private_data = c;
 
254
        state->stage = LOADFILE_OPEN;
 
255
 
 
256
        return c;
 
257
 
 
258
failed:
 
259
        talloc_free(c);
 
260
        return NULL;
 
261
}
 
262
 
 
263
 
 
264
/*
 
265
  composite loadfile call - recv side
 
266
*/
 
267
NTSTATUS smb_composite_loadfile_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
 
268
{
 
269
        NTSTATUS status;
 
270
 
 
271
        status = composite_wait(c);
 
272
 
 
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);
 
276
        }
 
277
 
 
278
        talloc_free(c);
 
279
        return status;
 
280
}
 
281
 
 
282
 
 
283
/*
 
284
  composite loadfile call - sync interface
 
285
*/
 
286
NTSTATUS smb_composite_loadfile(struct smbcli_tree *tree, 
 
287
                                TALLOC_CTX *mem_ctx,
 
288
                                struct smb_composite_loadfile *io)
 
289
{
 
290
        struct composite_context *c = smb_composite_loadfile_send(tree, io);
 
291
        return smb_composite_loadfile_recv(c, mem_ctx);
 
292
}
 
293