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