s4: update setntacl and getntacl to select the adaquate backend (fs/tdb) for storing...
[Samba/ekacnet.git] / source4 / ntvfs / posix / pvfs_open.c
blobaa66ad782d12906853e331efcb2308dede3dccf5
1 /*
2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - open and close
6 Copyright (C) Andrew Tridgell 2004
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.
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.
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/>.
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"
31 find open file handle given fnum
33 struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs,
34 struct ntvfs_request *req, struct ntvfs_handle *h)
36 void *p;
37 struct pvfs_file *f;
39 p = ntvfs_handle_get_backend_data(h, pvfs->ntvfs);
40 if (!p) return NULL;
42 f = talloc_get_type(p, struct pvfs_file);
43 if (!f) return NULL;
45 return f;
49 cleanup a open directory handle
51 static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h)
53 if (h->have_opendb_entry) {
54 struct odb_lock *lck;
55 NTSTATUS status;
56 const char *delete_path = NULL;
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;
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)));
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)));
76 if (rmdir(delete_path) != 0) {
77 DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n",
78 delete_path, strerror(errno)));
82 talloc_free(lck);
85 return 0;
89 cleanup a open directory fnum
91 static int pvfs_dir_fnum_destructor(struct pvfs_file *f)
93 DLIST_REMOVE(f->pvfs->files.list, f);
94 ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs);
96 return 0;
100 setup any EAs and the ACL on newly created files/directories
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 struct security_descriptor *sd)
109 NTSTATUS status = NT_STATUS_OK;
111 /* setup any EAs that were asked for */
112 if (io->ntcreatex.in.ea_list) {
113 status = pvfs_setfileinfo_ea_set(pvfs, name, fd,
114 io->ntcreatex.in.ea_list->num_eas,
115 io->ntcreatex.in.ea_list->eas);
116 if (!NT_STATUS_IS_OK(status)) {
117 return status;
121 /* setup an initial sec_desc if requested */
122 if (sd && (sd->type & SEC_DESC_DACL_PRESENT)) {
123 union smb_setfileinfo set;
125 * TODO: set the full ACL!
126 * - vista denies the creation of the file with NT_STATUS_PRIVILEGE_NOT_HELD,
127 * when a SACL is present on the sd,
128 * but the user doesn't have SeSecurityPrivilege
129 * - w2k3 allows it
131 set.set_secdesc.in.file.ntvfs = f->ntvfs;
132 set.set_secdesc.in.secinfo_flags = SECINFO_DACL;
133 set.set_secdesc.in.sd = sd;
135 status = pvfs_acl_set(pvfs, req, name, fd, SEC_STD_WRITE_DAC, &set);
138 return status;
142 form the lock context used for opendb locking. Note that we must
143 zero here to take account of possible padding on some architectures
145 NTSTATUS pvfs_locking_key(struct pvfs_filename *name,
146 TALLOC_CTX *mem_ctx, DATA_BLOB *key)
148 struct {
149 dev_t device;
150 ino_t inode;
151 } lock_context;
152 ZERO_STRUCT(lock_context);
154 lock_context.device = name->st.st_dev;
155 lock_context.inode = name->st.st_ino;
157 *key = data_blob_talloc(mem_ctx, &lock_context, sizeof(lock_context));
158 if (key->data == NULL) {
159 return NT_STATUS_NO_MEMORY;
162 return NT_STATUS_OK;
167 open a directory
169 static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs,
170 struct ntvfs_request *req,
171 struct pvfs_filename *name,
172 union smb_open *io)
174 struct pvfs_file *f;
175 struct ntvfs_handle *h;
176 NTSTATUS status;
177 uint32_t create_action;
178 uint32_t access_mask = io->generic.in.access_mask;
179 struct odb_lock *lck;
180 bool del_on_close;
181 uint32_t create_options;
182 uint32_t share_access;
183 bool forced;
184 struct security_descriptor *sd = NULL;
186 create_options = io->generic.in.create_options;
187 share_access = io->generic.in.share_access;
189 forced = (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)?true:false;
191 if (name->stream_name) {
192 if (forced) {
193 return NT_STATUS_NOT_A_DIRECTORY;
194 } else {
195 return NT_STATUS_FILE_IS_A_DIRECTORY;
199 /* if the client says it must be a directory, and it isn't,
200 then fail */
201 if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
202 return NT_STATUS_NOT_A_DIRECTORY;
205 /* found with gentest */
206 if (io->ntcreatex.in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED &&
207 (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) &&
208 (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
209 return NT_STATUS_INVALID_PARAMETER;
212 switch (io->generic.in.open_disposition) {
213 case NTCREATEX_DISP_OPEN_IF:
214 break;
216 case NTCREATEX_DISP_OPEN:
217 if (!name->exists) {
218 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
220 break;
222 case NTCREATEX_DISP_CREATE:
223 if (name->exists) {
224 return NT_STATUS_OBJECT_NAME_COLLISION;
226 break;
228 case NTCREATEX_DISP_OVERWRITE_IF:
229 case NTCREATEX_DISP_OVERWRITE:
230 case NTCREATEX_DISP_SUPERSEDE:
231 default:
232 return NT_STATUS_INVALID_PARAMETER;
235 status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
236 NT_STATUS_NOT_OK_RETURN(status);
238 f = talloc(h, struct pvfs_file);
239 if (f == NULL) {
240 return NT_STATUS_NO_MEMORY;
243 f->handle = talloc(f, struct pvfs_file_handle);
244 if (f->handle == NULL) {
245 return NT_STATUS_NO_MEMORY;
248 if (name->exists) {
249 /* check the security descriptor */
250 status = pvfs_access_check(pvfs, req, name, &access_mask);
251 } else {
252 sd = io->ntcreatex.in.sec_desc;
253 status = pvfs_access_check_create(pvfs, req, name, &access_mask, true, &sd);
255 NT_STATUS_NOT_OK_RETURN(status);
257 if (io->generic.in.query_maximal_access) {
258 status = pvfs_access_maximal_allowed(pvfs, req, name,
259 &io->generic.out.maximal_access);
260 NT_STATUS_NOT_OK_RETURN(status);
263 f->ntvfs = h;
264 f->pvfs = pvfs;
265 f->pending_list = NULL;
266 f->lock_count = 0;
267 f->share_access = io->generic.in.share_access;
268 f->impersonation = io->generic.in.impersonation;
269 f->access_mask = access_mask;
270 f->brl_handle = NULL;
271 f->notify_buffer = NULL;
272 f->search = NULL;
274 f->handle->pvfs = pvfs;
275 f->handle->name = talloc_steal(f->handle, name);
276 f->handle->fd = -1;
277 f->handle->odb_locking_key = data_blob(NULL, 0);
278 f->handle->create_options = io->generic.in.create_options;
279 f->handle->seek_offset = 0;
280 f->handle->position = 0;
281 f->handle->mode = 0;
282 f->handle->oplock = NULL;
283 ZERO_STRUCT(f->handle->write_time);
284 f->handle->open_completed = false;
286 if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
287 pvfs_directory_empty(pvfs, f->handle->name)) {
288 del_on_close = true;
289 } else {
290 del_on_close = false;
293 if (name->exists) {
294 /* form the lock context used for opendb locking */
295 status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
296 if (!NT_STATUS_IS_OK(status)) {
297 return status;
300 /* get a lock on this file before the actual open */
301 lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
302 if (lck == NULL) {
303 DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
304 name->full_name));
305 /* we were supposed to do a blocking lock, so something
306 is badly wrong! */
307 return NT_STATUS_INTERNAL_DB_CORRUPTION;
310 /* see if we are allowed to open at the same time as existing opens */
311 status = odb_can_open(lck, name->stream_id,
312 share_access, access_mask, del_on_close,
313 io->generic.in.open_disposition, false);
314 if (!NT_STATUS_IS_OK(status)) {
315 talloc_free(lck);
316 return status;
319 /* now really mark the file as open */
320 status = odb_open_file(lck, f->handle, name->full_name,
321 NULL, name->dos.write_time,
322 false, OPLOCK_NONE, NULL);
324 if (!NT_STATUS_IS_OK(status)) {
325 talloc_free(lck);
326 return status;
329 f->handle->have_opendb_entry = true;
332 DLIST_ADD(pvfs->files.list, f);
334 /* setup destructors to avoid leaks on abnormal termination */
335 talloc_set_destructor(f->handle, pvfs_dir_handle_destructor);
336 talloc_set_destructor(f, pvfs_dir_fnum_destructor);
338 if (!name->exists) {
339 uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY;
340 mode_t mode = pvfs_fileperms(pvfs, attrib);
342 if (mkdir(name->full_name, mode) == -1) {
343 return pvfs_map_errno(pvfs,errno);
346 pvfs_xattr_unlink_hook(pvfs, name->full_name);
348 status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name);
349 if (!NT_STATUS_IS_OK(status)) {
350 goto cleanup_delete;
353 status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io, sd);
354 if (!NT_STATUS_IS_OK(status)) {
355 goto cleanup_delete;
358 /* form the lock context used for opendb locking */
359 status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
360 if (!NT_STATUS_IS_OK(status)) {
361 return status;
364 lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
365 if (lck == NULL) {
366 DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
367 name->full_name));
368 /* we were supposed to do a blocking lock, so something
369 is badly wrong! */
370 return NT_STATUS_INTERNAL_DB_CORRUPTION;
373 status = odb_can_open(lck, name->stream_id,
374 share_access, access_mask, del_on_close,
375 io->generic.in.open_disposition, false);
377 if (!NT_STATUS_IS_OK(status)) {
378 goto cleanup_delete;
381 status = odb_open_file(lck, f->handle, name->full_name,
382 NULL, name->dos.write_time,
383 false, OPLOCK_NONE, NULL);
385 if (!NT_STATUS_IS_OK(status)) {
386 goto cleanup_delete;
389 f->handle->have_opendb_entry = true;
391 create_action = NTCREATEX_ACTION_CREATED;
393 notify_trigger(pvfs->notify_context,
394 NOTIFY_ACTION_ADDED,
395 FILE_NOTIFY_CHANGE_DIR_NAME,
396 name->full_name);
397 } else {
398 create_action = NTCREATEX_ACTION_EXISTED;
401 if (!name->exists) {
402 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
405 /* the open succeeded, keep this handle permanently */
406 status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f);
407 if (!NT_STATUS_IS_OK(status)) {
408 goto cleanup_delete;
411 f->handle->open_completed = true;
413 io->generic.out.oplock_level = OPLOCK_NONE;
414 io->generic.out.file.ntvfs = h;
415 io->generic.out.create_action = create_action;
416 io->generic.out.create_time = name->dos.create_time;
417 io->generic.out.access_time = name->dos.access_time;
418 io->generic.out.write_time = name->dos.write_time;
419 io->generic.out.change_time = name->dos.change_time;
420 io->generic.out.attrib = name->dos.attrib;
421 io->generic.out.alloc_size = name->dos.alloc_size;
422 io->generic.out.size = name->st.st_size;
423 io->generic.out.file_type = FILE_TYPE_DISK;
424 io->generic.out.ipc_state = 0;
425 io->generic.out.is_directory = 1;
427 return NT_STATUS_OK;
429 cleanup_delete:
430 rmdir(name->full_name);
431 return status;
435 destroy a struct pvfs_file_handle
437 static int pvfs_handle_destructor(struct pvfs_file_handle *h)
439 talloc_free(h->write_time.update_event);
440 h->write_time.update_event = NULL;
442 if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
443 h->name->stream_name) {
444 NTSTATUS status;
445 status = pvfs_stream_delete(h->pvfs, h->name, h->fd);
446 if (!NT_STATUS_IS_OK(status)) {
447 DEBUG(0,("Failed to delete stream '%s' on close of '%s'\n",
448 h->name->stream_name, h->name->full_name));
452 if (h->fd != -1) {
453 if (close(h->fd) != 0) {
454 DEBUG(0,("pvfs_handle_destructor: close(%d) failed for %s - %s\n",
455 h->fd, h->name->full_name, strerror(errno)));
457 h->fd = -1;
460 if (!h->write_time.update_forced &&
461 h->write_time.update_on_close &&
462 h->write_time.close_time == 0) {
463 struct timeval tv;
464 tv = timeval_current();
465 h->write_time.close_time = timeval_to_nttime(&tv);
468 if (h->have_opendb_entry) {
469 struct odb_lock *lck;
470 NTSTATUS status;
471 const char *delete_path = NULL;
473 lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key);
474 if (lck == NULL) {
475 DEBUG(0,("Unable to lock opendb for close\n"));
476 return 0;
479 if (h->write_time.update_forced) {
480 status = odb_get_file_infos(h->pvfs->odb_context,
481 &h->odb_locking_key,
482 NULL,
483 &h->write_time.close_time);
484 if (!NT_STATUS_IS_OK(status)) {
485 DEBUG(0,("Unable get write time for '%s' - %s\n",
486 h->name->full_name, nt_errstr(status)));
489 h->write_time.update_forced = false;
490 h->write_time.update_on_close = true;
491 } else if (h->write_time.update_on_close) {
492 status = odb_set_write_time(lck, h->write_time.close_time, true);
493 if (!NT_STATUS_IS_OK(status)) {
494 DEBUG(0,("Unable set write time for '%s' - %s\n",
495 h->name->full_name, nt_errstr(status)));
499 status = odb_close_file(lck, h, &delete_path);
500 if (!NT_STATUS_IS_OK(status)) {
501 DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n",
502 h->name->full_name, nt_errstr(status)));
505 if (h->name->stream_name == NULL &&
506 h->open_completed && delete_path) {
507 status = pvfs_xattr_unlink_hook(h->pvfs, delete_path);
508 if (!NT_STATUS_IS_OK(status)) {
509 DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n",
510 delete_path, nt_errstr(status)));
512 if (unlink(delete_path) != 0) {
513 DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n",
514 delete_path, strerror(errno)));
515 } else {
516 notify_trigger(h->pvfs->notify_context,
517 NOTIFY_ACTION_REMOVED,
518 FILE_NOTIFY_CHANGE_FILE_NAME,
519 delete_path);
521 h->write_time.update_on_close = false;
524 talloc_free(lck);
527 if (h->write_time.update_on_close) {
528 struct timeval tv[2];
530 nttime_to_timeval(&tv[0], h->name->dos.access_time);
531 nttime_to_timeval(&tv[1], h->write_time.close_time);
533 if (!timeval_is_zero(&tv[0]) || !timeval_is_zero(&tv[1])) {
534 if (utimes(h->name->full_name, tv) == -1) {
535 DEBUG(3,("pvfs_handle_destructor: utimes() failed '%s' - %s\n",
536 h->name->full_name, strerror(errno)));
541 return 0;
546 destroy a struct pvfs_file
548 static int pvfs_fnum_destructor(struct pvfs_file *f)
550 DLIST_REMOVE(f->pvfs->files.list, f);
551 pvfs_lock_close(f->pvfs, f);
552 ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs);
554 return 0;
559 form the lock context used for byte range locking. This is separate
560 from the locking key used for opendb locking as it needs to take
561 account of file streams (each stream is a separate byte range
562 locking space)
564 static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx,
565 struct pvfs_filename *name,
566 struct ntvfs_handle *ntvfs,
567 struct brl_handle **_h)
569 DATA_BLOB odb_key, key;
570 NTSTATUS status;
571 struct brl_handle *h;
573 status = pvfs_locking_key(name, mem_ctx, &odb_key);
574 NT_STATUS_NOT_OK_RETURN(status);
576 if (name->stream_name == NULL) {
577 key = odb_key;
578 } else {
579 key = data_blob_talloc(mem_ctx, NULL,
580 odb_key.length + strlen(name->stream_name) + 1);
581 NT_STATUS_HAVE_NO_MEMORY(key.data);
582 memcpy(key.data, odb_key.data, odb_key.length);
583 memcpy(key.data + odb_key.length,
584 name->stream_name, strlen(name->stream_name) + 1);
585 data_blob_free(&odb_key);
588 h = brl_create_handle(mem_ctx, ntvfs, &key);
589 NT_STATUS_HAVE_NO_MEMORY(h);
591 *_h = h;
592 return NT_STATUS_OK;
596 create a new file
598 static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs,
599 struct ntvfs_request *req,
600 struct pvfs_filename *name,
601 union smb_open *io)
603 struct pvfs_file *f;
604 NTSTATUS status;
605 struct ntvfs_handle *h;
606 int flags, fd;
607 struct odb_lock *lck;
608 uint32_t create_options = io->generic.in.create_options;
609 uint32_t share_access = io->generic.in.share_access;
610 uint32_t access_mask = io->generic.in.access_mask;
611 mode_t mode;
612 uint32_t attrib;
613 bool del_on_close;
614 struct pvfs_filename *parent;
615 uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
616 bool allow_level_II_oplock = false;
617 struct security_descriptor *sd = NULL;
619 if (io->ntcreatex.in.file_attr & ~FILE_ATTRIBUTE_ALL_MASK) {
620 return NT_STATUS_INVALID_PARAMETER;
623 if (io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_ENCRYPTED) {
624 return NT_STATUS_ACCESS_DENIED;
627 if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) &&
628 (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
629 return NT_STATUS_CANNOT_DELETE;
632 sd = io->ntcreatex.in.sec_desc;
633 status = pvfs_access_check_create(pvfs, req, name, &access_mask, false, &sd);
634 NT_STATUS_NOT_OK_RETURN(status);
636 /* check that the parent isn't opened with delete on close set */
637 status = pvfs_resolve_parent(pvfs, req, name, &parent);
638 if (NT_STATUS_IS_OK(status)) {
639 DATA_BLOB locking_key;
640 status = pvfs_locking_key(parent, req, &locking_key);
641 NT_STATUS_NOT_OK_RETURN(status);
642 status = odb_get_file_infos(pvfs->odb_context, &locking_key,
643 &del_on_close, NULL);
644 NT_STATUS_NOT_OK_RETURN(status);
645 if (del_on_close) {
646 return NT_STATUS_DELETE_PENDING;
650 if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) {
651 flags = O_RDWR;
652 } else {
653 flags = O_RDONLY;
656 status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
657 NT_STATUS_NOT_OK_RETURN(status);
659 f = talloc(h, struct pvfs_file);
660 NT_STATUS_HAVE_NO_MEMORY(f);
662 f->handle = talloc(f, struct pvfs_file_handle);
663 NT_STATUS_HAVE_NO_MEMORY(f->handle);
665 attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE;
666 mode = pvfs_fileperms(pvfs, attrib);
668 /* create the file */
669 fd = open(name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode);
670 if (fd == -1) {
671 return pvfs_map_errno(pvfs, errno);
674 pvfs_xattr_unlink_hook(pvfs, name->full_name);
676 /* if this was a stream create then create the stream as well */
677 if (name->stream_name) {
678 status = pvfs_stream_create(pvfs, name, fd);
679 if (!NT_STATUS_IS_OK(status)) {
680 close(fd);
681 return status;
685 /* re-resolve the open fd */
686 status = pvfs_resolve_name_fd(pvfs, fd, name, 0);
687 if (!NT_STATUS_IS_OK(status)) {
688 close(fd);
689 return status;
692 /* support initial alloc sizes */
693 name->dos.alloc_size = io->ntcreatex.in.alloc_size;
694 name->dos.attrib = attrib;
695 status = pvfs_dosattrib_save(pvfs, name, fd);
696 if (!NT_STATUS_IS_OK(status)) {
697 goto cleanup_delete;
701 status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io, sd);
702 if (!NT_STATUS_IS_OK(status)) {
703 goto cleanup_delete;
706 if (io->generic.in.query_maximal_access) {
707 status = pvfs_access_maximal_allowed(pvfs, req, name,
708 &io->generic.out.maximal_access);
709 NT_STATUS_NOT_OK_RETURN(status);
712 /* form the lock context used for byte range locking and
713 opendb locking */
714 status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
715 if (!NT_STATUS_IS_OK(status)) {
716 goto cleanup_delete;
719 status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle);
720 if (!NT_STATUS_IS_OK(status)) {
721 goto cleanup_delete;
724 /* grab a lock on the open file record */
725 lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
726 if (lck == NULL) {
727 DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
728 name->full_name));
729 /* we were supposed to do a blocking lock, so something
730 is badly wrong! */
731 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
732 goto cleanup_delete;
735 if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
736 del_on_close = true;
737 } else {
738 del_on_close = false;
741 if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
742 oplock_level = OPLOCK_NONE;
743 } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) {
744 oplock_level = OPLOCK_BATCH;
745 } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_OPLOCK) {
746 oplock_level = OPLOCK_EXCLUSIVE;
749 if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) {
750 allow_level_II_oplock = true;
753 status = odb_can_open(lck, name->stream_id,
754 share_access, access_mask, del_on_close,
755 io->generic.in.open_disposition, false);
756 if (!NT_STATUS_IS_OK(status)) {
757 talloc_free(lck);
758 /* bad news, we must have hit a race - we don't delete the file
759 here as the most likely scenario is that someone else created
760 the file at the same time */
761 close(fd);
762 return status;
765 f->ntvfs = h;
766 f->pvfs = pvfs;
767 f->pending_list = NULL;
768 f->lock_count = 0;
769 f->share_access = io->generic.in.share_access;
770 f->access_mask = access_mask;
771 f->impersonation = io->generic.in.impersonation;
772 f->notify_buffer = NULL;
773 f->search = NULL;
775 f->handle->pvfs = pvfs;
776 f->handle->name = talloc_steal(f->handle, name);
777 f->handle->fd = fd;
778 f->handle->create_options = io->generic.in.create_options;
779 f->handle->seek_offset = 0;
780 f->handle->position = 0;
781 f->handle->mode = 0;
782 f->handle->oplock = NULL;
783 f->handle->have_opendb_entry = true;
784 ZERO_STRUCT(f->handle->write_time);
785 f->handle->open_completed = false;
787 status = odb_open_file(lck, f->handle, name->full_name,
788 &f->handle->fd, name->dos.write_time,
789 allow_level_II_oplock,
790 oplock_level, &oplock_granted);
791 talloc_free(lck);
792 if (!NT_STATUS_IS_OK(status)) {
793 /* bad news, we must have hit a race - we don't delete the file
794 here as the most likely scenario is that someone else created
795 the file at the same time */
796 close(fd);
797 return status;
800 DLIST_ADD(pvfs->files.list, f);
802 /* setup a destructor to avoid file descriptor leaks on
803 abnormal termination */
804 talloc_set_destructor(f, pvfs_fnum_destructor);
805 talloc_set_destructor(f->handle, pvfs_handle_destructor);
807 if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
808 oplock_granted = OPLOCK_BATCH;
809 } else if (oplock_granted != OPLOCK_NONE) {
810 status = pvfs_setup_oplock(f, oplock_granted);
811 if (!NT_STATUS_IS_OK(status)) {
812 return status;
816 io->generic.out.oplock_level = oplock_granted;
817 io->generic.out.file.ntvfs = f->ntvfs;
818 io->generic.out.create_action = NTCREATEX_ACTION_CREATED;
819 io->generic.out.create_time = name->dos.create_time;
820 io->generic.out.access_time = name->dos.access_time;
821 io->generic.out.write_time = name->dos.write_time;
822 io->generic.out.change_time = name->dos.change_time;
823 io->generic.out.attrib = name->dos.attrib;
824 io->generic.out.alloc_size = name->dos.alloc_size;
825 io->generic.out.size = name->st.st_size;
826 io->generic.out.file_type = FILE_TYPE_DISK;
827 io->generic.out.ipc_state = 0;
828 io->generic.out.is_directory = 0;
830 /* success - keep the file handle */
831 status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f);
832 if (!NT_STATUS_IS_OK(status)) {
833 goto cleanup_delete;
836 f->handle->open_completed = true;
838 notify_trigger(pvfs->notify_context,
839 NOTIFY_ACTION_ADDED,
840 FILE_NOTIFY_CHANGE_FILE_NAME,
841 name->full_name);
843 return NT_STATUS_OK;
845 cleanup_delete:
846 close(fd);
847 unlink(name->full_name);
848 return status;
852 state of a pending retry
854 struct pvfs_odb_retry {
855 struct ntvfs_module_context *ntvfs;
856 struct ntvfs_request *req;
857 DATA_BLOB odb_locking_key;
858 void *io;
859 void *private_data;
860 void (*callback)(struct pvfs_odb_retry *r,
861 struct ntvfs_module_context *ntvfs,
862 struct ntvfs_request *req,
863 void *io,
864 void *private_data,
865 enum pvfs_wait_notice reason);
868 /* destroy a pending request */
869 static int pvfs_odb_retry_destructor(struct pvfs_odb_retry *r)
871 struct pvfs_state *pvfs = talloc_get_type(r->ntvfs->private_data,
872 struct pvfs_state);
873 if (r->odb_locking_key.data) {
874 struct odb_lock *lck;
875 lck = odb_lock(r->req, pvfs->odb_context, &r->odb_locking_key);
876 if (lck != NULL) {
877 odb_remove_pending(lck, r);
879 talloc_free(lck);
881 return 0;
884 static void pvfs_odb_retry_callback(void *_r, enum pvfs_wait_notice reason)
886 struct pvfs_odb_retry *r = talloc_get_type(_r, struct pvfs_odb_retry);
888 if (reason == PVFS_WAIT_EVENT) {
890 * The pending odb entry is already removed.
891 * We use a null locking key to indicate this
892 * to the destructor.
894 data_blob_free(&r->odb_locking_key);
897 r->callback(r, r->ntvfs, r->req, r->io, r->private_data, reason);
901 setup for a retry of a request that was rejected
902 by odb_can_open()
904 NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs,
905 struct ntvfs_request *req,
906 struct odb_lock *lck,
907 struct timeval end_time,
908 void *io,
909 void *private_data,
910 void (*callback)(struct pvfs_odb_retry *r,
911 struct ntvfs_module_context *ntvfs,
912 struct ntvfs_request *req,
913 void *io,
914 void *private_data,
915 enum pvfs_wait_notice reason))
917 struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
918 struct pvfs_state);
919 struct pvfs_odb_retry *r;
920 struct pvfs_wait *wait_handle;
921 NTSTATUS status;
923 r = talloc(req, struct pvfs_odb_retry);
924 NT_STATUS_HAVE_NO_MEMORY(r);
926 r->ntvfs = ntvfs;
927 r->req = req;
928 r->io = io;
929 r->private_data = private_data;
930 r->callback = callback;
931 r->odb_locking_key = odb_get_key(r, lck);
932 if (r->odb_locking_key.data == NULL) {
933 return NT_STATUS_NO_MEMORY;
936 /* setup a pending lock */
937 status = odb_open_file_pending(lck, r);
938 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND,status)) {
940 * maybe only a unix application
941 * has the file open
943 data_blob_free(&r->odb_locking_key);
944 } else if (!NT_STATUS_IS_OK(status)) {
945 return status;
948 talloc_free(lck);
950 talloc_set_destructor(r, pvfs_odb_retry_destructor);
952 wait_handle = pvfs_wait_message(pvfs, req,
953 MSG_PVFS_RETRY_OPEN, end_time,
954 pvfs_odb_retry_callback, r);
955 if (wait_handle == NULL) {
956 return NT_STATUS_NO_MEMORY;
959 talloc_steal(r, wait_handle);
961 return NT_STATUS_OK;
965 retry an open after a sharing violation
967 static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r,
968 struct ntvfs_module_context *ntvfs,
969 struct ntvfs_request *req,
970 void *_io,
971 void *private_data,
972 enum pvfs_wait_notice reason)
974 union smb_open *io = talloc_get_type(_io, union smb_open);
975 struct timeval *final_timeout = NULL;
976 NTSTATUS status;
978 if (private_data) {
979 final_timeout = talloc_get_type(private_data,
980 struct timeval);
983 /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably
984 just a bug in their server, but we better do the same */
985 if (reason == PVFS_WAIT_CANCEL) {
986 return;
989 if (reason == PVFS_WAIT_TIMEOUT) {
990 if (final_timeout &&
991 !timeval_expired(final_timeout)) {
993 * we need to retry periodictly
994 * after an EAGAIN as there's
995 * no way the kernel tell us
996 * an oplock is released.
998 goto retry;
1000 /* if it timed out, then give the failure
1001 immediately */
1002 talloc_free(r);
1003 req->async_states->status = NT_STATUS_SHARING_VIOLATION;
1004 req->async_states->send_fn(req);
1005 return;
1008 retry:
1009 talloc_free(r);
1011 /* try the open again, which could trigger another retry setup
1012 if it wants to, so we have to unmark the async flag so we
1013 will know if it does a second async reply */
1014 req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC;
1016 status = pvfs_open(ntvfs, req, io);
1017 if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) {
1018 /* the 2nd try also replied async, so we don't send
1019 the reply yet */
1020 return;
1023 /* re-mark it async, just in case someone up the chain does
1024 paranoid checking */
1025 req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
1027 /* send the reply up the chain */
1028 req->async_states->status = status;
1029 req->async_states->send_fn(req);
1034 special handling for openx DENY_DOS semantics
1036 This function attempts a reference open using an existing handle. If its allowed,
1037 then it returns NT_STATUS_OK, otherwise it returns any other code and normal
1038 open processing continues.
1040 static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs,
1041 struct ntvfs_request *req, union smb_open *io,
1042 struct pvfs_file *f, struct odb_lock *lck)
1044 struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
1045 struct pvfs_state);
1046 struct pvfs_file *f2;
1047 struct pvfs_filename *name;
1048 NTSTATUS status;
1050 /* search for an existing open with the right parameters. Note
1051 the magic ntcreatex options flag, which is set in the
1052 generic mapping code. This might look ugly, but its
1053 actually pretty much now w2k does it internally as well.
1055 If you look at the BASE-DENYDOS test you will see that a
1056 DENY_DOS is a very special case, and in the right
1057 circumstances you actually get the _same_ handle back
1058 twice, rather than a new handle.
1060 for (f2=pvfs->files.list;f2;f2=f2->next) {
1061 if (f2 != f &&
1062 f2->ntvfs->session_info == req->session_info &&
1063 f2->ntvfs->smbpid == req->smbpid &&
1064 (f2->handle->create_options &
1065 (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
1066 NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
1067 (f2->access_mask & SEC_FILE_WRITE_DATA) &&
1068 strcasecmp_m(f2->handle->name->original_name,
1069 io->generic.in.fname)==0) {
1070 break;
1074 if (!f2) {
1075 return NT_STATUS_SHARING_VIOLATION;
1078 /* quite an insane set of semantics ... */
1079 if (is_exe_filename(io->generic.in.fname) &&
1080 (f2->handle->create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
1081 return NT_STATUS_SHARING_VIOLATION;
1085 setup a reference to the existing handle
1087 talloc_free(f->handle);
1088 f->handle = talloc_reference(f, f2->handle);
1090 talloc_free(lck);
1092 name = f->handle->name;
1094 io->generic.out.oplock_level = OPLOCK_NONE;
1095 io->generic.out.file.ntvfs = f->ntvfs;
1096 io->generic.out.create_action = NTCREATEX_ACTION_EXISTED;
1097 io->generic.out.create_time = name->dos.create_time;
1098 io->generic.out.access_time = name->dos.access_time;
1099 io->generic.out.write_time = name->dos.write_time;
1100 io->generic.out.change_time = name->dos.change_time;
1101 io->generic.out.attrib = name->dos.attrib;
1102 io->generic.out.alloc_size = name->dos.alloc_size;
1103 io->generic.out.size = name->st.st_size;
1104 io->generic.out.file_type = FILE_TYPE_DISK;
1105 io->generic.out.ipc_state = 0;
1106 io->generic.out.is_directory = 0;
1108 status = ntvfs_handle_set_backend_data(f->ntvfs, ntvfs, f);
1109 NT_STATUS_NOT_OK_RETURN(status);
1111 return NT_STATUS_OK;
1117 setup for a open retry after a sharing violation
1119 static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs,
1120 struct ntvfs_request *req,
1121 union smb_open *io,
1122 struct pvfs_file *f,
1123 struct odb_lock *lck,
1124 NTSTATUS parent_status)
1126 struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
1127 struct pvfs_state);
1128 NTSTATUS status;
1129 struct timeval end_time;
1130 struct timeval *final_timeout = NULL;
1132 if (io->generic.in.create_options &
1133 (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
1134 /* see if we can satisfy the request using the special DENY_DOS
1135 code */
1136 status = pvfs_open_deny_dos(ntvfs, req, io, f, lck);
1137 if (NT_STATUS_IS_OK(status)) {
1138 return status;
1142 /* the retry should allocate a new file handle */
1143 talloc_free(f);
1145 if (NT_STATUS_EQUAL(parent_status, NT_STATUS_SHARING_VIOLATION)) {
1146 end_time = timeval_add(&req->statistics.request_time,
1147 0, pvfs->sharing_violation_delay);
1148 } else if (NT_STATUS_EQUAL(parent_status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1149 end_time = timeval_add(&req->statistics.request_time,
1150 pvfs->oplock_break_timeout, 0);
1151 } else if (NT_STATUS_EQUAL(parent_status, STATUS_MORE_ENTRIES)) {
1153 * we got EAGAIN which means a unix application
1154 * has an oplock or share mode
1156 * we retry every 4/5 of the sharing violation delay
1157 * to see if the unix application
1158 * has released the oplock or share mode.
1160 final_timeout = talloc(req, struct timeval);
1161 NT_STATUS_HAVE_NO_MEMORY(final_timeout);
1162 *final_timeout = timeval_add(&req->statistics.request_time,
1163 pvfs->oplock_break_timeout,
1165 end_time = timeval_current_ofs(0, (pvfs->sharing_violation_delay*4)/5);
1166 end_time = timeval_min(final_timeout, &end_time);
1167 } else {
1168 return NT_STATUS_INTERNAL_ERROR;
1171 return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io,
1172 final_timeout, pvfs_retry_open_sharing);
1176 open a file
1178 NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs,
1179 struct ntvfs_request *req, union smb_open *io)
1181 struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
1182 struct pvfs_state);
1183 int flags = 0;
1184 struct pvfs_filename *name;
1185 struct pvfs_file *f;
1186 struct ntvfs_handle *h;
1187 NTSTATUS status;
1188 int fd;
1189 struct odb_lock *lck;
1190 uint32_t create_options;
1191 uint32_t create_options_must_ignore_mask;
1192 uint32_t share_access;
1193 uint32_t access_mask;
1194 uint32_t create_action = NTCREATEX_ACTION_EXISTED;
1195 bool del_on_close;
1196 bool stream_existed, stream_truncate=false;
1197 uint32_t oplock_level = OPLOCK_NONE, oplock_granted;
1198 bool allow_level_II_oplock = false;
1200 /* use the generic mapping code to avoid implementing all the
1201 different open calls. */
1202 if (io->generic.level != RAW_OPEN_GENERIC &&
1203 io->generic.level != RAW_OPEN_NTTRANS_CREATE) {
1204 return ntvfs_map_open(ntvfs, req, io);
1207 ZERO_STRUCT(io->generic.out);
1209 create_options = io->generic.in.create_options;
1210 share_access = io->generic.in.share_access;
1211 access_mask = io->generic.in.access_mask;
1213 if (share_access & ~NTCREATEX_SHARE_ACCESS_MASK) {
1214 return NT_STATUS_INVALID_PARAMETER;
1218 * These options are ignored,
1219 * but we reuse some of them as private values for the generic mapping
1221 create_options_must_ignore_mask = NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
1222 create_options_must_ignore_mask &= ~NTCREATEX_OPTIONS_PRIVATE_MASK;
1223 create_options &= ~create_options_must_ignore_mask;
1225 if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) {
1226 DEBUG(2,(__location__ " create_options 0x%x not supported\n",
1227 create_options));
1228 return NT_STATUS_NOT_SUPPORTED;
1231 if (create_options & NTCREATEX_OPTIONS_INVALID_PARAM_MASK) {
1232 return NT_STATUS_INVALID_PARAMETER;
1235 /* TODO: When we implement HSM, add a hook here not to pull
1236 * the actual file off tape, when this option is passed from
1237 * the client */
1238 if (create_options & NTCREATEX_OPTIONS_NO_RECALL) {
1239 /* no-op */
1242 /* TODO: If (unlikely) Linux does a good compressed
1243 * filesystem, we might need an ioctl call for this */
1244 if (create_options & NTCREATEX_OPTIONS_NO_COMPRESSION) {
1245 /* no-op */
1248 if (create_options & NTCREATEX_OPTIONS_NO_INTERMEDIATE_BUFFERING) {
1249 create_options |= NTCREATEX_OPTIONS_WRITE_THROUGH;
1252 /* Open the file with sync, if they asked for it, but
1253 'strict sync = no' turns this client request into a no-op */
1254 if (create_options & (NTCREATEX_OPTIONS_WRITE_THROUGH) && !(pvfs->flags | PVFS_FLAG_STRICT_SYNC)) {
1255 flags |= O_SYNC;
1259 /* other create options are not allowed */
1260 if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) &&
1261 !(access_mask & SEC_STD_DELETE)) {
1262 return NT_STATUS_INVALID_PARAMETER;
1265 if (access_mask & SEC_MASK_INVALID) {
1266 return NT_STATUS_ACCESS_DENIED;
1269 /* what does this bit really mean?? */
1270 if (req->ctx->protocol == PROTOCOL_SMB2 &&
1271 access_mask == SEC_STD_SYNCHRONIZE) {
1272 return NT_STATUS_ACCESS_DENIED;
1275 /* cope with non-zero root_fid */
1276 if (io->ntcreatex.in.root_fid.ntvfs != NULL) {
1277 f = pvfs_find_fd(pvfs, req, io->ntcreatex.in.root_fid.ntvfs);
1278 if (f == NULL) {
1279 return NT_STATUS_INVALID_HANDLE;
1281 if (f->handle->fd != -1) {
1282 return NT_STATUS_INVALID_DEVICE_REQUEST;
1284 io->ntcreatex.in.fname = talloc_asprintf(req, "%s\\%s",
1285 f->handle->name->original_name,
1286 io->ntcreatex.in.fname);
1287 NT_STATUS_HAVE_NO_MEMORY(io->ntcreatex.in.fname);
1290 if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE|
1291 FILE_ATTRIBUTE_VOLUME|
1292 (~FILE_ATTRIBUTE_ALL_MASK))) {
1293 return NT_STATUS_INVALID_PARAMETER;
1296 /* we ignore some file_attr bits */
1297 io->ntcreatex.in.file_attr &= ~(FILE_ATTRIBUTE_NONINDEXED |
1298 FILE_ATTRIBUTE_COMPRESSED |
1299 FILE_ATTRIBUTE_REPARSE_POINT |
1300 FILE_ATTRIBUTE_SPARSE |
1301 FILE_ATTRIBUTE_NORMAL);
1303 /* resolve the cifs name to a posix name */
1304 status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname,
1305 PVFS_RESOLVE_STREAMS, &name);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 return status;
1310 /* if the client specified that it must not be a directory then
1311 check that it isn't */
1312 if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
1313 (io->generic.in.create_options & NTCREATEX_OPTIONS_NON_DIRECTORY_FILE)) {
1314 return NT_STATUS_FILE_IS_A_DIRECTORY;
1317 /* if the client specified that it must be a directory then
1318 check that it is */
1319 if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
1320 (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) {
1321 return NT_STATUS_NOT_A_DIRECTORY;
1324 /* directory opens are handled separately */
1325 if ((name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) ||
1326 (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) {
1327 return pvfs_open_directory(pvfs, req, name, io);
1330 /* FILE_ATTRIBUTE_DIRECTORY is ignored if the above test for directory
1331 open doesn't match */
1332 io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY;
1334 switch (io->generic.in.open_disposition) {
1335 case NTCREATEX_DISP_SUPERSEDE:
1336 case NTCREATEX_DISP_OVERWRITE_IF:
1337 if (name->stream_name == NULL) {
1338 flags = O_TRUNC;
1339 } else {
1340 stream_truncate = true;
1342 create_action = NTCREATEX_ACTION_TRUNCATED;
1343 break;
1345 case NTCREATEX_DISP_OPEN:
1346 if (!name->stream_exists) {
1347 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1349 flags = 0;
1350 break;
1352 case NTCREATEX_DISP_OVERWRITE:
1353 if (!name->stream_exists) {
1354 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1356 if (name->stream_name == NULL) {
1357 flags = O_TRUNC;
1358 } else {
1359 stream_truncate = true;
1361 create_action = NTCREATEX_ACTION_TRUNCATED;
1362 break;
1364 case NTCREATEX_DISP_CREATE:
1365 if (name->stream_exists) {
1366 return NT_STATUS_OBJECT_NAME_COLLISION;
1368 flags = 0;
1369 break;
1371 case NTCREATEX_DISP_OPEN_IF:
1372 flags = 0;
1373 break;
1375 default:
1376 return NT_STATUS_INVALID_PARAMETER;
1379 /* handle creating a new file separately */
1380 if (!name->exists) {
1381 status = pvfs_create_file(pvfs, req, name, io);
1382 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1383 return status;
1386 /* we've hit a race - the file was created during this call */
1387 if (io->generic.in.open_disposition == NTCREATEX_DISP_CREATE) {
1388 return status;
1391 /* try re-resolving the name */
1392 status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 return status;
1396 /* fall through to a normal open */
1399 if ((name->dos.attrib & FILE_ATTRIBUTE_READONLY) &&
1400 (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) {
1401 return NT_STATUS_CANNOT_DELETE;
1404 /* check the security descriptor */
1405 status = pvfs_access_check(pvfs, req, name, &access_mask);
1406 NT_STATUS_NOT_OK_RETURN(status);
1408 if (io->generic.in.query_maximal_access) {
1409 status = pvfs_access_maximal_allowed(pvfs, req, name,
1410 &io->generic.out.maximal_access);
1411 NT_STATUS_NOT_OK_RETURN(status);
1414 status = ntvfs_handle_new(pvfs->ntvfs, req, &h);
1415 NT_STATUS_NOT_OK_RETURN(status);
1417 f = talloc(h, struct pvfs_file);
1418 if (f == NULL) {
1419 return NT_STATUS_NO_MEMORY;
1422 f->handle = talloc(f, struct pvfs_file_handle);
1423 if (f->handle == NULL) {
1424 return NT_STATUS_NO_MEMORY;
1427 f->ntvfs = h;
1428 f->pvfs = pvfs;
1429 f->pending_list = NULL;
1430 f->lock_count = 0;
1431 f->share_access = io->generic.in.share_access;
1432 f->access_mask = access_mask;
1433 f->impersonation = io->generic.in.impersonation;
1434 f->notify_buffer = NULL;
1435 f->search = NULL;
1437 f->handle->pvfs = pvfs;
1438 f->handle->fd = -1;
1439 f->handle->name = talloc_steal(f->handle, name);
1440 f->handle->create_options = io->generic.in.create_options;
1441 f->handle->seek_offset = 0;
1442 f->handle->position = 0;
1443 f->handle->mode = 0;
1444 f->handle->oplock = NULL;
1445 f->handle->have_opendb_entry = false;
1446 ZERO_STRUCT(f->handle->write_time);
1447 f->handle->open_completed = false;
1449 /* form the lock context used for byte range locking and
1450 opendb locking */
1451 status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key);
1452 if (!NT_STATUS_IS_OK(status)) {
1453 return status;
1456 status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 return status;
1461 /* get a lock on this file before the actual open */
1462 lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
1463 if (lck == NULL) {
1464 DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n",
1465 name->full_name));
1466 /* we were supposed to do a blocking lock, so something
1467 is badly wrong! */
1468 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1471 DLIST_ADD(pvfs->files.list, f);
1473 /* setup a destructor to avoid file descriptor leaks on
1474 abnormal termination */
1475 talloc_set_destructor(f, pvfs_fnum_destructor);
1476 talloc_set_destructor(f->handle, pvfs_handle_destructor);
1479 * Only SMB2 takes care of the delete_on_close,
1480 * on existing files
1482 if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE &&
1483 req->ctx->protocol == PROTOCOL_SMB2) {
1484 del_on_close = true;
1485 } else {
1486 del_on_close = false;
1489 if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
1490 oplock_level = OPLOCK_NONE;
1491 } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) {
1492 oplock_level = OPLOCK_BATCH;
1493 } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_OPLOCK) {
1494 oplock_level = OPLOCK_EXCLUSIVE;
1497 if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) {
1498 allow_level_II_oplock = true;
1501 /* see if we are allowed to open at the same time as existing opens */
1502 status = odb_can_open(lck, name->stream_id,
1503 share_access, access_mask, del_on_close,
1504 io->generic.in.open_disposition, false);
1507 * on a sharing violation we need to retry when the file is closed by
1508 * the other user, or after 1 second
1509 * on a non granted oplock we need to retry when the file is closed by
1510 * the other user, or after 30 seconds
1512 if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1513 NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) &&
1514 (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
1515 return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
1518 if (!NT_STATUS_IS_OK(status)) {
1519 talloc_free(lck);
1520 return status;
1523 if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) {
1524 flags |= O_RDWR;
1525 } else {
1526 flags |= O_RDONLY;
1529 /* do the actual open */
1530 fd = open(f->handle->name->full_name, flags | O_NONBLOCK);
1531 if (fd == -1) {
1532 status = pvfs_map_errno(f->pvfs, errno);
1534 DEBUG(0,(__location__ " mapped errno %s for %s (was %d)\n",
1535 nt_errstr(status), f->handle->name->full_name, errno));
1537 * STATUS_MORE_ENTRIES is EAGAIN or EWOULDBLOCK
1539 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
1540 (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
1541 return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status);
1544 talloc_free(lck);
1545 return status;
1548 f->handle->fd = fd;
1550 /* now really mark the file as open */
1551 status = odb_open_file(lck, f->handle, name->full_name,
1552 &f->handle->fd, name->dos.write_time,
1553 allow_level_II_oplock,
1554 oplock_level, &oplock_granted);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 talloc_free(lck);
1558 return status;
1561 f->handle->have_opendb_entry = true;
1563 if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) {
1564 oplock_granted = OPLOCK_BATCH;
1565 } else if (oplock_granted != OPLOCK_NONE) {
1566 status = pvfs_setup_oplock(f, oplock_granted);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 talloc_free(lck);
1569 return status;
1573 stream_existed = name->stream_exists;
1575 /* if this was a stream create then create the stream as well */
1576 if (!name->stream_exists) {
1577 status = pvfs_stream_create(pvfs, f->handle->name, fd);
1578 if (!NT_STATUS_IS_OK(status)) {
1579 talloc_free(lck);
1580 return status;
1582 if (stream_truncate) {
1583 status = pvfs_stream_truncate(pvfs, f->handle->name, fd, 0);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 talloc_free(lck);
1586 return status;
1591 /* re-resolve the open fd */
1592 status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name, PVFS_RESOLVE_NO_OPENDB);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 talloc_free(lck);
1595 return status;
1598 if (f->handle->name->stream_id == 0 &&
1599 (io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE ||
1600 io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF)) {
1601 /* for overwrite we may need to replace file permissions */
1602 uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE;
1603 mode_t mode = pvfs_fileperms(pvfs, attrib);
1604 if (f->handle->name->st.st_mode != mode &&
1605 f->handle->name->dos.attrib != attrib &&
1606 fchmod(fd, mode) == -1) {
1607 talloc_free(lck);
1608 return pvfs_map_errno(pvfs, errno);
1610 name->dos.alloc_size = io->ntcreatex.in.alloc_size;
1611 name->dos.attrib = attrib;
1612 status = pvfs_dosattrib_save(pvfs, name, fd);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 talloc_free(lck);
1615 return status;
1619 talloc_free(lck);
1621 status = ntvfs_handle_set_backend_data(h, ntvfs, f);
1622 NT_STATUS_NOT_OK_RETURN(status);
1624 /* mark the open as having completed fully, so delete on close
1625 can now be used */
1626 f->handle->open_completed = true;
1628 io->generic.out.oplock_level = oplock_granted;
1629 io->generic.out.file.ntvfs = h;
1630 io->generic.out.create_action = stream_existed?
1631 create_action:NTCREATEX_ACTION_CREATED;
1633 io->generic.out.create_time = name->dos.create_time;
1634 io->generic.out.access_time = name->dos.access_time;
1635 io->generic.out.write_time = name->dos.write_time;
1636 io->generic.out.change_time = name->dos.change_time;
1637 io->generic.out.attrib = name->dos.attrib;
1638 io->generic.out.alloc_size = name->dos.alloc_size;
1639 io->generic.out.size = name->st.st_size;
1640 io->generic.out.file_type = FILE_TYPE_DISK;
1641 io->generic.out.ipc_state = 0;
1642 io->generic.out.is_directory = 0;
1644 return NT_STATUS_OK;
1649 close a file
1651 NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs,
1652 struct ntvfs_request *req, union smb_close *io)
1654 struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
1655 struct pvfs_state);
1656 struct pvfs_file *f;
1658 if (io->generic.level == RAW_CLOSE_SPLCLOSE) {
1659 return NT_STATUS_DOS(ERRSRV, ERRerror);
1662 if (io->generic.level != RAW_CLOSE_GENERIC) {
1663 return ntvfs_map_close(ntvfs, req, io);
1666 f = pvfs_find_fd(pvfs, req, io->generic.in.file.ntvfs);
1667 if (!f) {
1668 return NT_STATUS_INVALID_HANDLE;
1671 if (!null_time(io->generic.in.write_time)) {
1672 f->handle->write_time.update_forced = false;
1673 f->handle->write_time.update_on_close = true;
1674 unix_to_nt_time(&f->handle->write_time.close_time, io->generic.in.write_time);
1677 if (io->generic.in.flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) {
1678 struct pvfs_filename *name;
1679 NTSTATUS status;
1680 struct pvfs_file_handle *h = f->handle;
1682 status = pvfs_resolve_name_handle(pvfs, h);
1683 if (!NT_STATUS_IS_OK(status)) {
1684 return status;
1686 name = h->name;
1688 io->generic.out.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
1689 io->generic.out.create_time = name->dos.create_time;
1690 io->generic.out.access_time = name->dos.access_time;
1691 io->generic.out.write_time = name->dos.write_time;
1692 io->generic.out.change_time = name->dos.change_time;
1693 io->generic.out.alloc_size = name->dos.alloc_size;
1694 io->generic.out.size = name->st.st_size;
1695 io->generic.out.file_attr = name->dos.attrib;
1696 } else {
1697 ZERO_STRUCT(io->generic.out);
1700 talloc_free(f);
1702 return NT_STATUS_OK;
1707 logoff - close all file descriptors open by a vuid
1709 NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs,
1710 struct ntvfs_request *req)
1712 struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
1713 struct pvfs_state);
1714 struct pvfs_file *f, *next;
1716 /* If pvfs is NULL, we never logged on, and no files are open. */
1717 if(pvfs == NULL) {
1718 return NT_STATUS_OK;
1721 for (f=pvfs->files.list;f;f=next) {
1722 next = f->next;
1723 if (f->ntvfs->session_info == req->session_info) {
1724 talloc_free(f);
1728 return NT_STATUS_OK;
1733 exit - close files for the current pid
1735 NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs,
1736 struct ntvfs_request *req)
1738 struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
1739 struct pvfs_state);
1740 struct pvfs_file *f, *next;
1742 for (f=pvfs->files.list;f;f=next) {
1743 next = f->next;
1744 if (f->ntvfs->session_info == req->session_info &&
1745 f->ntvfs->smbpid == req->smbpid) {
1746 talloc_free(f);
1750 return NT_STATUS_OK;
1755 change the delete on close flag on an already open file
1757 NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs,
1758 struct ntvfs_request *req,
1759 struct pvfs_file *f, bool del_on_close)
1761 struct odb_lock *lck;
1762 NTSTATUS status;
1764 if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && del_on_close) {
1765 return NT_STATUS_CANNOT_DELETE;
1768 if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
1769 !pvfs_directory_empty(pvfs, f->handle->name)) {
1770 return NT_STATUS_DIRECTORY_NOT_EMPTY;
1773 if (del_on_close) {
1774 f->handle->create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1775 } else {
1776 f->handle->create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
1779 lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key);
1780 if (lck == NULL) {
1781 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1784 status = odb_set_delete_on_close(lck, del_on_close);
1786 talloc_free(lck);
1788 return status;
1793 determine if a file can be deleted, or if it is prevented by an
1794 already open file
1796 NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs,
1797 struct ntvfs_request *req,
1798 struct pvfs_filename *name,
1799 struct odb_lock **lckp)
1801 NTSTATUS status;
1802 DATA_BLOB key;
1803 struct odb_lock *lck;
1804 uint32_t share_access;
1805 uint32_t access_mask;
1806 bool delete_on_close;
1808 status = pvfs_locking_key(name, name, &key);
1809 if (!NT_STATUS_IS_OK(status)) {
1810 return NT_STATUS_NO_MEMORY;
1813 lck = odb_lock(req, pvfs->odb_context, &key);
1814 if (lck == NULL) {
1815 DEBUG(0,("Unable to lock opendb for can_delete\n"));
1816 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1819 share_access = NTCREATEX_SHARE_ACCESS_READ |
1820 NTCREATEX_SHARE_ACCESS_WRITE |
1821 NTCREATEX_SHARE_ACCESS_DELETE;
1822 access_mask = SEC_STD_DELETE;
1823 delete_on_close = true;
1825 status = odb_can_open(lck, name->stream_id,
1826 share_access, access_mask, delete_on_close,
1827 NTCREATEX_DISP_OPEN, false);
1829 if (NT_STATUS_IS_OK(status)) {
1830 status = pvfs_access_check_simple(pvfs, req, name, access_mask);
1834 * if it's a sharing violation or we got no oplock
1835 * only keep the lock if the caller requested access
1836 * to the lock
1838 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1839 NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1840 if (lckp) {
1841 *lckp = lck;
1842 } else {
1843 talloc_free(lck);
1845 } else if (!NT_STATUS_IS_OK(status)) {
1846 talloc_free(lck);
1847 if (lckp) {
1848 *lckp = NULL;
1850 } else if (lckp) {
1851 *lckp = lck;
1854 return status;
1858 determine if a file can be renamed, or if it is prevented by an
1859 already open file
1861 NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs,
1862 struct ntvfs_request *req,
1863 struct pvfs_filename *name,
1864 struct odb_lock **lckp)
1866 NTSTATUS status;
1867 DATA_BLOB key;
1868 struct odb_lock *lck;
1869 uint32_t share_access;
1870 uint32_t access_mask;
1871 bool delete_on_close;
1873 status = pvfs_locking_key(name, name, &key);
1874 if (!NT_STATUS_IS_OK(status)) {
1875 return NT_STATUS_NO_MEMORY;
1878 lck = odb_lock(req, pvfs->odb_context, &key);
1879 if (lck == NULL) {
1880 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1881 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1884 share_access = NTCREATEX_SHARE_ACCESS_READ |
1885 NTCREATEX_SHARE_ACCESS_WRITE;
1886 access_mask = SEC_STD_DELETE;
1887 delete_on_close = false;
1889 status = odb_can_open(lck, name->stream_id,
1890 share_access, access_mask, delete_on_close,
1891 NTCREATEX_DISP_OPEN, false);
1894 * if it's a sharing violation or we got no oplock
1895 * only keep the lock if the caller requested access
1896 * to the lock
1898 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1899 NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1900 if (lckp) {
1901 *lckp = lck;
1902 } else {
1903 talloc_free(lck);
1905 } else if (!NT_STATUS_IS_OK(status)) {
1906 talloc_free(lck);
1907 if (lckp) {
1908 *lckp = NULL;
1910 } else if (lckp) {
1911 *lckp = lck;
1914 return status;
1918 determine if the file size of a file can be changed,
1919 or if it is prevented by an already open file
1921 NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs,
1922 struct ntvfs_request *req,
1923 struct pvfs_filename *name,
1924 struct odb_lock **lckp)
1926 NTSTATUS status;
1927 DATA_BLOB key;
1928 struct odb_lock *lck;
1929 uint32_t share_access;
1930 uint32_t access_mask;
1931 bool break_to_none;
1932 bool delete_on_close;
1934 status = pvfs_locking_key(name, name, &key);
1935 if (!NT_STATUS_IS_OK(status)) {
1936 return NT_STATUS_NO_MEMORY;
1939 lck = odb_lock(req, pvfs->odb_context, &key);
1940 if (lck == NULL) {
1941 DEBUG(0,("Unable to lock opendb for can_stat\n"));
1942 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1945 share_access = NTCREATEX_SHARE_ACCESS_READ |
1946 NTCREATEX_SHARE_ACCESS_WRITE |
1947 NTCREATEX_SHARE_ACCESS_DELETE;
1949 * this code previous set only SEC_FILE_WRITE_ATTRIBUTE, with
1950 * a comment that this seemed to be wrong, but matched windows
1951 * behaviour. It now appears that this windows behaviour is
1952 * just a bug.
1954 access_mask = SEC_FILE_WRITE_ATTRIBUTE | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
1955 delete_on_close = false;
1956 break_to_none = true;
1958 status = odb_can_open(lck, name->stream_id,
1959 share_access, access_mask, delete_on_close,
1960 NTCREATEX_DISP_OPEN, break_to_none);
1963 * if it's a sharing violation or we got no oplock
1964 * only keep the lock if the caller requested access
1965 * to the lock
1967 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) ||
1968 NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) {
1969 if (lckp) {
1970 *lckp = lck;
1971 } else {
1972 talloc_free(lck);
1974 } else if (!NT_STATUS_IS_OK(status)) {
1975 talloc_free(lck);
1976 if (lckp) {
1977 *lckp = NULL;
1979 } else if (lckp) {
1980 *lckp = lck;
1983 return status;
1987 determine if file meta data can be accessed, or if it is prevented by an
1988 already open file
1990 NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs,
1991 struct ntvfs_request *req,
1992 struct pvfs_filename *name)
1994 NTSTATUS status;
1995 DATA_BLOB key;
1996 struct odb_lock *lck;
1997 uint32_t share_access;
1998 uint32_t access_mask;
1999 bool delete_on_close;
2001 status = pvfs_locking_key(name, name, &key);
2002 if (!NT_STATUS_IS_OK(status)) {
2003 return NT_STATUS_NO_MEMORY;
2006 lck = odb_lock(req, pvfs->odb_context, &key);
2007 if (lck == NULL) {
2008 DEBUG(0,("Unable to lock opendb for can_stat\n"));
2009 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2012 share_access = NTCREATEX_SHARE_ACCESS_READ |
2013 NTCREATEX_SHARE_ACCESS_WRITE;
2014 access_mask = SEC_FILE_READ_ATTRIBUTE;
2015 delete_on_close = false;
2017 status = odb_can_open(lck, name->stream_id,
2018 share_access, access_mask, delete_on_close,
2019 NTCREATEX_DISP_OPEN, false);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 talloc_free(lck);
2025 return status;
2030 determine if delete on close is set on
2032 bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h)
2034 NTSTATUS status;
2035 bool del_on_close;
2037 status = odb_get_file_infos(pvfs->odb_context, &h->odb_locking_key,
2038 &del_on_close, NULL);
2039 if (!NT_STATUS_IS_OK(status)) {
2040 DEBUG(1,("WARNING: unable to determine delete on close status for open file\n"));
2041 return false;
2044 return del_on_close;