Merge branch 'v4-0-test' into v4-0-gmake3
[ira/wip.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         /* directory opens are handled separately */
1121         if ((name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) ||
1122             (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) {
1123                 return pvfs_open_directory(pvfs, req, name, io);
1124         }
1125
1126         /* FILE_ATTRIBUTE_DIRECTORY is ignored if the above test for directory
1127            open doesn't match */
1128         io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY;
1129
1130         create_options = io->generic.in.create_options;
1131         share_access   = io->generic.in.share_access;
1132         access_mask    = io->generic.in.access_mask;
1133
1134         /* certain create options are not allowed */
1135         if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
1136             !(access_mask & SEC_STD_DELETE)) {
1137                 return NT_STATUS_INVALID_PARAMETER;
1138         }
1139
1140         flags = 0;
1141
1142         switch (io->generic.in.open_disposition) {
1143         case NTCREATEX_DISP_SUPERSEDE:
1144         case NTCREATEX_DISP_OVERWRITE_IF:
1145                 if (name->stream_name == NULL) {
1146                         flags = O_TRUNC;
1147                 } else {
1148                         stream_truncate = true;
1149                 }
1150                 break;
1151
1152         case NTCREATEX_DISP_OPEN:
1153                 if (!name->stream_exists) {
1154                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1155                 }
1156                 flags = 0;
1157                 break;
1158
1159         case NTCREATEX_DISP_OVERWRITE:
1160                 if (!name->stream_exists) {
1161                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1162                 }
1163                 if (name->stream_name == NULL) {
1164                         flags = O_TRUNC;
1165                 } else {
1166                         stream_truncate = true;
1167                 }
1168                 break;
1169
1170         case NTCREATEX_DISP_CREATE:
1171                 if (name->stream_exists) {
1172                         return NT_STATUS_OBJECT_NAME_COLLISION;
1173                 }
1174                 flags = 0;
1175                 break;
1176
1177         case NTCREATEX_DISP_OPEN_IF:
1178                 flags = 0;
1179                 break;
1180
1181         default:
1182                 return NT_STATUS_INVALID_PARAMETER;
1183         }
1184
1185         /* handle creating a new file separately */
1186         if (!name->exists) {
1187                 status = pvfs_create_file(pvfs, req, name, io);
1188                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1189                         return status;
1190                 }
1191
1192                 /* we've hit a race - the file was created during this call */
1193                 if (io->generic.in.open_disposition == NTCREATEX_DISP_CREATE) {
1194                         return status;
1195                 }
1196
1197                 /* try re-resolving the name */
1198                 status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name);
1199                 if (!NT_STATUS_IS_OK(status)) {
1200                         return status;
1201                 }
1202                 /* fall through to a normal open */
1203         }
1204
1205         if ((name->dos.attrib & FILE_ATTRIBUTE_READONLY) &&
1206             (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
1207                 return NT_STATUS_CANNOT_DELETE;
1208         }
1209
1210         /* check the security descriptor */
1211         status = pvfs_access_check(pvfs, req, name, &access_mask);
1212         if (!NT_STATUS_IS_OK(status)) {
1213                 return status;
1214         }
1215
1216         status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
1217         NT_STATUS_NOT_OK_RETURN(status);
1218
1219         f = talloc(h, struct pvfs_file);
1220         if (f == NULL) {
1221                 return NT_STATUS_NO_MEMORY;
1222         }
1223
1224         f->handle = talloc(f, struct pvfs_file_handle);
1225         if (f->handle == NULL) {
1226                 return NT_STATUS_NO_MEMORY;
1227         }
1228
1229         f->ntvfs         = h;
1230         f->pvfs          = pvfs;
1231         f->pending_list  = NULL;
1232         f->lock_count    = 0;
1233         f->share_access  = io->generic.in.share_access;
1234         f->access_mask   = access_mask;
1235         f->impersonation = io->generic.in.impersonation;
1236         f->notify_buffer = NULL;
1237         f->search        = NULL;
1238
1239         f->handle->pvfs              = pvfs;
1240         f->handle->fd                = -1;
1241         f->handle->name              = talloc_steal(f->handle, name);
1242         f->handle->create_options    = io->generic.in.create_options;
1243         f->handle->seek_offset       = 0;
1244         f->handle->position          = 0;
1245         f->handle->mode              = 0;
1246         f->handle->oplock            = NULL;
1247         f->handle->have_opendb_entry = false;
1248         f->handle->open_completed    = false;
1249
1250         /* form the lock context used for byte range locking and
1251            opendb locking */
1252         status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
1253         if (!NT_STATUS_IS_OK(status)) {
1254                 return status;
1255         }
1256
1257         status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle);
1258         if (!NT_STATUS_IS_OK(status)) {
1259                 return status;
1260         }
1261
1262         /* get a lock on this file before the actual open */
1263         lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
1264         if (lck == NULL) {
1265                 DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
1266                          name->full_name));
1267                 /* we were supposed to do a blocking lock, so something
1268                    is badly wrong! */
1269                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1270         }
1271
1272         DLIST_ADD(pvfs->files.list, f);
1273
1274         /* setup a destructor to avoid file descriptor leaks on
1275            abnormal termination */
1276         talloc_set_destructor(f, pvfs_fnum_destructor);
1277         talloc_set_destructor(f->handle, pvfs_handle_destructor);
1278
1279         /* 
1280          * Only SMB2 takes care of the delete_on_close,
1281          * on existing files
1282          */
1283         if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE &&
1284             req->ctx->protocol == PROTOCOL_SMB2) {
1285                 del_on_close = true;
1286         } else {
1287                 del_on_close = false;
1288         }
1289
1290         if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
1291                 oplock_level = OPLOCK_NONE;
1292         } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) {
1293                 oplock_level = OPLOCK_BATCH;
1294         } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_OPLOCK) {
1295                 oplock_level = OPLOCK_EXCLUSIVE;
1296         }
1297
1298         if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) {
1299                 allow_level_II_oplock = true;
1300         }
1301
1302         /* see if we are allowed to open at the same time as existing opens */
1303         status = odb_can_open(lck, name->stream_id,
1304                               share_access, access_mask, del_on_close,
1305                               io->generic.in.open_disposition, false);
1306
1307         /*
1308          * on a sharing violation we need to retry when the file is closed by
1309          * the other user, or after 1 second
1310          * on a non granted oplock we need to retry when the file is closed by
1311          * the other user, or after 30 seconds
1312         */
1313         if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1314              NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
1315             (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
1316                 return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
1317         }
1318
1319         if (!NT_STATUS_IS_OK(status)) {
1320                 talloc_free(lck);
1321                 return status;
1322         }
1323
1324         if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) {
1325                 flags |= O_RDWR;
1326         } else {
1327                 flags |= O_RDONLY;
1328         }
1329
1330         /* do the actual open */
1331         fd = open(f->handle->name->full_name, flags | O_NONBLOCK);
1332         if (fd == -1) {
1333                 status = pvfs_map_errno(f->pvfs, errno);
1334
1335                 /*
1336                  * STATUS_MORE_ENTRIES is EAGAIN or EWOULDBLOCK
1337                  */
1338                 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
1339                     (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
1340                         return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
1341                 }
1342
1343                 talloc_free(lck);
1344                 return status;
1345         }
1346
1347         f->handle->fd = fd;
1348
1349         /* now really mark the file as open */
1350         status = odb_open_file(lck, f->handle, name->full_name,
1351                                &f->handle->fd, allow_level_II_oplock,
1352                                oplock_level, &oplock_granted);
1353
1354         if (!NT_STATUS_IS_OK(status)) {
1355                 talloc_free(lck);
1356                 return status;
1357         }
1358
1359         f->handle->have_opendb_entry = true;
1360
1361         if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
1362                 oplock_granted = OPLOCK_BATCH;
1363         } else if (oplock_granted != OPLOCK_NONE) {
1364                 status = pvfs_setup_oplock(f, oplock_granted);
1365                 if (!NT_STATUS_IS_OK(status)) {
1366                         talloc_free(lck);
1367                         return status;
1368                 }
1369         }
1370
1371         stream_existed = name->stream_exists;
1372
1373         /* if this was a stream create then create the stream as well */
1374         if (!name->stream_exists) {
1375                 status = pvfs_stream_create(pvfs, f->handle->name, fd);
1376                 if (!NT_STATUS_IS_OK(status)) {
1377                         talloc_free(lck);
1378                         return status;
1379                 }
1380                 if (stream_truncate) {
1381                         status = pvfs_stream_truncate(pvfs, f->handle->name, fd, 0);
1382                         if (!NT_STATUS_IS_OK(status)) {
1383                                 talloc_free(lck);
1384                                 return status;
1385                         }
1386                 }
1387         }
1388
1389         /* re-resolve the open fd */
1390         status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name);
1391         if (!NT_STATUS_IS_OK(status)) {
1392                 talloc_free(lck);
1393                 return status;
1394         }
1395
1396         if (f->handle->name->stream_id == 0 &&
1397             (io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE ||
1398              io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF)) {
1399                 /* for overwrite we need to replace file permissions */
1400                 uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE;
1401                 mode_t mode = pvfs_fileperms(pvfs, attrib);
1402                 if (fchmod(fd, mode) == -1) {
1403                         talloc_free(lck);
1404                         return pvfs_map_errno(pvfs, errno);
1405                 }
1406                 name->dos.attrib = attrib;
1407                 status = pvfs_dosattrib_save(pvfs, name, fd);
1408                 if (!NT_STATUS_IS_OK(status)) {
1409                         talloc_free(lck);
1410                         return status;
1411                 }
1412         }
1413             
1414         talloc_free(lck);
1415
1416         status = ntvfs_handle_set_backend_data(h, ntvfs, f);
1417         NT_STATUS_NOT_OK_RETURN(status);
1418
1419         /* mark the open as having completed fully, so delete on close
1420            can now be used */
1421         f->handle->open_completed     = true;
1422
1423         io->generic.out.oplock_level  = oplock_granted;
1424         io->generic.out.file.ntvfs    = h;
1425         io->generic.out.create_action = stream_existed?
1426                 NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED;
1427         io->generic.out.create_time   = name->dos.create_time;
1428         io->generic.out.access_time   = name->dos.access_time;
1429         io->generic.out.write_time    = name->dos.write_time;
1430         io->generic.out.change_time   = name->dos.change_time;
1431         io->generic.out.attrib        = name->dos.attrib;
1432         io->generic.out.alloc_size    = name->dos.alloc_size;
1433         io->generic.out.size          = name->st.st_size;
1434         io->generic.out.file_type     = FILE_TYPE_DISK;
1435         io->generic.out.ipc_state     = 0;
1436         io->generic.out.is_directory  = 0;
1437
1438         return NT_STATUS_OK;
1439 }
1440
1441
1442 /*
1443   close a file
1444 */
1445 NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs,
1446                     struct ntvfs_request *req, union smb_close *io)
1447 {
1448         struct pvfs_state *pvfs = ntvfs->private_data;
1449         struct pvfs_file *f;
1450         struct utimbuf unix_times;
1451
1452         if (io->generic.level == RAW_CLOSE_SPLCLOSE) {
1453                 return NT_STATUS_DOS(ERRSRV, ERRerror);
1454         }
1455
1456         if (io->generic.level != RAW_CLOSE_CLOSE) {
1457                 return ntvfs_map_close(ntvfs, req, io);
1458         }
1459
1460         f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs);
1461         if (!f) {
1462                 return NT_STATUS_INVALID_HANDLE;
1463         }
1464
1465         if (!null_time(io->close.in.write_time)) {
1466                 unix_times.actime = 0;
1467                 unix_times.modtime = io->close.in.write_time;
1468                 utime(f->handle->name->full_name, &unix_times);
1469         }
1470
1471         talloc_free(f);
1472
1473         return NT_STATUS_OK;
1474 }
1475
1476
1477 /*
1478   logoff - close all file descriptors open by a vuid
1479 */
1480 NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs,
1481                      struct ntvfs_request *req)
1482 {
1483         struct pvfs_state *pvfs = ntvfs->private_data;
1484         struct pvfs_file *f, *next;
1485
1486         for (f=pvfs->files.list;f;f=next) {
1487                 next = f->next;
1488                 if (f->ntvfs->session_info == req->session_info) {
1489                         talloc_free(f);
1490                 }
1491         }
1492
1493         return NT_STATUS_OK;
1494 }
1495
1496
1497 /*
1498   exit - close files for the current pid
1499 */
1500 NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs,
1501                    struct ntvfs_request *req)
1502 {
1503         struct pvfs_state *pvfs = ntvfs->private_data;
1504         struct pvfs_file *f, *next;
1505
1506         for (f=pvfs->files.list;f;f=next) {
1507                 next = f->next;
1508                 if (f->ntvfs->session_info == req->session_info &&
1509                     f->ntvfs->smbpid == req->smbpid) {
1510                         talloc_free(f);
1511                 }
1512         }
1513
1514         return NT_STATUS_OK;
1515 }
1516
1517
1518 /*
1519   change the delete on close flag on an already open file
1520 */
1521 NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs,
1522                                   struct ntvfs_request *req, 
1523                                   struct pvfs_file *f, bool del_on_close)
1524 {
1525         struct odb_lock *lck;
1526         NTSTATUS status;
1527
1528         if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && del_on_close) {
1529                 return NT_STATUS_CANNOT_DELETE;
1530         }
1531         
1532         if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
1533             !pvfs_directory_empty(pvfs, f->handle->name)) {
1534                 return NT_STATUS_DIRECTORY_NOT_EMPTY;
1535         }
1536
1537         if (del_on_close) {
1538                 f->handle->create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1539         } else {
1540                 f->handle->create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1541         }
1542         
1543         lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
1544         if (lck == NULL) {
1545                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1546         }
1547
1548         status = odb_set_delete_on_close(lck, del_on_close);
1549
1550         talloc_free(lck);
1551
1552         return status;
1553 }
1554
1555
1556 /*
1557   determine if a file can be deleted, or if it is prevented by an
1558   already open file
1559 */
1560 NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, 
1561                          struct ntvfs_request *req,
1562                          struct pvfs_filename *name,
1563                          struct odb_lock **lckp)
1564 {
1565         NTSTATUS status;
1566         DATA_BLOB key;
1567         struct odb_lock *lck;
1568         uint32_t share_access;
1569         uint32_t access_mask;
1570         bool delete_on_close;
1571
1572         status = pvfs_locking_key(name, name, &key);
1573         if (!NT_STATUS_IS_OK(status)) {
1574                 return NT_STATUS_NO_MEMORY;
1575         }
1576
1577         lck = odb_lock(req, pvfs->odb_context, &key);
1578         if (lck == NULL) {
1579                 DEBUG(0,("Unable to lock opendb for can_delete\n"));
1580                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1581         }
1582
1583         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1584                           NTCREATEX_SHARE_ACCESS_WRITE |
1585                           NTCREATEX_SHARE_ACCESS_DELETE;
1586         access_mask     = SEC_STD_DELETE;
1587         delete_on_close = true;
1588
1589         status = odb_can_open(lck, name->stream_id,
1590                               share_access, access_mask, delete_on_close,
1591                               NTCREATEX_DISP_OPEN, false);
1592
1593         if (NT_STATUS_IS_OK(status)) {
1594                 status = pvfs_access_check_simple(pvfs, req, name, access_mask);
1595         }
1596
1597         /*
1598          * if it's a sharing violation or we got no oplock
1599          * only keep the lock if the caller requested access
1600          * to the lock
1601          */
1602         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1603             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1604                 if (lckp) {
1605                         *lckp = lck;
1606                 } else {
1607                         talloc_free(lck);
1608                 }
1609         } else if (!NT_STATUS_IS_OK(status)) {
1610                 talloc_free(lck);
1611                 if (lckp) {
1612                         *lckp = NULL;
1613                 }
1614         } else if (lckp) {
1615                 *lckp = lck;
1616         }
1617
1618         return status;
1619 }
1620
1621 /*
1622   determine if a file can be renamed, or if it is prevented by an
1623   already open file
1624 */
1625 NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, 
1626                          struct ntvfs_request *req,
1627                          struct pvfs_filename *name,
1628                          struct odb_lock **lckp)
1629 {
1630         NTSTATUS status;
1631         DATA_BLOB key;
1632         struct odb_lock *lck;
1633         uint32_t share_access;
1634         uint32_t access_mask;
1635         bool delete_on_close;
1636
1637         status = pvfs_locking_key(name, name, &key);
1638         if (!NT_STATUS_IS_OK(status)) {
1639                 return NT_STATUS_NO_MEMORY;
1640         }
1641
1642         lck = odb_lock(req, pvfs->odb_context, &key);
1643         if (lck == NULL) {
1644                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1645                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1646         }
1647
1648         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1649                           NTCREATEX_SHARE_ACCESS_WRITE;
1650         access_mask     = SEC_STD_DELETE;
1651         delete_on_close = false;
1652
1653         status = odb_can_open(lck, name->stream_id,
1654                               share_access, access_mask, delete_on_close,
1655                               NTCREATEX_DISP_OPEN, false);
1656
1657         /*
1658          * if it's a sharing violation or we got no oplock
1659          * only keep the lock if the caller requested access
1660          * to the lock
1661          */
1662         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1663             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1664                 if (lckp) {
1665                         *lckp = lck;
1666                 } else {
1667                         talloc_free(lck);
1668                 }
1669         } else if (!NT_STATUS_IS_OK(status)) {
1670                 talloc_free(lck);
1671                 if (lckp) {
1672                         *lckp = NULL;
1673                 }
1674         } else if (lckp) {
1675                 *lckp = lck;
1676         }
1677
1678         return status;
1679 }
1680
1681 /*
1682   determine if the file size of a file can be changed,
1683   or if it is prevented by an already open file
1684 */
1685 NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs,
1686                                    struct ntvfs_request *req,
1687                                    struct pvfs_filename *name,
1688                                    struct odb_lock **lckp)
1689 {
1690         NTSTATUS status;
1691         DATA_BLOB key;
1692         struct odb_lock *lck;
1693         uint32_t share_access;
1694         uint32_t access_mask;
1695         bool break_to_none;
1696         bool delete_on_close;
1697
1698         status = pvfs_locking_key(name, name, &key);
1699         if (!NT_STATUS_IS_OK(status)) {
1700                 return NT_STATUS_NO_MEMORY;
1701         }
1702
1703         lck = odb_lock(req, pvfs->odb_context, &key);
1704         if (lck == NULL) {
1705                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1706                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1707         }
1708
1709         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1710                           NTCREATEX_SHARE_ACCESS_WRITE |
1711                           NTCREATEX_SHARE_ACCESS_DELETE;
1712         /*
1713          * I would have thought that we would need to pass
1714          * SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA here too
1715          *
1716          * But you only need SEC_FILE_WRITE_ATTRIBUTE permissions
1717          * to set the filesize.
1718          *
1719          * --metze
1720          */
1721         access_mask     = SEC_FILE_WRITE_ATTRIBUTE;
1722         delete_on_close = false;
1723         break_to_none   = true;
1724
1725         status = odb_can_open(lck, name->stream_id,
1726                               share_access, access_mask, delete_on_close,
1727                               NTCREATEX_DISP_OPEN, break_to_none);
1728
1729         /*
1730          * if it's a sharing violation or we got no oplock
1731          * only keep the lock if the caller requested access
1732          * to the lock
1733          */
1734         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1735             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1736                 if (lckp) {
1737                         *lckp = lck;
1738                 } else {
1739                         talloc_free(lck);
1740                 }
1741         } else if (!NT_STATUS_IS_OK(status)) {
1742                 talloc_free(lck);
1743                 if (lckp) {
1744                         *lckp = NULL;
1745                 }
1746         } else if (lckp) {
1747                 *lckp = lck;
1748         }
1749
1750         return status;
1751 }
1752
1753 /*
1754   determine if file meta data can be accessed, or if it is prevented by an
1755   already open file
1756 */
1757 NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, 
1758                        struct ntvfs_request *req,
1759                        struct pvfs_filename *name)
1760 {
1761         NTSTATUS status;
1762         DATA_BLOB key;
1763         struct odb_lock *lck;
1764         uint32_t share_access;
1765         uint32_t access_mask;
1766         bool delete_on_close;
1767
1768         status = pvfs_locking_key(name, name, &key);
1769         if (!NT_STATUS_IS_OK(status)) {
1770                 return NT_STATUS_NO_MEMORY;
1771         }
1772
1773         lck = odb_lock(req, pvfs->odb_context, &key);
1774         if (lck == NULL) {
1775                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1776                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1777         }
1778
1779         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1780                           NTCREATEX_SHARE_ACCESS_WRITE;
1781         access_mask     = SEC_FILE_READ_ATTRIBUTE;
1782         delete_on_close = false;
1783
1784         status = odb_can_open(lck, name->stream_id,
1785                               share_access, access_mask, delete_on_close,
1786                               NTCREATEX_DISP_OPEN, false);
1787
1788         if (!NT_STATUS_IS_OK(status)) {
1789                 talloc_free(lck);
1790         }
1791
1792         return status;
1793 }
1794
1795
1796 /*
1797   determine if delete on close is set on 
1798 */
1799 bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h)
1800 {
1801         NTSTATUS status;
1802         bool del_on_close;
1803
1804         status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, 
1805                                          &del_on_close);
1806         if (!NT_STATUS_IS_OK(status)) {
1807                 DEBUG(1,("WARNING: unable to determine delete on close status for open file\n"));
1808                 return false;
1809         }
1810
1811         return del_on_close;
1812 }