~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/ntvfs/ntvfs_generic.c

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

Show diffs side-by-side

added added

removed removed

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