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