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