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