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