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