xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_open.c (revision bbf6f00c25b6a2bed23c35eac6d62998ecdb338c)
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 /*
227f667e74Sjose borrego  * Copyright 2009 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 
31*bbf6f00cSJordan Brown #include <sys/types.h>
32*bbf6f00cSJordan Brown #include <sys/cmn_err.h>
33da6c28aaSamw #include <sys/fcntl.h>
34dc20a302Sas #include <sys/nbmlock.h>
35*bbf6f00cSJordan Brown #include <smbsrv/string.h>
36*bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
37*bbf6f00cSJordan Brown #include <smbsrv/smb_fsops.h>
38*bbf6f00cSJordan Brown #include <smbsrv/smbinfo.h>
39da6c28aaSamw 
40faa1795aSjb volatile uint32_t smb_fids = 0;
417b59d02dSjb 
427b59d02dSjb static uint32_t smb_open_subr(smb_request_t *);
43faa1795aSjb 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 
47eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States static char *smb_pathname_strdup(smb_request_t *, const char *);
48*bbf6f00cSJordan Brown static char *smb_pathname_strcat(smb_request_t *, char *, const char *);
49eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
50da6c28aaSamw /*
51da6c28aaSamw  * smb_access_generic_to_file
52da6c28aaSamw  *
53da6c28aaSamw  * Search MSDN for IoCreateFile to see following mapping.
54da6c28aaSamw  *
55da6c28aaSamw  * GENERIC_READ		STANDARD_RIGHTS_READ, FILE_READ_DATA,
56da6c28aaSamw  *			FILE_READ_ATTRIBUTES and FILE_READ_EA
57da6c28aaSamw  *
58da6c28aaSamw  * GENERIC_WRITE	STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
59da6c28aaSamw  *               FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
60da6c28aaSamw  *
61da6c28aaSamw  * GENERIC_EXECUTE	STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
62da6c28aaSamw  */
63da6c28aaSamw uint32_t
64da6c28aaSamw smb_access_generic_to_file(uint32_t desired_access)
65da6c28aaSamw {
66da6c28aaSamw 	uint32_t access = 0;
67da6c28aaSamw 
68da6c28aaSamw 	if (desired_access & GENERIC_ALL)
69da6c28aaSamw 		return (FILE_ALL_ACCESS & ~SYNCHRONIZE);
70da6c28aaSamw 
71da6c28aaSamw 	if (desired_access & GENERIC_EXECUTE) {
72da6c28aaSamw 		desired_access &= ~GENERIC_EXECUTE;
73da6c28aaSamw 		access |= (STANDARD_RIGHTS_EXECUTE |
74da6c28aaSamw 		    SYNCHRONIZE | FILE_EXECUTE);
75da6c28aaSamw 	}
76da6c28aaSamw 
77da6c28aaSamw 	if (desired_access & GENERIC_WRITE) {
78da6c28aaSamw 		desired_access &= ~GENERIC_WRITE;
79da6c28aaSamw 		access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE);
80da6c28aaSamw 	}
81da6c28aaSamw 
82da6c28aaSamw 	if (desired_access & GENERIC_READ) {
83da6c28aaSamw 		desired_access &= ~GENERIC_READ;
84da6c28aaSamw 		access |= FILE_GENERIC_READ;
85da6c28aaSamw 	}
86da6c28aaSamw 
87da6c28aaSamw 	return (access | desired_access);
88da6c28aaSamw }
89da6c28aaSamw 
90da6c28aaSamw /*
91da6c28aaSamw  * smb_omode_to_amask
92da6c28aaSamw  *
93da6c28aaSamw  * This function converts open modes used by Open and Open AndX
94da6c28aaSamw  * commands to desired access bits used by NT Create AndX command.
95da6c28aaSamw  */
96da6c28aaSamw uint32_t
97da6c28aaSamw smb_omode_to_amask(uint32_t desired_access)
98da6c28aaSamw {
99da6c28aaSamw 	switch (desired_access & SMB_DA_ACCESS_MASK) {
100da6c28aaSamw 	case SMB_DA_ACCESS_READ:
101da6c28aaSamw 		return (FILE_GENERIC_READ);
102da6c28aaSamw 
103da6c28aaSamw 	case SMB_DA_ACCESS_WRITE:
104da6c28aaSamw 		return (FILE_GENERIC_WRITE);
105da6c28aaSamw 
106da6c28aaSamw 	case SMB_DA_ACCESS_READ_WRITE:
107da6c28aaSamw 		return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
108da6c28aaSamw 
109da6c28aaSamw 	case SMB_DA_ACCESS_EXECUTE:
110da6c28aaSamw 		return (FILE_GENERIC_EXECUTE);
111da6c28aaSamw 
1122c2961f8Sjose borrego 	default:
1132c2961f8Sjose borrego 		return (FILE_GENERIC_ALL);
1142c2961f8Sjose borrego 	}
115da6c28aaSamw }
116da6c28aaSamw 
117da6c28aaSamw /*
118da6c28aaSamw  * smb_denymode_to_sharemode
119da6c28aaSamw  *
120da6c28aaSamw  * This function converts deny modes used by Open and Open AndX
121da6c28aaSamw  * commands to share access bits used by NT Create AndX command.
122da6c28aaSamw  */
123da6c28aaSamw uint32_t
124da6c28aaSamw smb_denymode_to_sharemode(uint32_t desired_access, char *fname)
125da6c28aaSamw {
126da6c28aaSamw 	switch (desired_access & SMB_DA_SHARE_MASK) {
127da6c28aaSamw 	case SMB_DA_SHARE_COMPATIBILITY:
128da6c28aaSamw 		if (smb_is_executable(fname))
129da6c28aaSamw 			return (FILE_SHARE_READ | FILE_SHARE_WRITE);
130c8ec8eeaSjose borrego 
131c8ec8eeaSjose borrego 		return (FILE_SHARE_ALL);
132da6c28aaSamw 
133da6c28aaSamw 	case SMB_DA_SHARE_EXCLUSIVE:
134da6c28aaSamw 		return (FILE_SHARE_NONE);
135da6c28aaSamw 
136da6c28aaSamw 	case SMB_DA_SHARE_DENY_WRITE:
137da6c28aaSamw 		return (FILE_SHARE_READ);
138da6c28aaSamw 
139da6c28aaSamw 	case SMB_DA_SHARE_DENY_READ:
140da6c28aaSamw 		return (FILE_SHARE_WRITE);
141da6c28aaSamw 
142da6c28aaSamw 	case SMB_DA_SHARE_DENY_NONE:
1432c2961f8Sjose borrego 	default:
144da6c28aaSamw 		return (FILE_SHARE_READ | FILE_SHARE_WRITE);
145da6c28aaSamw 	}
146da6c28aaSamw }
147da6c28aaSamw 
148da6c28aaSamw /*
149da6c28aaSamw  * smb_ofun_to_crdisposition
150da6c28aaSamw  *
151da6c28aaSamw  * This function converts open function values used by Open and Open AndX
152da6c28aaSamw  * commands to create disposition values used by NT Create AndX command.
153da6c28aaSamw  */
154da6c28aaSamw uint32_t
155da6c28aaSamw smb_ofun_to_crdisposition(uint16_t  ofun)
156da6c28aaSamw {
157da6c28aaSamw 	static int ofun_cr_map[3][2] =
158da6c28aaSamw 	{
159da6c28aaSamw 		{ -1,			FILE_CREATE },
160da6c28aaSamw 		{ FILE_OPEN,		FILE_OPEN_IF },
161da6c28aaSamw 		{ FILE_OVERWRITE,	FILE_OVERWRITE_IF }
162da6c28aaSamw 	};
163da6c28aaSamw 
164da6c28aaSamw 	int row = ofun & SMB_OFUN_OPEN_MASK;
165da6c28aaSamw 	int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4;
166da6c28aaSamw 
167da6c28aaSamw 	if (row == 3)
1682c2961f8Sjose borrego 		return (FILE_MAXIMUM_DISPOSITION + 1);
169da6c28aaSamw 
170da6c28aaSamw 	return (ofun_cr_map[row][col]);
171da6c28aaSamw }
172da6c28aaSamw 
1737b59d02dSjb /*
1747b59d02dSjb  * Retry opens to avoid spurious sharing violations, due to timing
1757b59d02dSjb  * issues between closes and opens.  The client that already has the
1767b59d02dSjb  * file open may be in the process of closing it.
1777b59d02dSjb  */
1787b59d02dSjb uint32_t
1797b59d02dSjb smb_common_open(smb_request_t *sr)
1807b59d02dSjb {
181*bbf6f00cSJordan Brown 	open_param_t	*parg;
182*bbf6f00cSJordan Brown 	uint32_t	status = NT_STATUS_SUCCESS;
183*bbf6f00cSJordan Brown 	int		count;
184*bbf6f00cSJordan Brown 
185*bbf6f00cSJordan Brown 	parg = kmem_alloc(sizeof (*parg), KM_SLEEP);
186*bbf6f00cSJordan Brown 	bcopy(&sr->arg.open, parg, sizeof (*parg));
1877b59d02dSjb 
1887b59d02dSjb 	for (count = 0; count <= 4; count++) {
189*bbf6f00cSJordan Brown 		if (count != 0)
1907b59d02dSjb 			delay(MSEC_TO_TICK(400));
1917b59d02dSjb 
192faa1795aSjb 		status = smb_open_subr(sr);
193faa1795aSjb 		if (status != NT_STATUS_SHARING_VIOLATION)
1947b59d02dSjb 			break;
195*bbf6f00cSJordan Brown 
196*bbf6f00cSJordan Brown 		bcopy(parg, &sr->arg.open, sizeof (*parg));
1977b59d02dSjb 	}
1987b59d02dSjb 
199faa1795aSjb 	if (status == NT_STATUS_SHARING_VIOLATION) {
2007b59d02dSjb 		smbsr_error(sr, NT_STATUS_SHARING_VIOLATION,
2017b59d02dSjb 		    ERRDOS, ERROR_SHARING_VIOLATION);
2027b59d02dSjb 	}
2037b59d02dSjb 
2042c2961f8Sjose borrego 	if (status == NT_STATUS_NO_SUCH_FILE) {
2052c2961f8Sjose borrego 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
2062c2961f8Sjose borrego 		    ERRDOS, ERROR_FILE_NOT_FOUND);
2072c2961f8Sjose borrego 	}
2082c2961f8Sjose borrego 
209*bbf6f00cSJordan Brown 	kmem_free(parg, sizeof (*parg));
210*bbf6f00cSJordan Brown 
2117b59d02dSjb 	return (status);
2127b59d02dSjb }
2137b59d02dSjb 
214da6c28aaSamw /*
215da6c28aaSamw  * smb_open_subr
216da6c28aaSamw  *
217da6c28aaSamw  * Notes on write-through behaviour. It looks like pre-LM0.12 versions
218da6c28aaSamw  * of the protocol specify the write-through mode when a file is opened,
219da6c28aaSamw  * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
220da6c28aaSamw  * SmbWriteAndUnlock) don't need to contain a write-through flag.
221da6c28aaSamw  *
222da6c28aaSamw  * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
223da6c28aaSamw  * don't indicate which write-through mode to use. Instead the write
224da6c28aaSamw  * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
225da6c28aaSamw  * basis.
226da6c28aaSamw  *
227da6c28aaSamw  * We don't care which open call was used to get us here, we just need
228da6c28aaSamw  * to ensure that the write-through mode flag is copied from the open
229da6c28aaSamw  * parameters to the node. We test the omode write-through flag in all
230da6c28aaSamw  * write functions.
231da6c28aaSamw  *
232da6c28aaSamw  * This function will return NT status codes but it also raises errors,
233da6c28aaSamw  * in which case it won't return to the caller. Be careful how you
234da6c28aaSamw  * handle things in here.
2358c10a865Sas  *
2368c10a865Sas  * The following rules apply when processing a file open request:
2378c10a865Sas  *
2388c10a865Sas  * - Oplocks must be broken prior to share checking to prevent open
2398c10a865Sas  * starvation due to batch oplocks.  Checking share reservations first
2408c10a865Sas  * could potentially result in unnecessary open failures due to
2418c10a865Sas  * open/close batching on the client.
2428c10a865Sas  *
2438c10a865Sas  * - Share checks must take place prior to access checks for correct
2448c10a865Sas  * Windows semantics and to prevent unnecessary NFS delegation recalls.
2458c10a865Sas  *
2468c10a865Sas  * - Oplocks must be acquired after open to ensure the correct
2478c10a865Sas  * synchronization with NFS delegation and FEM installation.
248c8ec8eeaSjose borrego  *
249c8ec8eeaSjose borrego  *
250c8ec8eeaSjose borrego  * DOS readonly bit rules
251c8ec8eeaSjose borrego  *
252c8ec8eeaSjose borrego  * 1. The creator of a readonly file can write to/modify the size of the file
253c8ec8eeaSjose borrego  * using the original create fid, even though the file will appear as readonly
254c8ec8eeaSjose borrego  * to all other fids and via a CIFS getattr call.
255037cac00Sjoyce mcintosh  * The readonly bit therefore cannot be set in the filesystem until the file
256037cac00Sjoyce mcintosh  * is closed (smb_ofile_close). It is accounted for via ofile and node flags.
257c8ec8eeaSjose borrego  *
258c8ec8eeaSjose borrego  * 2. A setinfo operation (using either an open fid or a path) to set/unset
259c8ec8eeaSjose borrego  * readonly will be successful regardless of whether a creator of a readonly
260c8ec8eeaSjose borrego  * file has an open fid (and has the special privilege mentioned in #1,
261c8ec8eeaSjose borrego  * above).  I.e., the creator of a readonly fid holding that fid will no longer
262c8ec8eeaSjose borrego  * have a special privilege.
263c8ec8eeaSjose borrego  *
264c8ec8eeaSjose borrego  * 3. The DOS readonly bit affects only data and some metadata.
265c8ec8eeaSjose borrego  * The following metadata can be changed regardless of the readonly bit:
266c8ec8eeaSjose borrego  * 	- security descriptors
267c8ec8eeaSjose borrego  *	- DOS attributes
268c8ec8eeaSjose borrego  *	- timestamps
269c8ec8eeaSjose borrego  *
270c8ec8eeaSjose borrego  * In the current implementation, the file size cannot be changed (except for
271c8ec8eeaSjose borrego  * the exceptions in #1 and #2, above).
2722c1b14e5Sjose borrego  *
2732c1b14e5Sjose borrego  *
2742c1b14e5Sjose borrego  * DOS attribute rules
2752c1b14e5Sjose borrego  *
2762c1b14e5Sjose borrego  * These rules are specific to creating / opening files and directories.
2772c1b14e5Sjose borrego  * How the attribute value (specifically ZERO or FILE_ATTRIBUTE_NORMAL)
2782c1b14e5Sjose borrego  * should be interpreted may differ in other requests.
2792c1b14e5Sjose borrego  *
2802c1b14e5Sjose borrego  * - An attribute value equal to ZERO or FILE_ATTRIBUTE_NORMAL means that the
2812c1b14e5Sjose borrego  *   file's attributes should be cleared.
2822c1b14e5Sjose borrego  * - If FILE_ATTRIBUTE_NORMAL is specified with any other attributes,
2832c1b14e5Sjose borrego  *   FILE_ATTRIBUTE_NORMAL is ignored.
2842c1b14e5Sjose borrego  *
2852c1b14e5Sjose borrego  * 1. Creating a new file
2862c1b14e5Sjose borrego  * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file.
2872c1b14e5Sjose borrego  *
2882c1b14e5Sjose borrego  * 2. Creating a new directory
2892c1b14e5Sjose borrego  * - The request attributes + FILE_ATTRIBUTE_DIRECTORY are applied to the file.
2902c1b14e5Sjose borrego  * - FILE_ATTRIBUTE_ARCHIVE does not get set.
2912c1b14e5Sjose borrego  *
2922c1b14e5Sjose borrego  * 3. Overwriting an existing file
2932c1b14e5Sjose borrego  * - the request attributes are used as search attributes. If the existing
2942c1b14e5Sjose borrego  *   file does not meet the search criteria access is denied.
2952c1b14e5Sjose borrego  * - otherwise, applies attributes + FILE_ATTRIBUTE_ARCHIVE.
2962c1b14e5Sjose borrego  *
2972c1b14e5Sjose borrego  * 4. Opening an existing file or directory
2982c1b14e5Sjose borrego  *    The request attributes are ignored.
299da6c28aaSamw  */
3007b59d02dSjb static uint32_t
3017b59d02dSjb smb_open_subr(smb_request_t *sr)
302da6c28aaSamw {
303eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	created = B_FALSE;
304eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	boolean_t	last_comp_found = B_FALSE;
3052c2961f8Sjose borrego 	smb_node_t	*node = NULL;
3062c2961f8Sjose borrego 	smb_node_t	*dnode = NULL;
307eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_t	*cur_node = NULL;
3082c2961f8Sjose borrego 	open_param_t	*op = &sr->arg.open;
3092c2961f8Sjose borrego 	int		rc;
3102c2961f8Sjose borrego 	smb_ofile_t	*of;
3112c2961f8Sjose borrego 	smb_attr_t	new_attr;
3122c2961f8Sjose borrego 	int		pathlen;
3132c2961f8Sjose borrego 	int		max_requested = 0;
3142c2961f8Sjose borrego 	uint32_t	max_allowed;
3152c2961f8Sjose borrego 	uint32_t	status = NT_STATUS_SUCCESS;
3162c2961f8Sjose borrego 	int		is_dir;
3172c2961f8Sjose borrego 	smb_error_t	err;
3182c2961f8Sjose borrego 	boolean_t	is_stream = B_FALSE;
3192c2961f8Sjose borrego 	int		lookup_flags = SMB_FOLLOW_LINKS;
3202c2961f8Sjose borrego 	uint32_t	uniq_fid;
321eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_pathname_t	*pn = &op->fqi.fq_path;
322da6c28aaSamw 
323da6c28aaSamw 	is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
324da6c28aaSamw 
325037cac00Sjoyce mcintosh 	/*
326037cac00Sjoyce mcintosh 	 * If the object being created or opened is a directory
327037cac00Sjoyce mcintosh 	 * the Disposition parameter must be one of FILE_CREATE,
328037cac00Sjoyce mcintosh 	 * FILE_OPEN, or FILE_OPEN_IF
329037cac00Sjoyce mcintosh 	 */
330da6c28aaSamw 	if (is_dir) {
331da6c28aaSamw 		if ((op->create_disposition != FILE_CREATE) &&
332da6c28aaSamw 		    (op->create_disposition != FILE_OPEN_IF) &&
333da6c28aaSamw 		    (op->create_disposition != FILE_OPEN)) {
334dc20a302Sas 			smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
335da6c28aaSamw 			    ERRDOS, ERROR_INVALID_ACCESS);
3367b59d02dSjb 			return (NT_STATUS_INVALID_PARAMETER);
337da6c28aaSamw 		}
338da6c28aaSamw 	}
339da6c28aaSamw 
340da6c28aaSamw 	if (op->desired_access & MAXIMUM_ALLOWED) {
341da6c28aaSamw 		max_requested = 1;
342da6c28aaSamw 		op->desired_access &= ~MAXIMUM_ALLOWED;
343da6c28aaSamw 	}
344da6c28aaSamw 	op->desired_access = smb_access_generic_to_file(op->desired_access);
345da6c28aaSamw 
346da6c28aaSamw 	if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) {
347da6c28aaSamw 		ASSERT(sr->uid_user);
348da6c28aaSamw 		cmn_err(CE_NOTE, "smbd[%s\\%s]: %s", sr->uid_user->u_domain,
349da6c28aaSamw 		    sr->uid_user->u_name,
350da6c28aaSamw 		    xlate_nt_status(NT_STATUS_TOO_MANY_OPENED_FILES));
351da6c28aaSamw 
352dc20a302Sas 		smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
353da6c28aaSamw 		    ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
3547b59d02dSjb 		return (NT_STATUS_TOO_MANY_OPENED_FILES);
355da6c28aaSamw 	}
356da6c28aaSamw 
357da6c28aaSamw 	/* This must be NULL at this point */
358da6c28aaSamw 	sr->fid_ofile = NULL;
359da6c28aaSamw 
360da6c28aaSamw 	op->devstate = 0;
361da6c28aaSamw 
362da6c28aaSamw 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
363da6c28aaSamw 	case STYPE_DISKTREE:
364da6c28aaSamw 		break;
365da6c28aaSamw 
366da6c28aaSamw 	case STYPE_IPC:
367da6c28aaSamw 		/*
368da6c28aaSamw 		 * No further processing for IPC, we need to either
369da6c28aaSamw 		 * raise an exception or return success here.
370da6c28aaSamw 		 */
3713db3f65cSamw 		if ((status = smb_opipe_open(sr)) != NT_STATUS_SUCCESS)
3727b59d02dSjb 			smbsr_error(sr, status, 0, 0);
3737b59d02dSjb 		return (status);
374da6c28aaSamw 
375da6c28aaSamw 	default:
3767b59d02dSjb 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
3777b59d02dSjb 		    ERRDOS, ERROR_BAD_DEV_TYPE);
3787b59d02dSjb 		return (NT_STATUS_BAD_DEVICE_TYPE);
379da6c28aaSamw 	}
380da6c28aaSamw 
381eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if ((pathlen = strlen(pn->pn_path)) >= MAXPATHLEN) {
382dc20a302Sas 		smbsr_error(sr, 0, ERRSRV, ERRfilespecs);
3837b59d02dSjb 		return (NT_STATUS_NAME_TOO_LONG);
384da6c28aaSamw 	}
385da6c28aaSamw 
386da6c28aaSamw 	/*
387da6c28aaSamw 	 * Some clients pass null file names; NT interprets this as "\".
388da6c28aaSamw 	 */
389da6c28aaSamw 	if (pathlen == 0) {
390eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		pn->pn_path = "\\";
391da6c28aaSamw 		pathlen = 1;
392da6c28aaSamw 	}
393da6c28aaSamw 
394eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_pathname_setup(sr, pn);
395eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
396eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (is_dir)
397eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		status = smb_validate_dirname(pn->pn_path);
398eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	else
399eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		status = smb_validate_object_name(pn);
400da6c28aaSamw 
401eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (status != NT_STATUS_SUCCESS) {
402dc20a302Sas 		smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME);
4037b59d02dSjb 		return (status);
404da6c28aaSamw 	}
405da6c28aaSamw 
406eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	cur_node = op->fqi.fq_dnode ?
407eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	    op->fqi.fq_dnode : sr->tid_tree->t_snode;
408da6c28aaSamw 
409eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	/*
410eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	 * if no path or filename are specified the stream should be
411eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	 * created on cur_node
412eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	 */
413eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (!is_dir && !pn->pn_pname && !pn->pn_fname && pn->pn_sname) {
414eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
415eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		/* can't currently create a stream on the tree root */
416eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (cur_node == sr->tid_tree->t_snode) {
417eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
418eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			    ERROR_ACCESS_DENIED);
419eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			return (NT_STATUS_ACCESS_DENIED);
420eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		}
421eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
422eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		(void) snprintf(op->fqi.fq_last_comp,
423eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    sizeof (op->fqi.fq_last_comp),
424eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    "%s%s", cur_node->od_name, pn->pn_sname);
425eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
4261fcced4cSJordan Brown 		op->fqi.fq_dnode = cur_node->n_dnode;
427eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_ref(op->fqi.fq_dnode);
428eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	} else {
429eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
430eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode,
431eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    op->fqi.fq_last_comp)) {
432eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			smbsr_errno(sr, rc);
433eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			return (sr->smb_error.status);
434eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		}
435da6c28aaSamw 	}
436da6c28aaSamw 
437da6c28aaSamw 	/*
438da6c28aaSamw 	 * If the access mask has only DELETE set (ignore
439da6c28aaSamw 	 * FILE_READ_ATTRIBUTES), then assume that this
440da6c28aaSamw 	 * is a request to delete the link (if a link)
441da6c28aaSamw 	 * and do not follow links.  Otherwise, follow
442da6c28aaSamw 	 * the link to the target.
443da6c28aaSamw 	 */
444037cac00Sjoyce mcintosh 	if ((op->desired_access & ~FILE_READ_ATTRIBUTES) == DELETE)
445da6c28aaSamw 		lookup_flags &= ~SMB_FOLLOW_LINKS;
446da6c28aaSamw 
447da6c28aaSamw 	rc = smb_fsop_lookup_name(sr, kcred, lookup_flags,
448eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	    sr->tid_tree->t_snode, op->fqi.fq_dnode, op->fqi.fq_last_comp,
449037cac00Sjoyce mcintosh 	    &op->fqi.fq_fnode);
450da6c28aaSamw 
451da6c28aaSamw 	if (rc == 0) {
452eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		last_comp_found = B_TRUE;
453037cac00Sjoyce mcintosh 		rc = smb_node_getattr(sr, op->fqi.fq_fnode,
454037cac00Sjoyce mcintosh 		    &op->fqi.fq_fattr);
455037cac00Sjoyce mcintosh 		if (rc != 0) {
456037cac00Sjoyce mcintosh 			smb_node_release(op->fqi.fq_fnode);
457037cac00Sjoyce mcintosh 			smb_node_release(op->fqi.fq_dnode);
458037cac00Sjoyce mcintosh 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
459037cac00Sjoyce mcintosh 			    ERRDOS, ERROR_INTERNAL_ERROR);
460037cac00Sjoyce mcintosh 			return (sr->smb_error.status);
461037cac00Sjoyce mcintosh 		}
462da6c28aaSamw 	} else if (rc == ENOENT) {
463eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		last_comp_found = B_FALSE;
464eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->fqi.fq_fnode = NULL;
465da6c28aaSamw 		rc = 0;
466da6c28aaSamw 	} else {
467eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(op->fqi.fq_dnode);
468dc20a302Sas 		smbsr_errno(sr, rc);
4697b59d02dSjb 		return (sr->smb_error.status);
470da6c28aaSamw 	}
471da6c28aaSamw 
472037cac00Sjoyce mcintosh 
473dc20a302Sas 	/*
474dc20a302Sas 	 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
475dc20a302Sas 	 * which is used to uniquely identify open instances for the
476c8ec8eeaSjose borrego 	 * VFS share reservation and POSIX locks.
477dc20a302Sas 	 */
478dc20a302Sas 
479dc20a302Sas 	uniq_fid = SMB_UNIQ_FID();
480dc20a302Sas 
481eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (last_comp_found) {
4826537f381Sas 
483eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		if ((op->fqi.fq_fattr.sa_vattr.va_type != VREG) &&
484eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    (op->fqi.fq_fattr.sa_vattr.va_type != VDIR) &&
485eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    (op->fqi.fq_fattr.sa_vattr.va_type != VLNK)) {
4866537f381Sas 
487eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_release(op->fqi.fq_fnode);
488eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_release(op->fqi.fq_dnode);
4896537f381Sas 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
4906537f381Sas 			    ERRnoaccess);
4916537f381Sas 			return (NT_STATUS_ACCESS_DENIED);
4926537f381Sas 		}
4936537f381Sas 
494eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		node = op->fqi.fq_fnode;
495eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		dnode = op->fqi.fq_dnode;
496da6c28aaSamw 
497da6c28aaSamw 		/*
4982c1b14e5Sjose borrego 		 * Reject this request if either:
4992c1b14e5Sjose borrego 		 * - the target IS a directory and the client requires that
5002c1b14e5Sjose borrego 		 *   it must NOT be (required by Lotus Notes)
5012c1b14e5Sjose borrego 		 * - the target is NOT a directory and client requires that
5022c1b14e5Sjose borrego 		 *   it MUST be.
503da6c28aaSamw 		 */
504eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (op->fqi.fq_fattr.sa_vattr.va_type == VDIR) {
5052c1b14e5Sjose borrego 			if (op->create_options & FILE_NON_DIRECTORY_FILE) {
506da6c28aaSamw 				smb_node_release(node);
507da6c28aaSamw 				smb_node_release(dnode);
508dc20a302Sas 				smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY,
509da6c28aaSamw 				    ERRDOS, ERROR_ACCESS_DENIED);
5107b59d02dSjb 				return (NT_STATUS_FILE_IS_A_DIRECTORY);
511da6c28aaSamw 			}
5122c1b14e5Sjose borrego 		} else {
5132c1b14e5Sjose borrego 			if ((op->create_options & FILE_DIRECTORY_FILE) ||
5142c2961f8Sjose borrego 			    (op->nt_flags & NT_CREATE_FLAG_OPEN_TARGET_DIR)) {
5152c1b14e5Sjose borrego 				smb_node_release(node);
5162c1b14e5Sjose borrego 				smb_node_release(dnode);
5172c1b14e5Sjose borrego 				smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
5182c1b14e5Sjose borrego 				    ERRDOS, ERROR_DIRECTORY);
5192c1b14e5Sjose borrego 				return (NT_STATUS_NOT_A_DIRECTORY);
5202c1b14e5Sjose borrego 			}
521da6c28aaSamw 		}
522da6c28aaSamw 
523da6c28aaSamw 		/*
524da6c28aaSamw 		 * No more open should be accepted when "Delete on close"
525da6c28aaSamw 		 * flag is set.
526da6c28aaSamw 		 */
527da6c28aaSamw 		if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
528da6c28aaSamw 			smb_node_release(node);
529da6c28aaSamw 			smb_node_release(dnode);
530dc20a302Sas 			smbsr_error(sr, NT_STATUS_DELETE_PENDING,
531da6c28aaSamw 			    ERRDOS, ERROR_ACCESS_DENIED);
5327b59d02dSjb 			return (NT_STATUS_DELETE_PENDING);
533da6c28aaSamw 		}
534da6c28aaSamw 
535da6c28aaSamw 		/*
536da6c28aaSamw 		 * Specified file already exists so the operation should fail.
537da6c28aaSamw 		 */
538da6c28aaSamw 		if (op->create_disposition == FILE_CREATE) {
539da6c28aaSamw 			smb_node_release(node);
540da6c28aaSamw 			smb_node_release(dnode);
541dc20a302Sas 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION,
542b89a8333Snatalie li - Sun Microsystems - Irvine United States 			    ERRDOS, ERROR_FILE_EXISTS);
5437b59d02dSjb 			return (NT_STATUS_OBJECT_NAME_COLLISION);
544da6c28aaSamw 		}
545da6c28aaSamw 
546da6c28aaSamw 		/*
547da6c28aaSamw 		 * Windows seems to check read-only access before file
548da6c28aaSamw 		 * sharing check.
549c8ec8eeaSjose borrego 		 *
550c8ec8eeaSjose borrego 		 * Check to see if the file is currently readonly (irrespective
551c8ec8eeaSjose borrego 		 * of whether this open will make it readonly).
552da6c28aaSamw 		 */
553c8ec8eeaSjose borrego 		if (SMB_PATHFILE_IS_READONLY(sr, node)) {
554da6c28aaSamw 			/* Files data only */
555037cac00Sjoyce mcintosh 			if (!smb_node_is_dir(node)) {
556da6c28aaSamw 				if (op->desired_access & (FILE_WRITE_DATA |
557da6c28aaSamw 				    FILE_APPEND_DATA)) {
558da6c28aaSamw 					smb_node_release(node);
559da6c28aaSamw 					smb_node_release(dnode);
560dc20a302Sas 					smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
561dc20a302Sas 					    ERRDOS, ERRnoaccess);
5627b59d02dSjb 					return (NT_STATUS_ACCESS_DENIED);
563da6c28aaSamw 				}
564da6c28aaSamw 			}
565da6c28aaSamw 		}
566da6c28aaSamw 
5678c10a865Sas 		if (smb_oplock_conflict(node, sr->session, op))
568fc724630SAlan Wright 			(void) smb_oplock_break(node, sr->session, B_FALSE);
5698c10a865Sas 
5702c2961f8Sjose borrego 		smb_node_wrlock(node);
571dc20a302Sas 
572dc20a302Sas 		if ((op->create_disposition == FILE_SUPERSEDE) ||
573dc20a302Sas 		    (op->create_disposition == FILE_OVERWRITE_IF) ||
574dc20a302Sas 		    (op->create_disposition == FILE_OVERWRITE)) {
575dc20a302Sas 
5762c1b14e5Sjose borrego 			if ((!(op->desired_access &
5778c10a865Sas 			    (FILE_WRITE_DATA | FILE_APPEND_DATA |
5782c1b14e5Sjose borrego 			    FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA))) ||
579037cac00Sjoyce mcintosh 			    (!smb_sattr_check(op->fqi.fq_fattr.sa_dosattr,
5802c2961f8Sjose borrego 			    op->dattr))) {
5812c2961f8Sjose borrego 				smb_node_unlock(node);
582dc20a302Sas 				smb_node_release(node);
583dc20a302Sas 				smb_node_release(dnode);
584dc20a302Sas 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
585dc20a302Sas 				    ERRDOS, ERRnoaccess);
5867b59d02dSjb 				return (NT_STATUS_ACCESS_DENIED);
587dc20a302Sas 			}
588dc20a302Sas 		}
589dc20a302Sas 
590dc20a302Sas 		status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
591c8ec8eeaSjose borrego 		    op->desired_access, op->share_access);
592dc20a302Sas 
593da6c28aaSamw 		if (status == NT_STATUS_SHARING_VIOLATION) {
5942c2961f8Sjose borrego 			smb_node_unlock(node);
595da6c28aaSamw 			smb_node_release(node);
596da6c28aaSamw 			smb_node_release(dnode);
597da6c28aaSamw 			return (status);
598da6c28aaSamw 		}
599da6c28aaSamw 
600da6c28aaSamw 		status = smb_fsop_access(sr, sr->user_cr, node,
601da6c28aaSamw 		    op->desired_access);
602da6c28aaSamw 
603da6c28aaSamw 		if (status != NT_STATUS_SUCCESS) {
604dc20a302Sas 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
605dc20a302Sas 
6062c2961f8Sjose borrego 			smb_node_unlock(node);
607da6c28aaSamw 			smb_node_release(node);
608da6c28aaSamw 			smb_node_release(dnode);
609dc20a302Sas 
610da6c28aaSamw 			if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
611dc20a302Sas 				smbsr_error(sr, status,
612dc20a302Sas 				    ERRDOS, ERROR_PRIVILEGE_NOT_HELD);
6137b59d02dSjb 				return (status);
614da6c28aaSamw 			} else {
615dc20a302Sas 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
616dc20a302Sas 				    ERRDOS, ERROR_ACCESS_DENIED);
6177b59d02dSjb 				return (NT_STATUS_ACCESS_DENIED);
618da6c28aaSamw 			}
619da6c28aaSamw 		}
620da6c28aaSamw 
621da6c28aaSamw 		switch (op->create_disposition) {
622da6c28aaSamw 		case FILE_SUPERSEDE:
623da6c28aaSamw 		case FILE_OVERWRITE_IF:
624da6c28aaSamw 		case FILE_OVERWRITE:
625037cac00Sjoyce mcintosh 			if (smb_node_is_dir(node)) {
626dc20a302Sas 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
6272c2961f8Sjose borrego 				smb_node_unlock(node);
628da6c28aaSamw 				smb_node_release(node);
629da6c28aaSamw 				smb_node_release(dnode);
630dc20a302Sas 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
631dc20a302Sas 				    ERRDOS, ERROR_ACCESS_DENIED);
6327b59d02dSjb 				return (NT_STATUS_ACCESS_DENIED);
633da6c28aaSamw 			}
634da6c28aaSamw 
6352c1b14e5Sjose borrego 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
636037cac00Sjoyce mcintosh 			/* Don't apply readonly bit until smb_ofile_close */
6372c1b14e5Sjose borrego 			if (op->dattr & FILE_ATTRIBUTE_READONLY) {
6382c1b14e5Sjose borrego 				op->created_readonly = B_TRUE;
6392c1b14e5Sjose borrego 				op->dattr &= ~FILE_ATTRIBUTE_READONLY;
6402c1b14e5Sjose borrego 			}
6412c1b14e5Sjose borrego 
642037cac00Sjoyce mcintosh 			bzero(&new_attr, sizeof (new_attr));
643037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
644037cac00Sjoyce mcintosh 			new_attr.sa_vattr.va_size = op->dsize;
645037cac00Sjoyce mcintosh 			new_attr.sa_mask = SMB_AT_DOSATTR | SMB_AT_SIZE;
646037cac00Sjoyce mcintosh 			rc = smb_fsop_setattr(sr, sr->user_cr, node, &new_attr);
647037cac00Sjoyce mcintosh 			if (rc != 0) {
648037cac00Sjoyce mcintosh 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
649037cac00Sjoyce mcintosh 				smb_node_unlock(node);
650037cac00Sjoyce mcintosh 				smb_node_release(node);
651037cac00Sjoyce mcintosh 				smb_node_release(dnode);
652037cac00Sjoyce mcintosh 				smbsr_errno(sr, rc);
653037cac00Sjoyce mcintosh 				return (sr->smb_error.status);
654037cac00Sjoyce mcintosh 			}
6552c1b14e5Sjose borrego 
656da6c28aaSamw 			/*
657037cac00Sjoyce mcintosh 			 * If file is being replaced, remove existing streams
658da6c28aaSamw 			 */
659eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			if (SMB_IS_STREAM(node) == 0) {
660037cac00Sjoyce mcintosh 				rc = smb_fsop_remove_streams(sr, sr->user_cr,
661037cac00Sjoyce mcintosh 				    node);
662037cac00Sjoyce mcintosh 				if (rc != 0) {
663eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_fsop_unshrlock(sr->user_cr, node,
664eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					    uniq_fid);
665eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_unlock(node);
666eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_release(node);
667eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					smb_node_release(dnode);
668eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 					return (sr->smb_error.status);
669eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 				}
670eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			}
671da6c28aaSamw 
672da6c28aaSamw 			op->action_taken = SMB_OACT_TRUNCATED;
673da6c28aaSamw 			break;
674da6c28aaSamw 
675da6c28aaSamw 		default:
676da6c28aaSamw 			/*
677da6c28aaSamw 			 * FILE_OPEN or FILE_OPEN_IF.
678da6c28aaSamw 			 */
679da6c28aaSamw 			op->action_taken = SMB_OACT_OPENED;
680da6c28aaSamw 			break;
681da6c28aaSamw 		}
682da6c28aaSamw 	} else {
683da6c28aaSamw 		/* Last component was not found. */
684eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		dnode = op->fqi.fq_dnode;
685da6c28aaSamw 
6867b59d02dSjb 		if (is_dir == 0)
687eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			is_stream = smb_is_stream_name(pn->pn_path);
6887b59d02dSjb 
689da6c28aaSamw 		if ((op->create_disposition == FILE_OPEN) ||
690da6c28aaSamw 		    (op->create_disposition == FILE_OVERWRITE)) {
691da6c28aaSamw 			smb_node_release(dnode);
692faa1795aSjb 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
693faa1795aSjb 			    ERRDOS, ERROR_FILE_NOT_FOUND);
6947b59d02dSjb 			return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
695da6c28aaSamw 		}
696da6c28aaSamw 
6972c2961f8Sjose borrego 		if ((is_dir == 0) && (!is_stream) &&
698eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    smb_is_invalid_filename(op->fqi.fq_last_comp)) {
6992c2961f8Sjose borrego 			smb_node_release(dnode);
7002c2961f8Sjose borrego 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
7012c2961f8Sjose borrego 			    ERRDOS, ERROR_INVALID_NAME);
7022c2961f8Sjose borrego 			return (NT_STATUS_OBJECT_NAME_INVALID);
7032c2961f8Sjose borrego 		}
7042c2961f8Sjose borrego 
705da6c28aaSamw 		/*
706da6c28aaSamw 		 * lock the parent dir node in case another create
707da6c28aaSamw 		 * request to the same parent directory comes in.
708da6c28aaSamw 		 */
7092c2961f8Sjose borrego 		smb_node_wrlock(dnode);
710da6c28aaSamw 
711037cac00Sjoyce mcintosh 		/* Don't apply readonly bit until smb_ofile_close */
712037cac00Sjoyce mcintosh 		if (op->dattr & FILE_ATTRIBUTE_READONLY) {
713037cac00Sjoyce mcintosh 			op->dattr &= ~FILE_ATTRIBUTE_READONLY;
714037cac00Sjoyce mcintosh 			op->created_readonly = B_TRUE;
715037cac00Sjoyce mcintosh 		}
716c8ec8eeaSjose borrego 
717037cac00Sjoyce mcintosh 		bzero(&new_attr, sizeof (new_attr));
718c8ec8eeaSjose borrego 		if ((op->crtime.tv_sec != 0) &&
719c8ec8eeaSjose borrego 		    (op->crtime.tv_sec != UINT_MAX)) {
720c8ec8eeaSjose borrego 
721c8ec8eeaSjose borrego 			new_attr.sa_mask |= SMB_AT_CRTIME;
722c8ec8eeaSjose borrego 			new_attr.sa_crtime = op->crtime;
723c8ec8eeaSjose borrego 		}
724c8ec8eeaSjose borrego 
725da6c28aaSamw 		if (is_dir == 0) {
726037cac00Sjoyce mcintosh 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
727037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
728da6c28aaSamw 			new_attr.sa_vattr.va_type = VREG;
7297b59d02dSjb 			new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR :
7307b59d02dSjb 			    S_IRUSR | S_IRGRP | S_IROTH |
7317b59d02dSjb 			    S_IWUSR | S_IWGRP | S_IWOTH;
732037cac00Sjoyce mcintosh 			new_attr.sa_mask |=
733037cac00Sjoyce mcintosh 			    SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
734dc20a302Sas 
7356537f381Sas 			if (op->dsize) {
7366537f381Sas 				new_attr.sa_vattr.va_size = op->dsize;
7376537f381Sas 				new_attr.sa_mask |= SMB_AT_SIZE;
738dc20a302Sas 			}
739dc20a302Sas 
740da6c28aaSamw 			rc = smb_fsop_create(sr, sr->user_cr, dnode,
741037cac00Sjoyce mcintosh 			    op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
742dc20a302Sas 
743da6c28aaSamw 			if (rc != 0) {
7442c2961f8Sjose borrego 				smb_node_unlock(dnode);
745da6c28aaSamw 				smb_node_release(dnode);
746dc20a302Sas 				smbsr_errno(sr, rc);
7477b59d02dSjb 				return (sr->smb_error.status);
748da6c28aaSamw 			}
749da6c28aaSamw 
750eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			node = op->fqi.fq_fnode;
7512c2961f8Sjose borrego 			smb_node_wrlock(node);
752dc20a302Sas 
753faa1795aSjb 			status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
754c8ec8eeaSjose borrego 			    op->desired_access, op->share_access);
755dc20a302Sas 
756dc20a302Sas 			if (status == NT_STATUS_SHARING_VIOLATION) {
7572c2961f8Sjose borrego 				smb_node_unlock(node);
758037cac00Sjoyce mcintosh 				smb_delete_new_object(sr);
759dc20a302Sas 				smb_node_release(node);
7602c2961f8Sjose borrego 				smb_node_unlock(dnode);
761dc20a302Sas 				smb_node_release(dnode);
762dc20a302Sas 				return (status);
763dc20a302Sas 			}
764da6c28aaSamw 		} else {
7653db3f65cSamw 			op->dattr |= FILE_ATTRIBUTE_DIRECTORY;
766037cac00Sjoyce mcintosh 			new_attr.sa_dosattr = op->dattr;
767da6c28aaSamw 			new_attr.sa_vattr.va_type = VDIR;
768da6c28aaSamw 			new_attr.sa_vattr.va_mode = 0777;
769037cac00Sjoyce mcintosh 			new_attr.sa_mask |=
770037cac00Sjoyce mcintosh 			    SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
771c8ec8eeaSjose borrego 
772da6c28aaSamw 			rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
773037cac00Sjoyce mcintosh 			    op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
774da6c28aaSamw 			if (rc != 0) {
7752c2961f8Sjose borrego 				smb_node_unlock(dnode);
776da6c28aaSamw 				smb_node_release(dnode);
777dc20a302Sas 				smbsr_errno(sr, rc);
7787b59d02dSjb 				return (sr->smb_error.status);
779da6c28aaSamw 			}
780dc20a302Sas 
781eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			node = op->fqi.fq_fnode;
7822c2961f8Sjose borrego 			smb_node_wrlock(node);
783da6c28aaSamw 		}
784da6c28aaSamw 
785eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		created = B_TRUE;
786da6c28aaSamw 		op->action_taken = SMB_OACT_CREATED;
7872c1b14e5Sjose borrego 	}
788c8ec8eeaSjose borrego 
7892c1b14e5Sjose borrego 	if (max_requested) {
7902c1b14e5Sjose borrego 		smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
7912c1b14e5Sjose borrego 		op->desired_access |= max_allowed;
792c8ec8eeaSjose borrego 	}
793c8ec8eeaSjose borrego 
794037cac00Sjoyce mcintosh 	status = NT_STATUS_SUCCESS;
795c8ec8eeaSjose borrego 
796c8ec8eeaSjose borrego 	of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK,
797c8ec8eeaSjose borrego 	    uniq_fid, &err);
798da6c28aaSamw 	if (of == NULL) {
799dc20a302Sas 		smbsr_error(sr, err.status, err.errcls, err.errcode);
800037cac00Sjoyce mcintosh 		status = err.status;
801037cac00Sjoyce mcintosh 	}
802037cac00Sjoyce mcintosh 
803037cac00Sjoyce mcintosh 	if (status == NT_STATUS_SUCCESS) {
804037cac00Sjoyce mcintosh 		if (!smb_tree_is_connected(sr->tid_tree)) {
805037cac00Sjoyce mcintosh 			smbsr_error(sr, 0, ERRSRV, ERRinvnid);
806037cac00Sjoyce mcintosh 			status = NT_STATUS_UNSUCCESSFUL;
807037cac00Sjoyce mcintosh 		}
808037cac00Sjoyce mcintosh 	}
809037cac00Sjoyce mcintosh 
810037cac00Sjoyce mcintosh 	/*
811037cac00Sjoyce mcintosh 	 * This MUST be done after ofile creation, so that explicitly
812037cac00Sjoyce mcintosh 	 * set timestamps can be remembered on the ofile.
813037cac00Sjoyce mcintosh 	 */
814037cac00Sjoyce mcintosh 	if (status == NT_STATUS_SUCCESS) {
815037cac00Sjoyce mcintosh 		if ((rc = smb_set_open_timestamps(sr, of, created)) != 0) {
816037cac00Sjoyce mcintosh 			smbsr_errno(sr, rc);
817037cac00Sjoyce mcintosh 			status = sr->smb_error.status;
818037cac00Sjoyce mcintosh 		}
819037cac00Sjoyce mcintosh 	}
820037cac00Sjoyce mcintosh 
821037cac00Sjoyce mcintosh 	if (status == NT_STATUS_SUCCESS) {
822037cac00Sjoyce mcintosh 		if (smb_node_getattr(sr, node,  &op->fqi.fq_fattr) != 0) {
823037cac00Sjoyce mcintosh 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
824037cac00Sjoyce mcintosh 			    ERRDOS, ERROR_INTERNAL_ERROR);
825037cac00Sjoyce mcintosh 			status = NT_STATUS_INTERNAL_ERROR;
826037cac00Sjoyce mcintosh 		}
827da6c28aaSamw 	}
828da6c28aaSamw 
829037cac00Sjoyce mcintosh 	/*
830037cac00Sjoyce mcintosh 	 * smb_fsop_unshrlock is a no-op if node is a directory
831037cac00Sjoyce mcintosh 	 * smb_fsop_unshrlock is done in smb_ofile_close
832037cac00Sjoyce mcintosh 	 */
833037cac00Sjoyce mcintosh 	if (status != NT_STATUS_SUCCESS) {
834037cac00Sjoyce mcintosh 		if (of == NULL) {
835037cac00Sjoyce mcintosh 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
836037cac00Sjoyce mcintosh 		} else {
837037cac00Sjoyce mcintosh 			smb_ofile_close(of, 0);
838037cac00Sjoyce mcintosh 			smb_ofile_release(of);
839037cac00Sjoyce mcintosh 		}
8408b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (created)
8418b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_delete_new_object(sr);
8428b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_unlock(node);
8438b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(node);
8448b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (created)
8458b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 			smb_node_unlock(dnode);
8468b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		smb_node_release(dnode);
847037cac00Sjoyce mcintosh 		return (status);
8488b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
8498b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
8508c10a865Sas 	/*
8518c10a865Sas 	 * Propagate the write-through mode from the open params
8528c10a865Sas 	 * to the node: see the notes in the function header.
8538c10a865Sas 	 */
8548c10a865Sas 	if (sr->sr_cfg->skc_sync_enable ||
8558c10a865Sas 	    (op->create_options & FILE_WRITE_THROUGH))
8568c10a865Sas 		node->flags |= NODE_FLAGS_WRITE_THROUGH;
8578c10a865Sas 
858037cac00Sjoyce mcintosh 	/*
859037cac00Sjoyce mcintosh 	 * Set up the fileid and dosattr in open_param for response
860037cac00Sjoyce mcintosh 	 */
861eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	op->fileid = op->fqi.fq_fattr.sa_vattr.va_nodeid;
862037cac00Sjoyce mcintosh 	op->dattr = op->fqi.fq_fattr.sa_dosattr;
8638c10a865Sas 
864da6c28aaSamw 	/*
865da6c28aaSamw 	 * Set up the file type in open_param for the response
866da6c28aaSamw 	 */
867da6c28aaSamw 	op->ftype = SMB_FTYPE_DISK;
868da6c28aaSamw 	sr->smb_fid = of->f_fid;
869da6c28aaSamw 	sr->fid_ofile = of;
870da6c28aaSamw 
8712c2961f8Sjose borrego 	smb_node_unlock(node);
872dc20a302Sas 	if (created)
8732c2961f8Sjose borrego 		smb_node_unlock(dnode);
8742c2961f8Sjose borrego 
875eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (op->fqi.fq_fattr.sa_vattr.va_type == VREG) {
8762c2961f8Sjose borrego 		smb_oplock_acquire(node, of, op);
877eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		op->dsize = op->fqi.fq_fattr.sa_vattr.va_size;
8782c2961f8Sjose borrego 	} else { /* VDIR or VLNK */
8792c2961f8Sjose borrego 		op->op_oplock_level = SMB_OPLOCK_NONE;
8802c2961f8Sjose borrego 		op->dsize = 0;
8812c2961f8Sjose borrego 	}
882dc20a302Sas 
8838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_node_release(node);
884da6c28aaSamw 	smb_node_release(dnode);
885da6c28aaSamw 
886da6c28aaSamw 	return (NT_STATUS_SUCCESS);
887da6c28aaSamw }
888da6c28aaSamw 
889037cac00Sjoyce mcintosh /*
890037cac00Sjoyce mcintosh  * smb_set_open_timestamps
891037cac00Sjoyce mcintosh  *
892037cac00Sjoyce mcintosh  * Last write time:
893037cac00Sjoyce mcintosh  * - If the last_write time specified in the open params is not 0 or -1,
894037cac00Sjoyce mcintosh  *   use it as file's mtime. This will be considered an explicitly set
895037cac00Sjoyce mcintosh  *   timestamps, not reset by subsequent writes.
896037cac00Sjoyce mcintosh  *
897037cac00Sjoyce mcintosh  * Opening existing file (not directory):
898037cac00Sjoyce mcintosh  * - If opening an existing file for overwrite set initial ATIME, MTIME
899037cac00Sjoyce mcintosh  *   & CTIME to now. (This is achieved by setting them as pending then forcing
900037cac00Sjoyce mcintosh  *   an smb_node_setattr() to apply pending times.)
901037cac00Sjoyce mcintosh  *
902037cac00Sjoyce mcintosh  * - Note  If opening an existing file NOT for overwrite, windows would
903037cac00Sjoyce mcintosh  *   set the atime on file close, however setting the atime would cause
904037cac00Sjoyce mcintosh  *   the ARCHIVE attribute to be set, which does not occur on windows,
905037cac00Sjoyce mcintosh  *   so we do not do the atime update.
906037cac00Sjoyce mcintosh  *
907037cac00Sjoyce mcintosh  * Returns: errno
908037cac00Sjoyce mcintosh  */
909037cac00Sjoyce mcintosh static int
910037cac00Sjoyce mcintosh smb_set_open_timestamps(smb_request_t *sr, smb_ofile_t *of, boolean_t created)
911037cac00Sjoyce mcintosh {
912037cac00Sjoyce mcintosh 	int		rc = 0;
913037cac00Sjoyce mcintosh 	open_param_t	*op = &sr->arg.open;
914037cac00Sjoyce mcintosh 	smb_node_t	*node = of->f_node;
915037cac00Sjoyce mcintosh 	boolean_t	existing_file, set_times;
916037cac00Sjoyce mcintosh 	smb_attr_t	attr;
917037cac00Sjoyce mcintosh 
918037cac00Sjoyce mcintosh 	bzero(&attr, sizeof (smb_attr_t));
919037cac00Sjoyce mcintosh 	set_times = B_FALSE;
920037cac00Sjoyce mcintosh 
921037cac00Sjoyce mcintosh 	if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
922037cac00Sjoyce mcintosh 		attr.sa_mask = SMB_AT_MTIME;
923037cac00Sjoyce mcintosh 		attr.sa_vattr.va_mtime = op->mtime;
924037cac00Sjoyce mcintosh 		set_times = B_TRUE;
925037cac00Sjoyce mcintosh 	}
926037cac00Sjoyce mcintosh 
927037cac00Sjoyce mcintosh 	existing_file = !(created || smb_node_is_dir(node));
928037cac00Sjoyce mcintosh 	if (existing_file) {
929037cac00Sjoyce mcintosh 		switch (op->create_disposition) {
930037cac00Sjoyce mcintosh 		case FILE_SUPERSEDE:
931037cac00Sjoyce mcintosh 		case FILE_OVERWRITE_IF:
932037cac00Sjoyce mcintosh 		case FILE_OVERWRITE:
933037cac00Sjoyce mcintosh 			smb_ofile_set_write_time_pending(of);
934037cac00Sjoyce mcintosh 			set_times = B_TRUE;
935037cac00Sjoyce mcintosh 			break;
936037cac00Sjoyce mcintosh 		default:
937037cac00Sjoyce mcintosh 			break;
938037cac00Sjoyce mcintosh 		}
939037cac00Sjoyce mcintosh 	}
940037cac00Sjoyce mcintosh 
941037cac00Sjoyce mcintosh 	if (set_times)
942037cac00Sjoyce mcintosh 		rc = smb_node_setattr(sr, node, sr->user_cr, of, &attr);
943037cac00Sjoyce mcintosh 
944037cac00Sjoyce mcintosh 	return (rc);
945037cac00Sjoyce mcintosh }
946037cac00Sjoyce mcintosh 
947da6c28aaSamw /*
948da6c28aaSamw  * smb_validate_object_name
949da6c28aaSamw  *
9508d7e4166Sjose borrego  * Very basic file name validation.
9518d7e4166Sjose borrego  * For filenames, we check for names of the form "AAAn:". Names that
9528d7e4166Sjose borrego  * contain three characters, a single digit and a colon (:) are reserved
9538d7e4166Sjose borrego  * as DOS device names, i.e. "COM1:".
9548d7e4166Sjose borrego  * Stream name validation is handed off to smb_validate_stream_name
955da6c28aaSamw  *
956da6c28aaSamw  * Returns NT status codes.
957da6c28aaSamw  */
958da6c28aaSamw uint32_t
959eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States smb_validate_object_name(smb_pathname_t *pn)
960da6c28aaSamw {
961eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (pn->pn_fname &&
962eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	    strlen(pn->pn_fname) == 5 &&
963*bbf6f00cSJordan Brown 	    smb_isdigit(pn->pn_fname[3]) &&
964eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	    pn->pn_fname[4] == ':') {
965da6c28aaSamw 		return (NT_STATUS_OBJECT_NAME_INVALID);
966da6c28aaSamw 	}
967da6c28aaSamw 
968eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (pn->pn_sname)
969eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		return (smb_validate_stream_name(pn));
9708d7e4166Sjose borrego 
971eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	return (NT_STATUS_SUCCESS);
972da6c28aaSamw }
973da6c28aaSamw 
9748b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
975da6c28aaSamw /*
9768b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * This function is used to delete a newly created object (file or
9778b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States  * directory) if an error occurs after creation of the object.
978da6c28aaSamw  */
9798b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States static void
9808b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States smb_delete_new_object(smb_request_t *sr)
981da6c28aaSamw {
9828b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	open_param_t	*op = &sr->arg.open;
9838b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	smb_fqi_t	*fqi = &(op->fqi);
9848b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	uint32_t	flags = 0;
9858b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
9868b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
9878b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		flags |= SMB_IGNORE_CASE;
9888b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (SMB_TREE_SUPPORTS_CATIA(sr))
9898b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 		flags |= SMB_CATIA;
9908b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 
9918b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (op->create_options & FILE_DIRECTORY_FILE)
992eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
993eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    fqi->fq_last_comp, flags);
9948b2cc8acSafshin salek ardakani - Sun Microsystems - Irvine United States 	else
995eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		(void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode,
996eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    fqi->fq_last_comp, flags);
997eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States }
998eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
999eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States /*
1000eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * smb_pathname_setup
1001eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * Parse path: pname/fname:sname:stype
1002eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  *
1003*bbf6f00cSJordan Brown  * Elements of the smb_pathname_t structure are allocated using request
1004*bbf6f00cSJordan Brown  * specific storage and will be free'd when the sr is destroyed.
1005eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  *
1006eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * Eliminate duplicate slashes in pn->pn_path.
1007eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * Populate pn structure elements with the individual elements
1008eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * of pn->pn_path. pn->pn_sname will contain the whole stream name
1009eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * including the stream type and preceding colon: :sname:%DATA
1010eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * pn_stype will point to the stream type within pn_sname.
1011eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  *
1012eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * If any element is missing the pointer in pn will be NULL.
1013eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  */
1014eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States void
1015eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_setup(smb_request_t *sr, smb_pathname_t *pn)
1016eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States {
1017eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	char *pname, *fname, *sname;
1018eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	int len;
1019eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1020eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	(void) strcanon(pn->pn_path, "/\\");
1021eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1022eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	pname = pn->pn_path;
1023eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	fname = strrchr(pn->pn_path, '\\');
1024eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1025eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (fname) {
1026eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		if (fname == pname)
1027eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			pname = NULL;
1028eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		else {
1029eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			*fname = '\0';
1030eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			pn->pn_pname =
1031eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			    smb_pathname_strdup(sr, pname);
1032eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 			*fname = '\\';
1033eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		}
1034eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		++fname;
1035eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	} else {
1036eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		fname = pname;
1037eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		pn->pn_pname = NULL;
1038eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
1039eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1040eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (!smb_is_stream_name(fname)) {
1041eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		pn->pn_fname =
1042eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    smb_pathname_strdup(sr, fname);
1043eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		return;
1044eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
1045eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1046eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	/* sname can't be NULL smb_is_stream_name checks this */
1047eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	sname = strchr(fname, ':');
1048eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (sname == fname)
1049eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		fname = NULL;
1050eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	else {
1051eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		*sname = '\0';
1052eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		pn->pn_fname =
1053eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		    smb_pathname_strdup(sr, fname);
1054eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		*sname = ':';
1055eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
1056eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1057eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	pn->pn_sname = smb_pathname_strdup(sr, sname);
1058eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	pn->pn_stype = strchr(pn->pn_sname + 1, ':');
1059eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	if (pn->pn_stype) {
1060*bbf6f00cSJordan Brown 		(void) smb_strupr(pn->pn_stype);
1061eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	} else {
1062eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		len = strlen(pn->pn_sname);
1063*bbf6f00cSJordan Brown 		pn->pn_sname = smb_pathname_strcat(sr, pn->pn_sname, ":$DATA");
1064eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 		pn->pn_stype = pn->pn_sname + len;
1065eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	}
1066eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	++pn->pn_stype;
1067eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States }
1068eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1069eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States /*
1070eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * smb_pathname_strdup
1071eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  *
1072eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * Duplicate NULL terminated string s.
1073*bbf6f00cSJordan Brown  *
1074*bbf6f00cSJordan Brown  * The new string is allocated using request specific storage and will
1075*bbf6f00cSJordan Brown  * be free'd when the sr is destroyed.
1076eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  */
1077eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States static char *
1078eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States smb_pathname_strdup(smb_request_t *sr, const char *s)
1079eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States {
1080eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	char *s2;
1081eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	size_t n;
1082eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1083eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	n = strlen(s) + 1;
1084*bbf6f00cSJordan Brown 	s2 = smb_srm_alloc(sr, n);
1085eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	(void) strlcpy(s2, s, n);
1086eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	return (s2);
1087eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States }
1088eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1089eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States /*
1090eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * smb_pathname_strcat
1091eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  *
1092eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * Reallocate NULL terminated string s1 to accommodate
1093eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * concatenating  NULL terminated string s2.
1094eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  * Append s2 and return resulting NULL terminated string.
1095eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  *
1096*bbf6f00cSJordan Brown  * The string buffer is reallocated using request specific
1097*bbf6f00cSJordan Brown  * storage and will be free'd when the sr is destroyed.
1098eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States  */
1099eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States static char *
1100*bbf6f00cSJordan Brown smb_pathname_strcat(smb_request_t *sr, char *s1, const char *s2)
1101eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States {
1102eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	size_t n;
1103eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 
1104eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	n = strlen(s1) + strlen(s2) + 1;
1105*bbf6f00cSJordan Brown 	s1 = smb_srm_realloc(sr, s1, n);
1106eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	(void) strlcat(s1, s2, n);
1107eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States 	return (s1);
1108da6c28aaSamw }
1109