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