1399f120a7c7e902b3b04f18901bc4824bb97eae
[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         talloc_steal(pvfs, r);
885
886         return NT_STATUS_OK;
887 }
888
889 /*
890   retry an open after a sharing violation
891 */
892 static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r,
893                                     struct ntvfs_module_context *ntvfs,
894                                     struct ntvfs_request *req,
895                                     void *_io,
896                                     void *private_data,
897                                     enum pvfs_wait_notice reason)
898 {
899         union smb_open *io = talloc_get_type(_io, union smb_open);
900         struct timeval *final_timeout = NULL;
901         NTSTATUS status;
902
903         if (private_data) {
904                 final_timeout = talloc_get_type(private_data,
905                                                 struct timeval);
906         }
907
908         /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably
909            just a bug in their server, but we better do the same */
910         if (reason == PVFS_WAIT_CANCEL) {
911                 return;
912         }
913
914         if (reason == PVFS_WAIT_TIMEOUT) {
915                 if (final_timeout &&
916                     !timeval_expired(final_timeout)) {
917                         /*
918                          * we need to retry periodictly
919                          * after an EAGAIN as there's
920                          * no way the kernel tell us
921                          * an oplock is released.
922                          */
923                         goto retry;
924                 }
925                 /* if it timed out, then give the failure
926                    immediately */
927                 talloc_free(r);
928                 req->async_states->status = NT_STATUS_SHARING_VIOLATION;
929                 req->async_states->send_fn(req);
930                 return;
931         }
932
933 retry:
934         talloc_free(r);
935
936         /* try the open again, which could trigger another retry setup
937            if it wants to, so we have to unmark the async flag so we
938            will know if it does a second async reply */
939         req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC;
940
941         status = pvfs_open(ntvfs, req, io);
942         if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) {
943                 /* the 2nd try also replied async, so we don't send
944                    the reply yet */
945                 return;
946         }
947
948         /* re-mark it async, just in case someone up the chain does
949            paranoid checking */
950         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
951
952         /* send the reply up the chain */
953         req->async_states->status = status;
954         req->async_states->send_fn(req);
955 }
956
957
958 /*
959   special handling for openx DENY_DOS semantics
960
961   This function attempts a reference open using an existing handle. If its allowed,
962   then it returns NT_STATUS_OK, otherwise it returns any other code and normal
963   open processing continues.
964 */
965 static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs,
966                                    struct ntvfs_request *req, union smb_open *io,
967                                    struct pvfs_file *f, struct odb_lock *lck)
968 {
969         struct pvfs_state *pvfs = ntvfs->private_data;
970         struct pvfs_file *f2;
971         struct pvfs_filename *name;
972         NTSTATUS status;
973
974         /* search for an existing open with the right parameters. Note
975            the magic ntcreatex options flag, which is set in the
976            generic mapping code. This might look ugly, but its
977            actually pretty much now w2k does it internally as well. 
978            
979            If you look at the BASE-DENYDOS test you will see that a
980            DENY_DOS is a very special case, and in the right
981            circumstances you actually get the _same_ handle back
982            twice, rather than a new handle.
983         */
984         for (f2=pvfs->files.list;f2;f2=f2->next) {
985                 if (f2 != f &&
986                     f2->ntvfs->session_info == req->session_info &&
987                     f2->ntvfs->smbpid == req->smbpid &&
988                     (f2->handle->create_options & 
989                      (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
990                       NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
991                     (f2->access_mask & SEC_FILE_WRITE_DATA) &&
992                     strcasecmp_m(f2->handle->name->original_name, 
993                                io->generic.in.fname)==0) {
994                         break;
995                 }
996         }
997
998         if (!f2) {
999                 return NT_STATUS_SHARING_VIOLATION;
1000         }
1001
1002         /* quite an insane set of semantics ... */
1003         if (is_exe_filename(io->generic.in.fname) &&
1004             (f2->handle->create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
1005                 return NT_STATUS_SHARING_VIOLATION;
1006         }
1007
1008         /*
1009           setup a reference to the existing handle
1010          */
1011         talloc_free(f->handle);
1012         f->handle = talloc_reference(f, f2->handle);
1013
1014         talloc_free(lck);
1015
1016         name = f->handle->name;
1017
1018         io->generic.out.oplock_level  = OPLOCK_NONE;
1019         io->generic.out.file.ntvfs    = f->ntvfs;
1020         io->generic.out.create_action = NTCREATEX_ACTION_EXISTED;
1021         io->generic.out.create_time   = name->dos.create_time;
1022         io->generic.out.access_time   = name->dos.access_time;
1023         io->generic.out.write_time    = name->dos.write_time;
1024         io->generic.out.change_time   = name->dos.change_time;
1025         io->generic.out.attrib        = name->dos.attrib;
1026         io->generic.out.alloc_size    = name->dos.alloc_size;
1027         io->generic.out.size          = name->st.st_size;
1028         io->generic.out.file_type     = FILE_TYPE_DISK;
1029         io->generic.out.ipc_state     = 0;
1030         io->generic.out.is_directory  = 0;
1031  
1032         status = ntvfs_handle_set_backend_data(f->ntvfs, ntvfs, f);
1033         NT_STATUS_NOT_OK_RETURN(status);
1034
1035         return NT_STATUS_OK;
1036 }
1037
1038
1039
1040 /*
1041   setup for a open retry after a sharing violation
1042 */
1043 static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
1044                                       struct ntvfs_request *req, 
1045                                       union smb_open *io,
1046                                       struct pvfs_file *f,
1047                                       struct odb_lock *lck,
1048                                       NTSTATUS parent_status)
1049 {
1050         struct pvfs_state *pvfs = ntvfs->private_data;
1051         NTSTATUS status;
1052         struct timeval end_time;
1053         struct timeval *final_timeout = NULL;
1054
1055         if (io->generic.in.create_options & 
1056             (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
1057                 /* see if we can satisfy the request using the special DENY_DOS
1058                    code */
1059                 status = pvfs_open_deny_dos(ntvfs, req, io, f, lck);
1060                 if (NT_STATUS_IS_OK(status)) {
1061                         return status;
1062                 }
1063         }
1064
1065         /* the retry should allocate a new file handle */
1066         talloc_free(f);
1067
1068         if (NT_STATUS_EQUAL(parent_status, NT_STATUS_SHARING_VIOLATION)) {
1069                 end_time = timeval_add(&req->statistics.request_time,
1070                                        0, pvfs->sharing_violation_delay);
1071         } else if (NT_STATUS_EQUAL(parent_status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1072                 end_time = timeval_add(&req->statistics.request_time,
1073                                        pvfs->oplock_break_timeout, 0);
1074         } else if (NT_STATUS_EQUAL(parent_status, STATUS_MORE_ENTRIES)) {
1075                 /*
1076                  * we got EAGAIN which means a unix application
1077                  * has an oplock or share mode
1078                  *
1079                  * we retry every 4/5 of the sharing violation delay
1080                  * to see if the unix application
1081                  * has released the oplock or share mode.
1082                  */
1083                 final_timeout = talloc(req, struct timeval);
1084                 NT_STATUS_HAVE_NO_MEMORY(final_timeout);
1085                 *final_timeout = timeval_add(&req->statistics.request_time,
1086                                              pvfs->oplock_break_timeout,
1087                                              0);
1088                 end_time = timeval_current_ofs(0, (pvfs->sharing_violation_delay*4)/5);
1089                 end_time = timeval_min(final_timeout, &end_time);
1090         } else {
1091                 return NT_STATUS_INTERNAL_ERROR;
1092         }
1093
1094         return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io,
1095                                     final_timeout, pvfs_retry_open_sharing);
1096 }
1097
1098 /*
1099   open a file
1100 */
1101 NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
1102                    struct ntvfs_request *req, union smb_open *io)
1103 {
1104         struct pvfs_state *pvfs = ntvfs->private_data;
1105         int flags;
1106         struct pvfs_filename *name;
1107         struct pvfs_file *f;
1108         struct ntvfs_handle *h;
1109         NTSTATUS status;
1110         int fd;
1111         struct odb_lock *lck;
1112         uint32_t create_options;
1113         uint32_t share_access;
1114         uint32_t access_mask;
1115         bool del_on_close;
1116         bool stream_existed, stream_truncate=false;
1117         uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
1118         bool allow_level_II_oplock = false;
1119
1120         /* use the generic mapping code to avoid implementing all the
1121            different open calls. */
1122         if (io->generic.level != RAW_OPEN_GENERIC &&
1123             io->generic.level != RAW_OPEN_NTTRANS_CREATE) {
1124                 return ntvfs_map_open(ntvfs, req, io);
1125         }
1126
1127         /* resolve the cifs name to a posix name */
1128         status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 
1129                                    PVFS_RESOLVE_STREAMS, &name);
1130         if (!NT_STATUS_IS_OK(status)) {
1131                 return status;
1132         }
1133
1134         /* directory opens are handled separately */
1135         if ((name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) ||
1136             (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) {
1137                 return pvfs_open_directory(pvfs, req, name, io);
1138         }
1139
1140         /* FILE_ATTRIBUTE_DIRECTORY is ignored if the above test for directory
1141            open doesn't match */
1142         io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY;
1143
1144         create_options = io->generic.in.create_options;
1145         share_access   = io->generic.in.share_access;
1146         access_mask    = io->generic.in.access_mask;
1147
1148         /* certain create options are not allowed */
1149         if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
1150             !(access_mask & SEC_STD_DELETE)) {
1151                 return NT_STATUS_INVALID_PARAMETER;
1152         }
1153
1154         flags = 0;
1155
1156         switch (io->generic.in.open_disposition) {
1157         case NTCREATEX_DISP_SUPERSEDE:
1158         case NTCREATEX_DISP_OVERWRITE_IF:
1159                 if (name->stream_name == NULL) {
1160                         flags = O_TRUNC;
1161                 } else {
1162                         stream_truncate = true;
1163                 }
1164                 break;
1165
1166         case NTCREATEX_DISP_OPEN:
1167                 if (!name->stream_exists) {
1168                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1169                 }
1170                 flags = 0;
1171                 break;
1172
1173         case NTCREATEX_DISP_OVERWRITE:
1174                 if (!name->stream_exists) {
1175                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1176                 }
1177                 if (name->stream_name == NULL) {
1178                         flags = O_TRUNC;
1179                 } else {
1180                         stream_truncate = true;
1181                 }
1182                 break;
1183
1184         case NTCREATEX_DISP_CREATE:
1185                 if (name->stream_exists) {
1186                         return NT_STATUS_OBJECT_NAME_COLLISION;
1187                 }
1188                 flags = 0;
1189                 break;
1190
1191         case NTCREATEX_DISP_OPEN_IF:
1192                 flags = 0;
1193                 break;
1194
1195         default:
1196                 return NT_STATUS_INVALID_PARAMETER;
1197         }
1198
1199         /* handle creating a new file separately */
1200         if (!name->exists) {
1201                 status = pvfs_create_file(pvfs, req, name, io);
1202                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1203                         return status;
1204                 }
1205
1206                 /* we've hit a race - the file was created during this call */
1207                 if (io->generic.in.open_disposition == NTCREATEX_DISP_CREATE) {
1208                         return status;
1209                 }
1210
1211                 /* try re-resolving the name */
1212                 status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name);
1213                 if (!NT_STATUS_IS_OK(status)) {
1214                         return status;
1215                 }
1216                 /* fall through to a normal open */
1217         }
1218
1219         if ((name->dos.attrib & FILE_ATTRIBUTE_READONLY) &&
1220             (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
1221                 return NT_STATUS_CANNOT_DELETE;
1222         }
1223
1224         /* check the security descriptor */
1225         status = pvfs_access_check(pvfs, req, name, &access_mask);
1226         if (!NT_STATUS_IS_OK(status)) {
1227                 return status;
1228         }
1229
1230         status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
1231         NT_STATUS_NOT_OK_RETURN(status);
1232
1233         f = talloc(h, struct pvfs_file);
1234         if (f == NULL) {
1235                 return NT_STATUS_NO_MEMORY;
1236         }
1237
1238         f->handle = talloc(f, struct pvfs_file_handle);
1239         if (f->handle == NULL) {
1240                 return NT_STATUS_NO_MEMORY;
1241         }
1242
1243         f->ntvfs         = h;
1244         f->pvfs          = pvfs;
1245         f->pending_list  = NULL;
1246         f->lock_count    = 0;
1247         f->share_access  = io->generic.in.share_access;
1248         f->access_mask   = access_mask;
1249         f->impersonation = io->generic.in.impersonation;
1250         f->notify_buffer = NULL;
1251         f->search        = NULL;
1252
1253         f->handle->pvfs              = pvfs;
1254         f->handle->fd                = -1;
1255         f->handle->name              = talloc_steal(f->handle, name);
1256         f->handle->create_options    = io->generic.in.create_options;
1257         f->handle->seek_offset       = 0;
1258         f->handle->position          = 0;
1259         f->handle->mode              = 0;
1260         f->handle->oplock            = NULL;
1261         f->handle->have_opendb_entry = false;
1262         f->handle->sticky_write_time = false;
1263         f->handle->open_completed    = false;
1264
1265         /* form the lock context used for byte range locking and
1266            opendb locking */
1267         status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
1268         if (!NT_STATUS_IS_OK(status)) {
1269                 return status;
1270         }
1271
1272         status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle);
1273         if (!NT_STATUS_IS_OK(status)) {
1274                 return status;
1275         }
1276
1277         /* get a lock on this file before the actual open */
1278         lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
1279         if (lck == NULL) {
1280                 DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
1281                          name->full_name));
1282                 /* we were supposed to do a blocking lock, so something
1283                    is badly wrong! */
1284                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1285         }
1286
1287         DLIST_ADD(pvfs->files.list, f);
1288
1289         /* setup a destructor to avoid file descriptor leaks on
1290            abnormal termination */
1291         talloc_set_destructor(f, pvfs_fnum_destructor);
1292         talloc_set_destructor(f->handle, pvfs_handle_destructor);
1293
1294         /* 
1295          * Only SMB2 takes care of the delete_on_close,
1296          * on existing files
1297          */
1298         if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE &&
1299             req->ctx->protocol == PROTOCOL_SMB2) {
1300                 del_on_close = true;
1301         } else {
1302                 del_on_close = false;
1303         }
1304
1305         if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
1306                 oplock_level = OPLOCK_NONE;
1307         } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) {
1308                 oplock_level = OPLOCK_BATCH;
1309         } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_OPLOCK) {
1310                 oplock_level = OPLOCK_EXCLUSIVE;
1311         }
1312
1313         if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) {
1314                 allow_level_II_oplock = true;
1315         }
1316
1317         /* see if we are allowed to open at the same time as existing opens */
1318         status = odb_can_open(lck, name->stream_id,
1319                               share_access, access_mask, del_on_close,
1320                               io->generic.in.open_disposition, false);
1321
1322         /*
1323          * on a sharing violation we need to retry when the file is closed by
1324          * the other user, or after 1 second
1325          * on a non granted oplock we need to retry when the file is closed by
1326          * the other user, or after 30 seconds
1327         */
1328         if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1329              NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
1330             (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
1331                 return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
1332         }
1333
1334         if (!NT_STATUS_IS_OK(status)) {
1335                 talloc_free(lck);
1336                 return status;
1337         }
1338
1339         if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) {
1340                 flags |= O_RDWR;
1341         } else {
1342                 flags |= O_RDONLY;
1343         }
1344
1345         /* do the actual open */
1346         fd = open(f->handle->name->full_name, flags | O_NONBLOCK);
1347         if (fd == -1) {
1348                 status = pvfs_map_errno(f->pvfs, errno);
1349
1350                 /*
1351                  * STATUS_MORE_ENTRIES is EAGAIN or EWOULDBLOCK
1352                  */
1353                 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
1354                     (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
1355                         return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
1356                 }
1357
1358                 talloc_free(lck);
1359                 return status;
1360         }
1361
1362         f->handle->fd = fd;
1363
1364         /* now really mark the file as open */
1365         status = odb_open_file(lck, f->handle, name->full_name,
1366                                &f->handle->fd, allow_level_II_oplock,
1367                                oplock_level, &oplock_granted);
1368
1369         if (!NT_STATUS_IS_OK(status)) {
1370                 talloc_free(lck);
1371                 return status;
1372         }
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         f->handle->have_opendb_entry = true;
1385
1386         stream_existed = name->stream_exists;
1387
1388         /* if this was a stream create then create the stream as well */
1389         if (!name->stream_exists) {
1390                 status = pvfs_stream_create(pvfs, f->handle->name, fd);
1391                 if (!NT_STATUS_IS_OK(status)) {
1392                         talloc_free(lck);
1393                         return status;
1394                 }
1395                 if (stream_truncate) {
1396                         status = pvfs_stream_truncate(pvfs, f->handle->name, fd, 0);
1397                         if (!NT_STATUS_IS_OK(status)) {
1398                                 talloc_free(lck);
1399                                 return status;
1400                         }
1401                 }
1402         }
1403
1404         /* re-resolve the open fd */
1405         status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name);
1406         if (!NT_STATUS_IS_OK(status)) {
1407                 talloc_free(lck);
1408                 return status;
1409         }
1410
1411         if (f->handle->name->stream_id == 0 &&
1412             (io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE ||
1413              io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF)) {
1414                 /* for overwrite we need to replace file permissions */
1415                 uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE;
1416                 mode_t mode = pvfs_fileperms(pvfs, attrib);
1417                 if (fchmod(fd, mode) == -1) {
1418                         talloc_free(lck);
1419                         return pvfs_map_errno(pvfs, errno);
1420                 }
1421                 name->dos.attrib = attrib;
1422                 status = pvfs_dosattrib_save(pvfs, name, fd);
1423                 if (!NT_STATUS_IS_OK(status)) {
1424                         talloc_free(lck);
1425                         return status;
1426                 }
1427         }
1428             
1429         talloc_free(lck);
1430
1431         status = ntvfs_handle_set_backend_data(h, ntvfs, f);
1432         NT_STATUS_NOT_OK_RETURN(status);
1433
1434         /* mark the open as having completed fully, so delete on close
1435            can now be used */
1436         f->handle->open_completed     = true;
1437
1438         io->generic.out.oplock_level  = oplock_granted;
1439         io->generic.out.file.ntvfs    = h;
1440         io->generic.out.create_action = stream_existed?
1441                 NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED;
1442         io->generic.out.create_time   = name->dos.create_time;
1443         io->generic.out.access_time   = name->dos.access_time;
1444         io->generic.out.write_time    = name->dos.write_time;
1445         io->generic.out.change_time   = name->dos.change_time;
1446         io->generic.out.attrib        = name->dos.attrib;
1447         io->generic.out.alloc_size    = name->dos.alloc_size;
1448         io->generic.out.size          = name->st.st_size;
1449         io->generic.out.file_type     = FILE_TYPE_DISK;
1450         io->generic.out.ipc_state     = 0;
1451         io->generic.out.is_directory  = 0;
1452
1453         return NT_STATUS_OK;
1454 }
1455
1456
1457 /*
1458   close a file
1459 */
1460 NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs,
1461                     struct ntvfs_request *req, union smb_close *io)
1462 {
1463         struct pvfs_state *pvfs = ntvfs->private_data;
1464         struct pvfs_file *f;
1465         struct utimbuf unix_times;
1466
1467         if (io->generic.level == RAW_CLOSE_SPLCLOSE) {
1468                 return NT_STATUS_DOS(ERRSRV, ERRerror);
1469         }
1470
1471         if (io->generic.level != RAW_CLOSE_CLOSE) {
1472                 return ntvfs_map_close(ntvfs, req, io);
1473         }
1474
1475         f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs);
1476         if (!f) {
1477                 return NT_STATUS_INVALID_HANDLE;
1478         }
1479
1480         if (!null_time(io->close.in.write_time)) {
1481                 unix_times.actime = 0;
1482                 unix_times.modtime = io->close.in.write_time;
1483                 utime(f->handle->name->full_name, &unix_times);
1484         } else if (f->handle->sticky_write_time) {
1485                 unix_times.actime = 0;
1486                 unix_times.modtime = nt_time_to_unix(f->handle->name->dos.write_time);
1487                 utime(f->handle->name->full_name, &unix_times);
1488         }
1489
1490         talloc_free(f);
1491
1492         return NT_STATUS_OK;
1493 }
1494
1495
1496 /*
1497   logoff - close all file descriptors open by a vuid
1498 */
1499 NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs,
1500                      struct ntvfs_request *req)
1501 {
1502         struct pvfs_state *pvfs = ntvfs->private_data;
1503         struct pvfs_file *f, *next;
1504
1505         for (f=pvfs->files.list;f;f=next) {
1506                 next = f->next;
1507                 if (f->ntvfs->session_info == req->session_info) {
1508                         talloc_free(f);
1509                 }
1510         }
1511
1512         return NT_STATUS_OK;
1513 }
1514
1515
1516 /*
1517   exit - close files for the current pid
1518 */
1519 NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs,
1520                    struct ntvfs_request *req)
1521 {
1522         struct pvfs_state *pvfs = ntvfs->private_data;
1523         struct pvfs_file *f, *next;
1524
1525         for (f=pvfs->files.list;f;f=next) {
1526                 next = f->next;
1527                 if (f->ntvfs->session_info == req->session_info &&
1528                     f->ntvfs->smbpid == req->smbpid) {
1529                         talloc_free(f);
1530                 }
1531         }
1532
1533         return NT_STATUS_OK;
1534 }
1535
1536
1537 /*
1538   change the delete on close flag on an already open file
1539 */
1540 NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs,
1541                                   struct ntvfs_request *req, 
1542                                   struct pvfs_file *f, bool del_on_close)
1543 {
1544         struct odb_lock *lck;
1545         NTSTATUS status;
1546
1547         if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && del_on_close) {
1548                 return NT_STATUS_CANNOT_DELETE;
1549         }
1550         
1551         if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
1552             !pvfs_directory_empty(pvfs, f->handle->name)) {
1553                 return NT_STATUS_DIRECTORY_NOT_EMPTY;
1554         }
1555
1556         if (del_on_close) {
1557                 f->handle->create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1558         } else {
1559                 f->handle->create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1560         }
1561         
1562         lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
1563         if (lck == NULL) {
1564                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1565         }
1566
1567         status = odb_set_delete_on_close(lck, del_on_close);
1568
1569         talloc_free(lck);
1570
1571         return status;
1572 }
1573
1574
1575 /*
1576   determine if a file can be deleted, or if it is prevented by an
1577   already open file
1578 */
1579 NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, 
1580                          struct ntvfs_request *req,
1581                          struct pvfs_filename *name,
1582                          struct odb_lock **lckp)
1583 {
1584         NTSTATUS status;
1585         DATA_BLOB key;
1586         struct odb_lock *lck;
1587         uint32_t share_access;
1588         uint32_t access_mask;
1589         bool delete_on_close;
1590
1591         status = pvfs_locking_key(name, name, &key);
1592         if (!NT_STATUS_IS_OK(status)) {
1593                 return NT_STATUS_NO_MEMORY;
1594         }
1595
1596         lck = odb_lock(req, pvfs->odb_context, &key);
1597         if (lck == NULL) {
1598                 DEBUG(0,("Unable to lock opendb for can_delete\n"));
1599                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1600         }
1601
1602         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1603                           NTCREATEX_SHARE_ACCESS_WRITE |
1604                           NTCREATEX_SHARE_ACCESS_DELETE;
1605         access_mask     = SEC_STD_DELETE;
1606         delete_on_close = true;
1607
1608         status = odb_can_open(lck, name->stream_id,
1609                               share_access, access_mask, delete_on_close,
1610                               NTCREATEX_DISP_OPEN, false);
1611
1612         if (NT_STATUS_IS_OK(status)) {
1613                 status = pvfs_access_check_simple(pvfs, req, name, access_mask);
1614         }
1615
1616         /*
1617          * if it's a sharing violation or we got no oplock
1618          * only keep the lock if the caller requested access
1619          * to the lock
1620          */
1621         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1622             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1623                 if (lckp) {
1624                         *lckp = lck;
1625                 } else {
1626                         talloc_free(lck);
1627                 }
1628         } else if (!NT_STATUS_IS_OK(status)) {
1629                 talloc_free(lck);
1630                 if (lckp) {
1631                         *lckp = NULL;
1632                 }
1633         } else if (lckp) {
1634                 *lckp = lck;
1635         }
1636
1637         return status;
1638 }
1639
1640 /*
1641   determine if a file can be renamed, or if it is prevented by an
1642   already open file
1643 */
1644 NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, 
1645                          struct ntvfs_request *req,
1646                          struct pvfs_filename *name,
1647                          struct odb_lock **lckp)
1648 {
1649         NTSTATUS status;
1650         DATA_BLOB key;
1651         struct odb_lock *lck;
1652         uint32_t share_access;
1653         uint32_t access_mask;
1654         bool delete_on_close;
1655
1656         status = pvfs_locking_key(name, name, &key);
1657         if (!NT_STATUS_IS_OK(status)) {
1658                 return NT_STATUS_NO_MEMORY;
1659         }
1660
1661         lck = odb_lock(req, pvfs->odb_context, &key);
1662         if (lck == NULL) {
1663                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1664                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1665         }
1666
1667         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1668                           NTCREATEX_SHARE_ACCESS_WRITE;
1669         access_mask     = SEC_STD_DELETE;
1670         delete_on_close = false;
1671
1672         status = odb_can_open(lck, name->stream_id,
1673                               share_access, access_mask, delete_on_close,
1674                               NTCREATEX_DISP_OPEN, false);
1675
1676         /*
1677          * if it's a sharing violation or we got no oplock
1678          * only keep the lock if the caller requested access
1679          * to the lock
1680          */
1681         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1682             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1683                 if (lckp) {
1684                         *lckp = lck;
1685                 } else {
1686                         talloc_free(lck);
1687                 }
1688         } else if (!NT_STATUS_IS_OK(status)) {
1689                 talloc_free(lck);
1690                 if (lckp) {
1691                         *lckp = NULL;
1692                 }
1693         } else if (lckp) {
1694                 *lckp = lck;
1695         }
1696
1697         return status;
1698 }
1699
1700 /*
1701   determine if the file size of a file can be changed,
1702   or if it is prevented by an already open file
1703 */
1704 NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs,
1705                                    struct ntvfs_request *req,
1706                                    struct pvfs_filename *name,
1707                                    struct odb_lock **lckp)
1708 {
1709         NTSTATUS status;
1710         DATA_BLOB key;
1711         struct odb_lock *lck;
1712         uint32_t share_access;
1713         uint32_t access_mask;
1714         bool break_to_none;
1715         bool delete_on_close;
1716
1717         status = pvfs_locking_key(name, name, &key);
1718         if (!NT_STATUS_IS_OK(status)) {
1719                 return NT_STATUS_NO_MEMORY;
1720         }
1721
1722         lck = odb_lock(req, pvfs->odb_context, &key);
1723         if (lck == NULL) {
1724                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1725                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1726         }
1727
1728         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1729                           NTCREATEX_SHARE_ACCESS_WRITE |
1730                           NTCREATEX_SHARE_ACCESS_DELETE;
1731         /*
1732          * I would have thought that we would need to pass
1733          * SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA here too
1734          *
1735          * But you only need SEC_FILE_WRITE_ATTRIBUTE permissions
1736          * to set the filesize.
1737          *
1738          * --metze
1739          */
1740         access_mask     = SEC_FILE_WRITE_ATTRIBUTE;
1741         delete_on_close = false;
1742         break_to_none   = true;
1743
1744         status = odb_can_open(lck, name->stream_id,
1745                               share_access, access_mask, delete_on_close,
1746                               NTCREATEX_DISP_OPEN, break_to_none);
1747
1748         /*
1749          * if it's a sharing violation or we got no oplock
1750          * only keep the lock if the caller requested access
1751          * to the lock
1752          */
1753         if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1754             NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1755                 if (lckp) {
1756                         *lckp = lck;
1757                 } else {
1758                         talloc_free(lck);
1759                 }
1760         } else if (!NT_STATUS_IS_OK(status)) {
1761                 talloc_free(lck);
1762                 if (lckp) {
1763                         *lckp = NULL;
1764                 }
1765         } else if (lckp) {
1766                 *lckp = lck;
1767         }
1768
1769         return status;
1770 }
1771
1772 /*
1773   determine if file meta data can be accessed, or if it is prevented by an
1774   already open file
1775 */
1776 NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, 
1777                        struct ntvfs_request *req,
1778                        struct pvfs_filename *name)
1779 {
1780         NTSTATUS status;
1781         DATA_BLOB key;
1782         struct odb_lock *lck;
1783         uint32_t share_access;
1784         uint32_t access_mask;
1785         bool delete_on_close;
1786
1787         status = pvfs_locking_key(name, name, &key);
1788         if (!NT_STATUS_IS_OK(status)) {
1789                 return NT_STATUS_NO_MEMORY;
1790         }
1791
1792         lck = odb_lock(req, pvfs->odb_context, &key);
1793         if (lck == NULL) {
1794                 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1795                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1796         }
1797
1798         share_access    = NTCREATEX_SHARE_ACCESS_READ |
1799                           NTCREATEX_SHARE_ACCESS_WRITE;
1800         access_mask     = SEC_FILE_READ_ATTRIBUTE;
1801         delete_on_close = false;
1802
1803         status = odb_can_open(lck, name->stream_id,
1804                               share_access, access_mask, delete_on_close,
1805                               NTCREATEX_DISP_OPEN, false);
1806
1807         if (!NT_STATUS_IS_OK(status)) {
1808                 talloc_free(lck);
1809         }
1810
1811         return status;
1812 }
1813
1814
1815 /*
1816   determine if delete on close is set on 
1817 */
1818 bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h)
1819 {
1820         NTSTATUS status;
1821         bool del_on_close;
1822
1823         status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, 
1824                                          &del_on_close);
1825         if (!NT_STATUS_IS_OK(status)) {
1826                 DEBUG(1,("WARNING: unable to determine delete on close status for open file\n"));
1827                 return false;
1828         }
1829
1830         return del_on_close;
1831 }