xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_open.c (revision 9fb67ea305c66b6a297583b9b0db6796b0dfe497)
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  */
21da6c28aaSamw /*
22f96bd5c8SAlan Wright  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw /*
27da6c28aaSamw  * This module provides the common open functionality to the various
28da6c28aaSamw  * open and create SMB interface functions.
29da6c28aaSamw  */
30da6c28aaSamw 
31bbf6f00cSJordan Brown #include <sys/types.h>
32bbf6f00cSJordan Brown #include <sys/cmn_err.h>
33da6c28aaSamw #include <sys/fcntl.h>
34dc20a302Sas200622 #include <sys/nbmlock.h>
35bbf6f00cSJordan Brown #include <smbsrv/string.h>
36bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
37bbf6f00cSJordan Brown #include <smbsrv/smb_fsops.h>
38bbf6f00cSJordan Brown #include <smbsrv/smbinfo.h>
39da6c28aaSamw 
40faa1795aSjb150015 volatile uint32_t smb_fids = 0;
417b59d02dSjb150015 
427b59d02dSjb150015 static uint32_t smb_open_subr(smb_request_t *);
43faa1795aSjb150015 extern uint32_t smb_is_executable(char *);
448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static void smb_delete_new_object(smb_request_t *);
45037cac00Sjoyce mcintosh static int smb_set_open_timestamps(smb_request_t *, smb_ofile_t *, boolean_t);
46da6c28aaSamw 
47da6c28aaSamw /*
48da6c28aaSamw  * smb_access_generic_to_file
49da6c28aaSamw  *
50da6c28aaSamw  * Search MSDN for IoCreateFile to see following mapping.
51da6c28aaSamw  *
52da6c28aaSamw  * GENERIC_READ		STANDARD_RIGHTS_READ, FILE_READ_DATA,
53da6c28aaSamw  *			FILE_READ_ATTRIBUTES and FILE_READ_EA
54da6c28aaSamw  *
55da6c28aaSamw  * GENERIC_WRITE	STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
56da6c28aaSamw  *               FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
57da6c28aaSamw  *
58da6c28aaSamw  * GENERIC_EXECUTE	STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
59da6c28aaSamw  */
60da6c28aaSamw uint32_t
61da6c28aaSamw smb_access_generic_to_file(uint32_t desired_access)
62da6c28aaSamw {
63da6c28aaSamw 	uint32_t access = 0;
64da6c28aaSamw 
65da6c28aaSamw 	if (desired_access & GENERIC_ALL)
66da6c28aaSamw 		return (FILE_ALL_ACCESS & ~SYNCHRONIZE);
67da6c28aaSamw 
68da6c28aaSamw 	if (desired_access & GENERIC_EXECUTE) {
69da6c28aaSamw 		desired_access &= ~GENERIC_EXECUTE;
70da6c28aaSamw 		access |= (STANDARD_RIGHTS_EXECUTE |
71da6c28aaSamw 		    SYNCHRONIZE | FILE_EXECUTE);
72da6c28aaSamw 	}
73da6c28aaSamw 
74da6c28aaSamw 	if (desired_access & GENERIC_WRITE) {
75da6c28aaSamw 		desired_access &= ~GENERIC_WRITE;
76da6c28aaSamw 		access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE);
77da6c28aaSamw 	}
78da6c28aaSamw 
79da6c28aaSamw 	if (desired_access & GENERIC_READ) {
80da6c28aaSamw 		desired_access &= ~GENERIC_READ;
81da6c28aaSamw 		access |= FILE_GENERIC_READ;
82da6c28aaSamw 	}
83da6c28aaSamw 
84da6c28aaSamw 	return (access | desired_access);
85da6c28aaSamw }
86da6c28aaSamw 
87da6c28aaSamw /*
88da6c28aaSamw  * smb_omode_to_amask
89da6c28aaSamw  *
90da6c28aaSamw  * This function converts open modes used by Open and Open AndX
91da6c28aaSamw  * commands to desired access bits used by NT Create AndX command.
92da6c28aaSamw  */
93da6c28aaSamw uint32_t
94da6c28aaSamw smb_omode_to_amask(uint32_t desired_access)
95da6c28aaSamw {
96da6c28aaSamw 	switch (desired_access & SMB_DA_ACCESS_MASK) {
97da6c28aaSamw 	case SMB_DA_ACCESS_READ:
98da6c28aaSamw 		return (FILE_GENERIC_READ);
99da6c28aaSamw 
100da6c28aaSamw 	case SMB_DA_ACCESS_WRITE:
101da6c28aaSamw 		return (FILE_GENERIC_WRITE);
102da6c28aaSamw 
103da6c28aaSamw 	case SMB_DA_ACCESS_READ_WRITE:
104da6c28aaSamw 		return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
105da6c28aaSamw 
106da6c28aaSamw 	case SMB_DA_ACCESS_EXECUTE:
107da6c28aaSamw 		return (FILE_GENERIC_EXECUTE);
108da6c28aaSamw 
1092c2961f8Sjose borrego 	default:
1102c2961f8Sjose borrego 		return (FILE_GENERIC_ALL);
1112c2961f8Sjose borrego 	}
112da6c28aaSamw }
113da6c28aaSamw 
114da6c28aaSamw /*
115da6c28aaSamw  * smb_denymode_to_sharemode
116da6c28aaSamw  *
117da6c28aaSamw  * This function converts deny modes used by Open and Open AndX
118da6c28aaSamw  * commands to share access bits used by NT Create AndX command.
119da6c28aaSamw  */
120da6c28aaSamw uint32_t
121da6c28aaSamw smb_denymode_to_sharemode(uint32_t desired_access, char *fname)
122da6c28aaSamw {
123da6c28aaSamw 	switch (desired_access & SMB_DA_SHARE_MASK) {
124da6c28aaSamw 	case SMB_DA_SHARE_COMPATIBILITY:
125da6c28aaSamw 		if (smb_is_executable(fname))
126da6c28aaSamw 			return (FILE_SHARE_READ | FILE_SHARE_WRITE);
127c8ec8eeaSjose borrego 
128c8ec8eeaSjose borrego 		return (FILE_SHARE_ALL);
129da6c28aaSamw 
130da6c28aaSamw 	case SMB_DA_SHARE_EXCLUSIVE:
131da6c28aaSamw 		return (FILE_SHARE_NONE);
132da6c28aaSamw 
133da6c28aaSamw 	case SMB_DA_SHARE_DENY_WRITE:
134da6c28aaSamw 		return (FILE_SHARE_READ);
135da6c28aaSamw 
136da6c28aaSamw 	case SMB_DA_SHARE_DENY_READ:
137da6c28aaSamw 		return (FILE_SHARE_WRITE);
138da6c28aaSamw 
139da6c28aaSamw 	case SMB_DA_SHARE_DENY_NONE:
1402c2961f8Sjose borrego 	default:
141da6c28aaSamw 		return (FILE_SHARE_READ | FILE_SHARE_WRITE);
142da6c28aaSamw 	}
143da6c28aaSamw }
144da6c28aaSamw 
145da6c28aaSamw /*
146da6c28aaSamw  * smb_ofun_to_crdisposition
147da6c28aaSamw  *
148da6c28aaSamw  * This function converts open function values used by Open and Open AndX
149da6c28aaSamw  * commands to create disposition values used by NT Create AndX command.
150da6c28aaSamw  */
151da6c28aaSamw uint32_t
152da6c28aaSamw smb_ofun_to_crdisposition(uint16_t  ofun)
153da6c28aaSamw {
154da6c28aaSamw 	static int ofun_cr_map[3][2] =
155da6c28aaSamw 	{
156da6c28aaSamw 		{ -1,			FILE_CREATE },
157da6c28aaSamw 		{ FILE_OPEN,		FILE_OPEN_IF },
158da6c28aaSamw 		{ FILE_OVERWRITE,	FILE_OVERWRITE_IF }
159da6c28aaSamw 	};
160da6c28aaSamw 
161da6c28aaSamw 	int row = ofun & SMB_OFUN_OPEN_MASK;
162da6c28aaSamw 	int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4;
163da6c28aaSamw 
164da6c28aaSamw 	if (row == 3)
1652c2961f8Sjose borrego 		return (FILE_MAXIMUM_DISPOSITION + 1);
166da6c28aaSamw 
167da6c28aaSamw 	return (ofun_cr_map[row][col]);
168da6c28aaSamw }
169da6c28aaSamw 
170da6c28aaSamw /*
1717b59d02dSjb150015  * Retry opens to avoid spurious sharing violations, due to timing
1727b59d02dSjb150015  * issues between closes and opens.  The client that already has the
1737b59d02dSjb150015  * file open may be in the process of closing it.
1747b59d02dSjb150015  */
1757b59d02dSjb150015 uint32_t
1767b59d02dSjb150015 smb_common_open(smb_request_t *sr)
1777b59d02dSjb150015 {
178bbf6f00cSJordan Brown 	open_param_t	*parg;
1797b59d02dSjb150015 	uint32_t	status = NT_STATUS_SUCCESS;
1807b59d02dSjb150015 	int		count;
1817b59d02dSjb150015 
182bbf6f00cSJordan Brown 	parg = kmem_alloc(sizeof (*parg), KM_SLEEP);
183bbf6f00cSJordan Brown 	bcopy(&sr->arg.open, parg, sizeof (*parg));
184bbf6f00cSJordan Brown 
1857b59d02dSjb150015 	for (count = 0; count <= 4; count++) {
186bbf6f00cSJordan Brown 		if (count != 0)
1877b59d02dSjb150015 			delay(MSEC_TO_TICK(400));
1887b59d02dSjb150015 
189faa1795aSjb150015 		status = smb_open_subr(sr);
190faa1795aSjb150015 		if (status != NT_STATUS_SHARING_VIOLATION)
1917b59d02dSjb150015 			break;
192bbf6f00cSJordan Brown 
193bbf6f00cSJordan Brown 		bcopy(parg, &sr->arg.open, sizeof (*parg));
1947b59d02dSjb150015 	}
1957b59d02dSjb150015 
196faa1795aSjb150015 	if (status == NT_STATUS_SHARING_VIOLATION) {
1977b59d02dSjb150015 		smbsr_error(sr, NT_STATUS_SHARING_VIOLATION,
1987b59d02dSjb150015 		    ERRDOS, ERROR_SHARING_VIOLATION);
1997b59d02dSjb150015 	}
2007b59d02dSjb150015 
2012c2961f8Sjose borrego 	if (status == NT_STATUS_NO_SUCH_FILE) {
2022c2961f8Sjose borrego 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
2032c2961f8Sjose borrego 		    ERRDOS, ERROR_FILE_NOT_FOUND);
2042c2961f8Sjose borrego 	}
2052c2961f8Sjose borrego 
206bbf6f00cSJordan Brown 	kmem_free(parg, sizeof (*parg));
207bbf6f00cSJordan Brown 
2087b59d02dSjb150015 	return (status);
2097b59d02dSjb150015 }
2107b59d02dSjb150015 
2117b59d02dSjb150015 /*
212da6c28aaSamw  * smb_open_subr
213da6c28aaSamw  *
214da6c28aaSamw  * Notes on write-through behaviour. It looks like pre-LM0.12 versions
215da6c28aaSamw  * of the protocol specify the write-through mode when a file is opened,
216da6c28aaSamw  * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
217da6c28aaSamw  * SmbWriteAndUnlock) don't need to contain a write-through flag.
218da6c28aaSamw  *
219da6c28aaSamw  * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
220da6c28aaSamw  * don't indicate which write-through mode to use. Instead the write
221da6c28aaSamw  * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
222da6c28aaSamw  * basis.
223da6c28aaSamw  *
224da6c28aaSamw  * We don't care which open call was used to get us here, we just need
225da6c28aaSamw  * to ensure that the write-through mode flag is copied from the open
226da6c28aaSamw  * parameters to the node. We test the omode write-through flag in all
227da6c28aaSamw  * write functions.
228da6c28aaSamw  *
229da6c28aaSamw  * This function will return NT status codes but it also raises errors,
230da6c28aaSamw  * in which case it won't return to the caller. Be careful how you
231da6c28aaSamw  * handle things in here.
2328c10a865Sas200622  *
2338c10a865Sas200622  * The following rules apply when processing a file open request:
2348c10a865Sas200622  *
2358c10a865Sas200622  * - Oplocks must be broken prior to share checking to prevent open
2368c10a865Sas200622  * starvation due to batch oplocks.  Checking share reservations first
2378c10a865Sas200622  * could potentially result in unnecessary open failures due to
2388c10a865Sas200622  * open/close batching on the client.
2398c10a865Sas200622  *
2408c10a865Sas200622  * - Share checks must take place prior to access checks for correct
2418c10a865Sas200622  * Windows semantics and to prevent unnecessary NFS delegation recalls.
2428c10a865Sas200622  *
2438c10a865Sas200622  * - Oplocks must be acquired after open to ensure the correct
2448c10a865Sas200622  * synchronization with NFS delegation and FEM installation.
245c8ec8eeaSjose borrego  *
246c8ec8eeaSjose borrego  *
247c8ec8eeaSjose borrego  * DOS readonly bit rules
248c8ec8eeaSjose borrego  *
249c8ec8eeaSjose borrego  * 1. The creator of a readonly file can write to/modify the size of the file
250c8ec8eeaSjose borrego  * using the original create fid, even though the file will appear as readonly
251c8ec8eeaSjose borrego  * to all other fids and via a CIFS getattr call.
252037cac00Sjoyce mcintosh  * The readonly bit therefore cannot be set in the filesystem until the file
253037cac00Sjoyce mcintosh  * is closed (smb_ofile_close). It is accounted for via ofile and node flags.
254c8ec8eeaSjose borrego  *
255c8ec8eeaSjose borrego  * 2. A setinfo operation (using either an open fid or a path) to set/unset
256c8ec8eeaSjose borrego  * readonly will be successful regardless of whether a creator of a readonly
257c8ec8eeaSjose borrego  * file has an open fid (and has the special privilege mentioned in #1,
258c8ec8eeaSjose borrego  * above).  I.e., the creator of a readonly fid holding that fid will no longer
259c8ec8eeaSjose borrego  * have a special privilege.
260c8ec8eeaSjose borrego  *
261c8ec8eeaSjose borrego  * 3. The DOS readonly bit affects only data and some metadata.
262c8ec8eeaSjose borrego  * The following metadata can be changed regardless of the readonly bit:
263c8ec8eeaSjose borrego  * 	- security descriptors
264c8ec8eeaSjose borrego  *	- DOS attributes
265c8ec8eeaSjose borrego  *	- timestamps
266c8ec8eeaSjose borrego  *
267c8ec8eeaSjose borrego  * In the current implementation, the file size cannot be changed (except for
268c8ec8eeaSjose borrego  * the exceptions in #1 and #2, above).
2692c1b14e5Sjose borrego  *
2702c1b14e5Sjose borrego  *
2712c1b14e5Sjose borrego  * DOS attribute rules
2722c1b14e5Sjose borrego  *
2732c1b14e5Sjose borrego  * These rules are specific to creating / opening files and directories.
2742c1b14e5Sjose borrego  * How the attribute value (specifically ZERO or FILE_ATTRIBUTE_NORMAL)
2752c1b14e5Sjose borrego  * should be interpreted may differ in other requests.
2762c1b14e5Sjose borrego  *
2772c1b14e5Sjose borrego  * - An attribute value equal to ZERO or FILE_ATTRIBUTE_NORMAL means that the
2782c1b14e5Sjose borrego  *   file's attributes should be cleared.
2792c1b14e5Sjose borrego  * - If FILE_ATTRIBUTE_NORMAL is specified with any other attributes,
2802c1b14e5Sjose borrego  *   FILE_ATTRIBUTE_NORMAL is ignored.
2812c1b14e5Sjose borrego  *
2822c1b14e5Sjose borrego  * 1. Creating a new file
2832c1b14e5Sjose borrego  * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file.
2842c1b14e5Sjose borrego  *
2852c1b14e5Sjose borrego  * 2. Creating a new directory
2862c1b14e5Sjose borrego  * - The request attributes + FILE_ATTRIBUTE_DIRECTORY are applied to the file.
2872c1b14e5Sjose borrego  * - FILE_ATTRIBUTE_ARCHIVE does not get set.
2882c1b14e5Sjose borrego  *
2892c1b14e5Sjose borrego  * 3. Overwriting an existing file
2902c1b14e5Sjose borrego  * - the request attributes are used as search attributes. If the existing
2912c1b14e5Sjose borrego  *   file does not meet the search criteria access is denied.
2922c1b14e5Sjose borrego  * - otherwise, applies attributes + FILE_ATTRIBUTE_ARCHIVE.
2932c1b14e5Sjose borrego  *
2942c1b14e5Sjose borrego  * 4. Opening an existing file or directory
2952c1b14e5Sjose borrego  *    The request attributes are ignored.
296da6c28aaSamw  */
2977b59d02dSjb150015 static uint32_t
2987b59d02dSjb150015 smb_open_subr(smb_request_t *sr)
299da6c28aaSamw {
300eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	created = B_FALSE;
301eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	last_comp_found = B_FALSE;
3022c2961f8Sjose borrego 	smb_node_t	*node = NULL;
3032c2961f8Sjose borrego 	smb_node_t	*dnode = NULL;
304eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_t	*cur_node = NULL;
3052c2961f8Sjose borrego 	open_param_t	*op = &sr->arg.open;
306da6c28aaSamw 	int		rc;
3072c2961f8Sjose borrego 	smb_ofile_t	*of;
308da6c28aaSamw 	smb_attr_t	new_attr;
309da6c28aaSamw 	int		max_requested = 0;
310da6c28aaSamw 	uint32_t	max_allowed;
311da6c28aaSamw 	uint32_t	status = NT_STATUS_SUCCESS;
312da6c28aaSamw 	int		is_dir;
313da6c28aaSamw 	smb_error_t	err;
3142c2961f8Sjose borrego 	boolean_t	is_stream = B_FALSE;
315da6c28aaSamw 	int		lookup_flags = SMB_FOLLOW_LINKS;
316dc20a302Sas200622 	uint32_t	uniq_fid;
317eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_pathname_t	*pn = &op->fqi.fq_path;
318da6c28aaSamw 
319da6c28aaSamw 	is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
320da6c28aaSamw 
321da6c28aaSamw 	/*
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
325da6c28aaSamw 	 */
326037cac00Sjoyce mcintosh 	if (is_dir) {
327da6c28aaSamw 		if ((op->create_disposition != FILE_CREATE) &&
328da6c28aaSamw 		    (op->create_disposition != FILE_OPEN_IF) &&
329da6c28aaSamw 		    (op->create_disposition != FILE_OPEN)) {
330dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
331da6c28aaSamw 			    ERRDOS, ERROR_INVALID_ACCESS);
3327b59d02dSjb150015 			return (NT_STATUS_INVALID_PARAMETER);
333da6c28aaSamw 		}
334da6c28aaSamw 	}
335da6c28aaSamw 
336da6c28aaSamw 	if (op->desired_access & MAXIMUM_ALLOWED) {
337da6c28aaSamw 		max_requested = 1;
338da6c28aaSamw 		op->desired_access &= ~MAXIMUM_ALLOWED;
339da6c28aaSamw 	}
340da6c28aaSamw 	op->desired_access = smb_access_generic_to_file(op->desired_access);
341da6c28aaSamw 
342da6c28aaSamw 	if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) {
343da6c28aaSamw 		ASSERT(sr->uid_user);
344da6c28aaSamw 		cmn_err(CE_NOTE, "smbd[%s\\%s]: %s", sr->uid_user->u_domain,
345da6c28aaSamw 		    sr->uid_user->u_name,
346da6c28aaSamw 		    xlate_nt_status(NT_STATUS_TOO_MANY_OPENED_FILES));
347da6c28aaSamw 
348dc20a302Sas200622 		smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
349da6c28aaSamw 		    ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
3507b59d02dSjb150015 		return (NT_STATUS_TOO_MANY_OPENED_FILES);
351da6c28aaSamw 	}
352da6c28aaSamw 
353da6c28aaSamw 	/* This must be NULL at this point */
354da6c28aaSamw 	sr->fid_ofile = NULL;
355da6c28aaSamw 
356da6c28aaSamw 	op->devstate = 0;
357da6c28aaSamw 
358da6c28aaSamw 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
359da6c28aaSamw 	case STYPE_DISKTREE:
360f96bd5c8SAlan Wright 	case STYPE_PRINTQ:
361da6c28aaSamw 		break;
362da6c28aaSamw 
363da6c28aaSamw 	case STYPE_IPC:
364da6c28aaSamw 		/*
365da6c28aaSamw 		 * No further processing for IPC, we need to either
366da6c28aaSamw 		 * raise an exception or return success here.
367da6c28aaSamw 		 */
3683db3f65cSamw 		if ((status = smb_opipe_open(sr)) != NT_STATUS_SUCCESS)
3697b59d02dSjb150015 			smbsr_error(sr, status, 0, 0);
3707b59d02dSjb150015 		return (status);
371da6c28aaSamw 
372da6c28aaSamw 	default:
3737b59d02dSjb150015 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
3747b59d02dSjb150015 		    ERRDOS, ERROR_BAD_DEV_TYPE);
3757b59d02dSjb150015 		return (NT_STATUS_BAD_DEVICE_TYPE);
376da6c28aaSamw 	}
377da6c28aaSamw 
378fe1c642dSBill Krier 	smb_pathname_init(sr, pn, pn->pn_path);
379fe1c642dSBill Krier 	if (!smb_pathname_validate(sr, pn))
380fe1c642dSBill Krier 		return (sr->smb_error.status);
381fe1c642dSBill Krier 
382fe1c642dSBill Krier 	if (strlen(pn->pn_path) >= MAXPATHLEN) {
383dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRfilespecs);
3847b59d02dSjb150015 		return (NT_STATUS_NAME_TOO_LONG);
385da6c28aaSamw 	}
386da6c28aaSamw 
387fe1c642dSBill Krier 	if (is_dir) {
388fe1c642dSBill Krier 		if (!smb_validate_dirname(sr, pn))
389fe1c642dSBill Krier 			return (sr->smb_error.status);
390fe1c642dSBill Krier 	} else {
391fe1c642dSBill Krier 		if (!smb_validate_object_name(sr, pn))
392fe1c642dSBill Krier 			return (sr->smb_error.status);
393da6c28aaSamw 	}
394da6c28aaSamw 
395eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	cur_node = op->fqi.fq_dnode ?
396eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	    op->fqi.fq_dnode : sr->tid_tree->t_snode;
397da6c28aaSamw 
398eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	/*
399eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	 * if no path or filename are specified the stream should be
400eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	 * created on cur_node
401eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	 */
402eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (!is_dir && !pn->pn_pname && !pn->pn_fname && pn->pn_sname) {
403*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		/*
404*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 * Can't currently handle a stream on the tree root.
405*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 * If a stream is being opened return "not found", otherwise
406*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 * return "access denied".
407*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		 */
408eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (cur_node == sr->tid_tree->t_snode) {
409*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			if (op->create_disposition == FILE_OPEN) {
410*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
411*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				    ERRDOS, ERROR_FILE_NOT_FOUND);
412*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 				return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
413*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			}
414eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
415eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			    ERROR_ACCESS_DENIED);
416eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			return (NT_STATUS_ACCESS_DENIED);
417eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		}
418eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
419eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		(void) snprintf(op->fqi.fq_last_comp,
420eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    sizeof (op->fqi.fq_last_comp),
421eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    "%s%s", cur_node->od_name, pn->pn_sname);
422eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
4231fcced4cSJordan Brown 		op->fqi.fq_dnode = cur_node->n_dnode;
424eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_ref(op->fqi.fq_dnode);
425eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	} else {
426eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
427eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode,
428eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    op->fqi.fq_last_comp)) {
429dc20a302Sas200622 			smbsr_errno(sr, rc);
4307b59d02dSjb150015 			return (sr->smb_error.status);
431da6c28aaSamw 		}
432eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
433da6c28aaSamw 
434da6c28aaSamw 	/*
435da6c28aaSamw 	 * If the access mask has only DELETE set (ignore
436da6c28aaSamw 	 * FILE_READ_ATTRIBUTES), then assume that this
437da6c28aaSamw 	 * is a request to delete the link (if a link)
438da6c28aaSamw 	 * and do not follow links.  Otherwise, follow
439da6c28aaSamw 	 * the link to the target.
440da6c28aaSamw 	 */
441037cac00Sjoyce mcintosh 	if ((op->desired_access & ~FILE_READ_ATTRIBUTES) == DELETE)
442da6c28aaSamw 		lookup_flags &= ~SMB_FOLLOW_LINKS;
443da6c28aaSamw 
444da6c28aaSamw 	rc = smb_fsop_lookup_name(sr, kcred, lookup_flags,
445eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	    sr->tid_tree->t_snode, op->fqi.fq_dnode, op->fqi.fq_last_comp,
446037cac00Sjoyce mcintosh 	    &op->fqi.fq_fnode);
447da6c28aaSamw 
448da6c28aaSamw 	if (rc == 0) {
449eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		last_comp_found = B_TRUE;
450037cac00Sjoyce mcintosh 		rc = smb_node_getattr(sr, op->fqi.fq_fnode,
451037cac00Sjoyce mcintosh 		    &op->fqi.fq_fattr);
452037cac00Sjoyce mcintosh 		if (rc != 0) {
453037cac00Sjoyce mcintosh 			smb_node_release(op->fqi.fq_fnode);
454037cac00Sjoyce mcintosh 			smb_node_release(op->fqi.fq_dnode);
455037cac00Sjoyce mcintosh 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
456037cac00Sjoyce mcintosh 			    ERRDOS, ERROR_INTERNAL_ERROR);
457037cac00Sjoyce mcintosh 			return (sr->smb_error.status);
458037cac00Sjoyce mcintosh 		}
459da6c28aaSamw 	} else if (rc == ENOENT) {
460eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		last_comp_found = B_FALSE;
461eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->fqi.fq_fnode = NULL;
462da6c28aaSamw 		rc = 0;
463da6c28aaSamw 	} else {
464eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(op->fqi.fq_dnode);
465dc20a302Sas200622 		smbsr_errno(sr, rc);
4667b59d02dSjb150015 		return (sr->smb_error.status);
467da6c28aaSamw 	}
468da6c28aaSamw 
469037cac00Sjoyce mcintosh 
470dc20a302Sas200622 	/*
471dc20a302Sas200622 	 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
472dc20a302Sas200622 	 * which is used to uniquely identify open instances for the
473c8ec8eeaSjose borrego 	 * VFS share reservation and POSIX locks.
474dc20a302Sas200622 	 */
475dc20a302Sas200622 
476dc20a302Sas200622 	uniq_fid = SMB_UNIQ_FID();
477dc20a302Sas200622 
478eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (last_comp_found) {
4796537f381Sas200622 
480*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		node = op->fqi.fq_fnode;
481*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		dnode = op->fqi.fq_dnode;
4826537f381Sas200622 
483*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (!smb_node_is_file(node) && !smb_node_is_dir(node) &&
484*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		    !smb_node_is_symlink(node)) {
485*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_release(node);
486*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_release(dnode);
4876537f381Sas200622 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
4886537f381Sas200622 			    ERRnoaccess);
4896537f381Sas200622 			return (NT_STATUS_ACCESS_DENIED);
4906537f381Sas200622 		}
4916537f381Sas200622 
492da6c28aaSamw 		/*
4932c1b14e5Sjose borrego 		 * Reject this request if either:
4942c1b14e5Sjose borrego 		 * - the target IS a directory and the client requires that
4952c1b14e5Sjose borrego 		 *   it must NOT be (required by Lotus Notes)
4962c1b14e5Sjose borrego 		 * - the target is NOT a directory and client requires that
4972c1b14e5Sjose borrego 		 *   it MUST be.
498da6c28aaSamw 		 */
499*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (smb_node_is_dir(node)) {
5002c1b14e5Sjose borrego 			if (op->create_options & FILE_NON_DIRECTORY_FILE) {
501da6c28aaSamw 				smb_node_release(node);
502da6c28aaSamw 				smb_node_release(dnode);
503dc20a302Sas200622 				smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY,
504da6c28aaSamw 				    ERRDOS, ERROR_ACCESS_DENIED);
5057b59d02dSjb150015 				return (NT_STATUS_FILE_IS_A_DIRECTORY);
506da6c28aaSamw 			}
5072c1b14e5Sjose borrego 		} else {
5082c1b14e5Sjose borrego 			if ((op->create_options & FILE_DIRECTORY_FILE) ||
5092c2961f8Sjose borrego 			    (op->nt_flags & NT_CREATE_FLAG_OPEN_TARGET_DIR)) {
510da6c28aaSamw 				smb_node_release(node);
511da6c28aaSamw 				smb_node_release(dnode);
512dc20a302Sas200622 				smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
513da6c28aaSamw 				    ERRDOS, ERROR_DIRECTORY);
5147b59d02dSjb150015 				return (NT_STATUS_NOT_A_DIRECTORY);
515da6c28aaSamw 			}
5162c1b14e5Sjose borrego 		}
517da6c28aaSamw 
518da6c28aaSamw 		/*
519da6c28aaSamw 		 * No more open should be accepted when "Delete on close"
520da6c28aaSamw 		 * flag is set.
521da6c28aaSamw 		 */
522da6c28aaSamw 		if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
523da6c28aaSamw 			smb_node_release(node);
524da6c28aaSamw 			smb_node_release(dnode);
525dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_DELETE_PENDING,
526da6c28aaSamw 			    ERRDOS, ERROR_ACCESS_DENIED);
5277b59d02dSjb150015 			return (NT_STATUS_DELETE_PENDING);
528da6c28aaSamw 		}
529da6c28aaSamw 
530da6c28aaSamw 		/*
531da6c28aaSamw 		 * Specified file already exists so the operation should fail.
532da6c28aaSamw 		 */
533da6c28aaSamw 		if (op->create_disposition == FILE_CREATE) {
534da6c28aaSamw 			smb_node_release(node);
535da6c28aaSamw 			smb_node_release(dnode);
536dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION,
537b89a8333Snatalie li - Sun Microsystems - Irvine United States 			    ERRDOS, ERROR_FILE_EXISTS);
5387b59d02dSjb150015 			return (NT_STATUS_OBJECT_NAME_COLLISION);
539da6c28aaSamw 		}
540da6c28aaSamw 
541da6c28aaSamw 		/*
542da6c28aaSamw 		 * Windows seems to check read-only access before file
543da6c28aaSamw 		 * sharing check.
544c8ec8eeaSjose borrego 		 *
545c8ec8eeaSjose borrego 		 * Check to see if the file is currently readonly (irrespective
546c8ec8eeaSjose borrego 		 * of whether this open will make it readonly).
547da6c28aaSamw 		 */
548c8ec8eeaSjose borrego 		if (SMB_PATHFILE_IS_READONLY(sr, node)) {
549da6c28aaSamw 			/* Files data only */
550037cac00Sjoyce mcintosh 			if (!smb_node_is_dir(node)) {
551da6c28aaSamw 				if (op->desired_access & (FILE_WRITE_DATA |
552da6c28aaSamw 				    FILE_APPEND_DATA)) {
553da6c28aaSamw 					smb_node_release(node);
554da6c28aaSamw 					smb_node_release(dnode);
555dc20a302Sas200622 					smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
556dc20a302Sas200622 					    ERRDOS, ERRnoaccess);
5577b59d02dSjb150015 					return (NT_STATUS_ACCESS_DENIED);
558da6c28aaSamw 				}
559da6c28aaSamw 			}
560da6c28aaSamw 		}
561da6c28aaSamw 
5628c10a865Sas200622 		if (smb_oplock_conflict(node, sr->session, op))
563fc724630SAlan Wright 			(void) smb_oplock_break(node, sr->session, B_FALSE);
5648c10a865Sas200622 
5652c2961f8Sjose borrego 		smb_node_wrlock(node);
566dc20a302Sas200622 
567dc20a302Sas200622 		if ((op->create_disposition == FILE_SUPERSEDE) ||
568dc20a302Sas200622 		    (op->create_disposition == FILE_OVERWRITE_IF) ||
569dc20a302Sas200622 		    (op->create_disposition == FILE_OVERWRITE)) {
570dc20a302Sas200622 
5712c1b14e5Sjose borrego 			if ((!(op->desired_access &
5728c10a865Sas200622 			    (FILE_WRITE_DATA | FILE_APPEND_DATA |
5732c1b14e5Sjose borrego 			    FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA))) ||
574037cac00Sjoyce mcintosh 			    (!smb_sattr_check(op->fqi.fq_fattr.sa_dosattr,
5752c2961f8Sjose borrego 			    op->dattr))) {
5762c2961f8Sjose borrego 				smb_node_unlock(node);
577dc20a302Sas200622 				smb_node_release(node);
578dc20a302Sas200622 				smb_node_release(dnode);
579dc20a302Sas200622 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
580dc20a302Sas200622 				    ERRDOS, ERRnoaccess);
5817b59d02dSjb150015 				return (NT_STATUS_ACCESS_DENIED);
582dc20a302Sas200622 			}
583dc20a302Sas200622 		}
584dc20a302Sas200622 
585dc20a302Sas200622 		status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
586c8ec8eeaSjose borrego 		    op->desired_access, op->share_access);
587dc20a302Sas200622 
588da6c28aaSamw 		if (status == NT_STATUS_SHARING_VIOLATION) {
5892c2961f8Sjose borrego 			smb_node_unlock(node);
590da6c28aaSamw 			smb_node_release(node);
591da6c28aaSamw 			smb_node_release(dnode);
592da6c28aaSamw 			return (status);
593da6c28aaSamw 		}
594da6c28aaSamw 
595da6c28aaSamw 		status = smb_fsop_access(sr, sr->user_cr, node,
596da6c28aaSamw 		    op->desired_access);
597da6c28aaSamw 
598da6c28aaSamw 		if (status != NT_STATUS_SUCCESS) {
599dc20a302Sas200622 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
600dc20a302Sas200622 
6012c2961f8Sjose borrego 			smb_node_unlock(node);
602da6c28aaSamw 			smb_node_release(node);
603da6c28aaSamw 			smb_node_release(dnode);
604dc20a302Sas200622 
605da6c28aaSamw 			if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
606dc20a302Sas200622 				smbsr_error(sr, status,
607dc20a302Sas200622 				    ERRDOS, ERROR_PRIVILEGE_NOT_HELD);
6087b59d02dSjb150015 				return (status);
609da6c28aaSamw 			} else {
610dc20a302Sas200622 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
611dc20a302Sas200622 				    ERRDOS, ERROR_ACCESS_DENIED);
6127b59d02dSjb150015 				return (NT_STATUS_ACCESS_DENIED);
613da6c28aaSamw 			}
614da6c28aaSamw 		}
615da6c28aaSamw 
616da6c28aaSamw 		switch (op->create_disposition) {
617da6c28aaSamw 		case FILE_SUPERSEDE:
618da6c28aaSamw 		case FILE_OVERWRITE_IF:
619da6c28aaSamw 		case FILE_OVERWRITE:
620037cac00Sjoyce mcintosh 			if (smb_node_is_dir(node)) {
621dc20a302Sas200622 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
6222c2961f8Sjose borrego 				smb_node_unlock(node);
623da6c28aaSamw 				smb_node_release(node);
624da6c28aaSamw 				smb_node_release(dnode);
625dc20a302Sas200622 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
626dc20a302Sas200622 				    ERRDOS, ERROR_ACCESS_DENIED);
6277b59d02dSjb150015 				return (NT_STATUS_ACCESS_DENIED);
628da6c28aaSamw 			}
629da6c28aaSamw 
630037cac00Sjoyce mcintosh 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
631037cac00Sjoyce mcintosh 			/* Don't apply readonly bit until smb_ofile_close */
632037cac00Sjoyce mcintosh 			if (op->dattr & FILE_ATTRIBUTE_READONLY) {
633037cac00Sjoyce mcintosh 				op->created_readonly = B_TRUE;
634037cac00Sjoyce mcintosh 				op->dattr &= ~FILE_ATTRIBUTE_READONLY;
635037cac00Sjoyce mcintosh 			}
636037cac00Sjoyce mcintosh 
637dc20a302Sas200622 			bzero(&new_attr, sizeof (new_attr));
638037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
639da6c28aaSamw 			new_attr.sa_vattr.va_size = op->dsize;
640037cac00Sjoyce mcintosh 			new_attr.sa_mask = SMB_AT_DOSATTR | SMB_AT_SIZE;
641037cac00Sjoyce mcintosh 			rc = smb_fsop_setattr(sr, sr->user_cr, node, &new_attr);
642037cac00Sjoyce mcintosh 			if (rc != 0) {
643037cac00Sjoyce mcintosh 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
6442c2961f8Sjose borrego 				smb_node_unlock(node);
645da6c28aaSamw 				smb_node_release(node);
646da6c28aaSamw 				smb_node_release(dnode);
647dc20a302Sas200622 				smbsr_errno(sr, rc);
6487b59d02dSjb150015 				return (sr->smb_error.status);
649da6c28aaSamw 			}
650da6c28aaSamw 
651da6c28aaSamw 			/*
652037cac00Sjoyce mcintosh 			 * If file is being replaced, remove existing streams
653da6c28aaSamw 			 */
654eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			if (SMB_IS_STREAM(node) == 0) {
655037cac00Sjoyce mcintosh 				rc = smb_fsop_remove_streams(sr, sr->user_cr,
656037cac00Sjoyce mcintosh 				    node);
657037cac00Sjoyce mcintosh 				if (rc != 0) {
658eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_fsop_unshrlock(sr->user_cr, node,
659eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					    uniq_fid);
660eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_unlock(node);
661eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_release(node);
662eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_release(dnode);
663eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					return (sr->smb_error.status);
664eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 				}
665eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			}
666da6c28aaSamw 
667da6c28aaSamw 			op->action_taken = SMB_OACT_TRUNCATED;
668da6c28aaSamw 			break;
669da6c28aaSamw 
670da6c28aaSamw 		default:
671da6c28aaSamw 			/*
672da6c28aaSamw 			 * FILE_OPEN or FILE_OPEN_IF.
673da6c28aaSamw 			 */
674da6c28aaSamw 			op->action_taken = SMB_OACT_OPENED;
675da6c28aaSamw 			break;
676da6c28aaSamw 		}
677da6c28aaSamw 	} else {
678da6c28aaSamw 		/* Last component was not found. */
679eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		dnode = op->fqi.fq_dnode;
680da6c28aaSamw 
6817b59d02dSjb150015 		if (is_dir == 0)
682eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			is_stream = smb_is_stream_name(pn->pn_path);
6837b59d02dSjb150015 
684da6c28aaSamw 		if ((op->create_disposition == FILE_OPEN) ||
685da6c28aaSamw 		    (op->create_disposition == FILE_OVERWRITE)) {
686da6c28aaSamw 			smb_node_release(dnode);
687dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
688da6c28aaSamw 			    ERRDOS, ERROR_FILE_NOT_FOUND);
6897b59d02dSjb150015 			return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
690da6c28aaSamw 		}
691da6c28aaSamw 
692*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		if (pn->pn_fname && smb_is_invalid_filename(pn->pn_fname)) {
6932c2961f8Sjose borrego 			smb_node_release(dnode);
6942c2961f8Sjose borrego 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
6952c2961f8Sjose borrego 			    ERRDOS, ERROR_INVALID_NAME);
6962c2961f8Sjose borrego 			return (NT_STATUS_OBJECT_NAME_INVALID);
6972c2961f8Sjose borrego 		}
6982c2961f8Sjose borrego 
699da6c28aaSamw 		/*
700da6c28aaSamw 		 * lock the parent dir node in case another create
701da6c28aaSamw 		 * request to the same parent directory comes in.
702da6c28aaSamw 		 */
7032c2961f8Sjose borrego 		smb_node_wrlock(dnode);
704da6c28aaSamw 
705037cac00Sjoyce mcintosh 		/* Don't apply readonly bit until smb_ofile_close */
706037cac00Sjoyce mcintosh 		if (op->dattr & FILE_ATTRIBUTE_READONLY) {
707037cac00Sjoyce mcintosh 			op->dattr &= ~FILE_ATTRIBUTE_READONLY;
708037cac00Sjoyce mcintosh 			op->created_readonly = B_TRUE;
709037cac00Sjoyce mcintosh 		}
710037cac00Sjoyce mcintosh 
711da6c28aaSamw 		bzero(&new_attr, sizeof (new_attr));
712c8ec8eeaSjose borrego 		if ((op->crtime.tv_sec != 0) &&
713c8ec8eeaSjose borrego 		    (op->crtime.tv_sec != UINT_MAX)) {
714c8ec8eeaSjose borrego 
715c8ec8eeaSjose borrego 			new_attr.sa_mask |= SMB_AT_CRTIME;
716c8ec8eeaSjose borrego 			new_attr.sa_crtime = op->crtime;
717c8ec8eeaSjose borrego 		}
718c8ec8eeaSjose borrego 
719da6c28aaSamw 		if (is_dir == 0) {
720037cac00Sjoyce mcintosh 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
721037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
722da6c28aaSamw 			new_attr.sa_vattr.va_type = VREG;
7237b59d02dSjb150015 			new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR :
7247b59d02dSjb150015 			    S_IRUSR | S_IRGRP | S_IROTH |
7257b59d02dSjb150015 			    S_IWUSR | S_IWGRP | S_IWOTH;
726037cac00Sjoyce mcintosh 			new_attr.sa_mask |=
727037cac00Sjoyce mcintosh 			    SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
728dc20a302Sas200622 
7296537f381Sas200622 			if (op->dsize) {
7306537f381Sas200622 				new_attr.sa_vattr.va_size = op->dsize;
7316537f381Sas200622 				new_attr.sa_mask |= SMB_AT_SIZE;
732dc20a302Sas200622 			}
733dc20a302Sas200622 
734da6c28aaSamw 			rc = smb_fsop_create(sr, sr->user_cr, dnode,
735037cac00Sjoyce mcintosh 			    op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
736dc20a302Sas200622 
737da6c28aaSamw 			if (rc != 0) {
7382c2961f8Sjose borrego 				smb_node_unlock(dnode);
739da6c28aaSamw 				smb_node_release(dnode);
740dc20a302Sas200622 				smbsr_errno(sr, rc);
7417b59d02dSjb150015 				return (sr->smb_error.status);
742da6c28aaSamw 			}
743da6c28aaSamw 
744eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			node = op->fqi.fq_fnode;
7452c2961f8Sjose borrego 			smb_node_wrlock(node);
746dc20a302Sas200622 
747faa1795aSjb150015 			status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
748c8ec8eeaSjose borrego 			    op->desired_access, op->share_access);
749dc20a302Sas200622 
750dc20a302Sas200622 			if (status == NT_STATUS_SHARING_VIOLATION) {
7512c2961f8Sjose borrego 				smb_node_unlock(node);
7528b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 				smb_delete_new_object(sr);
753dc20a302Sas200622 				smb_node_release(node);
7542c2961f8Sjose borrego 				smb_node_unlock(dnode);
755dc20a302Sas200622 				smb_node_release(dnode);
756dc20a302Sas200622 				return (status);
757dc20a302Sas200622 			}
758da6c28aaSamw 		} else {
7593db3f65cSamw 			op->dattr |= FILE_ATTRIBUTE_DIRECTORY;
760037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
761da6c28aaSamw 			new_attr.sa_vattr.va_type = VDIR;
762da6c28aaSamw 			new_attr.sa_vattr.va_mode = 0777;
763037cac00Sjoyce mcintosh 			new_attr.sa_mask |=
764037cac00Sjoyce mcintosh 			    SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
765c8ec8eeaSjose borrego 
766da6c28aaSamw 			rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
767037cac00Sjoyce mcintosh 			    op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
768da6c28aaSamw 			if (rc != 0) {
7692c2961f8Sjose borrego 				smb_node_unlock(dnode);
770da6c28aaSamw 				smb_node_release(dnode);
771dc20a302Sas200622 				smbsr_errno(sr, rc);
7727b59d02dSjb150015 				return (sr->smb_error.status);
773da6c28aaSamw 			}
774dc20a302Sas200622 
775eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			node = op->fqi.fq_fnode;
7762c2961f8Sjose borrego 			smb_node_wrlock(node);
777da6c28aaSamw 		}
778da6c28aaSamw 
779eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		created = B_TRUE;
780da6c28aaSamw 		op->action_taken = SMB_OACT_CREATED;
781c8ec8eeaSjose borrego 	}
782c8ec8eeaSjose borrego 
7832c1b14e5Sjose borrego 	if (max_requested) {
7842c1b14e5Sjose borrego 		smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
7852c1b14e5Sjose borrego 		op->desired_access |= max_allowed;
7862c1b14e5Sjose borrego 	}
7872c1b14e5Sjose borrego 
788037cac00Sjoyce mcintosh 	status = NT_STATUS_SUCCESS;
7892c1b14e5Sjose borrego 
790c8ec8eeaSjose borrego 	of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK,
791c8ec8eeaSjose borrego 	    uniq_fid, &err);
792da6c28aaSamw 	if (of == NULL) {
793dc20a302Sas200622 		smbsr_error(sr, err.status, err.errcls, err.errcode);
794037cac00Sjoyce mcintosh 		status = err.status;
795da6c28aaSamw 	}
796da6c28aaSamw 
797037cac00Sjoyce mcintosh 	if (status == NT_STATUS_SUCCESS) {
7988b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (!smb_tree_is_connected(sr->tid_tree)) {
799037cac00Sjoyce mcintosh 			smbsr_error(sr, 0, ERRSRV, ERRinvnid);
800037cac00Sjoyce mcintosh 			status = NT_STATUS_UNSUCCESSFUL;
801037cac00Sjoyce mcintosh 		}
802037cac00Sjoyce mcintosh 	}
803037cac00Sjoyce mcintosh 
804037cac00Sjoyce mcintosh 	/*
805037cac00Sjoyce mcintosh 	 * This MUST be done after ofile creation, so that explicitly
806037cac00Sjoyce mcintosh 	 * set timestamps can be remembered on the ofile.
807037cac00Sjoyce mcintosh 	 */
808037cac00Sjoyce mcintosh 	if (status == NT_STATUS_SUCCESS) {
809037cac00Sjoyce mcintosh 		if ((rc = smb_set_open_timestamps(sr, of, created)) != 0) {
810037cac00Sjoyce mcintosh 			smbsr_errno(sr, rc);
811037cac00Sjoyce mcintosh 			status = sr->smb_error.status;
812037cac00Sjoyce mcintosh 		}
813037cac00Sjoyce mcintosh 	}
814037cac00Sjoyce mcintosh 
815037cac00Sjoyce mcintosh 	if (status == NT_STATUS_SUCCESS) {
816037cac00Sjoyce mcintosh 		if (smb_node_getattr(sr, node,  &op->fqi.fq_fattr) != 0) {
817037cac00Sjoyce mcintosh 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
818037cac00Sjoyce mcintosh 			    ERRDOS, ERROR_INTERNAL_ERROR);
819037cac00Sjoyce mcintosh 			status = NT_STATUS_INTERNAL_ERROR;
820037cac00Sjoyce mcintosh 		}
821037cac00Sjoyce mcintosh 	}
822037cac00Sjoyce mcintosh 
823037cac00Sjoyce mcintosh 	/*
824037cac00Sjoyce mcintosh 	 * smb_fsop_unshrlock is a no-op if node is a directory
825037cac00Sjoyce mcintosh 	 * smb_fsop_unshrlock is done in smb_ofile_close
826037cac00Sjoyce mcintosh 	 */
827037cac00Sjoyce mcintosh 	if (status != NT_STATUS_SUCCESS) {
828037cac00Sjoyce mcintosh 		if (of == NULL) {
829037cac00Sjoyce mcintosh 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
830037cac00Sjoyce mcintosh 		} else {
8318b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_ofile_close(of, 0);
8328b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_ofile_release(of);
833037cac00Sjoyce mcintosh 		}
8348b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (created)
8358b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_delete_new_object(sr);
8368b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_unlock(node);
8378b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(node);
8388b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (created)
8398b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_unlock(dnode);
8408b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(dnode);
841037cac00Sjoyce mcintosh 		return (status);
8428b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
8438b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
8448c10a865Sas200622 	/*
8458c10a865Sas200622 	 * Propagate the write-through mode from the open params
8468c10a865Sas200622 	 * to the node: see the notes in the function header.
8478c10a865Sas200622 	 */
8488c10a865Sas200622 	if (sr->sr_cfg->skc_sync_enable ||
8498c10a865Sas200622 	    (op->create_options & FILE_WRITE_THROUGH))
8508c10a865Sas200622 		node->flags |= NODE_FLAGS_WRITE_THROUGH;
8518c10a865Sas200622 
852037cac00Sjoyce mcintosh 	/*
853037cac00Sjoyce mcintosh 	 * Set up the fileid and dosattr in open_param for response
854037cac00Sjoyce mcintosh 	 */
855eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	op->fileid = op->fqi.fq_fattr.sa_vattr.va_nodeid;
856037cac00Sjoyce mcintosh 	op->dattr = op->fqi.fq_fattr.sa_dosattr;
8578c10a865Sas200622 
858da6c28aaSamw 	/*
859da6c28aaSamw 	 * Set up the file type in open_param for the response
860da6c28aaSamw 	 */
861da6c28aaSamw 	op->ftype = SMB_FTYPE_DISK;
862da6c28aaSamw 	sr->smb_fid = of->f_fid;
863da6c28aaSamw 	sr->fid_ofile = of;
864da6c28aaSamw 
8652c2961f8Sjose borrego 	smb_node_unlock(node);
866dc20a302Sas200622 	if (created)
8672c2961f8Sjose borrego 		smb_node_unlock(dnode);
8682c2961f8Sjose borrego 
869*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	if (smb_node_is_file(node)) {
8702c2961f8Sjose borrego 		smb_oplock_acquire(node, of, op);
871eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->dsize = op->fqi.fq_fattr.sa_vattr.va_size;
872*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	} else {
873*9fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		/* directory or symlink */
8742c2961f8Sjose borrego 		op->op_oplock_level = SMB_OPLOCK_NONE;
8752c2961f8Sjose borrego 		op->dsize = 0;
8762c2961f8Sjose borrego 	}
877dc20a302Sas200622 
8788b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_release(node);
879da6c28aaSamw 	smb_node_release(dnode);
880da6c28aaSamw 
881da6c28aaSamw 	return (NT_STATUS_SUCCESS);
882da6c28aaSamw }
883da6c28aaSamw 
884da6c28aaSamw /*
885037cac00Sjoyce mcintosh  * smb_set_open_timestamps
886037cac00Sjoyce mcintosh  *
887037cac00Sjoyce mcintosh  * Last write time:
888037cac00Sjoyce mcintosh  * - If the last_write time specified in the open params is not 0 or -1,
889037cac00Sjoyce mcintosh  *   use it as file's mtime. This will be considered an explicitly set
890037cac00Sjoyce mcintosh  *   timestamps, not reset by subsequent writes.
891037cac00Sjoyce mcintosh  *
892037cac00Sjoyce mcintosh  * Opening existing file (not directory):
893037cac00Sjoyce mcintosh  * - If opening an existing file for overwrite set initial ATIME, MTIME
894037cac00Sjoyce mcintosh  *   & CTIME to now. (This is achieved by setting them as pending then forcing
895037cac00Sjoyce mcintosh  *   an smb_node_setattr() to apply pending times.)
896037cac00Sjoyce mcintosh  *
897037cac00Sjoyce mcintosh  * - Note  If opening an existing file NOT for overwrite, windows would
898037cac00Sjoyce mcintosh  *   set the atime on file close, however setting the atime would cause
899037cac00Sjoyce mcintosh  *   the ARCHIVE attribute to be set, which does not occur on windows,
900037cac00Sjoyce mcintosh  *   so we do not do the atime update.
901037cac00Sjoyce mcintosh  *
902037cac00Sjoyce mcintosh  * Returns: errno
903037cac00Sjoyce mcintosh  */
904037cac00Sjoyce mcintosh static int
905037cac00Sjoyce mcintosh smb_set_open_timestamps(smb_request_t *sr, smb_ofile_t *of, boolean_t created)
906037cac00Sjoyce mcintosh {
907037cac00Sjoyce mcintosh 	int		rc = 0;
908037cac00Sjoyce mcintosh 	open_param_t	*op = &sr->arg.open;
909037cac00Sjoyce mcintosh 	smb_node_t	*node = of->f_node;
910037cac00Sjoyce mcintosh 	boolean_t	existing_file, set_times;
911037cac00Sjoyce mcintosh 	smb_attr_t	attr;
912037cac00Sjoyce mcintosh 
913037cac00Sjoyce mcintosh 	bzero(&attr, sizeof (smb_attr_t));
914037cac00Sjoyce mcintosh 	set_times = B_FALSE;
915037cac00Sjoyce mcintosh 
916037cac00Sjoyce mcintosh 	if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
917037cac00Sjoyce mcintosh 		attr.sa_mask = SMB_AT_MTIME;
918037cac00Sjoyce mcintosh 		attr.sa_vattr.va_mtime = op->mtime;
919037cac00Sjoyce mcintosh 		set_times = B_TRUE;
920037cac00Sjoyce mcintosh 	}
921037cac00Sjoyce mcintosh 
922037cac00Sjoyce mcintosh 	existing_file = !(created || smb_node_is_dir(node));
923037cac00Sjoyce mcintosh 	if (existing_file) {
924037cac00Sjoyce mcintosh 		switch (op->create_disposition) {
925037cac00Sjoyce mcintosh 		case FILE_SUPERSEDE:
926037cac00Sjoyce mcintosh 		case FILE_OVERWRITE_IF:
927037cac00Sjoyce mcintosh 		case FILE_OVERWRITE:
928037cac00Sjoyce mcintosh 			smb_ofile_set_write_time_pending(of);
929037cac00Sjoyce mcintosh 			set_times = B_TRUE;
930037cac00Sjoyce mcintosh 			break;
931037cac00Sjoyce mcintosh 		default:
932037cac00Sjoyce mcintosh 			break;
933037cac00Sjoyce mcintosh 		}
934037cac00Sjoyce mcintosh 	}
935037cac00Sjoyce mcintosh 
936037cac00Sjoyce mcintosh 	if (set_times)
937037cac00Sjoyce mcintosh 		rc = smb_node_setattr(sr, node, sr->user_cr, of, &attr);
938037cac00Sjoyce mcintosh 
939037cac00Sjoyce mcintosh 	return (rc);
940037cac00Sjoyce mcintosh }
941037cac00Sjoyce mcintosh 
942037cac00Sjoyce mcintosh /*
9438b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * This function is used to delete a newly created object (file or
9448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * directory) if an error occurs after creation of the object.
945da6c28aaSamw  */
9468b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static void
9478b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_delete_new_object(smb_request_t *sr)
948da6c28aaSamw {
9498b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	open_param_t	*op = &sr->arg.open;
9508b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_fqi_t	*fqi = &(op->fqi);
9518b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	uint32_t	flags = 0;
9528b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
9538b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
9548b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		flags |= SMB_IGNORE_CASE;
9558b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (SMB_TREE_SUPPORTS_CATIA(sr))
9568b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		flags |= SMB_CATIA;
9578b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
9588b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (op->create_options & FILE_DIRECTORY_FILE)
959eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
960eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    fqi->fq_last_comp, flags);
9618b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	else
962eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode,
963eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    fqi->fq_last_comp, flags);
964eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States }
965