xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_open.c (revision 148d1a4158dc830f7b293a2ceb62ee54c2ebd72f)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21148c5f43SAlan Wright 
22da6c28aaSamw /*
23148c5f43SAlan Wright  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245677e049SGordon Ross  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
25da6c28aaSamw  */
26da6c28aaSamw 
27da6c28aaSamw /*
28da6c28aaSamw  * This module provides the common open functionality to the various
29da6c28aaSamw  * open and create SMB interface functions.
30da6c28aaSamw  */
31da6c28aaSamw 
32bbf6f00cSJordan Brown #include <sys/types.h>
33bbf6f00cSJordan Brown #include <sys/cmn_err.h>
34da6c28aaSamw #include <sys/fcntl.h>
35dc20a302Sas #include <sys/nbmlock.h>
36bbf6f00cSJordan Brown #include <smbsrv/string.h>
37*148d1a41SMatt Barden #include <smbsrv/smb2_kproto.h>
38bbf6f00cSJordan Brown #include <smbsrv/smb_fsops.h>
39bbf6f00cSJordan Brown #include <smbsrv/smbinfo.h>
40da6c28aaSamw 
4191ca6bffSGordon Ross int smb_session_ofile_max = 32768;
4291ca6bffSGordon Ross 
4368b2bbf2SGordon Ross static volatile uint32_t smb_fids = 0;
44b819cea2SGordon Ross #define	SMB_UNIQ_FID()	atomic_inc_32_nv(&smb_fids)
457b59d02dSjb 
467b59d02dSjb static uint32_t smb_open_subr(smb_request_t *);
47faa1795aSjb extern uint32_t smb_is_executable(char *);
488b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static void smb_delete_new_object(smb_request_t *);
495fd03bc0SGordon Ross static int smb_set_open_attributes(smb_request_t *, smb_ofile_t *);
50cb174861Sjoyce mcintosh static void smb_open_oplock_break(smb_request_t *, smb_node_t *);
51cb174861Sjoyce mcintosh static boolean_t smb_open_attr_only(smb_arg_open_t *);
52cb174861Sjoyce mcintosh static boolean_t smb_open_overwrite(smb_arg_open_t *);
53da6c28aaSamw 
54da6c28aaSamw /*
55da6c28aaSamw  * smb_access_generic_to_file
56da6c28aaSamw  *
57da6c28aaSamw  * Search MSDN for IoCreateFile to see following mapping.
58da6c28aaSamw  *
59da6c28aaSamw  * GENERIC_READ		STANDARD_RIGHTS_READ, FILE_READ_DATA,
60da6c28aaSamw  *			FILE_READ_ATTRIBUTES and FILE_READ_EA
61da6c28aaSamw  *
62da6c28aaSamw  * GENERIC_WRITE	STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
63da6c28aaSamw  *               FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
64da6c28aaSamw  *
65da6c28aaSamw  * GENERIC_EXECUTE	STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
66da6c28aaSamw  */
67a90cf9f2SGordon Ross static uint32_t
68da6c28aaSamw smb_access_generic_to_file(uint32_t desired_access)
69da6c28aaSamw {
70a90cf9f2SGordon Ross 	uint32_t access = 0;
71da6c28aaSamw 
72da6c28aaSamw 	if (desired_access & GENERIC_ALL)
73da6c28aaSamw 		return (FILE_ALL_ACCESS & ~SYNCHRONIZE);
74da6c28aaSamw 
75da6c28aaSamw 	if (desired_access & GENERIC_EXECUTE) {
76da6c28aaSamw 		desired_access &= ~GENERIC_EXECUTE;
77da6c28aaSamw 		access |= (STANDARD_RIGHTS_EXECUTE |
78da6c28aaSamw 		    SYNCHRONIZE | FILE_EXECUTE);
79da6c28aaSamw 	}
80da6c28aaSamw 
81da6c28aaSamw 	if (desired_access & GENERIC_WRITE) {
82da6c28aaSamw 		desired_access &= ~GENERIC_WRITE;
83da6c28aaSamw 		access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE);
84da6c28aaSamw 	}
85da6c28aaSamw 
86da6c28aaSamw 	if (desired_access & GENERIC_READ) {
87da6c28aaSamw 		desired_access &= ~GENERIC_READ;
88da6c28aaSamw 		access |= FILE_GENERIC_READ;
89da6c28aaSamw 	}
90da6c28aaSamw 
91da6c28aaSamw 	return (access | desired_access);
92da6c28aaSamw }
93da6c28aaSamw 
94da6c28aaSamw /*
95da6c28aaSamw  * smb_omode_to_amask
96da6c28aaSamw  *
97da6c28aaSamw  * This function converts open modes used by Open and Open AndX
98da6c28aaSamw  * commands to desired access bits used by NT Create AndX command.
99da6c28aaSamw  */
100da6c28aaSamw uint32_t
101da6c28aaSamw smb_omode_to_amask(uint32_t desired_access)
102da6c28aaSamw {
103da6c28aaSamw 	switch (desired_access & SMB_DA_ACCESS_MASK) {
104da6c28aaSamw 	case SMB_DA_ACCESS_READ:
105da6c28aaSamw 		return (FILE_GENERIC_READ);
106da6c28aaSamw 
107da6c28aaSamw 	case SMB_DA_ACCESS_WRITE:
108da6c28aaSamw 		return (FILE_GENERIC_WRITE);
109da6c28aaSamw 
110da6c28aaSamw 	case SMB_DA_ACCESS_READ_WRITE:
111da6c28aaSamw 		return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
112da6c28aaSamw 
113da6c28aaSamw 	case SMB_DA_ACCESS_EXECUTE:
114c5f48fa5SGordon Ross 		return (FILE_GENERIC_READ | FILE_GENERIC_EXECUTE);
115da6c28aaSamw 
1162c2961f8Sjose borrego 	default:
1172c2961f8Sjose borrego 		return (FILE_GENERIC_ALL);
1182c2961f8Sjose borrego 	}
119da6c28aaSamw }
120da6c28aaSamw 
121da6c28aaSamw /*
122da6c28aaSamw  * smb_denymode_to_sharemode
123da6c28aaSamw  *
124da6c28aaSamw  * This function converts deny modes used by Open and Open AndX
125da6c28aaSamw  * commands to share access bits used by NT Create AndX command.
126da6c28aaSamw  */
127da6c28aaSamw uint32_t
128da6c28aaSamw smb_denymode_to_sharemode(uint32_t desired_access, char *fname)
129da6c28aaSamw {
130da6c28aaSamw 	switch (desired_access & SMB_DA_SHARE_MASK) {
131da6c28aaSamw 	case SMB_DA_SHARE_COMPATIBILITY:
132da6c28aaSamw 		if (smb_is_executable(fname))
133da6c28aaSamw 			return (FILE_SHARE_READ | FILE_SHARE_WRITE);
134c8ec8eeaSjose borrego 
135c8ec8eeaSjose borrego 		return (FILE_SHARE_ALL);
136da6c28aaSamw 
137da6c28aaSamw 	case SMB_DA_SHARE_EXCLUSIVE:
138da6c28aaSamw 		return (FILE_SHARE_NONE);
139da6c28aaSamw 
140da6c28aaSamw 	case SMB_DA_SHARE_DENY_WRITE:
141da6c28aaSamw 		return (FILE_SHARE_READ);
142da6c28aaSamw 
143da6c28aaSamw 	case SMB_DA_SHARE_DENY_READ:
144da6c28aaSamw 		return (FILE_SHARE_WRITE);
145da6c28aaSamw 
146da6c28aaSamw 	case SMB_DA_SHARE_DENY_NONE:
1472c2961f8Sjose borrego 	default:
148da6c28aaSamw 		return (FILE_SHARE_READ | FILE_SHARE_WRITE);
149da6c28aaSamw 	}
150da6c28aaSamw }
151da6c28aaSamw 
152da6c28aaSamw /*
153da6c28aaSamw  * smb_ofun_to_crdisposition
154da6c28aaSamw  *
155da6c28aaSamw  * This function converts open function values used by Open and Open AndX
156da6c28aaSamw  * commands to create disposition values used by NT Create AndX command.
157da6c28aaSamw  */
158da6c28aaSamw uint32_t
159da6c28aaSamw smb_ofun_to_crdisposition(uint16_t  ofun)
160da6c28aaSamw {
161da6c28aaSamw 	static int ofun_cr_map[3][2] =
162da6c28aaSamw 	{
163da6c28aaSamw 		{ -1,			FILE_CREATE },
164da6c28aaSamw 		{ FILE_OPEN,		FILE_OPEN_IF },
165da6c28aaSamw 		{ FILE_OVERWRITE,	FILE_OVERWRITE_IF }
166da6c28aaSamw 	};
167da6c28aaSamw 
168da6c28aaSamw 	int row = ofun & SMB_OFUN_OPEN_MASK;
169da6c28aaSamw 	int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4;
170da6c28aaSamw 
171da6c28aaSamw 	if (row == 3)
1722c2961f8Sjose borrego 		return (FILE_MAXIMUM_DISPOSITION + 1);
173da6c28aaSamw 
174da6c28aaSamw 	return (ofun_cr_map[row][col]);
175da6c28aaSamw }
176da6c28aaSamw 
1777b59d02dSjb /*
1787b59d02dSjb  * Retry opens to avoid spurious sharing violations, due to timing
1797b59d02dSjb  * issues between closes and opens.  The client that already has the
1807b59d02dSjb  * file open may be in the process of closing it.
1817b59d02dSjb  */
1827b59d02dSjb uint32_t
1837b59d02dSjb smb_common_open(smb_request_t *sr)
1847b59d02dSjb {
185148c5f43SAlan Wright 	smb_arg_open_t	*parg;
186bbf6f00cSJordan Brown 	uint32_t	status = NT_STATUS_SUCCESS;
187bbf6f00cSJordan Brown 	int		count;
188bbf6f00cSJordan Brown 
189bbf6f00cSJordan Brown 	parg = kmem_alloc(sizeof (*parg), KM_SLEEP);
190bbf6f00cSJordan Brown 	bcopy(&sr->arg.open, parg, sizeof (*parg));
1917b59d02dSjb 
1927b59d02dSjb 	for (count = 0; count <= 4; count++) {
193bbf6f00cSJordan Brown 		if (count != 0)
1947b59d02dSjb 			delay(MSEC_TO_TICK(400));
1957b59d02dSjb 
196faa1795aSjb 		status = smb_open_subr(sr);
197faa1795aSjb 		if (status != NT_STATUS_SHARING_VIOLATION)
1987b59d02dSjb 			break;
199bbf6f00cSJordan Brown 
200bbf6f00cSJordan Brown 		bcopy(parg, &sr->arg.open, sizeof (*parg));
2017b59d02dSjb 	}
2027b59d02dSjb 
203a90cf9f2SGordon Ross 	if (status == NT_STATUS_NO_SUCH_FILE)
204a90cf9f2SGordon Ross 		status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2052c2961f8Sjose borrego 
206bbf6f00cSJordan Brown 	kmem_free(parg, sizeof (*parg));
2077b59d02dSjb 	return (status);
2087b59d02dSjb }
2097b59d02dSjb 
210da6c28aaSamw /*
211da6c28aaSamw  * smb_open_subr
212da6c28aaSamw  *
213da6c28aaSamw  * Notes on write-through behaviour. It looks like pre-LM0.12 versions
214da6c28aaSamw  * of the protocol specify the write-through mode when a file is opened,
215da6c28aaSamw  * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
216da6c28aaSamw  * SmbWriteAndUnlock) don't need to contain a write-through flag.
217da6c28aaSamw  *
218da6c28aaSamw  * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
219da6c28aaSamw  * don't indicate which write-through mode to use. Instead the write
220da6c28aaSamw  * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
221da6c28aaSamw  * basis.
222da6c28aaSamw  *
223da6c28aaSamw  * We don't care which open call was used to get us here, we just need
224da6c28aaSamw  * to ensure that the write-through mode flag is copied from the open
225da6c28aaSamw  * parameters to the node. We test the omode write-through flag in all
226da6c28aaSamw  * write functions.
227da6c28aaSamw  *
228a90cf9f2SGordon Ross  * This function returns NT status codes.
2298c10a865Sas  *
2308c10a865Sas  * The following rules apply when processing a file open request:
2318c10a865Sas  *
232cb174861Sjoyce mcintosh  * - Oplocks must be broken prior to share checking as the break may
233cb174861Sjoyce mcintosh  *   cause other clients to close the file, which would affect sharing
234cb174861Sjoyce mcintosh  *   checks.
2358c10a865Sas  *
2368c10a865Sas  * - Share checks must take place prior to access checks for correct
2378c10a865Sas  * Windows semantics and to prevent unnecessary NFS delegation recalls.
2388c10a865Sas  *
2398c10a865Sas  * - Oplocks must be acquired after open to ensure the correct
2408c10a865Sas  * synchronization with NFS delegation and FEM installation.
241c8ec8eeaSjose borrego  *
242c8ec8eeaSjose borrego  * DOS readonly bit rules
243c8ec8eeaSjose borrego  *
244c8ec8eeaSjose borrego  * 1. The creator of a readonly file can write to/modify the size of the file
245c8ec8eeaSjose borrego  * using the original create fid, even though the file will appear as readonly
246c8ec8eeaSjose borrego  * to all other fids and via a CIFS getattr call.
247c8ec8eeaSjose borrego  *
248c8ec8eeaSjose borrego  * 2. A setinfo operation (using either an open fid or a path) to set/unset
249c8ec8eeaSjose borrego  * readonly will be successful regardless of whether a creator of a readonly
2505cb2894aSGordon Ross  * file has an open fid.
251c8ec8eeaSjose borrego  *
252c8ec8eeaSjose borrego  * 3. The DOS readonly bit affects only data and some metadata.
253c8ec8eeaSjose borrego  * The following metadata can be changed regardless of the readonly bit:
254c8ec8eeaSjose borrego  * 	- security descriptors
255c8ec8eeaSjose borrego  *	- DOS attributes
256c8ec8eeaSjose borrego  *	- timestamps
257c8ec8eeaSjose borrego  *
258c8ec8eeaSjose borrego  * In the current implementation, the file size cannot be changed (except for
259c8ec8eeaSjose borrego  * the exceptions in #1 and #2, above).
2602c1b14e5Sjose borrego  *
2612c1b14e5Sjose borrego  *
2622c1b14e5Sjose borrego  * DOS attribute rules
2632c1b14e5Sjose borrego  *
2642c1b14e5Sjose borrego  * These rules are specific to creating / opening files and directories.
2652c1b14e5Sjose borrego  * How the attribute value (specifically ZERO or FILE_ATTRIBUTE_NORMAL)
2662c1b14e5Sjose borrego  * should be interpreted may differ in other requests.
2672c1b14e5Sjose borrego  *
2682c1b14e5Sjose borrego  * - An attribute value equal to ZERO or FILE_ATTRIBUTE_NORMAL means that the
2692c1b14e5Sjose borrego  *   file's attributes should be cleared.
2702c1b14e5Sjose borrego  * - If FILE_ATTRIBUTE_NORMAL is specified with any other attributes,
2712c1b14e5Sjose borrego  *   FILE_ATTRIBUTE_NORMAL is ignored.
2722c1b14e5Sjose borrego  *
2732c1b14e5Sjose borrego  * 1. Creating a new file
2742c1b14e5Sjose borrego  * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file.
2752c1b14e5Sjose borrego  *
2762c1b14e5Sjose borrego  * 2. Creating a new directory
2772c1b14e5Sjose borrego  * - The request attributes + FILE_ATTRIBUTE_DIRECTORY are applied to the file.
2782c1b14e5Sjose borrego  * - FILE_ATTRIBUTE_ARCHIVE does not get set.
2792c1b14e5Sjose borrego  *
2802c1b14e5Sjose borrego  * 3. Overwriting an existing file
2812c1b14e5Sjose borrego  * - the request attributes are used as search attributes. If the existing
2822c1b14e5Sjose borrego  *   file does not meet the search criteria access is denied.
2832c1b14e5Sjose borrego  * - otherwise, applies attributes + FILE_ATTRIBUTE_ARCHIVE.
2842c1b14e5Sjose borrego  *
2852c1b14e5Sjose borrego  * 4. Opening an existing file or directory
2862c1b14e5Sjose borrego  *    The request attributes are ignored.
287da6c28aaSamw  */
2887b59d02dSjb static uint32_t
2897b59d02dSjb smb_open_subr(smb_request_t *sr)
290da6c28aaSamw {
291eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	created = B_FALSE;
292eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	last_comp_found = B_FALSE;
2932c2961f8Sjose borrego 	smb_node_t	*node = NULL;
2942c2961f8Sjose borrego 	smb_node_t	*dnode = NULL;
295eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_t	*cur_node = NULL;
296148c5f43SAlan Wright 	smb_arg_open_t	*op = &sr->sr_open;
2972c2961f8Sjose borrego 	int		rc;
2982c2961f8Sjose borrego 	smb_ofile_t	*of;
2992c2961f8Sjose borrego 	smb_attr_t	new_attr;
3002c2961f8Sjose borrego 	int		max_requested = 0;
3012c2961f8Sjose borrego 	uint32_t	max_allowed;
3022c2961f8Sjose borrego 	uint32_t	status = NT_STATUS_SUCCESS;
3032c2961f8Sjose borrego 	int		is_dir;
3042c2961f8Sjose borrego 	smb_error_t	err;
3052c2961f8Sjose borrego 	boolean_t	is_stream = B_FALSE;
3062c2961f8Sjose borrego 	int		lookup_flags = SMB_FOLLOW_LINKS;
3072c2961f8Sjose borrego 	uint32_t	uniq_fid;
308eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_pathname_t	*pn = &op->fqi.fq_path;
309cb174861Sjoyce mcintosh 	smb_server_t	*sv = sr->sr_server;
310da6c28aaSamw 
3115677e049SGordon Ross 	/* Get out now if we've been cancelled. */
3125677e049SGordon Ross 	mutex_enter(&sr->sr_mutex);
3135677e049SGordon Ross 	if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
3145677e049SGordon Ross 		mutex_exit(&sr->sr_mutex);
3155677e049SGordon Ross 		return (NT_STATUS_CANCELLED);
3165677e049SGordon Ross 	}
3175677e049SGordon Ross 	mutex_exit(&sr->sr_mutex);
3185677e049SGordon Ross 
319da6c28aaSamw 	is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
320da6c28aaSamw 
321037cac00Sjoyce mcintosh 	/*
322037cac00Sjoyce mcintosh 	 * If the object being created or opened is a directory
323037cac00Sjoyce mcintosh 	 * the Disposition parameter must be one of FILE_CREATE,
324037cac00Sjoyce mcintosh 	 * FILE_OPEN, or FILE_OPEN_IF
325037cac00Sjoyce mcintosh 	 */
326da6c28aaSamw 	if (is_dir) {
327da6c28aaSamw 		if ((op->create_disposition != FILE_CREATE) &&
328da6c28aaSamw 		    (op->create_disposition != FILE_OPEN_IF) &&
329da6c28aaSamw 		    (op->create_disposition != FILE_OPEN)) {
3307b59d02dSjb 			return (NT_STATUS_INVALID_PARAMETER);
331da6c28aaSamw 		}
332da6c28aaSamw 	}
333da6c28aaSamw 
334da6c28aaSamw 	if (op->desired_access & MAXIMUM_ALLOWED) {
335da6c28aaSamw 		max_requested = 1;
336da6c28aaSamw 		op->desired_access &= ~MAXIMUM_ALLOWED;
337da6c28aaSamw 	}
338da6c28aaSamw 	op->desired_access = smb_access_generic_to_file(op->desired_access);
339da6c28aaSamw 
34091ca6bffSGordon Ross 	if (sr->session->s_file_cnt >= smb_session_ofile_max) {
341da6c28aaSamw 		ASSERT(sr->uid_user);
342cb174861Sjoyce mcintosh 		cmn_err(CE_NOTE, "smbsrv[%s\\%s]: TOO_MANY_OPENED_FILES",
343148c5f43SAlan Wright 		    sr->uid_user->u_domain, sr->uid_user->u_name);
3447b59d02dSjb 		return (NT_STATUS_TOO_MANY_OPENED_FILES);
345da6c28aaSamw 	}
346da6c28aaSamw 
347da6c28aaSamw 	/* This must be NULL at this point */
348da6c28aaSamw 	sr->fid_ofile = NULL;
349da6c28aaSamw 
350da6c28aaSamw 	op->devstate = 0;
351da6c28aaSamw 
352da6c28aaSamw 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
353da6c28aaSamw 	case STYPE_DISKTREE:
354f96bd5c8SAlan Wright 	case STYPE_PRINTQ:
355da6c28aaSamw 		break;
356da6c28aaSamw 
357da6c28aaSamw 	case STYPE_IPC:
358a90cf9f2SGordon Ross 		/*
359a90cf9f2SGordon Ross 		 * Security descriptors for pipes are not implemented,
360a90cf9f2SGordon Ross 		 * so just setup a reasonable access mask.
361a90cf9f2SGordon Ross 		 */
362a90cf9f2SGordon Ross 		op->desired_access = (READ_CONTROL | SYNCHRONIZE |
363a90cf9f2SGordon Ross 		    FILE_READ_DATA | FILE_READ_ATTRIBUTES |
364a90cf9f2SGordon Ross 		    FILE_WRITE_DATA | FILE_APPEND_DATA);
365cb174861Sjoyce mcintosh 
366a90cf9f2SGordon Ross 		/*
367a90cf9f2SGordon Ross 		 * Limit the number of open pipe instances.
368a90cf9f2SGordon Ross 		 */
369cb174861Sjoyce mcintosh 		if ((rc = smb_threshold_enter(&sv->sv_opipe_ct)) != 0) {
370cb174861Sjoyce mcintosh 			status = RPC_NT_SERVER_TOO_BUSY;
371cb174861Sjoyce mcintosh 			return (status);
372cb174861Sjoyce mcintosh 		}
373cb174861Sjoyce mcintosh 
374da6c28aaSamw 		/*
375da6c28aaSamw 		 * No further processing for IPC, we need to either
376da6c28aaSamw 		 * raise an exception or return success here.
377da6c28aaSamw 		 */
37868b2bbf2SGordon Ross 		uniq_fid = SMB_UNIQ_FID();
37968b2bbf2SGordon Ross 		status = smb_opipe_open(sr, uniq_fid);
380856399cfSGordon Ross 		smb_threshold_exit(&sv->sv_opipe_ct);
3817b59d02dSjb 		return (status);
382da6c28aaSamw 
383da6c28aaSamw 	default:
3847b59d02dSjb 		return (NT_STATUS_BAD_DEVICE_TYPE);
385da6c28aaSamw 	}
386da6c28aaSamw 
387fe1c642dSBill Krier 	smb_pathname_init(sr, pn, pn->pn_path);
388fe1c642dSBill Krier 	if (!smb_pathname_validate(sr, pn))
389fe1c642dSBill Krier 		return (sr->smb_error.status);
390fe1c642dSBill Krier 
391b24e356bSPeer Dampmann 	if (strlen(pn->pn_path) >= SMB_MAXPATHLEN) {
392a90cf9f2SGordon Ross 		return (NT_STATUS_OBJECT_PATH_INVALID);
393da6c28aaSamw 	}
394da6c28aaSamw 
395fe1c642dSBill Krier 	if (is_dir) {
396fe1c642dSBill Krier 		if (!smb_validate_dirname(sr, pn))
397fe1c642dSBill Krier 			return (sr->smb_error.status);
398fe1c642dSBill Krier 	} else {
399fe1c642dSBill Krier 		if (!smb_validate_object_name(sr, pn))
400fe1c642dSBill Krier 			return (sr->smb_error.status);
401da6c28aaSamw 	}
402da6c28aaSamw 
403eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	cur_node = op->fqi.fq_dnode ?
404eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	    op->fqi.fq_dnode : sr->tid_tree->t_snode;
405da6c28aaSamw 
406d082c877SGordon Ross 	rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
407d082c877SGordon Ross 	    sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode,
408d082c877SGordon Ross 	    op->fqi.fq_last_comp);
409d082c877SGordon Ross 	if (rc != 0) {
410d082c877SGordon Ross 		return (smb_errno2status(rc));
411da6c28aaSamw 	}
412da6c28aaSamw 
413da6c28aaSamw 	/*
414da6c28aaSamw 	 * If the access mask has only DELETE set (ignore
415da6c28aaSamw 	 * FILE_READ_ATTRIBUTES), then assume that this
416da6c28aaSamw 	 * is a request to delete the link (if a link)
417da6c28aaSamw 	 * and do not follow links.  Otherwise, follow
418da6c28aaSamw 	 * the link to the target.
419da6c28aaSamw 	 */
420037cac00Sjoyce mcintosh 	if ((op->desired_access & ~FILE_READ_ATTRIBUTES) == DELETE)
421da6c28aaSamw 		lookup_flags &= ~SMB_FOLLOW_LINKS;
422da6c28aaSamw 
4238622ec45SGordon Ross 	rc = smb_fsop_lookup_name(sr, zone_kcred(), lookup_flags,
424eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	    sr->tid_tree->t_snode, op->fqi.fq_dnode, op->fqi.fq_last_comp,
425037cac00Sjoyce mcintosh 	    &op->fqi.fq_fnode);
426da6c28aaSamw 
427da6c28aaSamw 	if (rc == 0) {
428eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		last_comp_found = B_TRUE;
4295fd03bc0SGordon Ross 		/*
4305fd03bc0SGordon Ross 		 * Need the DOS attributes below, where we
4315fd03bc0SGordon Ross 		 * check the search attributes (sattr).
4325fd03bc0SGordon Ross 		 */
4335fd03bc0SGordon Ross 		op->fqi.fq_fattr.sa_mask = SMB_AT_DOSATTR;
4348622ec45SGordon Ross 		rc = smb_node_getattr(sr, op->fqi.fq_fnode, zone_kcred(),
4355fd03bc0SGordon Ross 		    NULL, &op->fqi.fq_fattr);
436037cac00Sjoyce mcintosh 		if (rc != 0) {
437037cac00Sjoyce mcintosh 			smb_node_release(op->fqi.fq_fnode);
438037cac00Sjoyce mcintosh 			smb_node_release(op->fqi.fq_dnode);
439a90cf9f2SGordon Ross 			return (NT_STATUS_INTERNAL_ERROR);
440037cac00Sjoyce mcintosh 		}
441da6c28aaSamw 	} else if (rc == ENOENT) {
442eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		last_comp_found = B_FALSE;
443eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->fqi.fq_fnode = NULL;
444da6c28aaSamw 		rc = 0;
445da6c28aaSamw 	} else {
446eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(op->fqi.fq_dnode);
447a90cf9f2SGordon Ross 		return (smb_errno2status(rc));
448da6c28aaSamw 	}
449da6c28aaSamw 
450037cac00Sjoyce mcintosh 
451dc20a302Sas 	/*
452dc20a302Sas 	 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
453dc20a302Sas 	 * which is used to uniquely identify open instances for the
454c8ec8eeaSjose borrego 	 * VFS share reservation and POSIX locks.
455dc20a302Sas 	 */
456dc20a302Sas 
457dc20a302Sas 	uniq_fid = SMB_UNIQ_FID();
458dc20a302Sas 
459eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (last_comp_found) {
4606537f381Sas 
4619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		node = op->fqi.fq_fnode;
4629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		dnode = op->fqi.fq_dnode;
4636537f381Sas 
4649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (!smb_node_is_file(node) && !smb_node_is_dir(node) &&
4659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    !smb_node_is_symlink(node)) {
4669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_release(node);
4679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_release(dnode);
4686537f381Sas 			return (NT_STATUS_ACCESS_DENIED);
4696537f381Sas 		}
4706537f381Sas 
471da6c28aaSamw 		/*
4722c1b14e5Sjose borrego 		 * Reject this request if either:
4732c1b14e5Sjose borrego 		 * - the target IS a directory and the client requires that
4742c1b14e5Sjose borrego 		 *   it must NOT be (required by Lotus Notes)
4752c1b14e5Sjose borrego 		 * - the target is NOT a directory and client requires that
4762c1b14e5Sjose borrego 		 *   it MUST be.
477da6c28aaSamw 		 */
4789fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (smb_node_is_dir(node)) {
4792c1b14e5Sjose borrego 			if (op->create_options & FILE_NON_DIRECTORY_FILE) {
480da6c28aaSamw 				smb_node_release(node);
481da6c28aaSamw 				smb_node_release(dnode);
4827b59d02dSjb 				return (NT_STATUS_FILE_IS_A_DIRECTORY);
483da6c28aaSamw 			}
4842c1b14e5Sjose borrego 		} else {
4852c1b14e5Sjose borrego 			if ((op->create_options & FILE_DIRECTORY_FILE) ||
4862c2961f8Sjose borrego 			    (op->nt_flags & NT_CREATE_FLAG_OPEN_TARGET_DIR)) {
4872c1b14e5Sjose borrego 				smb_node_release(node);
4882c1b14e5Sjose borrego 				smb_node_release(dnode);
4892c1b14e5Sjose borrego 				return (NT_STATUS_NOT_A_DIRECTORY);
4902c1b14e5Sjose borrego 			}
491da6c28aaSamw 		}
492da6c28aaSamw 
493da6c28aaSamw 		/*
494da6c28aaSamw 		 * No more open should be accepted when "Delete on close"
495da6c28aaSamw 		 * flag is set.
496da6c28aaSamw 		 */
497da6c28aaSamw 		if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
498da6c28aaSamw 			smb_node_release(node);
499da6c28aaSamw 			smb_node_release(dnode);
5007b59d02dSjb 			return (NT_STATUS_DELETE_PENDING);
501da6c28aaSamw 		}
502da6c28aaSamw 
503da6c28aaSamw 		/*
504da6c28aaSamw 		 * Specified file already exists so the operation should fail.
505da6c28aaSamw 		 */
506da6c28aaSamw 		if (op->create_disposition == FILE_CREATE) {
507da6c28aaSamw 			smb_node_release(node);
508da6c28aaSamw 			smb_node_release(dnode);
5097b59d02dSjb 			return (NT_STATUS_OBJECT_NAME_COLLISION);
510da6c28aaSamw 		}
511da6c28aaSamw 
512da6c28aaSamw 		/*
513da6c28aaSamw 		 * Windows seems to check read-only access before file
514da6c28aaSamw 		 * sharing check.
515c8ec8eeaSjose borrego 		 *
516c8ec8eeaSjose borrego 		 * Check to see if the file is currently readonly (irrespective
517c8ec8eeaSjose borrego 		 * of whether this open will make it readonly).
518da6c28aaSamw 		 */
519c8ec8eeaSjose borrego 		if (SMB_PATHFILE_IS_READONLY(sr, node)) {
520da6c28aaSamw 			/* Files data only */
521037cac00Sjoyce mcintosh 			if (!smb_node_is_dir(node)) {
522da6c28aaSamw 				if (op->desired_access & (FILE_WRITE_DATA |
523da6c28aaSamw 				    FILE_APPEND_DATA)) {
524da6c28aaSamw 					smb_node_release(node);
525da6c28aaSamw 					smb_node_release(dnode);
5267b59d02dSjb 					return (NT_STATUS_ACCESS_DENIED);
527da6c28aaSamw 				}
528b5b772b0SGordon Ross 				if (op->create_options & FILE_DELETE_ON_CLOSE) {
529b5b772b0SGordon Ross 					smb_node_release(node);
530b5b772b0SGordon Ross 					smb_node_release(dnode);
531b5b772b0SGordon Ross 					return (NT_STATUS_CANNOT_DELETE);
532b5b772b0SGordon Ross 				}
533da6c28aaSamw 			}
534da6c28aaSamw 		}
535da6c28aaSamw 
536dc20a302Sas 		if ((op->create_disposition == FILE_SUPERSEDE) ||
537dc20a302Sas 		    (op->create_disposition == FILE_OVERWRITE_IF) ||
538dc20a302Sas 		    (op->create_disposition == FILE_OVERWRITE)) {
539dc20a302Sas 
540fb699f1eSAlek Pinchuk 			if (!smb_sattr_check(op->fqi.fq_fattr.sa_dosattr,
541fb699f1eSAlek Pinchuk 			    op->dattr)) {
542dc20a302Sas 				smb_node_release(node);
543dc20a302Sas 				smb_node_release(dnode);
5447b59d02dSjb 				return (NT_STATUS_ACCESS_DENIED);
545dc20a302Sas 			}
546dc20a302Sas 
547fb699f1eSAlek Pinchuk 			if (smb_node_is_dir(node)) {
548fb699f1eSAlek Pinchuk 				smb_node_release(node);
549fb699f1eSAlek Pinchuk 				smb_node_release(dnode);
550fb699f1eSAlek Pinchuk 				return (NT_STATUS_ACCESS_DENIED);
551fb699f1eSAlek Pinchuk 			}
552da6c28aaSamw 		}
553da6c28aaSamw 
554fb699f1eSAlek Pinchuk 		/* MS-FSA 2.1.5.1.2 */
555fb699f1eSAlek Pinchuk 		if (op->create_disposition == FILE_SUPERSEDE)
556fb699f1eSAlek Pinchuk 			op->desired_access |= DELETE;
557fb699f1eSAlek Pinchuk 		if ((op->create_disposition == FILE_OVERWRITE_IF) ||
558fb699f1eSAlek Pinchuk 		    (op->create_disposition == FILE_OVERWRITE))
559fb699f1eSAlek Pinchuk 			op->desired_access |= FILE_WRITE_DATA;
560fb699f1eSAlek Pinchuk 
561da6c28aaSamw 		status = smb_fsop_access(sr, sr->user_cr, node,
562da6c28aaSamw 		    op->desired_access);
563da6c28aaSamw 		if (status != NT_STATUS_SUCCESS) {
564da6c28aaSamw 			smb_node_release(node);
565da6c28aaSamw 			smb_node_release(dnode);
566dc20a302Sas 
567a90cf9f2SGordon Ross 			/* SMB1 specific? NT_STATUS_PRIVILEGE_NOT_HELD */
568da6c28aaSamw 			if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
5697b59d02dSjb 				return (status);
570da6c28aaSamw 			} else {
5717b59d02dSjb 				return (NT_STATUS_ACCESS_DENIED);
572da6c28aaSamw 			}
573da6c28aaSamw 		}
574da6c28aaSamw 
575fb699f1eSAlek Pinchuk 		if (max_requested) {
576fb699f1eSAlek Pinchuk 			smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
577fb699f1eSAlek Pinchuk 			op->desired_access |= max_allowed;
578fb699f1eSAlek Pinchuk 		}
579a90cf9f2SGordon Ross 		/*
580a90cf9f2SGordon Ross 		 * According to MS "dochelp" mail in Mar 2015, any handle
581a90cf9f2SGordon Ross 		 * on which read or write access is granted implicitly
582a90cf9f2SGordon Ross 		 * gets "read attributes", even if it was not requested.
583a90cf9f2SGordon Ross 		 * This avoids unexpected access failures later that
584a90cf9f2SGordon Ross 		 * would happen if these were not granted.
585a90cf9f2SGordon Ross 		 */
586a90cf9f2SGordon Ross 		if ((op->desired_access & FILE_DATA_ALL) != 0) {
587a90cf9f2SGordon Ross 			op->desired_access |= (READ_CONTROL |
588a90cf9f2SGordon Ross 			    FILE_READ_ATTRIBUTES);
589a90cf9f2SGordon Ross 		}
590fb699f1eSAlek Pinchuk 
591fb699f1eSAlek Pinchuk 		/*
592fb699f1eSAlek Pinchuk 		 * Oplock break is done prior to sharing checks as the break
593fb699f1eSAlek Pinchuk 		 * may cause other clients to close the file which would
59449d83597SMatt Barden 		 * affect the sharing checks, and may delete the file due to
59549d83597SMatt Barden 		 * DELETE_ON_CLOSE. This may block, so set the file opening
59649d83597SMatt Barden 		 * count before oplock stuff.
597fb699f1eSAlek Pinchuk 		 */
598fb699f1eSAlek Pinchuk 		smb_node_inc_opening_count(node);
599fb699f1eSAlek Pinchuk 		smb_open_oplock_break(sr, node);
600fb699f1eSAlek Pinchuk 
60149d83597SMatt Barden 		if ((node->flags & NODE_FLAGS_DELETE_COMMITTED) != 0) {
60249d83597SMatt Barden 			/*
60349d83597SMatt Barden 			 * Breaking the oplock caused the file to be deleted,
60449d83597SMatt Barden 			 * so let's bail and pretend the file wasn't found
60549d83597SMatt Barden 			 */
60649d83597SMatt Barden 			smb_node_dec_opening_count(node);
60749d83597SMatt Barden 			smb_node_release(node);
60849d83597SMatt Barden 			last_comp_found = B_FALSE;
60949d83597SMatt Barden 			goto create;
61049d83597SMatt Barden 		}
61149d83597SMatt Barden 
612fb699f1eSAlek Pinchuk 		smb_node_wrlock(node);
613fb699f1eSAlek Pinchuk 
614fb699f1eSAlek Pinchuk 		/*
615fb699f1eSAlek Pinchuk 		 * Check for sharing violations
616fb699f1eSAlek Pinchuk 		 */
617fb699f1eSAlek Pinchuk 		status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
618fb699f1eSAlek Pinchuk 		    op->desired_access, op->share_access);
619fb699f1eSAlek Pinchuk 		if (status == NT_STATUS_SHARING_VIOLATION) {
620fb699f1eSAlek Pinchuk 			smb_node_unlock(node);
621fb699f1eSAlek Pinchuk 			smb_node_dec_opening_count(node);
622fb699f1eSAlek Pinchuk 			smb_node_release(node);
623fb699f1eSAlek Pinchuk 			smb_node_release(dnode);
624fb699f1eSAlek Pinchuk 			return (status);
625fb699f1eSAlek Pinchuk 		}
626fb699f1eSAlek Pinchuk 
627fb699f1eSAlek Pinchuk 		/*
628fb699f1eSAlek Pinchuk 		 * Go ahead with modifications as necessary.
629fb699f1eSAlek Pinchuk 		 */
630da6c28aaSamw 		switch (op->create_disposition) {
631da6c28aaSamw 		case FILE_SUPERSEDE:
632da6c28aaSamw 		case FILE_OVERWRITE_IF:
633da6c28aaSamw 		case FILE_OVERWRITE:
6342c1b14e5Sjose borrego 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
6355cb2894aSGordon Ross 			/* Don't apply readonly until smb_set_open_attributes */
6362c1b14e5Sjose borrego 			if (op->dattr & FILE_ATTRIBUTE_READONLY) {
6372c1b14e5Sjose borrego 				op->dattr &= ~FILE_ATTRIBUTE_READONLY;
6385cb2894aSGordon Ross 				op->created_readonly = B_TRUE;
6392c1b14e5Sjose borrego 			}
6402c1b14e5Sjose borrego 
641a90cf9f2SGordon Ross 			/*
642a90cf9f2SGordon Ross 			 * Truncate the file data here.
643a90cf9f2SGordon Ross 			 * We set alloc_size = op->dsize later,
644a90cf9f2SGordon Ross 			 * after we have an ofile.  See:
645a90cf9f2SGordon Ross 			 * smb_set_open_attributes
646a90cf9f2SGordon Ross 			 */
647037cac00Sjoyce mcintosh 			bzero(&new_attr, sizeof (new_attr));
648037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
649a90cf9f2SGordon Ross 			new_attr.sa_vattr.va_size = 0;
650037cac00Sjoyce mcintosh 			new_attr.sa_mask = SMB_AT_DOSATTR | SMB_AT_SIZE;
651037cac00Sjoyce mcintosh 			rc = smb_fsop_setattr(sr, sr->user_cr, node, &new_attr);
652037cac00Sjoyce mcintosh 			if (rc != 0) {
653037cac00Sjoyce mcintosh 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
654037cac00Sjoyce mcintosh 				smb_node_unlock(node);
655cb174861Sjoyce mcintosh 				smb_node_dec_opening_count(node);
656037cac00Sjoyce mcintosh 				smb_node_release(node);
657037cac00Sjoyce mcintosh 				smb_node_release(dnode);
658a90cf9f2SGordon Ross 				return (smb_errno2status(rc));
659037cac00Sjoyce mcintosh 			}
6602c1b14e5Sjose borrego 
661da6c28aaSamw 			/*
662037cac00Sjoyce mcintosh 			 * If file is being replaced, remove existing streams
663da6c28aaSamw 			 */
664eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			if (SMB_IS_STREAM(node) == 0) {
665a90cf9f2SGordon Ross 				status = smb_fsop_remove_streams(sr,
666a90cf9f2SGordon Ross 				    sr->user_cr, node);
667a90cf9f2SGordon Ross 				if (status != 0) {
668eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_fsop_unshrlock(sr->user_cr, node,
669eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					    uniq_fid);
670eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_unlock(node);
671cb174861Sjoyce mcintosh 					smb_node_dec_opening_count(node);
672eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_release(node);
673eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_release(dnode);
674a90cf9f2SGordon Ross 					return (status);
675eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 				}
676eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			}
677da6c28aaSamw 
678da6c28aaSamw 			op->action_taken = SMB_OACT_TRUNCATED;
679da6c28aaSamw 			break;
680da6c28aaSamw 
681da6c28aaSamw 		default:
682da6c28aaSamw 			/*
683da6c28aaSamw 			 * FILE_OPEN or FILE_OPEN_IF.
684da6c28aaSamw 			 */
685a90cf9f2SGordon Ross 			/*
686a90cf9f2SGordon Ross 			 * Ignore any user-specified alloc_size for
687a90cf9f2SGordon Ross 			 * existing files, to avoid truncation in
688a90cf9f2SGordon Ross 			 * smb_set_open_attributes
689a90cf9f2SGordon Ross 			 */
690a90cf9f2SGordon Ross 			op->dsize = 0L;
691da6c28aaSamw 			op->action_taken = SMB_OACT_OPENED;
692da6c28aaSamw 			break;
693da6c28aaSamw 		}
694da6c28aaSamw 	} else {
69549d83597SMatt Barden create:
696da6c28aaSamw 		/* Last component was not found. */
697eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		dnode = op->fqi.fq_dnode;
698da6c28aaSamw 
6997b59d02dSjb 		if (is_dir == 0)
700eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			is_stream = smb_is_stream_name(pn->pn_path);
7017b59d02dSjb 
702da6c28aaSamw 		if ((op->create_disposition == FILE_OPEN) ||
703da6c28aaSamw 		    (op->create_disposition == FILE_OVERWRITE)) {
704da6c28aaSamw 			smb_node_release(dnode);
7057b59d02dSjb 			return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
706da6c28aaSamw 		}
707da6c28aaSamw 
7089fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (pn->pn_fname && smb_is_invalid_filename(pn->pn_fname)) {
7092c2961f8Sjose borrego 			smb_node_release(dnode);
7102c2961f8Sjose borrego 			return (NT_STATUS_OBJECT_NAME_INVALID);
7112c2961f8Sjose borrego 		}
7122c2961f8Sjose borrego 
713a1096253SGordon Ross 		/*
714a1096253SGordon Ross 		 * Don't create in directories marked "Delete on close".
715a1096253SGordon Ross 		 */
716a1096253SGordon Ross 		if (dnode->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
717a1096253SGordon Ross 			smb_node_release(dnode);
718a1096253SGordon Ross 			return (NT_STATUS_DELETE_PENDING);
719a1096253SGordon Ross 		}
720a1096253SGordon Ross 
721da6c28aaSamw 		/*
722da6c28aaSamw 		 * lock the parent dir node in case another create
723da6c28aaSamw 		 * request to the same parent directory comes in.
724da6c28aaSamw 		 */
7252c2961f8Sjose borrego 		smb_node_wrlock(dnode);
726da6c28aaSamw 
7275cb2894aSGordon Ross 		/*
7285cb2894aSGordon Ross 		 * Create always sets the DOS attributes, type, and mode
7295cb2894aSGordon Ross 		 * in the if/else below (different for file vs directory).
7305cb2894aSGordon Ross 		 * Don't set the readonly bit until smb_set_open_attributes
7315cb2894aSGordon Ross 		 * or that would prevent this open.  Note that op->dattr
7325cb2894aSGordon Ross 		 * needs to be what smb_set_open_attributes will use,
7335cb2894aSGordon Ross 		 * except for the readonly bit.
7345cb2894aSGordon Ross 		 */
7355cb2894aSGordon Ross 		bzero(&new_attr, sizeof (new_attr));
7365cb2894aSGordon Ross 		new_attr.sa_mask = SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
737037cac00Sjoyce mcintosh 		if (op->dattr & FILE_ATTRIBUTE_READONLY) {
738037cac00Sjoyce mcintosh 			op->dattr &= ~FILE_ATTRIBUTE_READONLY;
739037cac00Sjoyce mcintosh 			op->created_readonly = B_TRUE;
740037cac00Sjoyce mcintosh 		}
741c8ec8eeaSjose borrego 
7425cb2894aSGordon Ross 		/*
7435cb2894aSGordon Ross 		 * SMB create can specify the create time.
7445cb2894aSGordon Ross 		 */
745c8ec8eeaSjose borrego 		if ((op->crtime.tv_sec != 0) &&
746c8ec8eeaSjose borrego 		    (op->crtime.tv_sec != UINT_MAX)) {
747c8ec8eeaSjose borrego 			new_attr.sa_mask |= SMB_AT_CRTIME;
748c8ec8eeaSjose borrego 			new_attr.sa_crtime = op->crtime;
749c8ec8eeaSjose borrego 		}
750c8ec8eeaSjose borrego 
751da6c28aaSamw 		if (is_dir == 0) {
752037cac00Sjoyce mcintosh 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
753037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
754da6c28aaSamw 			new_attr.sa_vattr.va_type = VREG;
7555cb2894aSGordon Ross 			if (is_stream)
7565cb2894aSGordon Ross 				new_attr.sa_vattr.va_mode = S_IRUSR | S_IWUSR;
7575cb2894aSGordon Ross 			else
7585cb2894aSGordon Ross 				new_attr.sa_vattr.va_mode =
7595cb2894aSGordon Ross 				    S_IRUSR | S_IRGRP | S_IROTH |
7605cb2894aSGordon Ross 				    S_IWUSR | S_IWGRP | S_IWOTH;
761dc20a302Sas 
762a90cf9f2SGordon Ross 			/*
763a90cf9f2SGordon Ross 			 * We set alloc_size = op->dsize later,
764c5f48fa5SGordon Ross 			 * (in smb_set_open_attributes) after we
765c5f48fa5SGordon Ross 			 * have an ofile on which to save that.
766c5f48fa5SGordon Ross 			 *
767c5f48fa5SGordon Ross 			 * Legacy Open&X sets size to alloc_size
768c5f48fa5SGordon Ross 			 * when creating a new file.
769a90cf9f2SGordon Ross 			 */
770c5f48fa5SGordon Ross 			if (sr->smb_com == SMB_COM_OPEN_ANDX) {
771c5f48fa5SGordon Ross 				new_attr.sa_vattr.va_size = op->dsize;
772c5f48fa5SGordon Ross 				new_attr.sa_mask |= SMB_AT_SIZE;
773c5f48fa5SGordon Ross 			}
774dc20a302Sas 
775da6c28aaSamw 			rc = smb_fsop_create(sr, sr->user_cr, dnode,
776037cac00Sjoyce mcintosh 			    op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
777dc20a302Sas 
778da6c28aaSamw 			if (rc != 0) {
7792c2961f8Sjose borrego 				smb_node_unlock(dnode);
780da6c28aaSamw 				smb_node_release(dnode);
781a90cf9f2SGordon Ross 				return (smb_errno2status(rc));
782da6c28aaSamw 			}
783da6c28aaSamw 
784eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			node = op->fqi.fq_fnode;
785cb174861Sjoyce mcintosh 			smb_node_inc_opening_count(node);
7862c2961f8Sjose borrego 			smb_node_wrlock(node);
787dc20a302Sas 
788faa1795aSjb 			status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
789c8ec8eeaSjose borrego 			    op->desired_access, op->share_access);
790dc20a302Sas 
791dc20a302Sas 			if (status == NT_STATUS_SHARING_VIOLATION) {
7922c2961f8Sjose borrego 				smb_node_unlock(node);
793cb174861Sjoyce mcintosh 				smb_node_dec_opening_count(node);
794037cac00Sjoyce mcintosh 				smb_delete_new_object(sr);
795dc20a302Sas 				smb_node_release(node);
7962c2961f8Sjose borrego 				smb_node_unlock(dnode);
797dc20a302Sas 				smb_node_release(dnode);
798dc20a302Sas 				return (status);
799dc20a302Sas 			}
800da6c28aaSamw 		} else {
8013db3f65cSamw 			op->dattr |= FILE_ATTRIBUTE_DIRECTORY;
802037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
803da6c28aaSamw 			new_attr.sa_vattr.va_type = VDIR;
804da6c28aaSamw 			new_attr.sa_vattr.va_mode = 0777;
805c8ec8eeaSjose borrego 
806da6c28aaSamw 			rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
807037cac00Sjoyce mcintosh 			    op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
808da6c28aaSamw 			if (rc != 0) {
8092c2961f8Sjose borrego 				smb_node_unlock(dnode);
810da6c28aaSamw 				smb_node_release(dnode);
811a90cf9f2SGordon Ross 				return (smb_errno2status(rc));
812da6c28aaSamw 			}
813dc20a302Sas 
814eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			node = op->fqi.fq_fnode;
815cb174861Sjoyce mcintosh 			smb_node_inc_opening_count(node);
8162c2961f8Sjose borrego 			smb_node_wrlock(node);
817da6c28aaSamw 		}
818da6c28aaSamw 
819eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		created = B_TRUE;
820da6c28aaSamw 		op->action_taken = SMB_OACT_CREATED;
821c8ec8eeaSjose borrego 
822fb699f1eSAlek Pinchuk 		if (max_requested) {
823fb699f1eSAlek Pinchuk 			smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
824fb699f1eSAlek Pinchuk 			op->desired_access |= max_allowed;
825fb699f1eSAlek Pinchuk 		}
826a90cf9f2SGordon Ross 		/*
827245d1332SMatt Barden 		 * We created this object (we own it) so grant
828245d1332SMatt Barden 		 * read_control + read_attributes on this handle,
829a90cf9f2SGordon Ross 		 * even if that was not requested.  This avoids
830245d1332SMatt Barden 		 * unexpected access failures later.
831a90cf9f2SGordon Ross 		 */
832245d1332SMatt Barden 		op->desired_access |= (READ_CONTROL | FILE_READ_ATTRIBUTES);
833c8ec8eeaSjose borrego 	}
834c8ec8eeaSjose borrego 
835037cac00Sjoyce mcintosh 	status = NT_STATUS_SUCCESS;
836c8ec8eeaSjose borrego 
83768b2bbf2SGordon Ross 	of = smb_ofile_open(sr, node, op, SMB_FTYPE_DISK, uniq_fid,
8383b13a1efSThomas Keiser 	    &err);
839da6c28aaSamw 	if (of == NULL) {
840037cac00Sjoyce mcintosh 		status = err.status;
841037cac00Sjoyce mcintosh 	}
842037cac00Sjoyce mcintosh 
84368b2bbf2SGordon Ross 	/*
84468b2bbf2SGordon Ross 	 * We might have blocked in smb_ofile_open long enough so a
84568b2bbf2SGordon Ross 	 * tree disconnect might have happened.  In that case, we've
84668b2bbf2SGordon Ross 	 * just added an ofile to a tree that's disconnecting, and
84768b2bbf2SGordon Ross 	 * need to undo that to avoid interfering with tear-down of
84868b2bbf2SGordon Ross 	 * the tree connection.
84968b2bbf2SGordon Ross 	 */
85068b2bbf2SGordon Ross 	if (status == NT_STATUS_SUCCESS &&
85168b2bbf2SGordon Ross 	    !smb_tree_is_connected(sr->tid_tree)) {
85268b2bbf2SGordon Ross 		status = NT_STATUS_INVALID_PARAMETER;
853037cac00Sjoyce mcintosh 	}
854037cac00Sjoyce mcintosh 
855037cac00Sjoyce mcintosh 	/*
856037cac00Sjoyce mcintosh 	 * This MUST be done after ofile creation, so that explicitly
8575cb2894aSGordon Ross 	 * set timestamps can be remembered on the ofile, and setting
8585cb2894aSGordon Ross 	 * the readonly flag won't affect access via this open.
859037cac00Sjoyce mcintosh 	 */
860037cac00Sjoyce mcintosh 	if (status == NT_STATUS_SUCCESS) {
8615fd03bc0SGordon Ross 		if ((rc = smb_set_open_attributes(sr, of)) != 0) {
862a90cf9f2SGordon Ross 			status = smb_errno2status(rc);
863037cac00Sjoyce mcintosh 		}
864037cac00Sjoyce mcintosh 	}
865037cac00Sjoyce mcintosh 
866037cac00Sjoyce mcintosh 	if (status == NT_STATUS_SUCCESS) {
8675fd03bc0SGordon Ross 		/*
8685fd03bc0SGordon Ross 		 * We've already done access checks above,
8695fd03bc0SGordon Ross 		 * and want this call to succeed even when
8705fd03bc0SGordon Ross 		 * !(desired_access & FILE_READ_ATTRIBUTES),
8715fd03bc0SGordon Ross 		 * so pass kcred here.
8725fd03bc0SGordon Ross 		 */
8735fd03bc0SGordon Ross 		op->fqi.fq_fattr.sa_mask = SMB_AT_ALL;
8748622ec45SGordon Ross 		rc = smb_node_getattr(sr, node, zone_kcred(), of,
8755fd03bc0SGordon Ross 		    &op->fqi.fq_fattr);
8765fd03bc0SGordon Ross 		if (rc != 0) {
877037cac00Sjoyce mcintosh 			status = NT_STATUS_INTERNAL_ERROR;
878037cac00Sjoyce mcintosh 		}
879da6c28aaSamw 	}
880da6c28aaSamw 
881037cac00Sjoyce mcintosh 	/*
882037cac00Sjoyce mcintosh 	 * smb_fsop_unshrlock is a no-op if node is a directory
883037cac00Sjoyce mcintosh 	 * smb_fsop_unshrlock is done in smb_ofile_close
884037cac00Sjoyce mcintosh 	 */
885037cac00Sjoyce mcintosh 	if (status != NT_STATUS_SUCCESS) {
886037cac00Sjoyce mcintosh 		if (of == NULL) {
887037cac00Sjoyce mcintosh 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
888037cac00Sjoyce mcintosh 		} else {
889037cac00Sjoyce mcintosh 			smb_ofile_close(of, 0);
890037cac00Sjoyce mcintosh 			smb_ofile_release(of);
891037cac00Sjoyce mcintosh 		}
8928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (created)
8938b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_delete_new_object(sr);
8948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_unlock(node);
895cb174861Sjoyce mcintosh 		smb_node_dec_opening_count(node);
8968b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(node);
8978b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (created)
8988b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_unlock(dnode);
8998b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(dnode);
900037cac00Sjoyce mcintosh 		return (status);
9018b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
9028b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
9038c10a865Sas 	/*
9048c10a865Sas 	 * Propagate the write-through mode from the open params
9058c10a865Sas 	 * to the node: see the notes in the function header.
9068c10a865Sas 	 */
9078c10a865Sas 	if (sr->sr_cfg->skc_sync_enable ||
9088c10a865Sas 	    (op->create_options & FILE_WRITE_THROUGH))
9098c10a865Sas 		node->flags |= NODE_FLAGS_WRITE_THROUGH;
9108c10a865Sas 
911037cac00Sjoyce mcintosh 	/*
912037cac00Sjoyce mcintosh 	 * Set up the fileid and dosattr in open_param for response
913037cac00Sjoyce mcintosh 	 */
914eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	op->fileid = op->fqi.fq_fattr.sa_vattr.va_nodeid;
915037cac00Sjoyce mcintosh 	op->dattr = op->fqi.fq_fattr.sa_dosattr;
9168c10a865Sas 
917da6c28aaSamw 	/*
918da6c28aaSamw 	 * Set up the file type in open_param for the response
919da6c28aaSamw 	 */
920da6c28aaSamw 	op->ftype = SMB_FTYPE_DISK;
921da6c28aaSamw 	sr->smb_fid = of->f_fid;
922da6c28aaSamw 	sr->fid_ofile = of;
923da6c28aaSamw 
9249fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smb_node_is_file(node)) {
925cb174861Sjoyce mcintosh 		smb_oplock_acquire(sr, node, of);
926eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->dsize = op->fqi.fq_fattr.sa_vattr.va_size;
9279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	} else {
9289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		/* directory or symlink */
9292c2961f8Sjose borrego 		op->op_oplock_level = SMB_OPLOCK_NONE;
9302c2961f8Sjose borrego 		op->dsize = 0;
9312c2961f8Sjose borrego 	}
932dc20a302Sas 
933cb174861Sjoyce mcintosh 	smb_node_dec_opening_count(node);
934cb174861Sjoyce mcintosh 
935cb174861Sjoyce mcintosh 	smb_node_unlock(node);
936cb174861Sjoyce mcintosh 	if (created)
937cb174861Sjoyce mcintosh 		smb_node_unlock(dnode);
938cb174861Sjoyce mcintosh 
9398b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_release(node);
940da6c28aaSamw 	smb_node_release(dnode);
941da6c28aaSamw 
942da6c28aaSamw 	return (NT_STATUS_SUCCESS);
943da6c28aaSamw }
944da6c28aaSamw 
945cb174861Sjoyce mcintosh /*
946cb174861Sjoyce mcintosh  * smb_open_oplock_break
947cb174861Sjoyce mcintosh  *
948cb174861Sjoyce mcintosh  * If the node has an ofile opened with share access none,
949cb174861Sjoyce mcintosh  * (smb_node_share_check = FALSE) only break BATCH oplock.
950cb174861Sjoyce mcintosh  * Otherwise:
951cb174861Sjoyce mcintosh  * If overwriting, break to SMB_OPLOCK_NONE, else
952cb174861Sjoyce mcintosh  * If opening for anything other than attribute access,
953cb174861Sjoyce mcintosh  * break oplock to LEVEL_II.
954cb174861Sjoyce mcintosh  */
955cb174861Sjoyce mcintosh static void
956cb174861Sjoyce mcintosh smb_open_oplock_break(smb_request_t *sr, smb_node_t *node)
957cb174861Sjoyce mcintosh {
958cb174861Sjoyce mcintosh 	smb_arg_open_t	*op = &sr->sr_open;
959cb174861Sjoyce mcintosh 	uint32_t	flags = 0;
960*148d1a41SMatt Barden 	int		rc = 0;
961*148d1a41SMatt Barden 
962*148d1a41SMatt Barden 	if (sr->session->dialect >= SMB_VERS_2_BASE &&
963*148d1a41SMatt Barden 	    sr->smb2_async == B_FALSE)
964*148d1a41SMatt Barden 		flags |= SMB_OPLOCK_BREAK_NOWAIT;
965cb174861Sjoyce mcintosh 
966cb174861Sjoyce mcintosh 	if (!smb_node_share_check(node))
967cb174861Sjoyce mcintosh 		flags |= SMB_OPLOCK_BREAK_BATCH;
968cb174861Sjoyce mcintosh 
969cb174861Sjoyce mcintosh 	if (smb_open_overwrite(op)) {
970cb174861Sjoyce mcintosh 		flags |= SMB_OPLOCK_BREAK_TO_NONE;
971*148d1a41SMatt Barden 		rc = smb_oplock_break(sr, node, flags);
972cb174861Sjoyce mcintosh 	} else if (!smb_open_attr_only(op)) {
973cb174861Sjoyce mcintosh 		flags |= SMB_OPLOCK_BREAK_TO_LEVEL_II;
974*148d1a41SMatt Barden 		rc = smb_oplock_break(sr, node, flags);
975*148d1a41SMatt Barden 	}
976*148d1a41SMatt Barden 
977*148d1a41SMatt Barden 	if (sr->session->dialect >= SMB_VERS_2_BASE &&
978*148d1a41SMatt Barden 	    rc == EAGAIN) {
979*148d1a41SMatt Barden 		(void) smb2sr_go_async(sr);
980*148d1a41SMatt Barden 		flags &= ~SMB_OPLOCK_BREAK_NOWAIT;
981cb174861Sjoyce mcintosh 		(void) smb_oplock_break(sr, node, flags);
982cb174861Sjoyce mcintosh 	}
983cb174861Sjoyce mcintosh }
984cb174861Sjoyce mcintosh 
985cb174861Sjoyce mcintosh /*
986cb174861Sjoyce mcintosh  * smb_open_attr_only
987cb174861Sjoyce mcintosh  *
988cb174861Sjoyce mcintosh  * Determine if file is being opened for attribute access only.
989cb174861Sjoyce mcintosh  * This is used to determine whether it is necessary to break
990cb174861Sjoyce mcintosh  * existing oplocks on the file.
991cb174861Sjoyce mcintosh  */
992cb174861Sjoyce mcintosh static boolean_t
993cb174861Sjoyce mcintosh smb_open_attr_only(smb_arg_open_t *op)
994cb174861Sjoyce mcintosh {
995cb174861Sjoyce mcintosh 	if (((op->desired_access & ~(FILE_READ_ATTRIBUTES |
996fb699f1eSAlek Pinchuk 	    FILE_WRITE_ATTRIBUTES | SYNCHRONIZE | READ_CONTROL)) == 0) &&
997cb174861Sjoyce mcintosh 	    (op->create_disposition != FILE_SUPERSEDE) &&
998cb174861Sjoyce mcintosh 	    (op->create_disposition != FILE_OVERWRITE)) {
999cb174861Sjoyce mcintosh 		return (B_TRUE);
1000cb174861Sjoyce mcintosh 	}
1001cb174861Sjoyce mcintosh 	return (B_FALSE);
1002cb174861Sjoyce mcintosh }
1003cb174861Sjoyce mcintosh 
1004cb174861Sjoyce mcintosh static boolean_t
1005cb174861Sjoyce mcintosh smb_open_overwrite(smb_arg_open_t *op)
1006cb174861Sjoyce mcintosh {
1007cb174861Sjoyce mcintosh 	if ((op->create_disposition == FILE_SUPERSEDE) ||
1008cb174861Sjoyce mcintosh 	    (op->create_disposition == FILE_OVERWRITE_IF) ||
1009cb174861Sjoyce mcintosh 	    (op->create_disposition == FILE_OVERWRITE)) {
1010cb174861Sjoyce mcintosh 		return (B_TRUE);
1011cb174861Sjoyce mcintosh 	}
1012cb174861Sjoyce mcintosh 	return (B_FALSE);
1013cb174861Sjoyce mcintosh }
10145fd03bc0SGordon Ross 
1015037cac00Sjoyce mcintosh /*
10165fd03bc0SGordon Ross  * smb_set_open_attributes
1017037cac00Sjoyce mcintosh  *
1018037cac00Sjoyce mcintosh  * Last write time:
1019037cac00Sjoyce mcintosh  * - If the last_write time specified in the open params is not 0 or -1,
1020037cac00Sjoyce mcintosh  *   use it as file's mtime. This will be considered an explicitly set
1021037cac00Sjoyce mcintosh  *   timestamps, not reset by subsequent writes.
1022037cac00Sjoyce mcintosh  *
10235fd03bc0SGordon Ross  * DOS attributes
10245fd03bc0SGordon Ross  * - If we created_readonly, we now store the real DOS attributes
10255fd03bc0SGordon Ross  *   (including the readonly bit) so subsequent opens will see it.
1026037cac00Sjoyce mcintosh  *
1027037cac00Sjoyce mcintosh  * Returns: errno
1028037cac00Sjoyce mcintosh  */
1029037cac00Sjoyce mcintosh static int
10305fd03bc0SGordon Ross smb_set_open_attributes(smb_request_t *sr, smb_ofile_t *of)
1031037cac00Sjoyce mcintosh {
10325fd03bc0SGordon Ross 	smb_attr_t	attr;
1033148c5f43SAlan Wright 	smb_arg_open_t	*op = &sr->sr_open;
1034037cac00Sjoyce mcintosh 	smb_node_t	*node = of->f_node;
10355fd03bc0SGordon Ross 	int		rc = 0;
1036037cac00Sjoyce mcintosh 
1037037cac00Sjoyce mcintosh 	bzero(&attr, sizeof (smb_attr_t));
10385fd03bc0SGordon Ross 
10395fd03bc0SGordon Ross 	if (op->created_readonly) {
10405fd03bc0SGordon Ross 		attr.sa_dosattr = op->dattr | FILE_ATTRIBUTE_READONLY;
10415fd03bc0SGordon Ross 		attr.sa_mask |= SMB_AT_DOSATTR;
10425fd03bc0SGordon Ross 	}
1043037cac00Sjoyce mcintosh 
1044a90cf9f2SGordon Ross 	if (op->dsize != 0) {
1045a90cf9f2SGordon Ross 		attr.sa_allocsz = op->dsize;
1046a90cf9f2SGordon Ross 		attr.sa_mask |= SMB_AT_ALLOCSZ;
1047a90cf9f2SGordon Ross 	}
1048a90cf9f2SGordon Ross 
1049037cac00Sjoyce mcintosh 	if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
1050037cac00Sjoyce mcintosh 		attr.sa_vattr.va_mtime = op->mtime;
10515fd03bc0SGordon Ross 		attr.sa_mask |= SMB_AT_MTIME;
1052037cac00Sjoyce mcintosh 	}
1053037cac00Sjoyce mcintosh 
10545fd03bc0SGordon Ross 	/*
10555fd03bc0SGordon Ross 	 * Used to have code here to set mtime, ctime, atime
10565fd03bc0SGordon Ross 	 * when the open op->create_disposition is any of:
10575fd03bc0SGordon Ross 	 * FILE_SUPERSEDE, FILE_OVERWRITE_IF, FILE_OVERWRITE.
10585fd03bc0SGordon Ross 	 * We know that in those cases we will have set the
10595fd03bc0SGordon Ross 	 * file size, in which case the file system will
10605fd03bc0SGordon Ross 	 * update those times, so we don't have to.
10615fd03bc0SGordon Ross 	 *
10625fd03bc0SGordon Ross 	 * However, keep track of the fact that we modified
10635fd03bc0SGordon Ross 	 * the file via this handle, so we can do the evil,
10645fd03bc0SGordon Ross 	 * gratuitious mtime update on close that Windows
10655cb2894aSGordon Ross 	 * clients expect.
10665fd03bc0SGordon Ross 	 */
10675fd03bc0SGordon Ross 	if (op->action_taken == SMB_OACT_TRUNCATED)
10685fd03bc0SGordon Ross 		of->f_written = B_TRUE;
1069037cac00Sjoyce mcintosh 
10705fd03bc0SGordon Ross 	if (attr.sa_mask != 0)
10715fd03bc0SGordon Ross 		rc = smb_node_setattr(sr, node, of->f_cr, of, &attr);
1072037cac00Sjoyce mcintosh 
1073037cac00Sjoyce mcintosh 	return (rc);
1074037cac00Sjoyce mcintosh }
1075037cac00Sjoyce mcintosh 
1076da6c28aaSamw /*
10778b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * This function is used to delete a newly created object (file or
10788b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * directory) if an error occurs after creation of the object.
1079da6c28aaSamw  */
10808b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static void
10818b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_delete_new_object(smb_request_t *sr)
1082da6c28aaSamw {
1083148c5f43SAlan Wright 	smb_arg_open_t	*op = &sr->sr_open;
10848b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_fqi_t	*fqi = &(op->fqi);
10858b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	uint32_t	flags = 0;
10868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
10878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
10888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		flags |= SMB_IGNORE_CASE;
10898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (SMB_TREE_SUPPORTS_CATIA(sr))
10908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		flags |= SMB_CATIA;
10918b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
10928b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (op->create_options & FILE_DIRECTORY_FILE)
1093eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
1094eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    fqi->fq_last_comp, flags);
10958b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	else
1096eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode,
1097eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    fqi->fq_last_comp, flags);
1098eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States }
1099