67937324ccfa9afcae974b8232ad3eebe01624fe
[kai/samba.git] / source4 / ntvfs / posix / pvfs_open.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend - open and close
5
6    Copyright (C) Andrew Tridgell 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 #include "includes.h"
23 #include "vfs_posix.h"
24 #include "system/dir.h"
25 #include "system/time.h"
26 #include "lib/util/dlinklist.h"
27 #include "messaging/messaging.h"
28 #include "librpc/gen_ndr/xattr.h"
29
30 /*
31   find open file handle given fnum
32 */
33 struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs,
34                                struct ntvfs_request *req, struct ntvfs_handle *h)
35 {
36         void *p;
37         struct pvfs_file *f;
38
39         p = ntvfs_handle_get_backend_data(h, pvfs->ntvfs);
40         if (!p) return NULL;
41
42         f = talloc_get_type(p, struct pvfs_file);
43         if (!f) return NULL;
44
45         return f;
46 }
47
48 /*
49   cleanup a open directory handle
50 */
51 static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h)
52 {
53         if (h->have_opendb_entry) {
54                 struct odb_lock *lck;
55                 NTSTATUS status;
56                 const char *delete_path = NULL;
57
58                 lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
59                 if (lck == NULL) {
60                         DEBUG(0,("Unable to lock opendb for close\n"));
61                         return 0;
62                 }
63
64                 status = odb_close_file(lck, h, &delete_path);
65                 if (!NT_STATUS_IS_OK(status)) {
66                         DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",
67                                  h->name->full_name, nt_errstr(status)));
68                 }
69
70                 if (h->name->stream_name == NULL && delete_path) {
71                         status = pvfs_xattr_unlink_hook(h->pvfs, delete_path);
72                         if (!NT_STATUS_IS_OK(status)) {
73                                 DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
74                                          delete_path, nt_errstr(status)));
75                         }
76                         if (rmdir(delete_path) != 0) {
77                                 DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n",
78                                          delete_path, strerror(errno)));
79                         }
80                 }
81
82                 talloc_free(lck);
83         }
84
85         return 0;
86 }
87
88 /*
89   cleanup a open directory fnum
90 */
91 static int pvfs_dir_fnum_destructor(struct pvfs_file *f)
92 {
93         DLIST_REMOVE(f->pvfs->files.list, f);
94         ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs);
95
96         return 0;
97 }
98
99 /*
100   setup any EAs and the ACL on newly created files/directories
101 */
102 static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs,
103                                         struct ntvfs_request *req,
104                                         struct pvfs_filename *name,
105                                         int fd, struct pvfs_file *f,
106                                         union smb_open *io)
107 {
108         NTSTATUS status;
109
110         /* setup any EAs that were asked for */
111         if (io->ntcreatex.in.ea_list) {
112                 status = pvfs_setfileinfo_ea_set(pvfs, name, fd, 
113                                                  io->ntcreatex.in.ea_list->num_eas,
114                                                  io->ntcreatex.in.ea_list->eas);
115                 if (!NT_STATUS_IS_OK(status)) {
116                         return status;
117                 }
118         }
119
120         /* setup an initial sec_desc if requested */
121         if (io->ntcreatex.in.sec_desc) {
122                 union smb_setfileinfo set;
123 /* 
124  * TODO: set the full ACL! 
125  *       - vista denies the creation of the file with NT_STATUS_PRIVILEGE_NOT_HELD,
126  *         when a SACL is present on the sd,
127  *         but the user doesn't have SeSecurityPrivilege
128  *       - w2k3 allows it
129  */
130                 set.set_secdesc.in.file.ntvfs = f->ntvfs;
131                 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
132                 set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc;
133
134                 status = pvfs_acl_set(pvfs, req, name, fd, SEC_STD_WRITE_DAC, &set);
135         } else {
136                 /* otherwise setup an inherited acl from the parent */
137                 status = pvfs_acl_inherit(pvfs, req, name, fd);
138         }
139
140         return status;
141 }
142
143 /*
144   form the lock context used for opendb locking. Note that we must
145   zero here to take account of possible padding on some architectures
146 */
147 NTSTATUS pvfs_locking_key(struct pvfs_filename *name,
148                           TALLOC_CTX *mem_ctx, DATA_BLOB *key)
149 {
150         struct {
151                 dev_t device;
152                 ino_t inode;
153         } lock_context;
154         ZERO_STRUCT(lock_context);
155
156         lock_context.device = name->st.st_dev;
157         lock_context.inode = name->st.st_ino;
158
159         *key = data_blob_talloc(mem_ctx, &lock_context, sizeof(lock_context));
160         if (key->data == NULL) {
161                 return NT_STATUS_NO_MEMORY;
162         }
163         
164         return NT_STATUS_OK;
165 }
166
167
168 /*
169   open a directory
170 */
171 static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, 
172                                     struct ntvfs_request *req, 
173                                     struct pvfs_filename *name, 
174                                     union smb_open *io)
175 {
176         struct pvfs_file *f;
177         struct ntvfs_handle *h;
178         NTSTATUS status;
179         uint32_t create_action;
180         uint32_t access_mask = io->generic.in.access_mask;
181         struct odb_lock *lck;
182         bool del_on_close;
183         uint32_t create_options;
184         uint32_t share_access;
185
186         create_options = io->generic.in.create_options;
187         share_access   = io->generic.in.share_access;
188
189         if (name->stream_name) {
190                 return NT_STATUS_NOT_A_DIRECTORY;
191         }
192
193         /* if the client says it must be a directory, and it isn't,
194            then fail */
195         if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
196                 return NT_STATUS_NOT_A_DIRECTORY;
197         }
198
199         switch (io->generic.in.open_disposition) {
200         case NTCREATEX_DISP_OPEN_IF:
201                 break;
202
203         case NTCREATEX_DISP_OPEN:
204                 if (!name->exists) {
205                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
206                 }
207                 break;
208
209         case NTCREATEX_DISP_CREATE:
210                 if (name->exists) {
211                         return NT_STATUS_OBJECT_NAME_COLLISION;
212                 }
213                 break;
214
215         case NTCREATEX_DISP_OVERWRITE_IF:
216         case NTCREATEX_DISP_OVERWRITE:
217         case NTCREATEX_DISP_SUPERSEDE:
218         default:
219                 return NT_STATUS_INVALID_PARAMETER;
220         }
221
222         status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
223         NT_STATUS_NOT_OK_RETURN(status);
224
225         f = talloc(h, struct pvfs_file);
226         if (f == NULL) {
227                 return NT_STATUS_NO_MEMORY;
228         }
229
230         f->handle = talloc(f, struct pvfs_file_handle);
231         if (f->handle == NULL) {
232                 return NT_STATUS_NO_MEMORY;
233         }
234
235         if (name->exists) {
236                 /* check the security descriptor */
237                 status = pvfs_access_check(pvfs, req, name, &access_mask);
238         } else {
239                 status = pvfs_access_check_create(pvfs, req, name, &access_mask);
240         }
241         if (!NT_STATUS_IS_OK(status)) {
242                 return status;
243         }
244
245         f->ntvfs         = h;
246         f->pvfs          = pvfs;
247         f->pending_list  = NULL;
248         f->lock_count    = 0;
249         f->share_access  = io->generic.in.share_access;
250         f->impersonation = io->generic.in.impersonation;
251         f->access_mask   = access_mask;
252         f->brl_handle    = NULL;
253         f->notify_buffer = NULL;
254         f->search        = NULL;
255
256         f->handle->pvfs              = pvfs;
257         f->handle->name              = talloc_steal(f->handle, name);
258         f->handle->fd                = -1;
259         f->handle->odb_locking_key   = data_blob(NULL, 0);
260         f->handle->create_options    = io->generic.in.create_options;
261         f->handle->seek_offset       = 0;
262         f->handle->position          = 0;
263         f->handle->mode              = 0;
264         f->handle->oplock            = NULL;
265         f->handle->open_completed    = false;
266
267         if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
268             pvfs_directory_empty(pvfs, f->handle->name)) {
269                 del_on_close = true;
270         } else {
271                 del_on_close = false;
272         }
273
274         if (name->exists) {
275                 /* form the lock context used for opendb locking */
276                 status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
277                 if (!NT_STATUS_IS_OK(status)) {
278                         return status;
279                 }
280
281                 /* get a lock on this file before the actual open */
282                 lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
283                 if (lck == NULL) {
284                         DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
285                                  name->full_name));
286                         /* we were supposed to do a blocking lock, so something
287                            is badly wrong! */
288                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
289                 }
290                 
291                 /* see if we are allowed to open at the same time as existing opens */
292                 status = odb_can_open(lck, name->stream_id,
293                                       share_access, access_mask, del_on_close,
294                                       io->generic.in.open_disposition, false);
295                 if (!NT_STATUS_IS_OK(status)) {
296                         talloc_free(lck);
297                         return status;
298                 }
299
300                 /* now really mark the file as open */
301                 status = odb_open_file(lck, f->handle, name->full_name,
302                                        NULL, false, OPLOCK_NONE, NULL);
303
304                 if (!NT_STATUS_IS_OK(status)) {
305                         talloc_free(lck);
306                         return status;
307                 }
308
309                 f->handle->have_opendb_entry = true;
310         }
311
312         DLIST_ADD(pvfs->files.list, f);
313
314         /* setup destructors to avoid leaks on abnormal termination */
315         talloc_set_destructor(f->handle, pvfs_dir_handle_destructor);
316         talloc_set_destructor(f, pvfs_dir_fnum_destructor);
317
318         if (!name->exists) {
319                 uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY;
320                 mode_t mode = pvfs_fileperms(pvfs, attrib);
321
322                 if (mkdir(name->full_name, mode) == -1) {
323                         return pvfs_map_errno(pvfs,errno);
324                 }
325
326                 pvfs_xattr_unlink_hook(pvfs, name->full_name);
327
328                 status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name);
329                 if (!NT_STATUS_IS_OK(status)) {
330                         goto cleanup_delete;
331                 }
332
333                 status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io);
334                 if (!NT_STATUS_IS_OK(status)) {
335                         goto cleanup_delete;
336                 }
337
338                 /* form the lock context used for opendb locking */
339                 status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
340                 if (!NT_STATUS_IS_OK(status)) {
341                         return status;
342                 }
343
344                 lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
345                 if (lck == NULL) {
346                         DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
347                                  name->full_name));
348                         /* we were supposed to do a blocking lock, so something
349                            is badly wrong! */
350                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
351                 }
352
353                 status = odb_can_open(lck, name->stream_id,
354                                       share_access, access_mask, del_on_close,
355                                       io->generic.in.open_disposition, false);
356
357                 if (!NT_STATUS_IS_OK(status)) {
358                         goto cleanup_delete;
359                 }
360
361                 status = odb_open_file(lck, f->handle, name->full_name,
362                                        NULL, false, OPLOCK_NONE, NULL);
363
364                 if (!NT_STATUS_IS_OK(status)) {
365                         goto cleanup_delete;
366                 }
367
368                 f->handle->have_opendb_entry = true;
369
370                 create_action = NTCREATEX_ACTION_CREATED;
371
372                 notify_trigger(pvfs->notify_context, 
373                                NOTIFY_ACTION_ADDED, 
374                                FILE_NOTIFY_CHANGE_DIR_NAME,
375                                name->full_name);
376         } else {
377                 create_action = NTCREATEX_ACTION_EXISTED;
378         }
379
380         if (!name->exists) {
381                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
382         }
383
384         /* the open succeeded, keep this handle permanently */
385         status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f);
386         if (!NT_STATUS_IS_OK(status)) {
387                 goto cleanup_delete;
388         }
389
390         f->handle->open_completed = true;
391
392         io->generic.out.oplock_level  = OPLOCK_NONE;
393         io->generic.out.file.ntvfs    = h;
394         io->generic.out.create_action = create_action;
395         io->generic.out.create_time   = name->dos.create_time;
396         io->generic.out.access_time   = name->dos.access_time;
397         io->generic.out.write_time    = name->dos.write_time;
398         io->generic.out.change_time   = name->dos.change_time;
399         io->generic.out.attrib        = name->dos.attrib;
400         io->generic.out.alloc_size    = name->dos.alloc_size;
401         io->generic.out.size          = name->st.st_size;
402         io->generic.out.file_type     = FILE_TYPE_DISK;
403         io->generic.out.ipc_state     = 0;
404         io->generic.out.is_directory  = 1;
405
406         return NT_STATUS_OK;
407
408 cleanup_delete:
409         rmdir(name->full_name);
410         return status;
411 }
412
413 /*
414   destroy a struct pvfs_file_handle
415 */
416 static int pvfs_handle_destructor(struct pvfs_file_handle *h)
417 {
418         if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
419             h->name->stream_name) {
420                 NTSTATUS status;
421                 status = pvfs_stream_delete(h->pvfs, h->name, h->fd);
422                 if (!NT_STATUS_IS_OK(status)) {
423                         DEBUG(0,("Failed to delete stream '%s' on close of '%s'\n",
424                                  h->name->stream_name, h->name->full_name));
425                 }
426         }
427
428         if (h->fd != -1) {
429                 if (close(h->fd) != 0) {
430                         DEBUG(0,("pvfs_handle_destructor: close(%d) failed for %s - %s\n",
431                                  h->fd, h->name->full_name, strerror(errno)));
432                 }
433                 h->fd = -1;
434         }
435
436         if (h->have_opendb_entry) {
437                 struct odb_lock *lck;
438                 NTSTATUS status;
439                 const char *delete_path = NULL;
440
441                 lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
442                 if (lck == NULL) {
443                         DEBUG(0,("Unable to lock opendb for close\n"));
444                         return 0;
445                 }
446
447                 status = odb_close_file(lck, h, &delete_path);
448                 if (!NT_STATUS_IS_OK(status)) {
449                         DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", 
450                                  h->name->full_name, nt_errstr(status)));
451                 }
452
453                 if (h->name->stream_name == NULL &&
454                     h->open_completed && delete_path) {
455                         status = pvfs_xattr_unlink_hook(h->pvfs, delete_path);
456                         if (!NT_STATUS_IS_OK(status)) {
457                                 DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
458                                          delete_path, nt_errstr(status)));
459                         }
460                         if (unlink(delete_path) != 0) {
461                                 DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n",
462                                          delete_path, strerror(errno)));
463                         } else {
464                                 notify_trigger(h->pvfs->notify_context,
465                                                NOTIFY_ACTION_REMOVED,
466                                                FILE_NOTIFY_CHANGE_FILE_NAME,
467                                                delete_path);
468                         }
469                 }
470
471                 talloc_free(lck);
472         }
473
474         return 0;
475 }
476
477
478 /*
479   destroy a struct pvfs_file
480 */
481 static int pvfs_fnum_destructor(struct pvfs_file *f)
482 {
483         DLIST_REMOVE(f->pvfs->files.list, f);
484         pvfs_lock_close(f->pvfs, f);
485         ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs);
486
487         return 0;
488 }
489
490
491 /*
492   form the lock context used for byte range locking. This is separate
493   from the locking key used for opendb locking as it needs to take
494   account of file streams (each stream is a separate byte range
495   locking space)
496 */
497 static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx,
498                                         struct pvfs_filename *name,
499                                         struct ntvfs_handle *ntvfs,
500                                         struct brl_handle **_h)
501 {
502         DATA_BLOB odb_key, key;
503         NTSTATUS status;
504         struct brl_handle *h;
505
506         status = pvfs_locking_key(name, mem_ctx, &odb_key);
507         NT_STATUS_NOT_OK_RETURN(status);
508
509         if (name->stream_name == NULL) {
510                 key = odb_key;
511         } else {
512                 key = data_blob_talloc(mem_ctx, NULL, 
513                                        odb_key.length + strlen(name->stream_name) + 1);
514                 NT_STATUS_HAVE_NO_MEMORY(key.data);
515                 memcpy(key.data, odb_key.data, odb_key.length);
516                 memcpy(key.data + odb_key.length, 
517                        name->stream_name, strlen(name->stream_name) + 1);
518                 data_blob_free(&odb_key);
519         }
520
521         h = brl_create_handle(mem_ctx, ntvfs, &key);
522         NT_STATUS_HAVE_NO_MEMORY(h);
523
524         *_h = h;
525         return NT_STATUS_OK;
526 }
527
528 /*
529   create a new file
530 */
531 static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, 
532                                  struct ntvfs_request *req, 
533                                  struct pvfs_filename *name, 
534                                  union smb_open *io)
535 {
536         struct pvfs_file *f;
537         NTSTATUS status;
538         struct ntvfs_handle *h;
539         int flags, fd;
540         struct odb_lock *lck;
541         uint32_t create_options = io->generic.in.create_options;
542         uint32_t share_access = io->generic.in.share_access;
543         uint32_t access_mask = io->generic.in.access_mask;
544         mode_t mode;
545         uint32_t attrib;
546         bool del_on_close;
547         struct pvfs_filename *parent;
548         uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
549         bool allow_level_II_oplock = false;
550
551         if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) &&
552             (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
553                 return NT_STATUS_CANNOT_DELETE;
554         }
555         
556         status = pvfs_access_check_create(pvfs, req, name, &access_mask);
557         NT_STATUS_NOT_OK_RETURN(status);
558
559         /* check that the parent isn't opened with delete on close set */
560         status = pvfs_resolve_parent(pvfs, req, name, &parent);
561         if (NT_STATUS_IS_OK(status)) {
562                 DATA_BLOB locking_key;
563                 status = pvfs_locking_key(parent, req, &locking_key);
564                 NT_STATUS_NOT_OK_RETURN(status);
565                 status = odb_get_delete_on_close(pvfs->odb_context, &locking_key, 
566                                                  &del_on_close);
567                 NT_STATUS_NOT_OK_RETURN(status);
568                 if (del_on_close) {
569                         return NT_STATUS_DELETE_PENDING;
570                 }
571         }
572
573         if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) {
574                 flags = O_RDWR;
575         } else {
576                 flags = O_RDONLY;
577         }
578
579         status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
580         NT_STATUS_NOT_OK_RETURN(status);
581
582         f = talloc(h, struct pvfs_file);
583         NT_STATUS_HAVE_NO_MEMORY(f);
584
585         f->handle = talloc(f, struct pvfs_file_handle);
586         NT_STATUS_HAVE_NO_MEMORY(f->handle);
587
588         attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE;
589         mode = pvfs_fileperms(pvfs, attrib);
590
591         /* create the file */
592         fd = open(name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode);
593         if (fd == -1) {
594                 return pvfs_map_errno(pvfs, errno);
595         }
596
597         pvfs_xattr_unlink_hook(pvfs, name->full_name);
598
599         /* if this was a stream create then create the stream as well */
600         if (name->stream_name) {
601                 status = pvfs_stream_create(pvfs, name, fd);
602                 if (!NT_STATUS_IS_OK(status)) {
603                         close(fd);
604                         return status;
605                 }
606         }
607
608         /* re-resolve the open fd */
609         status = pvfs_resolve_name_fd(pvfs, fd, name);
610         if (!NT_STATUS_IS_OK(status)) {
611                 close(fd);
612                 return status;
613         }
614
615         name->dos.attrib = attrib;
616         status = pvfs_dosattrib_save(pvfs, name, fd);
617         if (!NT_STATUS_IS_OK(status)) {
618                 goto cleanup_delete;
619         }
620
621
622         status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io);
623         if (!NT_STATUS_IS_OK(status)) {
624                 goto cleanup_delete;
625         }
626
627         /* form the lock context used for byte range locking and
628            opendb locking */
629         status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
630         if (!NT_STATUS_IS_OK(status)) {
631                 goto cleanup_delete;
632         }
633
634         status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle);
635         if (!NT_STATUS_IS_OK(status)) {
636                 goto cleanup_delete;
637         }
638
639         /* grab a lock on the open file record */
640         lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
641         if (lck == NULL) {
642                 DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
643                          name->full_name));
644                 /* we were supposed to do a blocking lock, so something
645                    is badly wrong! */
646                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
647                 goto cleanup_delete;
648         }
649
650         if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
651                 del_on_close = true;
652         } else {
653                 del_on_close = false;
654         }
655
656         if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
657                 oplock_level = OPLOCK_NONE;
658         } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) {
659                 oplock_level = OPLOCK_BATCH;
660         } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_OPLOCK) {
661                 oplock_level = OPLOCK_EXCLUSIVE;
662         }
663
664         if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) {
665                 allow_level_II_oplock = true;
666         }
667
668         status = odb_can_open(lck, name->stream_id,
669                               share_access, access_mask, del_on_close,
670                               io->generic.in.open_disposition, false);
671         if (!NT_STATUS_IS_OK(status)) {
672                 talloc_free(lck);
673                 /* bad news, we must have hit a race - we don't delete the file
674                    here as the most likely scenario is that someone else created
675                    the file at the same time */
676                 close(fd);
677                 return status;
678         }
679
680         f->ntvfs             = h;
681         f->pvfs              = pvfs;
682         f->pending_list      = NULL;
683         f->lock_count        = 0;
684         f->share_access      = io->generic.in.share_access;
685         f->access_mask       = access_mask;
686         f->impersonation     = io->generic.in.impersonation;
687         f->notify_buffer     = NULL;
688         f->search            = NULL;
689
690         f->handle->pvfs              = pvfs;
691         f->handle->name              = talloc_steal(f->handle, name);
692         f->handle->fd                = fd;
693         f->handle->create_options    = io->generic.in.create_options;
694         f->handle->seek_offset       = 0;
695         f->handle->position          = 0;
696         f->handle->mode              = 0;
697         f->handle->oplock            = NULL;
698         f->handle->have_opendb_entry = true;
699         f->handle->open_completed    = false;
700
701         status = odb_open_file(lck, f->handle, name->full_name,
702                                &f->handle->fd, allow_level_II_oplock,
703                                oplock_level, &oplock_granted);
704         talloc_free(lck);
705         if (!NT_STATUS_IS_OK(status)) {
706                 /* bad news, we must have hit a race - we don't delete the file
707                    here as the most likely scenario is that someone else created
708                    the file at the same time */
709                 close(fd);
710                 return status;
711         }
712
713         DLIST_ADD(pvfs->files.list, f);
714
715         /* setup a destructor to avoid file descriptor leaks on
716            abnormal termination */
717         talloc_set_destructor(f, pvfs_fnum_destructor);
718         talloc_set_destructor(f->handle, pvfs_handle_destructor);
719
720         if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
721                 oplock_granted = OPLOCK_BATCH;
722         } else if (oplock_granted != OPLOCK_NONE) {
723                 status = pvfs_setup_oplock(f, oplock_granted);
724                 if (!NT_STATUS_IS_OK(status)) {
725                         return status;
726                 }
727         }
728
729         io->generic.out.oplock_level  = oplock_granted;
730         io->generic.out.file.ntvfs    = f->ntvfs;
731         io->generic.out.create_action = NTCREATEX_ACTION_CREATED;
732         io->generic.out.create_time   = name->dos.create_time;
733         io->generic.out.access_time   = name->dos.access_time;
734         io->generic.out.write_time    = name->dos.write_time;
735         io->generic.out.change_time   = name->dos.change_time;
736         io->generic.out.attrib        = name->dos.attrib;
737         io->generic.out.alloc_size    = name->dos.alloc_size;
738         io->generic.out.size          = name->st.st_size;
739         io->generic.out.file_type     = FILE_TYPE_DISK;
740         io->generic.out.ipc_state     = 0;
741         io->generic.out.is_directory  = 0;
742
743         /* success - keep the file handle */
744         status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f);
745         if (!NT_STATUS_IS_OK(status)) {
746                 goto cleanup_delete;
747         }
748
749         f->handle->open_completed = true;
750
751         notify_trigger(pvfs->notify_context, 
752                        NOTIFY_ACTION_ADDED, 
753                        FILE_NOTIFY_CHANGE_FILE_NAME,
754                        name->full_name);
755
756         return NT_STATUS_OK;
757
758 cleanup_delete:
759         close(fd);
760         unlink(name->full_name);
761         return status;
762 }
763
764 /*
765   state of a pending retry
766 */
767 struct pvfs_odb_retry {
768         struct ntvfs_module_context *ntvfs;
769         struct ntvfs_request *req;
770         DATA_BLOB odb_locking_key;
771         void *io;
772         void *private_data;
773         void (*callback)(struct pvfs_odb_retry *r,
774                          struct ntvfs_module_context *ntvfs,
775                          struct ntvfs_request *req,
776                          void *io,
777                          void *private_data,
778                          enum pvfs_wait_notice reason);
779 };
780
781 /* destroy a pending request */
782 static int pvfs_odb_retry_destructor(struct pvfs_odb_retry *r)
783 {
784         struct pvfs_state *pvfs = r->ntvfs->private_data;
785         if (r->odb_locking_key.data) {
786                 struct odb_lock *lck;
787                 lck = odb_lock(r->req, pvfs->odb_context, &r->odb_locking_key);
788                 if (lck != NULL) {
789                         odb_remove_pending(lck, r);
790                 }
791                 talloc_free(lck);
792         }
793         return 0;
794 }
795
796 static void pvfs_odb_retry_callback(void *_r, enum pvfs_wait_notice reason)
797 {
798         struct pvfs_odb_retry *r = talloc_get_type(_r, struct pvfs_odb_retry);
799
800         if (reason == PVFS_WAIT_EVENT) {
801                 /*
802                  * The pending odb entry is already removed.
803                  * We use a null locking key to indicate this
804                  * to the destructor.
805                  */
806                 data_blob_free(&r->odb_locking_key);
807         }
808
809         r->callback(r, r->ntvfs, r->req, r->io, r->private_data, reason);
810 }
811
812 /*
813   setup for a retry of a request that was rejected
814   by odb_can_open()
815 */
816 NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs,
817                               struct ntvfs_request *req,
818                               struct odb_lock *lck,
819                               struct timeval end_time,
820                               void *io,
821                               void *private_data,
822                               void (*callback)(struct pvfs_odb_retry *r,
823                                                struct ntvfs_module_context *ntvfs,
824                                                struct ntvfs_request *req,
825                                                void *io,
826                                                void *private_data,
827                                                enum pvfs_wait_notice reason))
828 {
829         struct pvfs_state *pvfs = ntvfs->private_data;
830         struct pvfs_odb_retry *r;
831         struct pvfs_wait *wait_handle;
832         NTSTATUS status;
833
834         r = talloc(req, struct pvfs_odb_retry);
835         NT_STATUS_HAVE_NO_MEMORY(r);
836
837         r->ntvfs = ntvfs;
838         r->req = req;
839         r->io = io;
840         r->private_data = private_data;
841         r->callback = callback;
842         r->odb_locking_key = odb_get_key(r, lck);
843         if (r->odb_locking_key.data == NULL) {
844                 return NT_STATUS_NO_MEMORY;
845         }
846
847         /* setup a pending lock */
848         status = odb_open_file_pending(lck, r);
849         if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND,status)) {
850                 /*
851                  * maybe only a unix application
852                  * has the file open
853                  */
854                 data_blob_free(&r->odb_locking_key);
855         } else if (!NT_STATUS_IS_OK(status)) {
856                 return status;
857         }
858
859         talloc_free(lck);
860
861         talloc_set_destructor(r, pvfs_odb_retry_destructor);
862
863         wait_handle = pvfs_wait_message(pvfs, req,
864                                         MSG_PVFS_RETRY_OPEN, end_time,
865                                         pvfs_odb_retry_callback, r);
866         if (wait_handle == NULL) {
867                 return NT_STATUS_NO_MEMORY;
868         }
869
870         talloc_steal(r, wait_handle);
871
872         return NT_STATUS_OK;
873 }
874
875 /*
876   retry an open after a sharing violation
877 */
878 static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r,
879                                     struct ntvfs_module_context *ntvfs,
880                                     struct ntvfs_request *req,
881                                     void *_io,
882                                     void *private_data,
883                                     enum pvfs_wait_notice reason)
884 {
885         union smb_open *io = talloc_get_type(_io, union smb_open);
886         struct timeval *final_timeout = NULL;
887         NTSTATUS status;
888
889         if (private_data) {
890                 final_timeout = talloc_get_type(private_data,
891                                                 struct timeval);
892         }
893
894         /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably
895            just a bug in their server, but we better do the same */
896         if (reason == PVFS_WAIT_CANCEL) {
897                 return;
898         }
899
900         if (reason == PVFS_WAIT_TIMEOUT) {
901                 if (final_timeout &&
902                     !timeval_expired(final_timeout)) {
903                         /*
904                          * we need to retry periodictly
905                          * after an EAGAIN as there's
906                          * no way the kernel tell us
907                          * an oplock is released.
908                          */
909                         goto retry;
910                 }
911                 /* if it timed out, then give the failure
912                    immediately */
913                 talloc_free(r);
914                 req->async_states->status = NT_STATUS_SHARING_VIOLATION;
915                 req->async_states->send_fn(req);
916                 return;
917         }
918
919 retry:
920         talloc_free(r);
921
922         /* try the open again, which could trigger another retry setup
923            if it wants to, so we have to unmark the async flag so we
924            will know if it does a second async reply */
925         req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC;
926
927         status = pvfs_open(ntvfs, req, io);
928         if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) {
929                 /* the 2nd try also replied async, so we don't send
930                    the reply yet */
931                 return;
932         }
933
934         /* re-mark it async, just in case someone up the chain does
935            paranoid checking */
936         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
937
938         /* send the reply up the chain */
939         req->async_states->status = status;
940         req->async_states->send_fn(req);
941 }
942
943
944 /*
945   special handling for openx DENY_DOS semantics
946
947   This function attempts a reference open using an existing handle. If its allowed,
948   then it returns NT_STATUS_OK, otherwise it returns any other code and normal
949   open processing continues.
950 */
951 static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs,
952                                    struct ntvfs_request *req, union smb_open *io,
953                                    struct pvfs_file *f, struct odb_lock *lck)
954 {
955         struct pvfs_state *pvfs = ntvfs->private_data;
956         struct pvfs_file *f2;
957         struct pvfs_filename *name;
958         NTSTATUS status;
959
960         /* search for an existing open with the right parameters. Note
961            the magic ntcreatex options flag, which is set in the
962            generic mapping code. This might look ugly, but its
963            actually pretty much now w2k does it internally as well. 
964            
965            If you look at the BASE-DENYDOS test you will see that a
966            DENY_DOS is a very special case, and in the right
967            circumstances you actually get the _same_ handle back
968            twice, rather than a new handle.
969         */
970         for (f2=pvfs->files.list;f2;f2=f2->next) {
971                 if (f2 != f &&
972                     f2->ntvfs->session_info == req->session_info &&
973                     f2->ntvfs->smbpid == req->smbpid &&
974                     (f2->handle->create_options & 
975                      (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
976                       NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
977                     (f2->access_mask & SEC_FILE_WRITE_DATA) &&
978                     strcasecmp_m(f2->handle->name->original_name, 
979                                io->generic.in.fname)==0) {
980                         break;
981                 }
982         }
983
984         if (!f2) {
985                 return NT_STATUS_SHARING_VIOLATION;
986         }
987
988         /* quite an insane set of semantics ... */
989         if (is_exe_filename(io->generic.in.fname) &&
990             (f2->handle->create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
991                 return NT_STATUS_SHARING_VIOLATION;
992         }
993
994         /*
995           setup a reference to the existing handle
996          */
997         talloc_free(f->handle);
998         f->handle = talloc_reference(f, f2->handle);
999
1000         talloc_free(lck);
1001
1002         name = f->handle->name;
1003
1004         io->generic.out.oplock_level  = OPLOCK_NONE;
1005         io->generic.out.file.ntvfs    = f->ntvfs;
1006         io->generic.out.create_action = NTCREATEX_ACTION_EXISTED;
1007         io->generic.out.create_time   = name->dos.create_time;
1008         io->generic.out.access_time   = name->dos.access_time;
1009         io->generic.out.write_time    = name->dos.write_time;
1010         io->generic.out.change_time   = name->dos.change_time;
1011         io->generic.out.attrib        = name->dos.attrib;
1012         io->generic.out.alloc_size    = name->dos.alloc_size;
1013         io->generic.out.size          = name->st.st_size;
1014         io->generic.out.file_type     = FILE_TYPE_DISK;
1015         io->generic.out.ipc_state     = 0;
1016         io->generic.out.is_directory  = 0;
1017  
1018         status = ntvfs_handle_set_backend_data(f->ntvfs, ntvfs, f);
1019         NT_STATUS_NOT_OK_RETURN(status);
1020
1021         return NT_STATUS_OK;
1022 }
1023
1024
1025
1026 /*
1027   setup for a open retry after a sharing violation
1028 */
1029 static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
1030                                       struct ntvfs_request *req, 
1031                                       union smb_open *io,
1032                                       struct pvfs_file *f,
1033                                       struct odb_lock *lck,
1034                                       NTSTATUS parent_status)
1035 {
1036         struct pvfs_state *pvfs = ntvfs->private_data;
1037         NTSTATUS status;
1038         struct timeval end_time;
1039         struct timeval *final_timeout = NULL;
1040
1041         if (io->generic.in.create_options & 
1042             (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
1043                 /* see if we can satisfy the request using the special DENY_DOS
1044                    code */
1045                 status = pvfs_open_deny_dos(ntvfs, req, io, f, lck);
1046                 if (NT_STATUS_IS_OK(status)) {
1047                         return status;
1048                 }
1049         }
1050
1051         /* the retry should allocate a new file handle */
1052         talloc_free(f);
1053
1054         if (NT_STATUS_EQUAL(parent_status, NT_STATUS_SHARING_VIOLATION)) {
1055                 end_time = timeval_add(&req->statistics.request_time,
1056                                        0, pvfs->sharing_violation_delay);
1057         } else if (NT_STATUS_EQUAL(parent_status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1058                 end_time = timeval_add(&req->statistics.request_time,
1059                                        pvfs->oplock_break_timeout, 0);
1060         } else if (NT_STATUS_EQUAL(parent_status, STATUS_MORE_ENTRIES)) {
1061                 /*
1062                  * we got EAGAIN which means a unix application
1063                  * has an oplock or share mode
1064                  *
1065                  * we retry every 4/5 of the sharing violation delay
1066                  * to see if the unix application
1067                  * has released the oplock or share mode.
1068                  */
1069                 final_timeout = talloc(req, struct timeval);
1070                 NT_STATUS_HAVE_NO_MEMORY(final_timeout);
1071                 *final_timeout = timeval_add(&req->statistics.request_time,
1072                                              pvfs->oplock_break_timeout,
1073                                              0);
1074                 end_time = timeval_current_ofs(0, (pvfs->sharing_violation_delay*4)/5);
1075                 end_time = timeval_min(final_timeout, &end_time);
1076         } else {
1077                 return NT_STATUS_INTERNAL_ERROR;
1078         }
1079
1080         return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io,
1081                                     final_timeout, pvfs_retry_open_sharing);
1082 }
1083
1084 /*
1085   open a file
1086 */
1087 NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
1088                    struct ntvfs_request *req, union smb_open *io)
1089 {
1090         struct pvfs_state *pvfs = ntvfs->private_data;
1091         int flags;
1092         struct pvfs_filename *name;
1093         struct pvfs_file *f;
1094         struct ntvfs_handle *h;
1095         NTSTATUS status;
1096         int fd;
1097         struct odb_lock *lck;
1098         uint32_t create_options;
1099         uint32_t share_access;
1100         uint32_t access_mask;
1101         bool del_on_close;
1102         bool stream_existed, stream_truncate=false;
1103         uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
1104         bool allow_level_II_oplock = false;
1105
1106         /* use the generic mapping code to avoid implementing all the
1107            different open calls. */
1108         if (io->generic.level != RAW_OPEN_GENERIC &&
1109             io->generic.level != RAW_OPEN_NTTRANS_CREATE) {
1110                 return ntvfs_map_open(ntvfs, req, io);
1111         }
1112
1113         /* resolve the cifs name to a posix name */
1114         status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 
1115                                    PVFS_RESOLVE_STREAMS, &name);
1116         if (!NT_STATUS_IS_OK(status)) {
1117                 return status;
1118         }
1119
1120         /* if the client specified that it must not be a directory then
1121            check that it isn't */
1122         if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
1123             (io->generic.in.create_options & NTCREATEX_OPTIONS_NON_DIRECTORY_FILE)) {
1124                 return NT_STATUS_FILE_IS_A_DIRECTORY;
1125         }
1126
1127         /* if the client specified that it must be a directory then
1128            check that it is */
1129         if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
1130             (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) {
1131                 return NT_STATUS_NOT_A_DIRECTORY;
1132         }
1133
1134         /* directory opens are handled separately */
1135         if ((name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) ||
1136             (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) {
1137                 return pvfs_open_directory(pvfs, req, name, io);
1138         }
1139
1140         /* FILE_ATTRIBUTE_DIRECTORY is ignored if the above test for directory
1141            open doesn't match */
1142         io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY;
1143
1144         create_options = io->generic.in.create_options;
1145         share_access   = io->generic.in.share_access;
1146         access_mask    = io->generic.in.access_mask;
1147
1148         /* certain create options are not allowed */
1149         if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
1150             !(access_mask & SEC_STD_DELETE)) {
1151                 return NT_STATUS_INVALID_PARAMETER;
1152         }
1153
1154         flags = 0;
1155
1156         switch (io->generic.in.open_disposition) {
1157         case NTCREATEX_DISP_SUPERSEDE:
1158         case NTCREATEX_DISP_OVERWRITE_IF:
1159                 if (name->stream_name == NULL) {
1160                         flags = O_TRUNC;
1161                 } else {
1162                         stream_truncate = true;
1163                 }
1164                 break;
1165
1166         case NTCREATEX_DISP_OPEN:
1167                 if (!name->stream_exists) {
1168                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1169                 }
1170                 flags = 0;
1171                 break;
1172
1173         case NTCREATEX_DISP_OVERWRITE:
1174                 if (!name->stream_exists) {
1175                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1176                 }
1177                 if (name->stream_name == NULL) {
1178                         flags = O_TRUNC;
1179                 } else {
1180                         stream_truncate = true;
1181                 }
1182                 break;
1183
1184         case NTCREATEX_DISP_CREATE:
1185                 if (name->stream_exists) {
1186                         return NT_STATUS_OBJECT_NAME_COLLISION;
1187                 }
1188                 flags = 0;
1189                 break;
1190
1191         case NTCREATEX_DISP_OPEN_IF:
1192                 flags = 0;
1193                 break;
1194
1195         default:
1196                 return NT_STATUS_INVALID_PARAMETER;
1197         }
1198
1199         /* handle creating a new file separately */
1200         if (!name->exists) {
1201                 status = pvfs_create_file(pvfs, req, name, io);
1202                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1203                         return status;
1204                 }
1205
1206                 /* we've hit a race - the file was created during this call */
1207                 if (io->generic.in.open_disposition == NTCREATEX_DISP_CREATE) {
1208                         return status;
1209                 }
1210
1211                 /* try re-resolving the name */
1212                 status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name);
1213                 if (!NT_STATUS_IS_OK(status)) {
1214                         return status;
1215                 }
1216                 /* fall through to a normal open */
1217         }
1218
1219         if ((name->dos.attrib & FILE_ATTRIBUTE_READONLY) &&
1220             (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
1221                 return NT_STATUS_CANNOT_DELETE;
1222         }
1223
1224         /* check the security descriptor */
1225         status = pvfs_access_check(pvfs, req, name, &access_mask);
1226         if (!NT_STATUS_IS_OK(status)) {
1227                 return status;
1228         }
1229
1230         status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
1231         NT_STATUS_NOT_OK_RETURN(status);
1232
1233         f = talloc(h, struct pvfs_file);
1234         if (f == NULL) {
1235                 return NT_STATUS_NO_MEMORY;
1236         }
1237
1238         f->handle = talloc(f, struct pvfs_file_handle);
1239         if (f->handle == NULL) {
1240                 return NT_STATUS_NO_MEMORY;
1241         }
1242
1243         f->ntvfs         = h;
1244         f->pvfs          = pvfs;
1245         f->pending_list  = NULL;
1246         f->lock_count    = 0;
1247         f->share_access  = io->generic.in.share_access;
1248         f->access_mask   = access_mask;
1249         f->impersonation = io->generic.in.impersonation;
1250         f->notify_buffer = NULL;
1251         f->search        = NULL;
1252
1253         f->handle->pvfs              = pvfs;
1254         f->handle->fd                = -1;
1255         f->handle->name              = talloc_steal(f->handle, name);
1256         f->handle->create_options    = io->generic.in.create_options;
1257         f->handle->seek_offset       = 0;
1258         f->handle->position          = 0;
1259         f->handle->mode              = 0;
1260         f->handle->oplock            = NULL;
1261         f->handle->have_opendb_entry = false;
1262         f->handle->open_completed    = false;
1263
1264         /* form the lock context used for byte range locking and
1265            opendb locking */
1266         status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
1267         if (!NT_STATUS_IS_OK(status)) {
1268                 return status;
1269         }
1270
1271         status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle);
1272         if (!NT_STATUS_IS_OK(status)) {
1273                 return status;
1274         }
1275
1276         /* get a lock on this file before the actual open */
1277         lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
1278         if (lck == NULL) {
1279                 DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
1280                          name->full_name));
1281                 /* we were supposed to do a blocking lock, so something
1282                    is badly wrong! */
1283                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1284         }
1285
1286         DLIST_ADD(pvfs->files.list, f);
1287
1288         /* setup a destructor to avoid file descriptor leaks on
1289            abnormal termination */
1290         talloc_set_destructor(f, pvfs_fnum_destructor);
1291         talloc_set_destructor(f->handle, pvfs_handle_destructor);
1292
1293         /* 
1294          * Only SMB2 takes care of the delete_on_close,
1295          * on existing files
1296          */
1297         if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE &&
1298             req->ctx->protocol == PROTOCOL_SMB2) {
1299                 del_on_close = true;
1300         } else {
1301                 del_on_close = false;
1302         }
1303
1304         if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
1305                 oplock_level = OPLOCK_NONE;
1306         } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) {
1307                 oplock_level = OPLOCK_BATCH;
1308         } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_OPLOCK) {
1309                 oplock_level = OPLOCK_EXCLUSIVE;
1310         }
1311
1312         if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) {
1313                 allow_level_II_oplock = true;
1314         }
1315
1316         /* see if we are allowed to open at the same time as existing opens */
1317         status = odb_can_open(lck, name->stream_id,
1318                               share_access, access_mask, del_on_close,
1319                               io->generic.in.open_disposition, false);
1320
1321         /*
1322          * on a sharing violation we need to retry when the file is closed by
1323          * the other user, or after 1 second
1324          * on a non granted oplock we need to retry when the file is closed by
1325          * the other user, or after 30 seconds
1326         */
1327         if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1328              NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
1329             (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
1330                 return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
1331         }
1332
1333         if (!NT_STATUS_IS_OK(status)) {
1334                 talloc_free(lck);
1335                 return status;
1336         }
1337
1338         if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) {
1339                 flags |= O_RDWR;
1340         } else {
1341                 flags |= O_RDONLY;
1342         }
1343
1344         /* do the actual open */
1345         fd = open(f->handle->name->full_name, flags | O_NONBLOCK);
1346         if (fd == -1) {
1347                 status = pvfs_map_errno(f->pvfs, errno);
1348
1349                 /*
1350                  * STATUS_MORE_ENTRIES is EAGAIN or EWOULDBLOCK
1351                  */
1352                 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
1353                     (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
1354                         return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
1355                 }
1356
1357                 talloc_free(lck);
1358                 return status;
1359         }
1360
1361         f->handle->fd = fd;
1362
1363         /* now really mark the file as open */
1364         status = odb_open_file(lck, f->handle, name->full_name,
1365                                &f->handle->fd, allow_level_II_oplock,
1366                                oplock_level, &oplock_granted);
1367
1368         if (!NT_STATUS_IS_OK(status)) {
1369                 talloc_free(lck);
1370                 return status;
1371         }
1372
1373         f->handle->have_opendb_entry = true;
1374
1375         if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
1376                 oplock_granted = OPLOCK_BATCH;
1377         } else if (oplock_granted != OPLOCK_NONE) {
1378                 status = pvfs_setup_oplock(f, oplock_granted);
1379                 if (!NT_STATUS_IS_OK(status)) {
1380                         talloc_free(lck);
1381                         return status;
1382                 }
1383         }
1384
1385         stream_existed = name->stream_exists;
1386
1387         /* if this was a stream create then create the stream as well */
1388         if (!name->stream_exists) {
1389                 status = pvfs_stream_create(pvfs, f->handle->name, fd);
1390                 if (!NT_STATUS_IS_OK(status)) {
1391                         talloc_free(lck);
1392                         return status;
1393                 }
1394                 if (stream_truncate) {
1395                         status = pvfs_stream_truncate(pvfs, f->handle->name, fd, 0);
1396                         if (!NT_STATUS_IS_OK(status)) {
1397                                 talloc_free(lck);
1398                                 return status;
1399                         }
1400                 }
1401         }
1402
1403         /* re-resolve the open fd */
1404         status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name);
1405         if (!NT_STATUS_IS_OK(status)) {
1406                 talloc_free(lck);
1407                 return status;
1408         }
1409
1410         if (f->handle->name->stream_id == 0 &&
1411             (io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE ||
1412              io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF)) {
1413                 /* for overwrite we need to replace file permissions */
1414                 uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE;
1415                 mode_t mode = pvfs_fileperms(pvfs, attrib);
1416                 if (fchmod(fd, mode) == -1) {
1417                         talloc_free(lck);
1418                         return pvfs_map_errno(pvfs, errno);
1419                 }
1420                 name->dos.attrib = attrib;
1421                 status = pvfs_dosattrib_save(pvfs, name, fd);
1422                 if (!NT_STATUS_IS_OK(status)) {
1423                         talloc_free(lck);
1424                         return status;
1425                 }
1426         }
1427             
1428         talloc_free(lck);
1429
1430         status = ntvfs_handle_set_backend_data(h, ntvfs, f);
1431         NT_STATUS_NOT_OK_RETURN(status);
1432
1433         /* mark the open as having completed fully, so delete on close
1434            can now be used */
1435         f->handle->open_completed     = true;
1436
1437         io->generic.out.oplock_level  = oplock_granted;
1438         io->generic.out.file.ntvfs    = h;
1439         io->generic.out.create_action = stream_existed?
1440                 NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED;
1441         io->generic.out.create_time   = name->dos.create_time;
1442         io->generic.out.access_time   = name->dos.access_time;
1443         io->generic.out.write_time    = name->dos.write_time;
1444         io->generic.out.change_time   = name->dos.change_time;
1445         io->generic.out.attrib        = name->dos.attrib;
1446         io->generic.out.alloc_size    = name->dos.alloc_size;
1447         io->generic.out.size          = name->st.st_size;
1448         io->generic.out.file_type     = FILE_TYPE_DISK;
1449         io->generic.out.ipc_state     = 0;
1450         io->generic.out.is_directory  = 0;
1451
1452         return NT_STATUS_OK;
1453 }
1454
1455
1456 /*
1457   close a file
1458 */
1459 NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs,
1460                     struct ntvfs_request *req, union smb_close *io)
1461 {
1462         struct pvfs_state *pvfs = ntvfs->private_data;
1463         struct pvfs_file *f;
1464         struct utimbuf unix_times;
1465
1466         if (io->generic.level == RAW_CLOSE_SPLCLOSE) {
1467                 return NT_STATUS_DOS(ERRSRV, ERRerror);
1468         }
1469
1470         if (io->generic.level != RAW_CLOSE_CLOSE) {
1471                 return ntvfs_map_close(ntvfs, req, io);
1472         }
1473
1474         f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs);
1475         if (!f) {
1476                 return NT_STATUS_INVALID_HANDLE;
1477         }
1478
1479         if (!null_time(io->close.in.write_time)) {
1480                 unix_times.actime = 0;
1481                 unix_times.modtime = io->close.in.write_time;
1482                 utime(f->handle->name->full_name, &unix_times);
1483         }
1484
1485         talloc_free(f);
1486
1487         return NT_STATUS_OK;
1488 }
1489
1490
1491 /*
1492   logoff - close all file descriptors open by a vuid
1493 */
1494 NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs,
1495                      struct ntvfs_request *req)
1496 {
1497         struct pvfs_state *pvfs = ntvfs->private_data;
1498         struct pvfs_file *f, *next;
1499
1500         for (f=pvfs->files.list;f;f=next) {
1501                 next = f->next;
1502                 if (f->ntvfs->session_info == req->session_info) {
1503                         talloc_free(f);
1504                 }
1505         }
1506
1507         return NT_STATUS_OK;
1508 }
1509
1510
1511 /*
1512   exit - close files for the current pid
1513 */
1514 NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs,
1515                    struct ntvfs_request *req)
1516 {
1517         struct pvfs_state *pvfs = ntvfs->private_data;
1518         struct pvfs_file *f, *next;
1519
1520         for (f=pvfs->files.list;f;f=next) {
1521                 next = f->next;
1522                 if (f->ntvfs->session_info == req->session_info &&
1523                     f->ntvfs->smbpid == req->smbpid) {
1524                         talloc_free(f);
1525                 }
1526         }
1527
1528         return NT_STATUS_OK;
1529 }
1530
1531
1532 /*
1533   change the delete on close flag on an already open file
1534 */
1535 NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs,
1536                                   struct ntvfs_request *req, 
1537                                   struct pvfs_file *f, bool del_on_close)
1538 {
1539         struct odb_lock *lck;
1540         NTSTATUS status;
1541
1542         if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && del_on_close) {
1543                 return NT_STATUS_CANNOT_DELETE;
1544         }
1545         
1546         if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
1547             !pvfs_directory_empty(pvfs, f->handle->name)) {
1548                 return NT_STATUS_DIRECTORY_NOT_EMPTY;
1549         }
1550
1551         if (del_on_close) {
1552                 f->handle->create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1553         } else {
1554                 f->handle->create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1555         }
1556         
1557         lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
1558         if (lck == NULL) {
1559                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1560         }
1561
1562         status = odb_set_delete_on_close(lck, del_on_close);
1563
1564         talloc_free(lck);
1565
1566         return status;
1567 }
1568
1569
1570 /*
1571   determine if a file can be deleted, or if it is prevented by an
1572   already open file
1573 */
1574 NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, 
1575                          struct ntvfs_request *req,
1576                          struct pvfs_filename *name,
1577                          struct odb_lock **lckp)
1578 {
1579         NTSTATUS status;
1580         DATA_BLOB key;
1581         struct odb_lock *lck;
1582         uint32_t share_access;
1583         uint32_t access_mask;
1584         bool delete_on_close;
1585
1586         status = pvfs_locking_key(name, name, &key);
1587         if (!NT_STATUS_IS_OK(status)) {
1588                 return NT_STATUS_NO_MEMORY;
1589         }
1590
1591         lck = odb_lock(req, pvfs->odb_context, &key);
1592         if (lck == NULL) {
1593                 DEBUG(0,("Unable to lock opendb for can_delete\n"));
1594                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1595         }
1596
1597         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1598                           NTCREATEX_SHARE_ACCESS_WRITE |
1599                           NTCREATEX_SHARE_ACCESS_DELETE;
1600         access_mask     = SEC_STD_DELETE;
1601         delete_on_close = true;
1602
1603         status = odb_can_open(lck, name->stream_id,
1604                               share_access, access_mask, delete_on_close,
1605                               NTCREATEX_DISP_OPEN, false);
1606
1607         if (NT_STATUS_IS_OK(status)) {
1608                 status = pvfs_access_check_simple(pvfs, req, name, access_mask);
1609         }
1610
1611         /*
1612          * if it's a sharing violation or we got no oplock
1613          * only keep the lock if the caller requested access
1614          * to the lock
1615          */
1616         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1617             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1618                 if (lckp) {
1619                         *lckp = lck;
1620                 } else {
1621                         talloc_free(lck);
1622                 }
1623         } else if (!NT_STATUS_IS_OK(status)) {
1624                 talloc_free(lck);
1625                 if (lckp) {
1626                         *lckp = NULL;
1627                 }
1628         } else if (lckp) {
1629                 *lckp = lck;
1630         }
1631
1632         return status;
1633 }
1634
1635 /*
1636   determine if a file can be renamed, or if it is prevented by an
1637   already open file
1638 */
1639 NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, 
1640                          struct ntvfs_request *req,
1641                          struct pvfs_filename *name,
1642                          struct odb_lock **lckp)
1643 {
1644         NTSTATUS status;
1645         DATA_BLOB key;
1646         struct odb_lock *lck;
1647         uint32_t share_access;
1648         uint32_t access_mask;
1649         bool delete_on_close;
1650
1651         status = pvfs_locking_key(name, name, &key);
1652         if (!NT_STATUS_IS_OK(status)) {
1653                 return NT_STATUS_NO_MEMORY;
1654         }
1655
1656         lck = odb_lock(req, pvfs->odb_context, &key);
1657         if (lck == NULL) {
1658                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1659                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1660         }
1661
1662         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1663                           NTCREATEX_SHARE_ACCESS_WRITE;
1664         access_mask     = SEC_STD_DELETE;
1665         delete_on_close = false;
1666
1667         status = odb_can_open(lck, name->stream_id,
1668                               share_access, access_mask, delete_on_close,
1669                               NTCREATEX_DISP_OPEN, false);
1670
1671         /*
1672          * if it's a sharing violation or we got no oplock
1673          * only keep the lock if the caller requested access
1674          * to the lock
1675          */
1676         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1677             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1678                 if (lckp) {
1679                         *lckp = lck;
1680                 } else {
1681                         talloc_free(lck);
1682                 }
1683         } else if (!NT_STATUS_IS_OK(status)) {
1684                 talloc_free(lck);
1685                 if (lckp) {
1686                         *lckp = NULL;
1687                 }
1688         } else if (lckp) {
1689                 *lckp = lck;
1690         }
1691
1692         return status;
1693 }
1694
1695 /*
1696   determine if the file size of a file can be changed,
1697   or if it is prevented by an already open file
1698 */
1699 NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs,
1700                                    struct ntvfs_request *req,
1701                                    struct pvfs_filename *name,
1702                                    struct odb_lock **lckp)
1703 {
1704         NTSTATUS status;
1705         DATA_BLOB key;
1706         struct odb_lock *lck;
1707         uint32_t share_access;
1708         uint32_t access_mask;
1709         bool break_to_none;
1710         bool delete_on_close;
1711
1712         status = pvfs_locking_key(name, name, &key);
1713         if (!NT_STATUS_IS_OK(status)) {
1714                 return NT_STATUS_NO_MEMORY;
1715         }
1716
1717         lck = odb_lock(req, pvfs->odb_context, &key);
1718         if (lck == NULL) {
1719                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1720                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1721         }
1722
1723         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1724                           NTCREATEX_SHARE_ACCESS_WRITE |
1725                           NTCREATEX_SHARE_ACCESS_DELETE;
1726         /*
1727          * I would have thought that we would need to pass
1728          * SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA here too
1729          *
1730          * But you only need SEC_FILE_WRITE_ATTRIBUTE permissions
1731          * to set the filesize.
1732          *
1733          * --metze
1734          */
1735         access_mask     = SEC_FILE_WRITE_ATTRIBUTE;
1736         delete_on_close = false;
1737         break_to_none   = true;
1738
1739         status = odb_can_open(lck, name->stream_id,
1740                               share_access, access_mask, delete_on_close,
1741                               NTCREATEX_DISP_OPEN, break_to_none);
1742
1743         /*
1744          * if it's a sharing violation or we got no oplock
1745          * only keep the lock if the caller requested access
1746          * to the lock
1747          */
1748         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1749             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1750                 if (lckp) {
1751                         *lckp = lck;
1752                 } else {
1753                         talloc_free(lck);
1754                 }
1755         } else if (!NT_STATUS_IS_OK(status)) {
1756                 talloc_free(lck);
1757                 if (lckp) {
1758                         *lckp = NULL;
1759                 }
1760         } else if (lckp) {
1761                 *lckp = lck;
1762         }
1763
1764         return status;
1765 }
1766
1767 /*
1768   determine if file meta data can be accessed, or if it is prevented by an
1769   already open file
1770 */
1771 NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, 
1772                        struct ntvfs_request *req,
1773                        struct pvfs_filename *name)
1774 {
1775         NTSTATUS status;
1776         DATA_BLOB key;
1777         struct odb_lock *lck;
1778         uint32_t share_access;
1779         uint32_t access_mask;
1780         bool delete_on_close;
1781
1782         status = pvfs_locking_key(name, name, &key);
1783         if (!NT_STATUS_IS_OK(status)) {
1784                 return NT_STATUS_NO_MEMORY;
1785         }
1786
1787         lck = odb_lock(req, pvfs->odb_context, &key);
1788         if (lck == NULL) {
1789                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1790                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1791         }
1792
1793         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1794                           NTCREATEX_SHARE_ACCESS_WRITE;
1795         access_mask     = SEC_FILE_READ_ATTRIBUTE;
1796         delete_on_close = false;
1797
1798         status = odb_can_open(lck, name->stream_id,
1799                               share_access, access_mask, delete_on_close,
1800                               NTCREATEX_DISP_OPEN, false);
1801
1802         if (!NT_STATUS_IS_OK(status)) {
1803                 talloc_free(lck);
1804         }
1805
1806         return status;
1807 }
1808
1809
1810 /*
1811   determine if delete on close is set on 
1812 */
1813 bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h)
1814 {
1815         NTSTATUS status;
1816         bool del_on_close;
1817
1818         status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, 
1819                                          &del_on_close);
1820         if (!NT_STATUS_IS_OK(status)) {
1821                 DEBUG(1,("WARNING: unable to determine delete on close status for open file\n"));
1822                 return false;
1823         }
1824
1825         return del_on_close;
1826 }