4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
28 * This module provides the common open functionality to the various
29 * open and create SMB interface functions.
32 #include <sys/types.h>
33 #include <sys/cmn_err.h>
34 #include <sys/fcntl.h>
35 #include <sys/nbmlock.h>
36 #include <smbsrv/string.h>
37 #include <smbsrv/smb_kproto.h>
38 #include <smbsrv/smb_fsops.h>
39 #include <smbsrv/smbinfo.h>
41 volatile uint32_t smb_fids
= 0;
42 #define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_fids)
44 static uint32_t smb_open_subr(smb_request_t
*);
45 extern uint32_t smb_is_executable(char *);
46 static void smb_delete_new_object(smb_request_t
*);
47 static int smb_set_open_attributes(smb_request_t
*, smb_ofile_t
*);
48 static void smb_open_oplock_break(smb_request_t
*, smb_node_t
*);
49 static boolean_t
smb_open_attr_only(smb_arg_open_t
*);
50 static boolean_t
smb_open_overwrite(smb_arg_open_t
*);
53 * smb_access_generic_to_file
55 * Search MSDN for IoCreateFile to see following mapping.
57 * GENERIC_READ STANDARD_RIGHTS_READ, FILE_READ_DATA,
58 * FILE_READ_ATTRIBUTES and FILE_READ_EA
60 * GENERIC_WRITE STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
61 * FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
63 * GENERIC_EXECUTE STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
65 * Careful, we have to emulate some Windows behavior here.
66 * When requested access == zero, you get READ_CONTROL.
67 * MacOS 10.7 depends on this.
70 smb_access_generic_to_file(uint32_t desired_access
)
72 uint32_t access
= READ_CONTROL
;
74 if (desired_access
& GENERIC_ALL
)
75 return (FILE_ALL_ACCESS
& ~SYNCHRONIZE
);
77 if (desired_access
& GENERIC_EXECUTE
) {
78 desired_access
&= ~GENERIC_EXECUTE
;
79 access
|= (STANDARD_RIGHTS_EXECUTE
|
80 SYNCHRONIZE
| FILE_EXECUTE
);
83 if (desired_access
& GENERIC_WRITE
) {
84 desired_access
&= ~GENERIC_WRITE
;
85 access
|= (FILE_GENERIC_WRITE
& ~SYNCHRONIZE
);
88 if (desired_access
& GENERIC_READ
) {
89 desired_access
&= ~GENERIC_READ
;
90 access
|= FILE_GENERIC_READ
;
93 return (access
| desired_access
);
99 * This function converts open modes used by Open and Open AndX
100 * commands to desired access bits used by NT Create AndX command.
103 smb_omode_to_amask(uint32_t desired_access
)
105 switch (desired_access
& SMB_DA_ACCESS_MASK
) {
106 case SMB_DA_ACCESS_READ
:
107 return (FILE_GENERIC_READ
);
109 case SMB_DA_ACCESS_WRITE
:
110 return (FILE_GENERIC_WRITE
);
112 case SMB_DA_ACCESS_READ_WRITE
:
113 return (FILE_GENERIC_READ
| FILE_GENERIC_WRITE
);
115 case SMB_DA_ACCESS_EXECUTE
:
116 return (FILE_GENERIC_EXECUTE
);
119 return (FILE_GENERIC_ALL
);
124 * smb_denymode_to_sharemode
126 * This function converts deny modes used by Open and Open AndX
127 * commands to share access bits used by NT Create AndX command.
130 smb_denymode_to_sharemode(uint32_t desired_access
, char *fname
)
132 switch (desired_access
& SMB_DA_SHARE_MASK
) {
133 case SMB_DA_SHARE_COMPATIBILITY
:
134 if (smb_is_executable(fname
))
135 return (FILE_SHARE_READ
| FILE_SHARE_WRITE
);
137 return (FILE_SHARE_ALL
);
139 case SMB_DA_SHARE_EXCLUSIVE
:
140 return (FILE_SHARE_NONE
);
142 case SMB_DA_SHARE_DENY_WRITE
:
143 return (FILE_SHARE_READ
);
145 case SMB_DA_SHARE_DENY_READ
:
146 return (FILE_SHARE_WRITE
);
148 case SMB_DA_SHARE_DENY_NONE
:
150 return (FILE_SHARE_READ
| FILE_SHARE_WRITE
);
155 * smb_ofun_to_crdisposition
157 * This function converts open function values used by Open and Open AndX
158 * commands to create disposition values used by NT Create AndX command.
161 smb_ofun_to_crdisposition(uint16_t ofun
)
163 static int ofun_cr_map
[3][2] =
166 { FILE_OPEN
, FILE_OPEN_IF
},
167 { FILE_OVERWRITE
, FILE_OVERWRITE_IF
}
170 int row
= ofun
& SMB_OFUN_OPEN_MASK
;
171 int col
= (ofun
& SMB_OFUN_CREATE_MASK
) >> 4;
174 return (FILE_MAXIMUM_DISPOSITION
+ 1);
176 return (ofun_cr_map
[row
][col
]);
180 * Retry opens to avoid spurious sharing violations, due to timing
181 * issues between closes and opens. The client that already has the
182 * file open may be in the process of closing it.
185 smb_common_open(smb_request_t
*sr
)
187 smb_arg_open_t
*parg
;
188 uint32_t status
= NT_STATUS_SUCCESS
;
191 parg
= kmem_alloc(sizeof (*parg
), KM_SLEEP
);
192 bcopy(&sr
->arg
.open
, parg
, sizeof (*parg
));
194 for (count
= 0; count
<= 4; count
++) {
196 delay(MSEC_TO_TICK(400));
198 status
= smb_open_subr(sr
);
199 if (status
!= NT_STATUS_SHARING_VIOLATION
)
202 bcopy(parg
, &sr
->arg
.open
, sizeof (*parg
));
205 if (status
== NT_STATUS_SHARING_VIOLATION
) {
206 smbsr_error(sr
, NT_STATUS_SHARING_VIOLATION
,
207 ERRDOS
, ERROR_SHARING_VIOLATION
);
210 if (status
== NT_STATUS_NO_SUCH_FILE
) {
211 smbsr_error(sr
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
212 ERRDOS
, ERROR_FILE_NOT_FOUND
);
215 kmem_free(parg
, sizeof (*parg
));
222 * Notes on write-through behaviour. It looks like pre-LM0.12 versions
223 * of the protocol specify the write-through mode when a file is opened,
224 * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
225 * SmbWriteAndUnlock) don't need to contain a write-through flag.
227 * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
228 * don't indicate which write-through mode to use. Instead the write
229 * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
232 * We don't care which open call was used to get us here, we just need
233 * to ensure that the write-through mode flag is copied from the open
234 * parameters to the node. We test the omode write-through flag in all
237 * This function will return NT status codes but it also raises errors,
238 * in which case it won't return to the caller. Be careful how you
239 * handle things in here.
241 * The following rules apply when processing a file open request:
243 * - Oplocks must be broken prior to share checking as the break may
244 * cause other clients to close the file, which would affect sharing
247 * - Share checks must take place prior to access checks for correct
248 * Windows semantics and to prevent unnecessary NFS delegation recalls.
250 * - Oplocks must be acquired after open to ensure the correct
251 * synchronization with NFS delegation and FEM installation.
253 * DOS readonly bit rules
255 * 1. The creator of a readonly file can write to/modify the size of the file
256 * using the original create fid, even though the file will appear as readonly
257 * to all other fids and via a CIFS getattr call.
258 * The readonly bit therefore cannot be set in the filesystem until the file
259 * is closed (smb_ofile_close). It is accounted for via ofile and node flags.
261 * 2. A setinfo operation (using either an open fid or a path) to set/unset
262 * readonly will be successful regardless of whether a creator of a readonly
263 * file has an open fid (and has the special privilege mentioned in #1,
264 * above). I.e., the creator of a readonly fid holding that fid will no longer
265 * have a special privilege.
267 * 3. The DOS readonly bit affects only data and some metadata.
268 * The following metadata can be changed regardless of the readonly bit:
269 * - security descriptors
273 * In the current implementation, the file size cannot be changed (except for
274 * the exceptions in #1 and #2, above).
277 * DOS attribute rules
279 * These rules are specific to creating / opening files and directories.
280 * How the attribute value (specifically ZERO or FILE_ATTRIBUTE_NORMAL)
281 * should be interpreted may differ in other requests.
283 * - An attribute value equal to ZERO or FILE_ATTRIBUTE_NORMAL means that the
284 * file's attributes should be cleared.
285 * - If FILE_ATTRIBUTE_NORMAL is specified with any other attributes,
286 * FILE_ATTRIBUTE_NORMAL is ignored.
288 * 1. Creating a new file
289 * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file.
291 * 2. Creating a new directory
292 * - The request attributes + FILE_ATTRIBUTE_DIRECTORY are applied to the file.
293 * - FILE_ATTRIBUTE_ARCHIVE does not get set.
295 * 3. Overwriting an existing file
296 * - the request attributes are used as search attributes. If the existing
297 * file does not meet the search criteria access is denied.
298 * - otherwise, applies attributes + FILE_ATTRIBUTE_ARCHIVE.
300 * 4. Opening an existing file or directory
301 * The request attributes are ignored.
304 smb_open_subr(smb_request_t
*sr
)
306 boolean_t created
= B_FALSE
;
307 boolean_t last_comp_found
= B_FALSE
;
308 smb_node_t
*node
= NULL
;
309 smb_node_t
*dnode
= NULL
;
310 smb_node_t
*cur_node
= NULL
;
311 smb_arg_open_t
*op
= &sr
->sr_open
;
315 int max_requested
= 0;
316 uint32_t max_allowed
;
317 uint32_t status
= NT_STATUS_SUCCESS
;
320 boolean_t is_stream
= B_FALSE
;
321 int lookup_flags
= SMB_FOLLOW_LINKS
;
323 smb_pathname_t
*pn
= &op
->fqi
.fq_path
;
324 smb_server_t
*sv
= sr
->sr_server
;
326 is_dir
= (op
->create_options
& FILE_DIRECTORY_FILE
) ? 1 : 0;
329 * If the object being created or opened is a directory
330 * the Disposition parameter must be one of FILE_CREATE,
331 * FILE_OPEN, or FILE_OPEN_IF
334 if ((op
->create_disposition
!= FILE_CREATE
) &&
335 (op
->create_disposition
!= FILE_OPEN_IF
) &&
336 (op
->create_disposition
!= FILE_OPEN
)) {
337 smbsr_error(sr
, NT_STATUS_INVALID_PARAMETER
,
338 ERRDOS
, ERROR_INVALID_ACCESS
);
339 return (NT_STATUS_INVALID_PARAMETER
);
343 if (op
->desired_access
& MAXIMUM_ALLOWED
) {
345 op
->desired_access
&= ~MAXIMUM_ALLOWED
;
347 op
->desired_access
= smb_access_generic_to_file(op
->desired_access
);
349 if (sr
->session
->s_file_cnt
>= SMB_SESSION_OFILE_MAX
) {
350 ASSERT(sr
->uid_user
);
351 cmn_err(CE_NOTE
, "smbsrv[%s\\%s]: TOO_MANY_OPENED_FILES",
352 sr
->uid_user
->u_domain
, sr
->uid_user
->u_name
);
354 smbsr_error(sr
, NT_STATUS_TOO_MANY_OPENED_FILES
,
355 ERRDOS
, ERROR_TOO_MANY_OPEN_FILES
);
356 return (NT_STATUS_TOO_MANY_OPENED_FILES
);
359 /* This must be NULL at this point */
360 sr
->fid_ofile
= NULL
;
364 switch (sr
->tid_tree
->t_res_type
& STYPE_MASK
) {
371 if ((rc
= smb_threshold_enter(&sv
->sv_opipe_ct
)) != 0) {
372 status
= RPC_NT_SERVER_TOO_BUSY
;
373 smbsr_error(sr
, status
, 0, 0);
378 * No further processing for IPC, we need to either
379 * raise an exception or return success here.
381 if ((status
= smb_opipe_open(sr
)) != NT_STATUS_SUCCESS
)
382 smbsr_error(sr
, status
, 0, 0);
384 smb_threshold_exit(&sv
->sv_opipe_ct
);
388 smbsr_error(sr
, NT_STATUS_BAD_DEVICE_TYPE
,
389 ERRDOS
, ERROR_BAD_DEV_TYPE
);
390 return (NT_STATUS_BAD_DEVICE_TYPE
);
393 smb_pathname_init(sr
, pn
, pn
->pn_path
);
394 if (!smb_pathname_validate(sr
, pn
))
395 return (sr
->smb_error
.status
);
397 if (strlen(pn
->pn_path
) >= MAXPATHLEN
) {
398 smbsr_error(sr
, 0, ERRSRV
, ERRfilespecs
);
399 return (NT_STATUS_NAME_TOO_LONG
);
403 if (!smb_validate_dirname(sr
, pn
))
404 return (sr
->smb_error
.status
);
406 if (!smb_validate_object_name(sr
, pn
))
407 return (sr
->smb_error
.status
);
410 cur_node
= op
->fqi
.fq_dnode
?
411 op
->fqi
.fq_dnode
: sr
->tid_tree
->t_snode
;
414 * if no path or filename are specified the stream should be
415 * created on cur_node
417 if (!is_dir
&& !pn
->pn_pname
&& !pn
->pn_fname
&& pn
->pn_sname
) {
419 * Can't currently handle a stream on the tree root.
420 * If a stream is being opened return "not found", otherwise
421 * return "access denied".
423 if (cur_node
== sr
->tid_tree
->t_snode
) {
424 if (op
->create_disposition
== FILE_OPEN
) {
425 smbsr_error(sr
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
426 ERRDOS
, ERROR_FILE_NOT_FOUND
);
427 return (NT_STATUS_OBJECT_NAME_NOT_FOUND
);
429 smbsr_error(sr
, NT_STATUS_ACCESS_DENIED
, ERRDOS
,
430 ERROR_ACCESS_DENIED
);
431 return (NT_STATUS_ACCESS_DENIED
);
434 (void) snprintf(op
->fqi
.fq_last_comp
,
435 sizeof (op
->fqi
.fq_last_comp
),
436 "%s%s", cur_node
->od_name
, pn
->pn_sname
);
438 op
->fqi
.fq_dnode
= cur_node
->n_dnode
;
439 smb_node_ref(op
->fqi
.fq_dnode
);
441 rc
= smb_pathname_reduce(sr
, sr
->user_cr
, pn
->pn_path
,
442 sr
->tid_tree
->t_snode
, cur_node
, &op
->fqi
.fq_dnode
,
443 op
->fqi
.fq_last_comp
);
446 return (sr
->smb_error
.status
);
451 * If the access mask has only DELETE set (ignore
452 * FILE_READ_ATTRIBUTES), then assume that this
453 * is a request to delete the link (if a link)
454 * and do not follow links. Otherwise, follow
455 * the link to the target.
457 if ((op
->desired_access
& ~FILE_READ_ATTRIBUTES
) == DELETE
)
458 lookup_flags
&= ~SMB_FOLLOW_LINKS
;
460 rc
= smb_fsop_lookup_name(sr
, zone_kcred(), lookup_flags
,
461 sr
->tid_tree
->t_snode
, op
->fqi
.fq_dnode
, op
->fqi
.fq_last_comp
,
465 last_comp_found
= B_TRUE
;
467 * Need the DOS attributes below, where we
468 * check the search attributes (sattr).
470 op
->fqi
.fq_fattr
.sa_mask
= SMB_AT_DOSATTR
;
471 rc
= smb_node_getattr(sr
, op
->fqi
.fq_fnode
, zone_kcred(),
472 NULL
, &op
->fqi
.fq_fattr
);
474 smb_node_release(op
->fqi
.fq_fnode
);
475 smb_node_release(op
->fqi
.fq_dnode
);
476 smbsr_error(sr
, NT_STATUS_INTERNAL_ERROR
,
477 ERRDOS
, ERROR_INTERNAL_ERROR
);
478 return (sr
->smb_error
.status
);
480 } else if (rc
== ENOENT
) {
481 last_comp_found
= B_FALSE
;
482 op
->fqi
.fq_fnode
= NULL
;
485 smb_node_release(op
->fqi
.fq_dnode
);
487 return (sr
->smb_error
.status
);
492 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
493 * which is used to uniquely identify open instances for the
494 * VFS share reservation and POSIX locks.
497 uniq_fid
= SMB_UNIQ_FID();
499 if (last_comp_found
) {
501 node
= op
->fqi
.fq_fnode
;
502 dnode
= op
->fqi
.fq_dnode
;
504 if (!smb_node_is_file(node
) && !smb_node_is_dir(node
) &&
505 !smb_node_is_symlink(node
)) {
506 smb_node_release(node
);
507 smb_node_release(dnode
);
508 smbsr_error(sr
, NT_STATUS_ACCESS_DENIED
, ERRDOS
,
510 return (NT_STATUS_ACCESS_DENIED
);
514 * Reject this request if either:
515 * - the target IS a directory and the client requires that
516 * it must NOT be (required by Lotus Notes)
517 * - the target is NOT a directory and client requires that
520 if (smb_node_is_dir(node
)) {
521 if (op
->create_options
& FILE_NON_DIRECTORY_FILE
) {
522 smb_node_release(node
);
523 smb_node_release(dnode
);
524 smbsr_error(sr
, NT_STATUS_FILE_IS_A_DIRECTORY
,
525 ERRDOS
, ERROR_ACCESS_DENIED
);
526 return (NT_STATUS_FILE_IS_A_DIRECTORY
);
529 if ((op
->create_options
& FILE_DIRECTORY_FILE
) ||
530 (op
->nt_flags
& NT_CREATE_FLAG_OPEN_TARGET_DIR
)) {
531 smb_node_release(node
);
532 smb_node_release(dnode
);
533 smbsr_error(sr
, NT_STATUS_NOT_A_DIRECTORY
,
534 ERRDOS
, ERROR_DIRECTORY
);
535 return (NT_STATUS_NOT_A_DIRECTORY
);
540 * No more open should be accepted when "Delete on close"
543 if (node
->flags
& NODE_FLAGS_DELETE_ON_CLOSE
) {
544 smb_node_release(node
);
545 smb_node_release(dnode
);
546 smbsr_error(sr
, NT_STATUS_DELETE_PENDING
,
547 ERRDOS
, ERROR_ACCESS_DENIED
);
548 return (NT_STATUS_DELETE_PENDING
);
552 * Specified file already exists so the operation should fail.
554 if (op
->create_disposition
== FILE_CREATE
) {
555 smb_node_release(node
);
556 smb_node_release(dnode
);
557 smbsr_error(sr
, NT_STATUS_OBJECT_NAME_COLLISION
,
558 ERRDOS
, ERROR_FILE_EXISTS
);
559 return (NT_STATUS_OBJECT_NAME_COLLISION
);
563 * Windows seems to check read-only access before file
566 * Check to see if the file is currently readonly (irrespective
567 * of whether this open will make it readonly).
569 if (SMB_PATHFILE_IS_READONLY(sr
, node
)) {
570 /* Files data only */
571 if (!smb_node_is_dir(node
)) {
572 if (op
->desired_access
& (FILE_WRITE_DATA
|
574 smb_node_release(node
);
575 smb_node_release(dnode
);
576 smbsr_error(sr
, NT_STATUS_ACCESS_DENIED
,
577 ERRDOS
, ERRnoaccess
);
578 return (NT_STATUS_ACCESS_DENIED
);
583 if ((op
->create_disposition
== FILE_SUPERSEDE
) ||
584 (op
->create_disposition
== FILE_OVERWRITE_IF
) ||
585 (op
->create_disposition
== FILE_OVERWRITE
)) {
587 if (!smb_sattr_check(op
->fqi
.fq_fattr
.sa_dosattr
,
589 smb_node_release(node
);
590 smb_node_release(dnode
);
591 smbsr_error(sr
, NT_STATUS_ACCESS_DENIED
,
592 ERRDOS
, ERRnoaccess
);
593 return (NT_STATUS_ACCESS_DENIED
);
596 if (smb_node_is_dir(node
)) {
597 smb_node_release(node
);
598 smb_node_release(dnode
);
599 return (NT_STATUS_ACCESS_DENIED
);
603 /* MS-FSA 2.1.5.1.2 */
604 if (op
->create_disposition
== FILE_SUPERSEDE
)
605 op
->desired_access
|= DELETE
;
606 if ((op
->create_disposition
== FILE_OVERWRITE_IF
) ||
607 (op
->create_disposition
== FILE_OVERWRITE
))
608 op
->desired_access
|= FILE_WRITE_DATA
;
610 status
= smb_fsop_access(sr
, sr
->user_cr
, node
,
612 if (status
!= NT_STATUS_SUCCESS
) {
613 smb_node_release(node
);
614 smb_node_release(dnode
);
616 if (status
== NT_STATUS_PRIVILEGE_NOT_HELD
) {
617 smbsr_error(sr
, status
,
618 ERRDOS
, ERROR_PRIVILEGE_NOT_HELD
);
621 smbsr_error(sr
, NT_STATUS_ACCESS_DENIED
,
622 ERRDOS
, ERROR_ACCESS_DENIED
);
623 return (NT_STATUS_ACCESS_DENIED
);
628 smb_fsop_eaccess(sr
, sr
->user_cr
, node
, &max_allowed
);
629 op
->desired_access
|= max_allowed
;
633 * Oplock break is done prior to sharing checks as the break
634 * may cause other clients to close the file which would
635 * affect the sharing checks. This may block, so set the
636 * file opening count before oplock stuff.
638 smb_node_inc_opening_count(node
);
639 smb_open_oplock_break(sr
, node
);
641 smb_node_wrlock(node
);
644 * Check for sharing violations
646 status
= smb_fsop_shrlock(sr
->user_cr
, node
, uniq_fid
,
647 op
->desired_access
, op
->share_access
);
648 if (status
== NT_STATUS_SHARING_VIOLATION
) {
649 smb_node_unlock(node
);
650 smb_node_dec_opening_count(node
);
651 smb_node_release(node
);
652 smb_node_release(dnode
);
657 * Go ahead with modifications as necessary.
659 switch (op
->create_disposition
) {
661 case FILE_OVERWRITE_IF
:
663 op
->dattr
|= FILE_ATTRIBUTE_ARCHIVE
;
664 /* Don't apply readonly bit until smb_ofile_close */
665 if (op
->dattr
& FILE_ATTRIBUTE_READONLY
) {
666 op
->created_readonly
= B_TRUE
;
667 op
->dattr
&= ~FILE_ATTRIBUTE_READONLY
;
670 bzero(&new_attr
, sizeof (new_attr
));
671 new_attr
.sa_dosattr
= op
->dattr
;
672 new_attr
.sa_vattr
.va_size
= op
->dsize
;
673 new_attr
.sa_mask
= SMB_AT_DOSATTR
| SMB_AT_SIZE
;
674 rc
= smb_fsop_setattr(sr
, sr
->user_cr
, node
, &new_attr
);
676 smb_fsop_unshrlock(sr
->user_cr
, node
, uniq_fid
);
677 smb_node_unlock(node
);
678 smb_node_dec_opening_count(node
);
679 smb_node_release(node
);
680 smb_node_release(dnode
);
682 return (sr
->smb_error
.status
);
686 * If file is being replaced, remove existing streams
688 if (SMB_IS_STREAM(node
) == 0) {
689 rc
= smb_fsop_remove_streams(sr
, sr
->user_cr
,
692 smb_fsop_unshrlock(sr
->user_cr
, node
,
694 smb_node_unlock(node
);
695 smb_node_dec_opening_count(node
);
696 smb_node_release(node
);
697 smb_node_release(dnode
);
698 return (sr
->smb_error
.status
);
702 op
->action_taken
= SMB_OACT_TRUNCATED
;
707 * FILE_OPEN or FILE_OPEN_IF.
709 op
->action_taken
= SMB_OACT_OPENED
;
713 /* Last component was not found. */
714 dnode
= op
->fqi
.fq_dnode
;
717 is_stream
= smb_is_stream_name(pn
->pn_path
);
719 if ((op
->create_disposition
== FILE_OPEN
) ||
720 (op
->create_disposition
== FILE_OVERWRITE
)) {
721 smb_node_release(dnode
);
722 smbsr_error(sr
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
723 ERRDOS
, ERROR_FILE_NOT_FOUND
);
724 return (NT_STATUS_OBJECT_NAME_NOT_FOUND
);
727 if (pn
->pn_fname
&& smb_is_invalid_filename(pn
->pn_fname
)) {
728 smb_node_release(dnode
);
729 smbsr_error(sr
, NT_STATUS_OBJECT_NAME_INVALID
,
730 ERRDOS
, ERROR_INVALID_NAME
);
731 return (NT_STATUS_OBJECT_NAME_INVALID
);
735 * lock the parent dir node in case another create
736 * request to the same parent directory comes in.
738 smb_node_wrlock(dnode
);
740 /* Don't apply readonly bit until smb_ofile_close */
741 if (op
->dattr
& FILE_ATTRIBUTE_READONLY
) {
742 op
->dattr
&= ~FILE_ATTRIBUTE_READONLY
;
743 op
->created_readonly
= B_TRUE
;
746 bzero(&new_attr
, sizeof (new_attr
));
747 if ((op
->crtime
.tv_sec
!= 0) &&
748 (op
->crtime
.tv_sec
!= UINT_MAX
)) {
750 new_attr
.sa_mask
|= SMB_AT_CRTIME
;
751 new_attr
.sa_crtime
= op
->crtime
;
755 op
->dattr
|= FILE_ATTRIBUTE_ARCHIVE
;
756 new_attr
.sa_dosattr
= op
->dattr
;
757 new_attr
.sa_vattr
.va_type
= VREG
;
758 new_attr
.sa_vattr
.va_mode
= is_stream
? S_IRUSR
:
759 S_IRUSR
| S_IRGRP
| S_IROTH
|
760 S_IWUSR
| S_IWGRP
| S_IWOTH
;
762 SMB_AT_DOSATTR
| SMB_AT_TYPE
| SMB_AT_MODE
;
765 new_attr
.sa_vattr
.va_size
= op
->dsize
;
766 new_attr
.sa_mask
|= SMB_AT_SIZE
;
769 rc
= smb_fsop_create(sr
, sr
->user_cr
, dnode
,
770 op
->fqi
.fq_last_comp
, &new_attr
, &op
->fqi
.fq_fnode
);
773 smb_node_unlock(dnode
);
774 smb_node_release(dnode
);
776 return (sr
->smb_error
.status
);
779 node
= op
->fqi
.fq_fnode
;
780 smb_node_inc_opening_count(node
);
781 smb_node_wrlock(node
);
783 status
= smb_fsop_shrlock(sr
->user_cr
, node
, uniq_fid
,
784 op
->desired_access
, op
->share_access
);
786 if (status
== NT_STATUS_SHARING_VIOLATION
) {
787 smb_node_unlock(node
);
788 smb_node_dec_opening_count(node
);
789 smb_delete_new_object(sr
);
790 smb_node_release(node
);
791 smb_node_unlock(dnode
);
792 smb_node_release(dnode
);
796 op
->dattr
|= FILE_ATTRIBUTE_DIRECTORY
;
797 new_attr
.sa_dosattr
= op
->dattr
;
798 new_attr
.sa_vattr
.va_type
= VDIR
;
799 new_attr
.sa_vattr
.va_mode
= 0777;
801 SMB_AT_DOSATTR
| SMB_AT_TYPE
| SMB_AT_MODE
;
803 rc
= smb_fsop_mkdir(sr
, sr
->user_cr
, dnode
,
804 op
->fqi
.fq_last_comp
, &new_attr
, &op
->fqi
.fq_fnode
);
806 smb_node_unlock(dnode
);
807 smb_node_release(dnode
);
809 return (sr
->smb_error
.status
);
812 node
= op
->fqi
.fq_fnode
;
813 smb_node_inc_opening_count(node
);
814 smb_node_wrlock(node
);
818 op
->action_taken
= SMB_OACT_CREATED
;
821 smb_fsop_eaccess(sr
, sr
->user_cr
, node
, &max_allowed
);
822 op
->desired_access
|= max_allowed
;
826 status
= NT_STATUS_SUCCESS
;
828 of
= smb_ofile_open(sr
, node
, sr
->smb_pid
, op
, SMB_FTYPE_DISK
, uniq_fid
,
831 smbsr_error(sr
, err
.status
, err
.errcls
, err
.errcode
);
835 if (status
== NT_STATUS_SUCCESS
) {
836 if (!smb_tree_is_connected(sr
->tid_tree
)) {
837 smbsr_error(sr
, 0, ERRSRV
, ERRinvnid
);
838 status
= NT_STATUS_UNSUCCESSFUL
;
843 * This MUST be done after ofile creation, so that explicitly
844 * set timestamps can be remembered on the ofile, and the
845 * readonly flag will be stored "pending" on the node.
847 if (status
== NT_STATUS_SUCCESS
) {
848 if ((rc
= smb_set_open_attributes(sr
, of
)) != 0) {
850 status
= sr
->smb_error
.status
;
854 if (status
== NT_STATUS_SUCCESS
) {
856 * We've already done access checks above,
857 * and want this call to succeed even when
858 * !(desired_access & FILE_READ_ATTRIBUTES),
859 * so pass kcred here.
861 op
->fqi
.fq_fattr
.sa_mask
= SMB_AT_ALL
;
862 rc
= smb_node_getattr(sr
, node
, zone_kcred(), of
,
865 smbsr_error(sr
, NT_STATUS_INTERNAL_ERROR
,
866 ERRDOS
, ERROR_INTERNAL_ERROR
);
867 status
= NT_STATUS_INTERNAL_ERROR
;
872 * smb_fsop_unshrlock is a no-op if node is a directory
873 * smb_fsop_unshrlock is done in smb_ofile_close
875 if (status
!= NT_STATUS_SUCCESS
) {
877 smb_fsop_unshrlock(sr
->user_cr
, node
, uniq_fid
);
879 smb_ofile_close(of
, 0);
880 smb_ofile_release(of
);
883 smb_delete_new_object(sr
);
884 smb_node_unlock(node
);
885 smb_node_dec_opening_count(node
);
886 smb_node_release(node
);
888 smb_node_unlock(dnode
);
889 smb_node_release(dnode
);
894 * Propagate the write-through mode from the open params
895 * to the node: see the notes in the function header.
897 if (sr
->sr_cfg
->skc_sync_enable
||
898 (op
->create_options
& FILE_WRITE_THROUGH
))
899 node
->flags
|= NODE_FLAGS_WRITE_THROUGH
;
902 * Set up the fileid and dosattr in open_param for response
904 op
->fileid
= op
->fqi
.fq_fattr
.sa_vattr
.va_nodeid
;
905 op
->dattr
= op
->fqi
.fq_fattr
.sa_dosattr
;
908 * Set up the file type in open_param for the response
910 op
->ftype
= SMB_FTYPE_DISK
;
911 sr
->smb_fid
= of
->f_fid
;
914 if (smb_node_is_file(node
)) {
915 smb_oplock_acquire(sr
, node
, of
);
916 op
->dsize
= op
->fqi
.fq_fattr
.sa_vattr
.va_size
;
918 /* directory or symlink */
919 op
->op_oplock_level
= SMB_OPLOCK_NONE
;
923 smb_node_dec_opening_count(node
);
925 smb_node_unlock(node
);
927 smb_node_unlock(dnode
);
929 smb_node_release(node
);
930 smb_node_release(dnode
);
932 return (NT_STATUS_SUCCESS
);
936 * smb_open_oplock_break
938 * If the node has an ofile opened with share access none,
939 * (smb_node_share_check = FALSE) only break BATCH oplock.
941 * If overwriting, break to SMB_OPLOCK_NONE, else
942 * If opening for anything other than attribute access,
943 * break oplock to LEVEL_II.
946 smb_open_oplock_break(smb_request_t
*sr
, smb_node_t
*node
)
948 smb_arg_open_t
*op
= &sr
->sr_open
;
951 if (!smb_node_share_check(node
))
952 flags
|= SMB_OPLOCK_BREAK_BATCH
;
954 if (smb_open_overwrite(op
)) {
955 flags
|= SMB_OPLOCK_BREAK_TO_NONE
;
956 (void) smb_oplock_break(sr
, node
, flags
);
957 } else if (!smb_open_attr_only(op
)) {
958 flags
|= SMB_OPLOCK_BREAK_TO_LEVEL_II
;
959 (void) smb_oplock_break(sr
, node
, flags
);
966 * Determine if file is being opened for attribute access only.
967 * This is used to determine whether it is necessary to break
968 * existing oplocks on the file.
971 smb_open_attr_only(smb_arg_open_t
*op
)
973 if (((op
->desired_access
& ~(FILE_READ_ATTRIBUTES
|
974 FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE
| READ_CONTROL
)) == 0) &&
975 (op
->create_disposition
!= FILE_SUPERSEDE
) &&
976 (op
->create_disposition
!= FILE_OVERWRITE
)) {
983 smb_open_overwrite(smb_arg_open_t
*op
)
985 if ((op
->create_disposition
== FILE_SUPERSEDE
) ||
986 (op
->create_disposition
== FILE_OVERWRITE_IF
) ||
987 (op
->create_disposition
== FILE_OVERWRITE
)) {
994 * smb_set_open_attributes
997 * - If the last_write time specified in the open params is not 0 or -1,
998 * use it as file's mtime. This will be considered an explicitly set
999 * timestamps, not reset by subsequent writes.
1002 * - If we created_readonly, we now store the real DOS attributes
1003 * (including the readonly bit) so subsequent opens will see it.
1005 * Both are stored "pending" rather than in the file system.
1010 smb_set_open_attributes(smb_request_t
*sr
, smb_ofile_t
*of
)
1013 smb_arg_open_t
*op
= &sr
->sr_open
;
1014 smb_node_t
*node
= of
->f_node
;
1017 bzero(&attr
, sizeof (smb_attr_t
));
1019 if (op
->created_readonly
) {
1020 attr
.sa_dosattr
= op
->dattr
| FILE_ATTRIBUTE_READONLY
;
1021 attr
.sa_mask
|= SMB_AT_DOSATTR
;
1024 if ((op
->mtime
.tv_sec
!= 0) && (op
->mtime
.tv_sec
!= UINT_MAX
)) {
1025 attr
.sa_vattr
.va_mtime
= op
->mtime
;
1026 attr
.sa_mask
|= SMB_AT_MTIME
;
1030 * Used to have code here to set mtime, ctime, atime
1031 * when the open op->create_disposition is any of:
1032 * FILE_SUPERSEDE, FILE_OVERWRITE_IF, FILE_OVERWRITE.
1033 * We know that in those cases we will have set the
1034 * file size, in which case the file system will
1035 * update those times, so we don't have to.
1037 * However, keep track of the fact that we modified
1038 * the file via this handle, so we can do the evil,
1039 * gratuitious mtime update on close that Windows
1040 * clients appear to expect.
1042 if (op
->action_taken
== SMB_OACT_TRUNCATED
)
1043 of
->f_written
= B_TRUE
;
1045 if (attr
.sa_mask
!= 0)
1046 rc
= smb_node_setattr(sr
, node
, of
->f_cr
, of
, &attr
);
1052 * This function is used to delete a newly created object (file or
1053 * directory) if an error occurs after creation of the object.
1056 smb_delete_new_object(smb_request_t
*sr
)
1058 smb_arg_open_t
*op
= &sr
->sr_open
;
1059 smb_fqi_t
*fqi
= &(op
->fqi
);
1062 if (SMB_TREE_IS_CASEINSENSITIVE(sr
))
1063 flags
|= SMB_IGNORE_CASE
;
1064 if (SMB_TREE_SUPPORTS_CATIA(sr
))
1067 if (op
->create_options
& FILE_DIRECTORY_FILE
)
1068 (void) smb_fsop_rmdir(sr
, sr
->user_cr
, fqi
->fq_dnode
,
1069 fqi
->fq_last_comp
, flags
);
1071 (void) smb_fsop_remove(sr
, sr
->user_cr
, fqi
->fq_dnode
,
1072 fqi
->fq_last_comp
, flags
);