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