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