Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : NTVFS generic level mapping code
5 :
6 : Copyright (C) Andrew Tridgell 2003-2004
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 : /*
22 : this implements mappings between info levels for NTVFS backend calls
23 :
24 : the idea is that each of these functions implements one of the NTVFS
25 : backend calls in terms of the 'generic' call. All backends that use
26 : these functions must supply the generic call, but can if it wants to
27 : also implement other levels if the need arises
28 :
29 : this allows backend writers to only implement one variant of each
30 : call unless they need fine grained control of the calls.
31 : */
32 :
33 : #include "includes.h"
34 : #include "ntvfs/ntvfs.h"
35 : #include "libcli/smb2/smb2.h"
36 : #include "libcli/smb2/smb2_calls.h"
37 :
38 : #undef strcasecmp
39 :
40 : /* a second stage function converts from the out parameters of the generic
41 : call onto the out parameters of the specific call made */
42 : typedef NTSTATUS (*second_stage_t)(struct ntvfs_module_context *,
43 : struct ntvfs_request *,
44 : void *, void *, NTSTATUS);
45 :
46 : /*
47 : this structure holds the async state for pending mapped async calls
48 : */
49 : struct ntvfs_map_async {
50 : struct ntvfs_module_context *ntvfs;
51 : void *io, *io2;
52 : second_stage_t fn;
53 : };
54 :
55 : /*
56 : this is a async wrapper, called from the backend when it has completed
57 : a function that it has decided to reply to in an async fashion
58 : */
59 5396 : static void ntvfs_map_async_send(struct ntvfs_request *req)
60 : {
61 5396 : struct ntvfs_map_async *m = talloc_get_type(req->async_states->private_data,
62 : struct ntvfs_map_async);
63 :
64 5396 : ntvfs_async_state_pop(req);
65 :
66 : /* call the _finish function setup in ntvfs_map_async_setup() */
67 5396 : req->async_states->status = m->fn(m->ntvfs, req, m->io, m->io2, req->async_states->status);
68 :
69 : /* call the send function from the next module up */
70 5396 : req->async_states->send_fn(req);
71 5396 : }
72 :
73 : /*
74 : prepare for calling a ntvfs backend with async support
75 : io is the original call structure
76 : io2 is the new call structure for the mapped call
77 : fn is a second stage function for processing the out arguments
78 : */
79 424940 : static NTSTATUS ntvfs_map_async_setup(struct ntvfs_module_context *ntvfs,
80 : struct ntvfs_request *req,
81 : void *io, void *io2,
82 : second_stage_t fn)
83 : {
84 0 : struct ntvfs_map_async *m;
85 424940 : m = talloc(req, struct ntvfs_map_async);
86 424940 : if (m == NULL) {
87 0 : return NT_STATUS_NO_MEMORY;
88 : }
89 424940 : m->ntvfs = ntvfs;
90 424940 : m->io = io;
91 424940 : m->io2 = io2;
92 424940 : m->fn = fn;
93 424940 : return ntvfs_async_state_push(ntvfs, req, m, ntvfs_map_async_send);
94 : }
95 :
96 : /*
97 : called when first stage processing is complete.
98 : */
99 424940 : static NTSTATUS ntvfs_map_async_finish(struct ntvfs_request *req, NTSTATUS status)
100 : {
101 0 : struct ntvfs_map_async *m;
102 :
103 : /* if the backend has decided to reply in an async fashion then
104 : we don't need to do any work here */
105 424940 : if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) {
106 5396 : return status;
107 : }
108 :
109 : /* the backend is replying immediately. call the 2nd stage function after popping our local
110 : async state */
111 419544 : m = talloc_get_type(req->async_states->private_data,
112 : struct ntvfs_map_async);
113 :
114 419544 : ntvfs_async_state_pop(req);
115 :
116 419544 : return m->fn(m->ntvfs, req, m->io, m->io2, status);
117 : }
118 :
119 : /*
120 : see if a filename ends in EXE COM DLL or SYM. This is needed for the
121 : DENY_DOS mapping for OpenX
122 : */
123 1388 : bool is_exe_filename(const char *fname)
124 : {
125 0 : char *p;
126 1388 : p = strrchr(fname, '.');
127 1388 : if (!p) {
128 273 : return false;
129 : }
130 1115 : p++;
131 1115 : if (strcasecmp(p, "EXE") == 0 ||
132 635 : strcasecmp(p, "COM") == 0 ||
133 635 : strcasecmp(p, "DLL") == 0 ||
134 635 : strcasecmp(p, "SYM") == 0) {
135 480 : return true;
136 : }
137 635 : return false;
138 : }
139 :
140 :
141 : /*
142 : NTVFS openx to ntcreatex mapper
143 : */
144 217211 : static NTSTATUS ntvfs_map_open_finish(struct ntvfs_module_context *ntvfs,
145 : struct ntvfs_request *req,
146 : union smb_open *io,
147 : union smb_open *io2,
148 : NTSTATUS status)
149 : {
150 217211 : time_t write_time = 0;
151 217211 : uint32_t set_size = 0;
152 0 : union smb_setfileinfo *sf;
153 0 : unsigned int state;
154 :
155 217211 : if (!NT_STATUS_IS_OK(status)) {
156 69171 : return status;
157 : }
158 :
159 148040 : switch (io->generic.level) {
160 8 : case RAW_OPEN_OPEN:
161 8 : io->openold.out.file.ntvfs = io2->generic.out.file.ntvfs;
162 8 : io->openold.out.attrib = io2->generic.out.attrib;
163 8 : io->openold.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
164 8 : io->openold.out.size = io2->generic.out.size;
165 8 : io->openold.out.rmode = io->openold.in.open_mode;
166 8 : break;
167 :
168 6409 : case RAW_OPEN_OPENX:
169 6409 : io->openx.out.file.ntvfs = io2->generic.out.file.ntvfs;
170 6409 : io->openx.out.attrib = io2->generic.out.attrib;
171 6409 : io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
172 6409 : io->openx.out.size = io2->generic.out.size;
173 6409 : io->openx.out.access = (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK);
174 6409 : io->openx.out.ftype = 0;
175 6409 : io->openx.out.devstate = 0;
176 6409 : io->openx.out.action = io2->generic.out.create_action;
177 6409 : io->openx.out.unique_fid = 0;
178 6409 : io->openx.out.access_mask = SEC_STD_ALL;
179 6409 : io->openx.out.unknown = 0;
180 :
181 : /* we need to extend the file to the requested size if
182 : it was newly created */
183 6409 : if (io2->generic.out.create_action == NTCREATEX_ACTION_CREATED) {
184 3108 : set_size = io->openx.in.size;
185 : }
186 6409 : break;
187 :
188 11 : case RAW_OPEN_T2OPEN:
189 11 : io->t2open.out.file.ntvfs = io2->generic.out.file.ntvfs;
190 11 : io->t2open.out.attrib = io2->generic.out.attrib;
191 11 : io->t2open.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
192 11 : io->t2open.out.size = io2->generic.out.size;
193 11 : io->t2open.out.access = io->t2open.in.open_mode;
194 11 : io->t2open.out.ftype = 0;
195 11 : io->t2open.out.devstate = 0;
196 11 : io->t2open.out.action = io2->generic.out.create_action;
197 11 : io->t2open.out.file_id = 0;
198 11 : break;
199 :
200 7 : case RAW_OPEN_MKNEW:
201 : case RAW_OPEN_CREATE:
202 7 : io->mknew.out.file.ntvfs= io2->generic.out.file.ntvfs;
203 7 : write_time = io->mknew.in.write_time;
204 7 : break;
205 :
206 4 : case RAW_OPEN_CTEMP:
207 4 : io->ctemp.out.file.ntvfs= io2->generic.out.file.ntvfs;
208 8 : io->ctemp.out.name = talloc_strdup(req, io2->generic.in.fname +
209 4 : strlen(io->ctemp.in.directory) + 1);
210 4 : NT_STATUS_HAVE_NO_MEMORY(io->ctemp.out.name);
211 4 : break;
212 :
213 141601 : case RAW_OPEN_SMB2:
214 141601 : ZERO_STRUCT(io->smb2.out);
215 141601 : io->smb2.out.file.ntvfs = io2->generic.out.file.ntvfs;
216 141601 : switch (io2->generic.out.oplock_level) {
217 48 : case BATCH_OPLOCK_RETURN:
218 48 : io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_BATCH;
219 48 : break;
220 14 : case EXCLUSIVE_OPLOCK_RETURN:
221 14 : io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
222 14 : break;
223 27 : case LEVEL_II_OPLOCK_RETURN:
224 27 : io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_II;
225 27 : break;
226 141512 : default:
227 141512 : io->smb2.out.oplock_level = SMB2_OPLOCK_LEVEL_NONE;
228 141512 : break;
229 : }
230 141601 : io->smb2.out.reserved = 0;
231 141601 : io->smb2.out.create_action = io2->generic.out.create_action;
232 141601 : io->smb2.out.create_time = io2->generic.out.create_time;
233 141601 : io->smb2.out.access_time = io2->generic.out.access_time;
234 141601 : io->smb2.out.write_time = io2->generic.out.write_time;
235 141601 : io->smb2.out.change_time = io2->generic.out.change_time;
236 141601 : io->smb2.out.alloc_size = io2->generic.out.alloc_size;
237 141601 : io->smb2.out.size = io2->generic.out.size;
238 141601 : io->smb2.out.file_attr = io2->generic.out.attrib;
239 141601 : io->smb2.out.reserved2 = 0;
240 141601 : io->smb2.out.maximal_access = io2->generic.out.maximal_access;
241 141601 : memcpy(io->smb2.out.on_disk_id, io2->generic.out.on_disk_id,
242 : sizeof(io2->generic.out.on_disk_id));
243 141601 : break;
244 :
245 0 : default:
246 0 : return NT_STATUS_INVALID_LEVEL;
247 : }
248 :
249 : /* doing a secondary request async is more trouble than its
250 : worth */
251 148040 : state = req->async_states->state;
252 148040 : req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
253 :
254 148040 : if (write_time != 0) {
255 4 : sf = talloc(req, union smb_setfileinfo);
256 4 : NT_STATUS_HAVE_NO_MEMORY(sf);
257 4 : sf->generic.level = RAW_SFILEINFO_STANDARD;
258 4 : sf->generic.in.file.ntvfs = io2->generic.out.file.ntvfs;
259 4 : sf->standard.in.create_time = 0;
260 4 : sf->standard.in.write_time = write_time;
261 4 : sf->standard.in.access_time = 0;
262 4 : status = ntvfs->ops->setfileinfo_fn(ntvfs, req, sf);
263 : }
264 :
265 148040 : if (set_size != 0) {
266 6 : sf = talloc(req, union smb_setfileinfo);
267 6 : NT_STATUS_HAVE_NO_MEMORY(sf);
268 6 : sf->generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
269 6 : sf->generic.in.file.ntvfs = io2->generic.out.file.ntvfs;
270 6 : sf->end_of_file_info.in.size = set_size;
271 6 : status = ntvfs->ops->setfileinfo_fn(ntvfs, req, sf);
272 6 : if (NT_STATUS_IS_OK(status)) {
273 6 : io->openx.out.size = io->openx.in.size;
274 : }
275 : }
276 :
277 148040 : req->async_states->state = state;
278 :
279 148040 : return NT_STATUS_OK;
280 : }
281 :
282 : /*
283 : the core of the mapping between openx style parameters and ntcreatex
284 : parameters
285 : */
286 8622 : static NTSTATUS map_openx_open(uint16_t flags, uint16_t open_mode,
287 : uint16_t open_func, const char *fname,
288 : union smb_open *io2)
289 : {
290 8622 : io2->generic.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
291 8622 : io2->generic.in.private_flags = 0;
292 :
293 8622 : if (flags & OPENX_FLAGS_REQUEST_OPLOCK) {
294 3 : io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
295 : }
296 8622 : if (flags & OPENX_FLAGS_REQUEST_BATCH_OPLOCK) {
297 3 : io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
298 : }
299 :
300 8622 : switch (open_mode & OPENX_MODE_ACCESS_MASK) {
301 1672 : case OPENX_MODE_ACCESS_READ:
302 : case OPENX_MODE_ACCESS_EXEC:
303 1672 : io2->generic.in.access_mask = SEC_RIGHTS_FILE_READ;
304 1672 : break;
305 1451 : case OPENX_MODE_ACCESS_WRITE:
306 1451 : io2->generic.in.access_mask = SEC_RIGHTS_FILE_WRITE;
307 1451 : break;
308 5493 : case OPENX_MODE_ACCESS_RDWR:
309 : case OPENX_MODE_ACCESS_FCB:
310 5493 : io2->generic.in.access_mask =
311 : SEC_RIGHTS_FILE_READ |
312 : SEC_RIGHTS_FILE_WRITE;
313 5493 : break;
314 6 : default:
315 6 : return NT_STATUS_DOS(ERRDOS, ERRbadaccess);
316 : }
317 :
318 8616 : switch (open_mode & OPENX_MODE_DENY_MASK) {
319 864 : case OPENX_MODE_DENY_READ:
320 864 : io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
321 864 : break;
322 871 : case OPENX_MODE_DENY_WRITE:
323 871 : io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
324 871 : break;
325 974 : case OPENX_MODE_DENY_ALL:
326 974 : io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
327 974 : break;
328 3765 : case OPENX_MODE_DENY_NONE:
329 3765 : io2->generic.in.share_access =
330 : NTCREATEX_SHARE_ACCESS_READ |
331 : NTCREATEX_SHARE_ACCESS_WRITE;
332 3765 : break;
333 1273 : case OPENX_MODE_DENY_DOS:
334 : /* DENY_DOS is quite strange - it depends on the filename! */
335 1273 : io2->generic.in.private_flags |=
336 : NTCREATEX_FLAG_DENY_DOS;
337 1273 : if (is_exe_filename(fname)) {
338 432 : io2->generic.in.share_access =
339 : NTCREATEX_SHARE_ACCESS_READ |
340 : NTCREATEX_SHARE_ACCESS_WRITE;
341 : } else {
342 841 : if ((open_mode & OPENX_MODE_ACCESS_MASK) == OPENX_MODE_ACCESS_READ) {
343 312 : io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
344 : } else {
345 529 : io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
346 : }
347 : }
348 1273 : break;
349 867 : case OPENX_MODE_DENY_FCB:
350 867 : io2->generic.in.private_flags |= NTCREATEX_FLAG_DENY_FCB;
351 867 : io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
352 867 : break;
353 2 : default:
354 2 : return NT_STATUS_DOS(ERRDOS, ERRbadaccess);
355 : }
356 :
357 8614 : switch (open_func) {
358 5345 : case (OPENX_OPEN_FUNC_OPEN):
359 5345 : io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
360 5345 : break;
361 11 : case (OPENX_OPEN_FUNC_TRUNC):
362 11 : io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
363 11 : break;
364 107 : case (OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE):
365 107 : io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
366 107 : break;
367 2793 : case (OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE):
368 2793 : io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
369 2793 : break;
370 351 : case (OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE):
371 351 : io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
372 351 : break;
373 7 : default:
374 : /* this one is very strange */
375 7 : if ((open_mode & OPENX_MODE_ACCESS_MASK) == OPENX_MODE_ACCESS_EXEC) {
376 3 : io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
377 3 : break;
378 : }
379 4 : return NT_STATUS_DOS(ERRDOS, ERRbadaccess);
380 : }
381 :
382 8610 : return NT_STATUS_OK;
383 : }
384 :
385 : /*
386 : NTVFS open generic to any mapper
387 : */
388 217211 : NTSTATUS ntvfs_map_open(struct ntvfs_module_context *ntvfs,
389 : struct ntvfs_request *req,
390 : union smb_open *io)
391 : {
392 0 : NTSTATUS status;
393 0 : union smb_open *io2;
394 :
395 217211 : io2 = talloc_zero(req, union smb_open);
396 217211 : if (io2 == NULL) {
397 0 : return NT_STATUS_NO_MEMORY;
398 : }
399 :
400 217211 : status = ntvfs_map_async_setup(ntvfs, req,
401 : io, io2,
402 : (second_stage_t)ntvfs_map_open_finish);
403 217211 : if (!NT_STATUS_IS_OK(status)) {
404 0 : return status;
405 : }
406 :
407 217211 : io2->generic.level = RAW_OPEN_GENERIC;
408 :
409 217211 : switch (io->generic.level) {
410 8589 : case RAW_OPEN_OPENX:
411 8589 : status = map_openx_open(io->openx.in.flags,
412 8589 : io->openx.in.open_mode,
413 8589 : io->openx.in.open_func,
414 : io->openx.in.fname,
415 : io2);
416 8589 : if (!NT_STATUS_IS_OK(status)) {
417 14 : goto done;
418 : }
419 :
420 8583 : io2->generic.in.file_attr = io->openx.in.file_attrs;
421 8583 : io2->generic.in.fname = io->openx.in.fname;
422 :
423 8583 : status = ntvfs->ops->open_fn(ntvfs, req, io2);
424 217197 : break;
425 :
426 :
427 18 : case RAW_OPEN_OPEN:
428 18 : status = map_openx_open(0,
429 18 : io->openold.in.open_mode,
430 : OPENX_OPEN_FUNC_OPEN,
431 : io->openold.in.fname,
432 : io2);
433 18 : if (!NT_STATUS_IS_OK(status)) {
434 6 : goto done;
435 : }
436 :
437 12 : io2->generic.in.file_attr = io->openold.in.search_attrs;
438 12 : io2->generic.in.fname = io->openold.in.fname;
439 :
440 12 : status = ntvfs->ops->open_fn(ntvfs, req, io2);
441 12 : break;
442 :
443 17 : case RAW_OPEN_T2OPEN:
444 17 : io2->generic.level = RAW_OPEN_NTTRANS_CREATE;
445 :
446 17 : if (io->t2open.in.open_func == 0) {
447 2 : status = NT_STATUS_OBJECT_NAME_COLLISION;
448 2 : goto done;
449 : }
450 :
451 15 : status = map_openx_open(io->t2open.in.flags,
452 15 : io->t2open.in.open_mode,
453 15 : io->t2open.in.open_func,
454 : io->t2open.in.fname,
455 : io2);
456 15 : if (!NT_STATUS_IS_OK(status)) {
457 0 : goto done;
458 : }
459 :
460 15 : io2->generic.in.file_attr = io->t2open.in.file_attrs;
461 15 : io2->generic.in.fname = io->t2open.in.fname;
462 15 : io2->generic.in.ea_list = talloc(io2, struct smb_ea_list);
463 15 : io2->generic.in.ea_list->num_eas = io->t2open.in.num_eas;
464 15 : io2->generic.in.ea_list->eas = io->t2open.in.eas;
465 :
466 15 : status = ntvfs->ops->open_fn(ntvfs, req, io2);
467 15 : break;
468 :
469 4 : case RAW_OPEN_MKNEW:
470 4 : io2->generic.in.file_attr = io->mknew.in.attrib;
471 4 : io2->generic.in.fname = io->mknew.in.fname;
472 4 : io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
473 4 : io2->generic.in.access_mask =
474 : SEC_RIGHTS_FILE_READ |
475 : SEC_RIGHTS_FILE_WRITE;
476 4 : io2->generic.in.share_access =
477 : NTCREATEX_SHARE_ACCESS_READ |
478 : NTCREATEX_SHARE_ACCESS_WRITE;
479 4 : status = ntvfs->ops->open_fn(ntvfs, req, io2);
480 4 : break;
481 :
482 4 : case RAW_OPEN_CREATE:
483 4 : io2->generic.in.file_attr = io->mknew.in.attrib;
484 4 : io2->generic.in.fname = io->mknew.in.fname;
485 4 : io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
486 4 : io2->generic.in.access_mask =
487 : SEC_RIGHTS_FILE_READ |
488 : SEC_RIGHTS_FILE_WRITE;
489 4 : io2->generic.in.share_access =
490 : NTCREATEX_SHARE_ACCESS_READ |
491 : NTCREATEX_SHARE_ACCESS_WRITE;
492 4 : status = ntvfs->ops->open_fn(ntvfs, req, io2);
493 4 : break;
494 :
495 4 : case RAW_OPEN_CTEMP:
496 4 : io2->generic.in.file_attr = io->ctemp.in.attrib;
497 4 : io2->generic.in.fname =
498 4 : talloc_asprintf(io2, "%s\\SRV%s",
499 : io->ctemp.in.directory,
500 : generate_random_str_list(io2, 5, "0123456789"));
501 4 : io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
502 4 : io2->generic.in.access_mask =
503 : SEC_RIGHTS_FILE_READ |
504 : SEC_RIGHTS_FILE_WRITE;
505 4 : io2->generic.in.share_access =
506 : NTCREATEX_SHARE_ACCESS_READ |
507 : NTCREATEX_SHARE_ACCESS_WRITE;
508 4 : status = ntvfs->ops->open_fn(ntvfs, req, io2);
509 4 : break;
510 208575 : case RAW_OPEN_SMB2:
511 208575 : switch (io->smb2.in.oplock_level) {
512 70 : case SMB2_OPLOCK_LEVEL_BATCH:
513 70 : io2->generic.in.flags = NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK |
514 : NTCREATEX_FLAGS_REQUEST_OPLOCK;
515 70 : break;
516 26 : case SMB2_OPLOCK_LEVEL_EXCLUSIVE:
517 26 : io2->generic.in.flags = NTCREATEX_FLAGS_REQUEST_OPLOCK;
518 26 : break;
519 208479 : default:
520 208479 : io2->generic.in.flags = 0;
521 208479 : break;
522 : }
523 208575 : io2->generic.in.root_fid.fnum = 0;
524 208575 : io2->generic.in.access_mask = io->smb2.in.desired_access;
525 208575 : io2->generic.in.alloc_size = io->smb2.in.alloc_size;
526 208575 : io2->generic.in.file_attr = io->smb2.in.file_attributes;
527 208575 : io2->generic.in.share_access = io->smb2.in.share_access;
528 208575 : io2->generic.in.open_disposition= io->smb2.in.create_disposition;
529 208575 : io2->generic.in.create_options = io->smb2.in.create_options;
530 208575 : io2->generic.in.impersonation = io->smb2.in.impersonation_level;
531 208575 : io2->generic.in.security_flags = 0;
532 208575 : io2->generic.in.fname = io->smb2.in.fname;
533 208575 : io2->generic.in.sec_desc = io->smb2.in.sec_desc;
534 208575 : io2->generic.in.ea_list = &io->smb2.in.eas;
535 208575 : io2->generic.in.query_maximal_access = io->smb2.in.query_maximal_access;
536 208575 : io2->generic.in.query_on_disk_id = io->smb2.in.query_on_disk_id;
537 208575 : io2->generic.in.private_flags = 0;
538 :
539 : /* we don't support timewarp yet */
540 208575 : if (io->smb2.in.timewarp != 0) {
541 1 : status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
542 1 : break;
543 : }
544 :
545 : /* we need to check these bits before we check the private mask */
546 208574 : if (io2->generic.in.create_options & SMB2_CREATE_OPTIONS_NOT_SUPPORTED_MASK) {
547 2 : DEBUG(2,(__location__ " create_options 0x%x not supported\n",
548 : io2->generic.in.create_options));
549 2 : status = NT_STATUS_NOT_SUPPORTED;
550 2 : break;
551 : }
552 :
553 : /* TODO: find out why only SMB2 ignores these */
554 208572 : io2->generic.in.create_options &= ~NTCREATEX_OPTIONS_SYNC_ALERT;
555 208572 : io2->generic.in.create_options &= ~NTCREATEX_OPTIONS_ASYNC_ALERT;
556 :
557 208572 : status = ntvfs->ops->open_fn(ntvfs, req, io2);
558 208572 : break;
559 :
560 0 : default:
561 0 : status = NT_STATUS_INVALID_LEVEL;
562 0 : break;
563 : }
564 217211 : done:
565 217211 : return ntvfs_map_async_finish(req, status);
566 : }
567 :
568 :
569 : /*
570 : NTVFS any to fsinfo mapper
571 : */
572 0 : static NTSTATUS ntvfs_map_fsinfo_finish(struct ntvfs_module_context *ntvfs,
573 : struct ntvfs_request *req,
574 : union smb_fsinfo *fs,
575 : union smb_fsinfo *fs2,
576 : NTSTATUS status)
577 : {
578 0 : if (!NT_STATUS_IS_OK(status)) {
579 0 : return status;
580 : }
581 :
582 : /* and convert it to the required level */
583 0 : switch (fs->generic.level) {
584 0 : case RAW_QFS_DSKATTR: {
585 : /* map from generic to DSKATTR */
586 0 : unsigned int bpunit = 64;
587 :
588 : /* we need to scale the sizes to fit */
589 0 : for (bpunit=64; bpunit<0x10000; bpunit *= 2) {
590 0 : if (fs2->generic.out.blocks_total * (double)fs2->generic.out.block_size < bpunit * 512 * 65535.0) {
591 0 : break;
592 : }
593 : }
594 :
595 0 : fs->dskattr.out.blocks_per_unit = bpunit;
596 0 : fs->dskattr.out.block_size = 512;
597 0 : fs->dskattr.out.units_total =
598 0 : (fs2->generic.out.blocks_total * (double)fs2->generic.out.block_size) / (bpunit * 512);
599 0 : fs->dskattr.out.units_free =
600 0 : (fs2->generic.out.blocks_free * (double)fs2->generic.out.block_size) / (bpunit * 512);
601 :
602 : /* we must return a maximum of 2G to old DOS systems, or they get very confused */
603 0 : if (bpunit > 64 && req->ctx->protocol <= PROTOCOL_LANMAN2) {
604 0 : fs->dskattr.out.blocks_per_unit = 64;
605 0 : fs->dskattr.out.units_total = 0xFFFF;
606 0 : fs->dskattr.out.units_free = 0xFFFF;
607 : }
608 0 : return NT_STATUS_OK;
609 : }
610 :
611 0 : case RAW_QFS_ALLOCATION:
612 0 : fs->allocation.out.fs_id = fs2->generic.out.fs_id;
613 0 : fs->allocation.out.total_alloc_units = fs2->generic.out.blocks_total;
614 0 : fs->allocation.out.avail_alloc_units = fs2->generic.out.blocks_free;
615 0 : fs->allocation.out.sectors_per_unit = 1;
616 0 : fs->allocation.out.bytes_per_sector = fs2->generic.out.block_size;
617 0 : return NT_STATUS_OK;
618 :
619 0 : case RAW_QFS_VOLUME:
620 0 : fs->volume.out.serial_number = fs2->generic.out.serial_number;
621 0 : fs->volume.out.volume_name.s = fs2->generic.out.volume_name;
622 0 : return NT_STATUS_OK;
623 :
624 0 : case RAW_QFS_VOLUME_INFO:
625 : case RAW_QFS_VOLUME_INFORMATION:
626 0 : fs->volume_info.out.create_time = fs2->generic.out.create_time;
627 0 : fs->volume_info.out.serial_number = fs2->generic.out.serial_number;
628 0 : fs->volume_info.out.volume_name.s = fs2->generic.out.volume_name;
629 0 : return NT_STATUS_OK;
630 :
631 0 : case RAW_QFS_SIZE_INFO:
632 : case RAW_QFS_SIZE_INFORMATION:
633 0 : fs->size_info.out.total_alloc_units = fs2->generic.out.blocks_total;
634 0 : fs->size_info.out.avail_alloc_units = fs2->generic.out.blocks_free;
635 0 : fs->size_info.out.sectors_per_unit = 1;
636 0 : fs->size_info.out.bytes_per_sector = fs2->generic.out.block_size;
637 0 : return NT_STATUS_OK;
638 :
639 0 : case RAW_QFS_DEVICE_INFO:
640 : case RAW_QFS_DEVICE_INFORMATION:
641 0 : fs->device_info.out.device_type = fs2->generic.out.device_type;
642 0 : fs->device_info.out.characteristics = fs2->generic.out.device_characteristics;
643 0 : return NT_STATUS_OK;
644 :
645 0 : case RAW_QFS_ATTRIBUTE_INFO:
646 : case RAW_QFS_ATTRIBUTE_INFORMATION:
647 0 : fs->attribute_info.out.fs_attr = fs2->generic.out.fs_attr;
648 0 : fs->attribute_info.out.max_file_component_length = fs2->generic.out.max_file_component_length;
649 0 : fs->attribute_info.out.fs_type.s = fs2->generic.out.fs_type;
650 0 : return NT_STATUS_OK;
651 :
652 0 : case RAW_QFS_QUOTA_INFORMATION:
653 0 : ZERO_STRUCT(fs->quota_information.out.unknown);
654 0 : fs->quota_information.out.quota_soft = fs2->generic.out.quota_soft;
655 0 : fs->quota_information.out.quota_hard = fs2->generic.out.quota_hard;
656 0 : fs->quota_information.out.quota_flags = fs2->generic.out.quota_flags;
657 0 : return NT_STATUS_OK;
658 :
659 0 : case RAW_QFS_FULL_SIZE_INFORMATION:
660 0 : fs->full_size_information.out.total_alloc_units = fs2->generic.out.blocks_total;
661 0 : fs->full_size_information.out.call_avail_alloc_units = fs2->generic.out.blocks_free;
662 0 : fs->full_size_information.out.actual_avail_alloc_units = fs2->generic.out.blocks_free;
663 0 : fs->full_size_information.out.sectors_per_unit = 1;
664 0 : fs->full_size_information.out.bytes_per_sector = fs2->generic.out.block_size;
665 0 : return NT_STATUS_OK;
666 :
667 0 : case RAW_QFS_OBJECTID_INFORMATION:
668 0 : fs->objectid_information.out.guid = fs2->generic.out.guid;
669 0 : ZERO_STRUCT(fs->objectid_information.out.unknown);
670 0 : return NT_STATUS_OK;
671 :
672 0 : case RAW_QFS_SECTOR_SIZE_INFORMATION:
673 0 : fs->sector_size_info.out.logical_bytes_per_sector
674 0 : = fs2->generic.out.block_size;
675 0 : fs->sector_size_info.out.phys_bytes_per_sector_atomic
676 0 : = fs2->generic.out.block_size;
677 0 : fs->sector_size_info.out.phys_bytes_per_sector_perf
678 0 : = fs2->generic.out.block_size;
679 0 : fs->sector_size_info.out.fs_effective_phys_bytes_per_sector_atomic
680 0 : = fs2->generic.out.block_size;
681 0 : fs->sector_size_info.out.flags
682 0 : = QFS_SSINFO_FLAGS_ALIGNED_DEVICE
683 : | QFS_SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE;
684 0 : fs->sector_size_info.out.byte_off_sector_align = 0;
685 0 : fs->sector_size_info.out.byte_off_partition_align = 0;
686 0 : return NT_STATUS_OK;
687 :
688 0 : case RAW_QFS_GENERIC:
689 : case RAW_QFS_UNIX_INFO:
690 0 : return NT_STATUS_INVALID_LEVEL;
691 : }
692 :
693 0 : return NT_STATUS_INVALID_LEVEL;
694 : }
695 :
696 : /*
697 : NTVFS fsinfo any to generic mapper
698 : */
699 0 : NTSTATUS ntvfs_map_fsinfo(struct ntvfs_module_context *ntvfs,
700 : struct ntvfs_request *req,
701 : union smb_fsinfo *fs)
702 : {
703 0 : NTSTATUS status;
704 0 : union smb_fsinfo *fs2;
705 :
706 0 : fs2 = talloc(req, union smb_fsinfo);
707 0 : if (fs2 == NULL) {
708 0 : return NT_STATUS_NO_MEMORY;
709 : }
710 :
711 0 : if (fs->generic.level == RAW_QFS_GENERIC) {
712 0 : return NT_STATUS_INVALID_LEVEL;
713 : }
714 :
715 0 : status = ntvfs_map_async_setup(ntvfs, req, fs, fs2,
716 : (second_stage_t)ntvfs_map_fsinfo_finish);
717 0 : if (!NT_STATUS_IS_OK(status)) {
718 0 : return status;
719 : }
720 :
721 : /* ask the backend for the generic info */
722 0 : fs2->generic.level = RAW_QFS_GENERIC;
723 :
724 0 : status = ntvfs->ops->fsinfo_fn(ntvfs, req, fs2);
725 0 : return ntvfs_map_async_finish(req, status);
726 : }
727 :
728 :
729 : /*
730 : NTVFS fileinfo generic to any mapper
731 : */
732 20 : NTSTATUS ntvfs_map_fileinfo(TALLOC_CTX *mem_ctx,
733 : union smb_fileinfo *info,
734 : union smb_fileinfo *info2)
735 : {
736 0 : int i;
737 : /* and convert it to the required level using results in info2 */
738 20 : switch (info->generic.level) {
739 0 : case RAW_FILEINFO_GETATTR:
740 0 : info->getattr.out.attrib = info2->generic.out.attrib & 0xff;
741 0 : info->getattr.out.size = info2->generic.out.size;
742 0 : info->getattr.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
743 0 : return NT_STATUS_OK;
744 :
745 1 : case RAW_FILEINFO_GETATTRE:
746 1 : info->getattre.out.attrib = info2->generic.out.attrib;
747 1 : info->getattre.out.size = info2->generic.out.size;
748 1 : info->getattre.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
749 1 : info->getattre.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
750 1 : info->getattre.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
751 1 : info->getattre.out.alloc_size = info2->generic.out.alloc_size;
752 1 : return NT_STATUS_OK;
753 :
754 0 : case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
755 0 : info->network_open_information.out.create_time = info2->generic.out.create_time;
756 0 : info->network_open_information.out.access_time = info2->generic.out.access_time;
757 0 : info->network_open_information.out.write_time = info2->generic.out.write_time;
758 0 : info->network_open_information.out.change_time = info2->generic.out.change_time;
759 0 : info->network_open_information.out.alloc_size = info2->generic.out.alloc_size;
760 0 : info->network_open_information.out.size = info2->generic.out.size;
761 0 : info->network_open_information.out.attrib = info2->generic.out.attrib;
762 0 : return NT_STATUS_OK;
763 :
764 2 : case RAW_FILEINFO_ALL_INFO:
765 : case RAW_FILEINFO_ALL_INFORMATION:
766 2 : info->all_info.out.create_time = info2->generic.out.create_time;
767 2 : info->all_info.out.access_time = info2->generic.out.access_time;
768 2 : info->all_info.out.write_time = info2->generic.out.write_time;
769 2 : info->all_info.out.change_time = info2->generic.out.change_time;
770 2 : info->all_info.out.attrib = info2->generic.out.attrib;
771 2 : info->all_info.out.alloc_size = info2->generic.out.alloc_size;
772 2 : info->all_info.out.size = info2->generic.out.size;
773 2 : info->all_info.out.nlink = info2->generic.out.nlink;
774 2 : info->all_info.out.delete_pending = info2->generic.out.delete_pending;
775 2 : info->all_info.out.directory = info2->generic.out.directory;
776 2 : info->all_info.out.ea_size = info2->generic.out.ea_size;
777 2 : info->all_info.out.fname.s = info2->generic.out.fname.s;
778 2 : info->all_info.out.fname.private_length = info2->generic.out.fname.private_length;
779 2 : return NT_STATUS_OK;
780 :
781 2 : case RAW_FILEINFO_BASIC_INFO:
782 : case RAW_FILEINFO_BASIC_INFORMATION:
783 2 : info->basic_info.out.create_time = info2->generic.out.create_time;
784 2 : info->basic_info.out.access_time = info2->generic.out.access_time;
785 2 : info->basic_info.out.write_time = info2->generic.out.write_time;
786 2 : info->basic_info.out.change_time = info2->generic.out.change_time;
787 2 : info->basic_info.out.attrib = info2->generic.out.attrib;
788 2 : return NT_STATUS_OK;
789 :
790 1 : case RAW_FILEINFO_STANDARD:
791 1 : info->standard.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
792 1 : info->standard.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
793 1 : info->standard.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
794 1 : info->standard.out.size = info2->generic.out.size;
795 1 : info->standard.out.alloc_size = info2->generic.out.alloc_size;
796 1 : info->standard.out.attrib = info2->generic.out.attrib;
797 1 : return NT_STATUS_OK;
798 :
799 1 : case RAW_FILEINFO_EA_SIZE:
800 1 : info->ea_size.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
801 1 : info->ea_size.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
802 1 : info->ea_size.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
803 1 : info->ea_size.out.size = info2->generic.out.size;
804 1 : info->ea_size.out.alloc_size = info2->generic.out.alloc_size;
805 1 : info->ea_size.out.attrib = info2->generic.out.attrib;
806 1 : info->ea_size.out.ea_size = info2->generic.out.ea_size;
807 1 : return NT_STATUS_OK;
808 :
809 2 : case RAW_FILEINFO_STANDARD_INFO:
810 : case RAW_FILEINFO_STANDARD_INFORMATION:
811 2 : info->standard_info.out.alloc_size = info2->generic.out.alloc_size;
812 2 : info->standard_info.out.size = info2->generic.out.size;
813 2 : info->standard_info.out.nlink = info2->generic.out.nlink;
814 2 : info->standard_info.out.delete_pending = info2->generic.out.delete_pending;
815 2 : info->standard_info.out.directory = info2->generic.out.directory;
816 2 : return NT_STATUS_OK;
817 :
818 1 : case RAW_FILEINFO_INTERNAL_INFORMATION:
819 1 : info->internal_information.out.file_id = info2->generic.out.file_id;
820 1 : return NT_STATUS_OK;
821 :
822 2 : case RAW_FILEINFO_EA_INFO:
823 : case RAW_FILEINFO_EA_INFORMATION:
824 2 : info->ea_info.out.ea_size = info2->generic.out.ea_size;
825 2 : return NT_STATUS_OK;
826 :
827 0 : case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
828 0 : info->attribute_tag_information.out.attrib = info2->generic.out.attrib;
829 0 : info->attribute_tag_information.out.reparse_tag = info2->generic.out.reparse_tag;
830 0 : return NT_STATUS_OK;
831 :
832 0 : case RAW_FILEINFO_STREAM_INFO:
833 : case RAW_FILEINFO_STREAM_INFORMATION:
834 0 : info->stream_info.out.num_streams = info2->generic.out.num_streams;
835 0 : if (info->stream_info.out.num_streams > 0) {
836 0 : info->stream_info.out.streams =
837 0 : talloc_array(mem_ctx,
838 : struct stream_struct,
839 : info->stream_info.out.num_streams);
840 0 : if (!info->stream_info.out.streams) {
841 0 : DEBUG(2,("ntvfs_map_fileinfo: no memory for %d streams\n",
842 : info->stream_info.out.num_streams));
843 0 : return NT_STATUS_NO_MEMORY;
844 : }
845 0 : for (i=0; i < info->stream_info.out.num_streams; i++) {
846 0 : info->stream_info.out.streams[i] = info2->generic.out.streams[i];
847 0 : info->stream_info.out.streams[i].stream_name.s =
848 0 : talloc_strdup(info->stream_info.out.streams,
849 0 : info2->generic.out.streams[i].stream_name.s);
850 0 : if (!info->stream_info.out.streams[i].stream_name.s) {
851 0 : DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
852 0 : return NT_STATUS_NO_MEMORY;
853 : }
854 : }
855 : }
856 0 : return NT_STATUS_OK;
857 :
858 2 : case RAW_FILEINFO_NAME_INFO:
859 : case RAW_FILEINFO_NAME_INFORMATION:
860 2 : info->name_info.out.fname.s = talloc_strdup(mem_ctx, info2->generic.out.fname.s);
861 2 : NT_STATUS_HAVE_NO_MEMORY(info->name_info.out.fname.s);
862 2 : info->name_info.out.fname.private_length = info2->generic.out.fname.private_length;
863 2 : return NT_STATUS_OK;
864 :
865 0 : case RAW_FILEINFO_ALT_NAME_INFO:
866 : case RAW_FILEINFO_ALT_NAME_INFORMATION:
867 : case RAW_FILEINFO_SMB2_ALT_NAME_INFORMATION:
868 0 : info->alt_name_info.out.fname.s = talloc_strdup(mem_ctx, info2->generic.out.alt_fname.s);
869 0 : NT_STATUS_HAVE_NO_MEMORY(info->alt_name_info.out.fname.s);
870 0 : info->alt_name_info.out.fname.private_length = info2->generic.out.alt_fname.private_length;
871 0 : return NT_STATUS_OK;
872 :
873 1 : case RAW_FILEINFO_POSITION_INFORMATION:
874 1 : info->position_information.out.position = info2->generic.out.position;
875 1 : return NT_STATUS_OK;
876 :
877 0 : case RAW_FILEINFO_ALL_EAS:
878 0 : info->all_eas.out.num_eas = info2->generic.out.num_eas;
879 0 : if (info->all_eas.out.num_eas > 0) {
880 0 : info->all_eas.out.eas = talloc_array(mem_ctx,
881 : struct ea_struct,
882 : info->all_eas.out.num_eas);
883 0 : if (!info->all_eas.out.eas) {
884 0 : DEBUG(2,("ntvfs_map_fileinfo: no memory for %d eas\n",
885 : info->all_eas.out.num_eas));
886 0 : return NT_STATUS_NO_MEMORY;
887 : }
888 0 : for (i = 0; i < info->all_eas.out.num_eas; i++) {
889 0 : info->all_eas.out.eas[i] = info2->generic.out.eas[i];
890 0 : info->all_eas.out.eas[i].name.s =
891 0 : talloc_strdup(info->all_eas.out.eas,
892 0 : info2->generic.out.eas[i].name.s);
893 0 : if (!info->all_eas.out.eas[i].name.s) {
894 0 : DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
895 0 : return NT_STATUS_NO_MEMORY;
896 : }
897 0 : info->all_eas.out.eas[i].value.data =
898 0 : (uint8_t *)talloc_memdup(info->all_eas.out.eas,
899 : info2->generic.out.eas[i].value.data,
900 : info2->generic.out.eas[i].value.length);
901 0 : if (!info->all_eas.out.eas[i].value.data) {
902 0 : DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
903 0 : return NT_STATUS_NO_MEMORY;
904 : }
905 : }
906 : }
907 0 : return NT_STATUS_OK;
908 :
909 0 : case RAW_FILEINFO_IS_NAME_VALID:
910 0 : return NT_STATUS_OK;
911 :
912 0 : case RAW_FILEINFO_COMPRESSION_INFO:
913 : case RAW_FILEINFO_COMPRESSION_INFORMATION:
914 0 : info->compression_info.out.compressed_size = info2->generic.out.compressed_size;
915 0 : info->compression_info.out.format = info2->generic.out.format;
916 0 : info->compression_info.out.unit_shift = info2->generic.out.unit_shift;
917 0 : info->compression_info.out.chunk_shift = info2->generic.out.chunk_shift;
918 0 : info->compression_info.out.cluster_shift = info2->generic.out.cluster_shift;
919 0 : return NT_STATUS_OK;
920 :
921 1 : case RAW_FILEINFO_ACCESS_INFORMATION:
922 1 : info->access_information.out.access_flags = info2->generic.out.access_flags;
923 1 : return NT_STATUS_OK;
924 :
925 1 : case RAW_FILEINFO_MODE_INFORMATION:
926 1 : info->mode_information.out.mode = info2->generic.out.mode;
927 1 : return NT_STATUS_OK;
928 :
929 1 : case RAW_FILEINFO_ALIGNMENT_INFORMATION:
930 1 : info->alignment_information.out.alignment_requirement =
931 1 : info2->generic.out.alignment_requirement;
932 1 : return NT_STATUS_OK;
933 1 : case RAW_FILEINFO_UNIX_BASIC:
934 : #if 1
935 1 : return NT_STATUS_INVALID_LEVEL;
936 : #else
937 : info->unix_basic_info.out.end_of_file = info2->generic.out.end_of_file;
938 : info->unix_basic_info.out.num_bytes = info2->generic.out.size;
939 : info->unix_basic_info.out.status_change_time = info2->generic.out.change_time;
940 : info->unix_basic_info.out.access_time = info2->generic.out.access_time;
941 : info->unix_basic_info.out.change_time = info2->generic.out.change_time;
942 : info->unix_basic_info.out.uid = info2->generic.out.uid;
943 : info->unix_basic_info.out.gid = info2->generic.out.gid;
944 : info->unix_basic_info.out.file_type = info2->generic.out.file_type;
945 : info->unix_basic_info.out.dev_major = info2->generic.out.device;
946 : info->unix_basic_info.out.dev_minor = info2->generic.out.device;
947 : info->unix_basic_info.out.unique_id = info2->generic.out.inode;
948 : info->unix_basic_info.out.permissions = info2->generic.out.permissions;
949 : info->unix_basic_info.out.nlink = info2->generic.out.nlink;
950 : return NT_STATUS_OK;
951 : #endif
952 1 : case RAW_FILEINFO_UNIX_LINK:
953 : #if 1
954 1 : return NT_STATUS_INVALID_LEVEL;
955 : #else
956 : info->unix_link_info.out.link_dest = info2->generic.out.link_dest;
957 : return NT_STATUS_OK;
958 : #endif
959 0 : case RAW_FILEINFO_GENERIC:
960 : case RAW_FILEINFO_SEC_DESC:
961 : case RAW_FILEINFO_EA_LIST:
962 : case RAW_FILEINFO_UNIX_INFO2:
963 : case RAW_FILEINFO_SMB2_ALL_EAS:
964 : case RAW_FILEINFO_SMB2_ALL_INFORMATION:
965 0 : return NT_STATUS_INVALID_LEVEL;
966 0 : case RAW_FILEINFO_NORMALIZED_NAME_INFORMATION:
967 0 : return NT_STATUS_NOT_SUPPORTED;
968 : }
969 :
970 0 : return NT_STATUS_INVALID_LEVEL;
971 : }
972 :
973 : /*
974 : NTVFS any to fileinfo mapper
975 : */
976 20 : static NTSTATUS ntvfs_map_qfileinfo_finish(struct ntvfs_module_context *ntvfs,
977 : struct ntvfs_request *req,
978 : union smb_fileinfo *info,
979 : union smb_fileinfo *info2,
980 : NTSTATUS status)
981 : {
982 20 : if (!NT_STATUS_IS_OK(status)) {
983 0 : return status;
984 : }
985 :
986 20 : return ntvfs_map_fileinfo(req, info, info2);
987 : }
988 :
989 : /*
990 : NTVFS fileinfo generic to any mapper
991 : */
992 20 : NTSTATUS ntvfs_map_qfileinfo(struct ntvfs_module_context *ntvfs,
993 : struct ntvfs_request *req,
994 : union smb_fileinfo *info)
995 : {
996 0 : NTSTATUS status;
997 0 : union smb_fileinfo *info2;
998 :
999 20 : info2 = talloc(req, union smb_fileinfo);
1000 20 : if (info2 == NULL) {
1001 0 : return NT_STATUS_NO_MEMORY;
1002 : }
1003 :
1004 20 : if (info->generic.level == RAW_FILEINFO_GENERIC) {
1005 0 : return NT_STATUS_INVALID_LEVEL;
1006 : }
1007 :
1008 20 : status = ntvfs_map_async_setup(ntvfs, req, info, info2,
1009 : (second_stage_t)ntvfs_map_qfileinfo_finish);
1010 20 : if (!NT_STATUS_IS_OK(status)) {
1011 0 : return status;
1012 : }
1013 :
1014 : /* ask the backend for the generic info */
1015 20 : info2->generic.level = RAW_FILEINFO_GENERIC;
1016 20 : info2->generic.in.file.ntvfs= info->generic.in.file.ntvfs;
1017 :
1018 20 : status = ntvfs->ops->qfileinfo_fn(ntvfs, req, info2);
1019 20 : return ntvfs_map_async_finish(req, status);
1020 : }
1021 :
1022 : /*
1023 : NTVFS any to fileinfo mapper
1024 : */
1025 29 : static NTSTATUS ntvfs_map_qpathinfo_finish(struct ntvfs_module_context *ntvfs,
1026 : struct ntvfs_request *req,
1027 : union smb_fileinfo *info,
1028 : union smb_fileinfo *info2,
1029 : NTSTATUS status)
1030 : {
1031 29 : if (!NT_STATUS_IS_OK(status)) {
1032 29 : return status;
1033 : }
1034 :
1035 0 : return ntvfs_map_fileinfo(req, info, info2);
1036 : }
1037 :
1038 : /*
1039 : NTVFS pathinfo generic to any mapper
1040 : */
1041 29 : NTSTATUS ntvfs_map_qpathinfo(struct ntvfs_module_context *ntvfs,
1042 : struct ntvfs_request *req,
1043 : union smb_fileinfo *info)
1044 : {
1045 0 : NTSTATUS status;
1046 0 : union smb_fileinfo *info2;
1047 :
1048 29 : info2 = talloc(req, union smb_fileinfo);
1049 29 : if (info2 == NULL) {
1050 0 : return NT_STATUS_NO_MEMORY;
1051 : }
1052 :
1053 29 : if (info->generic.level == RAW_FILEINFO_GENERIC) {
1054 0 : return NT_STATUS_INVALID_LEVEL;
1055 : }
1056 :
1057 29 : status = ntvfs_map_async_setup(ntvfs, req, info, info2,
1058 : (second_stage_t)ntvfs_map_qpathinfo_finish);
1059 29 : if (!NT_STATUS_IS_OK(status)) {
1060 0 : return status;
1061 : }
1062 :
1063 : /* ask the backend for the generic info */
1064 29 : info2->generic.level = RAW_FILEINFO_GENERIC;
1065 29 : info2->generic.in.file.path = info->generic.in.file.path;
1066 :
1067 29 : status = ntvfs->ops->qpathinfo_fn(ntvfs, req, info2);
1068 29 : return ntvfs_map_async_finish(req, status);
1069 : }
1070 :
1071 :
1072 : /*
1073 : NTVFS lock generic to any mapper
1074 : */
1075 462 : NTSTATUS ntvfs_map_lock(struct ntvfs_module_context *ntvfs,
1076 : struct ntvfs_request *req,
1077 : union smb_lock *lck)
1078 : {
1079 0 : union smb_lock *lck2;
1080 0 : struct smb_lock_entry *locks;
1081 :
1082 462 : lck2 = talloc(req, union smb_lock);
1083 462 : if (lck2 == NULL) {
1084 0 : return NT_STATUS_NO_MEMORY;
1085 : }
1086 :
1087 462 : locks = talloc_array(lck2, struct smb_lock_entry, 1);
1088 462 : if (locks == NULL) {
1089 0 : return NT_STATUS_NO_MEMORY;
1090 : }
1091 :
1092 462 : switch (lck->generic.level) {
1093 0 : case RAW_LOCK_LOCKX:
1094 9 : return NT_STATUS_INVALID_LEVEL;
1095 :
1096 23 : case RAW_LOCK_LOCK:
1097 23 : lck2->generic.level = RAW_LOCK_GENERIC;
1098 23 : lck2->generic.in.file.ntvfs= lck->lock.in.file.ntvfs;
1099 23 : lck2->generic.in.mode = 0;
1100 23 : lck2->generic.in.timeout = 0;
1101 23 : lck2->generic.in.ulock_cnt = 0;
1102 23 : lck2->generic.in.lock_cnt = 1;
1103 23 : lck2->generic.in.locks = locks;
1104 23 : locks->pid = req->smbpid;
1105 23 : locks->offset = lck->lock.in.offset;
1106 23 : locks->count = lck->lock.in.count;
1107 453 : break;
1108 :
1109 16 : case RAW_LOCK_UNLOCK:
1110 16 : lck2->generic.level = RAW_LOCK_GENERIC;
1111 16 : lck2->generic.in.file.ntvfs= lck->unlock.in.file.ntvfs;
1112 16 : lck2->generic.in.mode = 0;
1113 16 : lck2->generic.in.timeout = 0;
1114 16 : lck2->generic.in.ulock_cnt = 1;
1115 16 : lck2->generic.in.lock_cnt = 0;
1116 16 : lck2->generic.in.locks = locks;
1117 16 : locks->pid = req->smbpid;
1118 16 : locks->offset = lck->unlock.in.offset;
1119 16 : locks->count = lck->unlock.in.count;
1120 16 : break;
1121 :
1122 381 : case RAW_LOCK_SMB2: {
1123 : /* this is only approximate! We need to change the
1124 : generic structure to fix this properly */
1125 0 : int i;
1126 0 : bool isunlock;
1127 381 : if (lck->smb2.in.lock_count < 1) {
1128 0 : return NT_STATUS_INVALID_PARAMETER;
1129 : }
1130 :
1131 381 : lck2->generic.level = RAW_LOCK_GENERIC;
1132 381 : lck2->generic.in.file.ntvfs= lck->smb2.in.file.ntvfs;
1133 381 : lck2->generic.in.timeout = UINT32_MAX;
1134 381 : lck2->generic.in.mode = 0;
1135 381 : lck2->generic.in.lock_cnt = 0;
1136 381 : lck2->generic.in.ulock_cnt = 0;
1137 381 : lck2->generic.in.locks = talloc_zero_array(lck2, struct smb_lock_entry,
1138 : lck->smb2.in.lock_count);
1139 381 : if (lck2->generic.in.locks == NULL) {
1140 0 : return NT_STATUS_NO_MEMORY;
1141 : }
1142 : /* only the first lock gives the UNLOCK bit - see
1143 : MS-SMB2 3.3.5.14 */
1144 381 : if (lck->smb2.in.locks[0].flags & SMB2_LOCK_FLAG_UNLOCK) {
1145 136 : if (lck->smb2.in.locks[0].flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) {
1146 1 : return NT_STATUS_INVALID_PARAMETER;
1147 : }
1148 135 : lck2->generic.in.ulock_cnt = lck->smb2.in.lock_count;
1149 135 : isunlock = true;
1150 : } else {
1151 245 : lck2->generic.in.lock_cnt = lck->smb2.in.lock_count;
1152 245 : isunlock = false;
1153 : }
1154 759 : for (i=0;i<lck->smb2.in.lock_count;i++) {
1155 387 : if (!isunlock &&
1156 248 : lck->smb2.in.locks[i].flags == SMB2_LOCK_FLAG_NONE) {
1157 2 : return NT_STATUS_INVALID_PARAMETER;
1158 : }
1159 :
1160 385 : if (lck->smb2.in.locks[i].flags & ~SMB2_LOCK_FLAG_ALL_MASK) {
1161 1 : return NT_STATUS_INVALID_PARAMETER;
1162 : }
1163 :
1164 384 : if (isunlock &&
1165 139 : (lck->smb2.in.locks[i].flags &
1166 : (SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_EXCLUSIVE))) {
1167 5 : return NT_STATUS_INVALID_PARAMETER;
1168 : }
1169 379 : if (!isunlock &&
1170 245 : (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_UNLOCK)) {
1171 0 : return NT_STATUS_INVALID_PARAMETER;
1172 : }
1173 379 : lck2->generic.in.locks[i].pid = req->smbpid;
1174 379 : lck2->generic.in.locks[i].offset = lck->smb2.in.locks[i].offset;
1175 379 : lck2->generic.in.locks[i].count = lck->smb2.in.locks[i].length;
1176 379 : if (!(lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_EXCLUSIVE)) {
1177 167 : lck2->generic.in.mode = LOCKING_ANDX_SHARED_LOCK;
1178 : }
1179 379 : if (lck->smb2.in.locks[i].flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) {
1180 224 : lck2->generic.in.timeout = 0;
1181 : }
1182 : }
1183 : /* initialize output value */
1184 372 : lck->smb2.out.reserved = 0;
1185 372 : break;
1186 : }
1187 :
1188 42 : case RAW_LOCK_SMB2_BREAK:
1189 42 : lck2->generic.level = RAW_LOCK_GENERIC;
1190 42 : lck2->generic.in.file.ntvfs = lck->smb2_break.in.file.ntvfs;
1191 42 : lck2->generic.in.mode = LOCKING_ANDX_OPLOCK_RELEASE |
1192 42 : ((lck->smb2_break.in.oplock_level << 8) & 0xFF00);
1193 42 : lck2->generic.in.timeout = 0;
1194 42 : lck2->generic.in.ulock_cnt = 0;
1195 42 : lck2->generic.in.lock_cnt = 0;
1196 42 : lck2->generic.in.locks = NULL;
1197 :
1198 : /* initialize output value */
1199 42 : lck->smb2_break.out.oplock_level= lck->smb2_break.in.oplock_level;
1200 42 : lck->smb2_break.out.reserved = lck->smb2_break.in.reserved;
1201 42 : lck->smb2_break.out.reserved2 = lck->smb2_break.in.reserved2;
1202 42 : lck->smb2_break.out.file = lck->smb2_break.in.file;
1203 42 : break;
1204 : }
1205 :
1206 : /*
1207 : * we don't need to call ntvfs_map_async_setup() here,
1208 : * as lock() doesn't have any output fields
1209 : */
1210 :
1211 453 : return ntvfs->ops->lock_fn(ntvfs, req, lck2);
1212 : }
1213 :
1214 :
1215 : /*
1216 : NTVFS write generic to any mapper
1217 : */
1218 1852 : static NTSTATUS ntvfs_map_write_finish(struct ntvfs_module_context *ntvfs,
1219 : struct ntvfs_request *req,
1220 : union smb_write *wr,
1221 : union smb_write *wr2,
1222 : NTSTATUS status)
1223 : {
1224 0 : union smb_lock *lck;
1225 0 : union smb_close *cl;
1226 0 : unsigned int state;
1227 :
1228 1852 : if (NT_STATUS_IS_ERR(status)) {
1229 45 : return status;
1230 : }
1231 :
1232 1807 : switch (wr->generic.level) {
1233 16 : case RAW_WRITE_WRITE:
1234 16 : wr->write.out.nwritten = wr2->generic.out.nwritten;
1235 16 : break;
1236 :
1237 6 : case RAW_WRITE_WRITEUNLOCK:
1238 6 : wr->writeunlock.out.nwritten = wr2->generic.out.nwritten;
1239 :
1240 6 : lck = talloc(wr2, union smb_lock);
1241 6 : if (lck == NULL) {
1242 0 : return NT_STATUS_NO_MEMORY;
1243 : }
1244 :
1245 6 : lck->unlock.level = RAW_LOCK_UNLOCK;
1246 6 : lck->unlock.in.file.ntvfs = wr->writeunlock.in.file.ntvfs;
1247 6 : lck->unlock.in.count = wr->writeunlock.in.count;
1248 6 : lck->unlock.in.offset = wr->writeunlock.in.offset;
1249 :
1250 6 : if (lck->unlock.in.count != 0) {
1251 : /* do the lock sync for now */
1252 5 : state = req->async_states->state;
1253 5 : req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
1254 5 : status = ntvfs->ops->lock_fn(ntvfs, req, lck);
1255 5 : req->async_states->state = state;
1256 : }
1257 6 : break;
1258 :
1259 6 : case RAW_WRITE_WRITECLOSE:
1260 6 : wr->writeclose.out.nwritten = wr2->generic.out.nwritten;
1261 :
1262 6 : cl = talloc(wr2, union smb_close);
1263 6 : if (cl == NULL) {
1264 0 : return NT_STATUS_NO_MEMORY;
1265 : }
1266 :
1267 6 : cl->close.level = RAW_CLOSE_CLOSE;
1268 6 : cl->close.in.file.ntvfs = wr->writeclose.in.file.ntvfs;
1269 6 : cl->close.in.write_time = wr->writeclose.in.mtime;
1270 :
1271 6 : if (wr2->generic.in.count != 0) {
1272 : /* do the close sync for now */
1273 4 : state = req->async_states->state;
1274 4 : req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
1275 4 : status = ntvfs->ops->close_fn(ntvfs, req, cl);
1276 4 : req->async_states->state = state;
1277 : }
1278 6 : break;
1279 :
1280 0 : case RAW_WRITE_SPLWRITE:
1281 0 : break;
1282 :
1283 1779 : case RAW_WRITE_SMB2:
1284 1779 : wr->smb2.out._pad = 0;
1285 1779 : wr->smb2.out.nwritten = wr2->generic.out.nwritten;
1286 1779 : wr->smb2.out.unknown1 = 0;
1287 1779 : break;
1288 :
1289 0 : default:
1290 0 : return NT_STATUS_INVALID_LEVEL;
1291 : }
1292 :
1293 1807 : return status;
1294 : }
1295 :
1296 :
1297 : /*
1298 : NTVFS write generic to any mapper
1299 : */
1300 1852 : NTSTATUS ntvfs_map_write(struct ntvfs_module_context *ntvfs,
1301 : struct ntvfs_request *req,
1302 : union smb_write *wr)
1303 : {
1304 0 : union smb_write *wr2;
1305 0 : NTSTATUS status;
1306 :
1307 1852 : wr2 = talloc(req, union smb_write);
1308 1852 : if (wr2 == NULL) {
1309 0 : return NT_STATUS_NO_MEMORY;
1310 : }
1311 :
1312 1852 : status = ntvfs_map_async_setup(ntvfs, req, wr, wr2,
1313 : (second_stage_t)ntvfs_map_write_finish);
1314 1852 : if (!NT_STATUS_IS_OK(status)) {
1315 0 : return status;
1316 : }
1317 :
1318 1852 : wr2->writex.level = RAW_WRITE_GENERIC;
1319 :
1320 1852 : switch (wr->generic.level) {
1321 0 : case RAW_WRITE_WRITEX:
1322 0 : status = NT_STATUS_INVALID_LEVEL;
1323 29 : break;
1324 :
1325 17 : case RAW_WRITE_WRITE:
1326 17 : wr2->writex.in.file.ntvfs= wr->write.in.file.ntvfs;
1327 17 : wr2->writex.in.offset = wr->write.in.offset;
1328 17 : wr2->writex.in.wmode = 0;
1329 17 : wr2->writex.in.remaining = wr->write.in.remaining;
1330 17 : wr2->writex.in.count = wr->write.in.count;
1331 17 : wr2->writex.in.data = wr->write.in.data;
1332 17 : status = ntvfs->ops->write_fn(ntvfs, req, wr2);
1333 17 : break;
1334 :
1335 6 : case RAW_WRITE_WRITEUNLOCK:
1336 6 : wr2->writex.in.file.ntvfs= wr->writeunlock.in.file.ntvfs;
1337 6 : wr2->writex.in.offset = wr->writeunlock.in.offset;
1338 6 : wr2->writex.in.wmode = 0;
1339 6 : wr2->writex.in.remaining = wr->writeunlock.in.remaining;
1340 6 : wr2->writex.in.count = wr->writeunlock.in.count;
1341 6 : wr2->writex.in.data = wr->writeunlock.in.data;
1342 6 : status = ntvfs->ops->write_fn(ntvfs, req, wr2);
1343 6 : break;
1344 :
1345 6 : case RAW_WRITE_WRITECLOSE:
1346 6 : wr2->writex.in.file.ntvfs= wr->writeclose.in.file.ntvfs;
1347 6 : wr2->writex.in.offset = wr->writeclose.in.offset;
1348 6 : wr2->writex.in.wmode = 0;
1349 6 : wr2->writex.in.remaining = 0;
1350 6 : wr2->writex.in.count = wr->writeclose.in.count;
1351 6 : wr2->writex.in.data = wr->writeclose.in.data;
1352 6 : status = ntvfs->ops->write_fn(ntvfs, req, wr2);
1353 6 : break;
1354 :
1355 0 : case RAW_WRITE_SPLWRITE:
1356 0 : wr2->writex.in.file.ntvfs= wr->splwrite.in.file.ntvfs;
1357 0 : wr2->writex.in.offset = 0;
1358 0 : wr2->writex.in.wmode = 0;
1359 0 : wr2->writex.in.remaining = 0;
1360 0 : wr2->writex.in.count = wr->splwrite.in.count;
1361 0 : wr2->writex.in.data = wr->splwrite.in.data;
1362 0 : status = ntvfs->ops->write_fn(ntvfs, req, wr2);
1363 0 : break;
1364 :
1365 1823 : case RAW_WRITE_SMB2:
1366 1823 : wr2->writex.in.file.ntvfs= wr->smb2.in.file.ntvfs;
1367 1823 : wr2->writex.in.offset = wr->smb2.in.offset;
1368 1823 : wr2->writex.in.wmode = 0;
1369 1823 : wr2->writex.in.remaining = 0;
1370 1823 : wr2->writex.in.count = wr->smb2.in.data.length;
1371 1823 : wr2->writex.in.data = wr->smb2.in.data.data;
1372 1823 : status = ntvfs->ops->write_fn(ntvfs, req, wr2);
1373 : }
1374 :
1375 1852 : return ntvfs_map_async_finish(req, status);
1376 : }
1377 :
1378 :
1379 : /*
1380 : NTVFS read generic to any mapper - finish the out mapping
1381 : */
1382 1647 : static NTSTATUS ntvfs_map_read_finish(struct ntvfs_module_context *ntvfs,
1383 : struct ntvfs_request *req,
1384 : union smb_read *rd,
1385 : union smb_read *rd2,
1386 : NTSTATUS status)
1387 : {
1388 1647 : switch (rd->generic.level) {
1389 7 : case RAW_READ_READ:
1390 7 : rd->read.out.nread = rd2->generic.out.nread;
1391 7 : break;
1392 11 : case RAW_READ_READBRAW:
1393 11 : rd->readbraw.out.nread = rd2->generic.out.nread;
1394 11 : break;
1395 12 : case RAW_READ_LOCKREAD:
1396 12 : rd->lockread.out.nread = rd2->generic.out.nread;
1397 12 : break;
1398 1617 : case RAW_READ_SMB2:
1399 1617 : rd->smb2.out.data.length= rd2->generic.out.nread;
1400 1617 : rd->smb2.out.remaining = 0;
1401 1617 : rd->smb2.out.reserved = 0;
1402 1617 : break;
1403 0 : default:
1404 0 : return NT_STATUS_INVALID_LEVEL;
1405 : }
1406 :
1407 1647 : return status;
1408 : }
1409 :
1410 : /*
1411 : NTVFS read* to readx mapper
1412 : */
1413 1647 : NTSTATUS ntvfs_map_read(struct ntvfs_module_context *ntvfs,
1414 : struct ntvfs_request *req,
1415 : union smb_read *rd)
1416 : {
1417 0 : union smb_read *rd2;
1418 0 : union smb_lock *lck;
1419 0 : NTSTATUS status;
1420 0 : unsigned int state;
1421 :
1422 1647 : rd2 = talloc(req, union smb_read);
1423 1647 : if (rd2 == NULL) {
1424 0 : return NT_STATUS_NO_MEMORY;
1425 : }
1426 :
1427 1647 : status = ntvfs_map_async_setup(ntvfs, req, rd, rd2,
1428 : (second_stage_t)ntvfs_map_read_finish);
1429 1647 : if (!NT_STATUS_IS_OK(status)) {
1430 0 : return status;
1431 : }
1432 :
1433 1647 : rd2->readx.level = RAW_READ_READX;
1434 1647 : rd2->readx.in.read_for_execute = false;
1435 :
1436 1647 : switch (rd->generic.level) {
1437 0 : case RAW_READ_READX:
1438 0 : status = NT_STATUS_INVALID_LEVEL;
1439 1647 : break;
1440 :
1441 7 : case RAW_READ_READ:
1442 7 : rd2->readx.in.file.ntvfs= rd->read.in.file.ntvfs;
1443 7 : rd2->readx.in.offset = rd->read.in.offset;
1444 7 : rd2->readx.in.mincnt = rd->read.in.count;
1445 7 : rd2->readx.in.maxcnt = rd->read.in.count;
1446 7 : rd2->readx.in.remaining = rd->read.in.remaining;
1447 7 : rd2->readx.out.data = rd->read.out.data;
1448 7 : status = ntvfs->ops->read_fn(ntvfs, req, rd2);
1449 7 : break;
1450 :
1451 11 : case RAW_READ_READBRAW:
1452 11 : rd2->readx.in.file.ntvfs= rd->readbraw.in.file.ntvfs;
1453 11 : rd2->readx.in.offset = rd->readbraw.in.offset;
1454 11 : rd2->readx.in.mincnt = rd->readbraw.in.mincnt;
1455 11 : rd2->readx.in.maxcnt = rd->readbraw.in.maxcnt;
1456 11 : rd2->readx.in.remaining = 0;
1457 11 : rd2->readx.out.data = rd->readbraw.out.data;
1458 11 : status = ntvfs->ops->read_fn(ntvfs, req, rd2);
1459 11 : break;
1460 :
1461 12 : case RAW_READ_LOCKREAD:
1462 : /* do the initial lock sync for now */
1463 12 : state = req->async_states->state;
1464 12 : req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
1465 :
1466 12 : lck = talloc(rd2, union smb_lock);
1467 12 : if (lck == NULL) {
1468 0 : status = NT_STATUS_NO_MEMORY;
1469 0 : goto done;
1470 : }
1471 12 : lck->lock.level = RAW_LOCK_LOCK;
1472 12 : lck->lock.in.file.ntvfs = rd->lockread.in.file.ntvfs;
1473 12 : lck->lock.in.count = rd->lockread.in.count;
1474 12 : lck->lock.in.offset = rd->lockread.in.offset;
1475 12 : status = ntvfs->ops->lock_fn(ntvfs, req, lck);
1476 12 : req->async_states->state = state;
1477 :
1478 12 : rd2->readx.in.file.ntvfs= rd->lockread.in.file.ntvfs;
1479 12 : rd2->readx.in.offset = rd->lockread.in.offset;
1480 12 : rd2->readx.in.mincnt = rd->lockread.in.count;
1481 12 : rd2->readx.in.maxcnt = rd->lockread.in.count;
1482 12 : rd2->readx.in.remaining = rd->lockread.in.remaining;
1483 12 : rd2->readx.out.data = rd->lockread.out.data;
1484 :
1485 12 : if (NT_STATUS_IS_OK(status)) {
1486 6 : status = ntvfs->ops->read_fn(ntvfs, req, rd2);
1487 : }
1488 12 : break;
1489 :
1490 1617 : case RAW_READ_SMB2:
1491 1617 : rd2->readx.in.file.ntvfs= rd->smb2.in.file.ntvfs;
1492 1617 : rd2->readx.in.offset = rd->smb2.in.offset;
1493 1617 : rd2->readx.in.mincnt = rd->smb2.in.min_count;
1494 1617 : rd2->readx.in.maxcnt = rd->smb2.in.length;
1495 1617 : rd2->readx.in.remaining = 0;
1496 1617 : rd2->readx.out.data = rd->smb2.out.data.data;
1497 1617 : status = ntvfs->ops->read_fn(ntvfs, req, rd2);
1498 1617 : break;
1499 : }
1500 :
1501 1647 : done:
1502 1647 : return ntvfs_map_async_finish(req, status);
1503 : }
1504 :
1505 :
1506 : /*
1507 : NTVFS close generic to any mapper
1508 : */
1509 204181 : static NTSTATUS ntvfs_map_close_finish(struct ntvfs_module_context *ntvfs,
1510 : struct ntvfs_request *req,
1511 : union smb_close *cl,
1512 : union smb_close *cl2,
1513 : NTSTATUS status)
1514 : {
1515 204181 : NT_STATUS_NOT_OK_RETURN(status);
1516 :
1517 204181 : switch (cl->generic.level) {
1518 142663 : case RAW_CLOSE_SMB2:
1519 142663 : cl->smb2.out.flags = cl2->generic.out.flags;
1520 142663 : cl->smb2.out._pad = 0;
1521 142663 : cl->smb2.out.create_time = cl2->generic.out.create_time;
1522 142663 : cl->smb2.out.access_time = cl2->generic.out.access_time;
1523 142663 : cl->smb2.out.write_time = cl2->generic.out.write_time;
1524 142663 : cl->smb2.out.change_time = cl2->generic.out.change_time;
1525 142663 : cl->smb2.out.alloc_size = cl2->generic.out.alloc_size;
1526 142663 : cl->smb2.out.size = cl2->generic.out.size;
1527 142663 : cl->smb2.out.file_attr = cl2->generic.out.file_attr;
1528 142663 : break;
1529 61518 : default:
1530 61518 : break;
1531 : }
1532 :
1533 204181 : return status;
1534 : }
1535 :
1536 : /*
1537 : NTVFS close generic to any mapper
1538 : */
1539 204181 : NTSTATUS ntvfs_map_close(struct ntvfs_module_context *ntvfs,
1540 : struct ntvfs_request *req,
1541 : union smb_close *cl)
1542 : {
1543 0 : union smb_close *cl2;
1544 0 : NTSTATUS status;
1545 :
1546 204181 : cl2 = talloc(req, union smb_close);
1547 204181 : if (cl2 == NULL) {
1548 0 : return NT_STATUS_NO_MEMORY;
1549 : }
1550 :
1551 204181 : switch (cl->generic.level) {
1552 0 : case RAW_CLOSE_GENERIC:
1553 0 : return NT_STATUS_INVALID_LEVEL;
1554 :
1555 61518 : case RAW_CLOSE_CLOSE:
1556 61518 : cl2->generic.level = RAW_CLOSE_GENERIC;
1557 61518 : cl2->generic.in.file = cl->close.in.file;
1558 61518 : cl2->generic.in.write_time = cl->close.in.write_time;
1559 61518 : cl2->generic.in.flags = 0;
1560 204181 : break;
1561 :
1562 0 : case RAW_CLOSE_SPLCLOSE:
1563 0 : cl2->generic.level = RAW_CLOSE_GENERIC;
1564 0 : cl2->generic.in.file = cl->splclose.in.file;
1565 0 : cl2->generic.in.write_time = 0;
1566 0 : cl2->generic.in.flags = 0;
1567 0 : break;
1568 :
1569 142663 : case RAW_CLOSE_SMB2:
1570 142663 : cl2->generic.level = RAW_CLOSE_GENERIC;
1571 142663 : cl2->generic.in.file = cl->smb2.in.file;
1572 142663 : cl2->generic.in.write_time = 0;
1573 142663 : cl2->generic.in.flags = cl->smb2.in.flags;
1574 142663 : break;
1575 : }
1576 :
1577 204181 : status = ntvfs_map_async_setup(ntvfs, req, cl, cl2,
1578 : (second_stage_t)ntvfs_map_close_finish);
1579 204181 : NT_STATUS_NOT_OK_RETURN(status);
1580 :
1581 204181 : status = ntvfs->ops->close_fn(ntvfs, req, cl2);
1582 :
1583 204181 : return ntvfs_map_async_finish(req, status);
1584 : }
1585 :
1586 : /*
1587 : NTVFS notify generic to any mapper
1588 : */
1589 0 : static NTSTATUS ntvfs_map_notify_finish(struct ntvfs_module_context *ntvfs,
1590 : struct ntvfs_request *req,
1591 : union smb_notify *nt,
1592 : union smb_notify *nt2,
1593 : NTSTATUS status)
1594 : {
1595 0 : NT_STATUS_NOT_OK_RETURN(status);
1596 :
1597 0 : switch (nt->nttrans.level) {
1598 0 : case RAW_NOTIFY_SMB2:
1599 0 : if (nt2->nttrans.out.num_changes == 0) {
1600 0 : return NT_STATUS_NOTIFY_ENUM_DIR;
1601 : }
1602 0 : nt->smb2.out.num_changes = nt2->nttrans.out.num_changes;
1603 0 : nt->smb2.out.changes = talloc_steal(req, nt2->nttrans.out.changes);
1604 0 : break;
1605 :
1606 0 : default:
1607 0 : return NT_STATUS_INVALID_LEVEL;
1608 : }
1609 :
1610 0 : return status;
1611 : }
1612 :
1613 :
1614 : /*
1615 : NTVFS notify generic to any mapper
1616 : */
1617 0 : NTSTATUS ntvfs_map_notify(struct ntvfs_module_context *ntvfs,
1618 : struct ntvfs_request *req,
1619 : union smb_notify *nt)
1620 : {
1621 0 : union smb_notify *nt2;
1622 0 : NTSTATUS status;
1623 :
1624 0 : nt2 = talloc(req, union smb_notify);
1625 0 : NT_STATUS_HAVE_NO_MEMORY(nt2);
1626 :
1627 0 : status = ntvfs_map_async_setup(ntvfs, req, nt, nt2,
1628 : (second_stage_t)ntvfs_map_notify_finish);
1629 0 : NT_STATUS_NOT_OK_RETURN(status);
1630 :
1631 0 : nt2->nttrans.level = RAW_NOTIFY_NTTRANS;
1632 :
1633 0 : switch (nt->nttrans.level) {
1634 0 : case RAW_NOTIFY_NTTRANS:
1635 0 : status = NT_STATUS_INVALID_LEVEL;
1636 0 : break;
1637 :
1638 0 : case RAW_NOTIFY_SMB2:
1639 0 : nt2->nttrans.in.file.ntvfs = nt->smb2.in.file.ntvfs;
1640 0 : nt2->nttrans.in.buffer_size = nt->smb2.in.buffer_size;
1641 0 : nt2->nttrans.in.completion_filter = nt->smb2.in.completion_filter;
1642 0 : nt2->nttrans.in.recursive = nt->smb2.in.recursive;
1643 0 : status = ntvfs->ops->notify_fn(ntvfs, req, nt2);
1644 0 : break;
1645 : }
1646 :
1647 0 : return ntvfs_map_async_finish(req, status);
1648 : }
|