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