xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_common_open.c (revision 12890:16985853e3aa)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
2112508Samw@Sun.COM 
225331Samw /*
2312508Samw@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
245331Samw  */
255331Samw 
265331Samw /*
275331Samw  * This module provides the common open functionality to the various
285331Samw  * open and create SMB interface functions.
295331Samw  */
305331Samw 
3110966SJordan.Brown@Sun.COM #include <sys/types.h>
3210966SJordan.Brown@Sun.COM #include <sys/cmn_err.h>
335331Samw #include <sys/fcntl.h>
345772Sas200622 #include <sys/nbmlock.h>
3510966SJordan.Brown@Sun.COM #include <smbsrv/string.h>
3610966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
3710966SJordan.Brown@Sun.COM #include <smbsrv/smb_fsops.h>
3810966SJordan.Brown@Sun.COM #include <smbsrv/smbinfo.h>
395331Samw 
406139Sjb150015 volatile uint32_t smb_fids = 0;
416030Sjb150015 
426030Sjb150015 static uint32_t smb_open_subr(smb_request_t *);
436139Sjb150015 extern uint32_t smb_is_executable(char *);
449231SAfshin.Ardakani@Sun.COM static void smb_delete_new_object(smb_request_t *);
4510001SJoyce.McIntosh@Sun.COM static int smb_set_open_timestamps(smb_request_t *, smb_ofile_t *, boolean_t);
46*12890SJoyce.McIntosh@Sun.COM static void smb_open_oplock_break(smb_request_t *, smb_node_t *);
47*12890SJoyce.McIntosh@Sun.COM static boolean_t smb_open_attr_only(smb_arg_open_t *);
48*12890SJoyce.McIntosh@Sun.COM static boolean_t smb_open_overwrite(smb_arg_open_t *);
495331Samw 
505331Samw /*
515331Samw  * smb_access_generic_to_file
525331Samw  *
535331Samw  * Search MSDN for IoCreateFile to see following mapping.
545331Samw  *
555331Samw  * GENERIC_READ		STANDARD_RIGHTS_READ, FILE_READ_DATA,
565331Samw  *			FILE_READ_ATTRIBUTES and FILE_READ_EA
575331Samw  *
585331Samw  * GENERIC_WRITE	STANDARD_RIGHTS_WRITE, FILE_WRITE_DATA,
595331Samw  *               FILE_WRITE_ATTRIBUTES, FILE_WRITE_EA, and FILE_APPEND_DATA
605331Samw  *
615331Samw  * GENERIC_EXECUTE	STANDARD_RIGHTS_EXECUTE, SYNCHRONIZE, and FILE_EXECUTE.
625331Samw  */
635331Samw uint32_t
smb_access_generic_to_file(uint32_t desired_access)645331Samw smb_access_generic_to_file(uint32_t desired_access)
655331Samw {
665331Samw 	uint32_t access = 0;
675331Samw 
685331Samw 	if (desired_access & GENERIC_ALL)
695331Samw 		return (FILE_ALL_ACCESS & ~SYNCHRONIZE);
705331Samw 
715331Samw 	if (desired_access & GENERIC_EXECUTE) {
725331Samw 		desired_access &= ~GENERIC_EXECUTE;
735331Samw 		access |= (STANDARD_RIGHTS_EXECUTE |
745331Samw 		    SYNCHRONIZE | FILE_EXECUTE);
755331Samw 	}
765331Samw 
775331Samw 	if (desired_access & GENERIC_WRITE) {
785331Samw 		desired_access &= ~GENERIC_WRITE;
795331Samw 		access |= (FILE_GENERIC_WRITE & ~SYNCHRONIZE);
805331Samw 	}
815331Samw 
825331Samw 	if (desired_access & GENERIC_READ) {
835331Samw 		desired_access &= ~GENERIC_READ;
845331Samw 		access |= FILE_GENERIC_READ;
855331Samw 	}
865331Samw 
875331Samw 	return (access | desired_access);
885331Samw }
895331Samw 
905331Samw /*
915331Samw  * smb_omode_to_amask
925331Samw  *
935331Samw  * This function converts open modes used by Open and Open AndX
945331Samw  * commands to desired access bits used by NT Create AndX command.
955331Samw  */
965331Samw uint32_t
smb_omode_to_amask(uint32_t desired_access)975331Samw smb_omode_to_amask(uint32_t desired_access)
985331Samw {
995331Samw 	switch (desired_access & SMB_DA_ACCESS_MASK) {
1005331Samw 	case SMB_DA_ACCESS_READ:
1015331Samw 		return (FILE_GENERIC_READ);
1025331Samw 
1035331Samw 	case SMB_DA_ACCESS_WRITE:
1045331Samw 		return (FILE_GENERIC_WRITE);
1055331Samw 
1065331Samw 	case SMB_DA_ACCESS_READ_WRITE:
1075331Samw 		return (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
1085331Samw 
1095331Samw 	case SMB_DA_ACCESS_EXECUTE:
1105331Samw 		return (FILE_GENERIC_EXECUTE);
1118934SJose.Borrego@Sun.COM 
1128934SJose.Borrego@Sun.COM 	default:
1138934SJose.Borrego@Sun.COM 		return (FILE_GENERIC_ALL);
1145331Samw 	}
1155331Samw }
1165331Samw 
1175331Samw /*
1185331Samw  * smb_denymode_to_sharemode
1195331Samw  *
1205331Samw  * This function converts deny modes used by Open and Open AndX
1215331Samw  * commands to share access bits used by NT Create AndX command.
1225331Samw  */
1235331Samw uint32_t
smb_denymode_to_sharemode(uint32_t desired_access,char * fname)1245331Samw smb_denymode_to_sharemode(uint32_t desired_access, char *fname)
1255331Samw {
1265331Samw 	switch (desired_access & SMB_DA_SHARE_MASK) {
1275331Samw 	case SMB_DA_SHARE_COMPATIBILITY:
1285331Samw 		if (smb_is_executable(fname))
1295331Samw 			return (FILE_SHARE_READ | FILE_SHARE_WRITE);
1307348SJose.Borrego@Sun.COM 
1317348SJose.Borrego@Sun.COM 		return (FILE_SHARE_ALL);
1325331Samw 
1335331Samw 	case SMB_DA_SHARE_EXCLUSIVE:
1345331Samw 		return (FILE_SHARE_NONE);
1355331Samw 
1365331Samw 	case SMB_DA_SHARE_DENY_WRITE:
1375331Samw 		return (FILE_SHARE_READ);
1385331Samw 
1395331Samw 	case SMB_DA_SHARE_DENY_READ:
1405331Samw 		return (FILE_SHARE_WRITE);
1415331Samw 
1425331Samw 	case SMB_DA_SHARE_DENY_NONE:
1438934SJose.Borrego@Sun.COM 	default:
1445331Samw 		return (FILE_SHARE_READ | FILE_SHARE_WRITE);
1455331Samw 	}
1465331Samw }
1475331Samw 
1485331Samw /*
1495331Samw  * smb_ofun_to_crdisposition
1505331Samw  *
1515331Samw  * This function converts open function values used by Open and Open AndX
1525331Samw  * commands to create disposition values used by NT Create AndX command.
1535331Samw  */
1545331Samw uint32_t
smb_ofun_to_crdisposition(uint16_t ofun)1555331Samw smb_ofun_to_crdisposition(uint16_t  ofun)
1565331Samw {
1575331Samw 	static int ofun_cr_map[3][2] =
1585331Samw 	{
1595331Samw 		{ -1,			FILE_CREATE },
1605331Samw 		{ FILE_OPEN,		FILE_OPEN_IF },
1615331Samw 		{ FILE_OVERWRITE,	FILE_OVERWRITE_IF }
1625331Samw 	};
1635331Samw 
1645331Samw 	int row = ofun & SMB_OFUN_OPEN_MASK;
1655331Samw 	int col = (ofun & SMB_OFUN_CREATE_MASK) >> 4;
1665331Samw 
1675331Samw 	if (row == 3)
1688934SJose.Borrego@Sun.COM 		return (FILE_MAXIMUM_DISPOSITION + 1);
1695331Samw 
1705331Samw 	return (ofun_cr_map[row][col]);
1715331Samw }
1725331Samw 
1735331Samw /*
1746030Sjb150015  * Retry opens to avoid spurious sharing violations, due to timing
1756030Sjb150015  * issues between closes and opens.  The client that already has the
1766030Sjb150015  * file open may be in the process of closing it.
1776030Sjb150015  */
1786030Sjb150015 uint32_t
smb_common_open(smb_request_t * sr)1796030Sjb150015 smb_common_open(smb_request_t *sr)
1806030Sjb150015 {
18112508Samw@Sun.COM 	smb_arg_open_t	*parg;
18210966SJordan.Brown@Sun.COM 	uint32_t	status = NT_STATUS_SUCCESS;
18310966SJordan.Brown@Sun.COM 	int		count;
18410966SJordan.Brown@Sun.COM 
18510966SJordan.Brown@Sun.COM 	parg = kmem_alloc(sizeof (*parg), KM_SLEEP);
18610966SJordan.Brown@Sun.COM 	bcopy(&sr->arg.open, parg, sizeof (*parg));
1876030Sjb150015 
1886030Sjb150015 	for (count = 0; count <= 4; count++) {
18910966SJordan.Brown@Sun.COM 		if (count != 0)
1906030Sjb150015 			delay(MSEC_TO_TICK(400));
1916030Sjb150015 
1926139Sjb150015 		status = smb_open_subr(sr);
1936139Sjb150015 		if (status != NT_STATUS_SHARING_VIOLATION)
1946030Sjb150015 			break;
19510966SJordan.Brown@Sun.COM 
19610966SJordan.Brown@Sun.COM 		bcopy(parg, &sr->arg.open, sizeof (*parg));
1976030Sjb150015 	}
1986030Sjb150015 
1996139Sjb150015 	if (status == NT_STATUS_SHARING_VIOLATION) {
2006030Sjb150015 		smbsr_error(sr, NT_STATUS_SHARING_VIOLATION,
2016030Sjb150015 		    ERRDOS, ERROR_SHARING_VIOLATION);
2026030Sjb150015 	}
2036030Sjb150015 
2048934SJose.Borrego@Sun.COM 	if (status == NT_STATUS_NO_SUCH_FILE) {
2058934SJose.Borrego@Sun.COM 		smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
2068934SJose.Borrego@Sun.COM 		    ERRDOS, ERROR_FILE_NOT_FOUND);
2078934SJose.Borrego@Sun.COM 	}
2088934SJose.Borrego@Sun.COM 
20910966SJordan.Brown@Sun.COM 	kmem_free(parg, sizeof (*parg));
2106030Sjb150015 	return (status);
2116030Sjb150015 }
2126030Sjb150015 
2136030Sjb150015 /*
2145331Samw  * smb_open_subr
2155331Samw  *
2165331Samw  * Notes on write-through behaviour. It looks like pre-LM0.12 versions
2175331Samw  * of the protocol specify the write-through mode when a file is opened,
2185331Samw  * (SmbOpen, SmbOpenAndX) so the write calls (SmbWrite, SmbWriteAndClose,
2195331Samw  * SmbWriteAndUnlock) don't need to contain a write-through flag.
2205331Samw  *
2215331Samw  * With LM0.12, the open calls (SmbCreateAndX, SmbNtTransactCreate)
2225331Samw  * don't indicate which write-through mode to use. Instead the write
2235331Samw  * calls (SmbWriteAndX, SmbWriteRaw) specify the mode on a per call
2245331Samw  * basis.
2255331Samw  *
2265331Samw  * We don't care which open call was used to get us here, we just need
2275331Samw  * to ensure that the write-through mode flag is copied from the open
2285331Samw  * parameters to the node. We test the omode write-through flag in all
2295331Samw  * write functions.
2305331Samw  *
2315331Samw  * This function will return NT status codes but it also raises errors,
2325331Samw  * in which case it won't return to the caller. Be careful how you
2335331Samw  * handle things in here.
2346600Sas200622  *
2356600Sas200622  * The following rules apply when processing a file open request:
2366600Sas200622  *
237*12890SJoyce.McIntosh@Sun.COM  * - Oplocks must be broken prior to share checking as the break may
238*12890SJoyce.McIntosh@Sun.COM  *   cause other clients to close the file, which would affect sharing
239*12890SJoyce.McIntosh@Sun.COM  *   checks.
2406600Sas200622  *
2416600Sas200622  * - Share checks must take place prior to access checks for correct
2426600Sas200622  * Windows semantics and to prevent unnecessary NFS delegation recalls.
2436600Sas200622  *
2446600Sas200622  * - Oplocks must be acquired after open to ensure the correct
2456600Sas200622  * synchronization with NFS delegation and FEM installation.
2467348SJose.Borrego@Sun.COM  *
2477348SJose.Borrego@Sun.COM  * DOS readonly bit rules
2487348SJose.Borrego@Sun.COM  *
2497348SJose.Borrego@Sun.COM  * 1. The creator of a readonly file can write to/modify the size of the file
2507348SJose.Borrego@Sun.COM  * using the original create fid, even though the file will appear as readonly
2517348SJose.Borrego@Sun.COM  * to all other fids and via a CIFS getattr call.
25210001SJoyce.McIntosh@Sun.COM  * The readonly bit therefore cannot be set in the filesystem until the file
25310001SJoyce.McIntosh@Sun.COM  * is closed (smb_ofile_close). It is accounted for via ofile and node flags.
2547348SJose.Borrego@Sun.COM  *
2557348SJose.Borrego@Sun.COM  * 2. A setinfo operation (using either an open fid or a path) to set/unset
2567348SJose.Borrego@Sun.COM  * readonly will be successful regardless of whether a creator of a readonly
2577348SJose.Borrego@Sun.COM  * file has an open fid (and has the special privilege mentioned in #1,
2587348SJose.Borrego@Sun.COM  * above).  I.e., the creator of a readonly fid holding that fid will no longer
2597348SJose.Borrego@Sun.COM  * have a special privilege.
2607348SJose.Borrego@Sun.COM  *
2617348SJose.Borrego@Sun.COM  * 3. The DOS readonly bit affects only data and some metadata.
2627348SJose.Borrego@Sun.COM  * The following metadata can be changed regardless of the readonly bit:
2637348SJose.Borrego@Sun.COM  * 	- security descriptors
2647348SJose.Borrego@Sun.COM  *	- DOS attributes
2657348SJose.Borrego@Sun.COM  *	- timestamps
2667348SJose.Borrego@Sun.COM  *
2677348SJose.Borrego@Sun.COM  * In the current implementation, the file size cannot be changed (except for
2687348SJose.Borrego@Sun.COM  * the exceptions in #1 and #2, above).
2697619SJose.Borrego@Sun.COM  *
2707619SJose.Borrego@Sun.COM  *
2717619SJose.Borrego@Sun.COM  * DOS attribute rules
2727619SJose.Borrego@Sun.COM  *
2737619SJose.Borrego@Sun.COM  * These rules are specific to creating / opening files and directories.
2747619SJose.Borrego@Sun.COM  * How the attribute value (specifically ZERO or FILE_ATTRIBUTE_NORMAL)
2757619SJose.Borrego@Sun.COM  * should be interpreted may differ in other requests.
2767619SJose.Borrego@Sun.COM  *
2777619SJose.Borrego@Sun.COM  * - An attribute value equal to ZERO or FILE_ATTRIBUTE_NORMAL means that the
2787619SJose.Borrego@Sun.COM  *   file's attributes should be cleared.
2797619SJose.Borrego@Sun.COM  * - If FILE_ATTRIBUTE_NORMAL is specified with any other attributes,
2807619SJose.Borrego@Sun.COM  *   FILE_ATTRIBUTE_NORMAL is ignored.
2817619SJose.Borrego@Sun.COM  *
2827619SJose.Borrego@Sun.COM  * 1. Creating a new file
2837619SJose.Borrego@Sun.COM  * - The request attributes + FILE_ATTRIBUTE_ARCHIVE are applied to the file.
2847619SJose.Borrego@Sun.COM  *
2857619SJose.Borrego@Sun.COM  * 2. Creating a new directory
2867619SJose.Borrego@Sun.COM  * - The request attributes + FILE_ATTRIBUTE_DIRECTORY are applied to the file.
2877619SJose.Borrego@Sun.COM  * - FILE_ATTRIBUTE_ARCHIVE does not get set.
2887619SJose.Borrego@Sun.COM  *
2897619SJose.Borrego@Sun.COM  * 3. Overwriting an existing file
2907619SJose.Borrego@Sun.COM  * - the request attributes are used as search attributes. If the existing
2917619SJose.Borrego@Sun.COM  *   file does not meet the search criteria access is denied.
2927619SJose.Borrego@Sun.COM  * - otherwise, applies attributes + FILE_ATTRIBUTE_ARCHIVE.
2937619SJose.Borrego@Sun.COM  *
2947619SJose.Borrego@Sun.COM  * 4. Opening an existing file or directory
2957619SJose.Borrego@Sun.COM  *    The request attributes are ignored.
2965331Samw  */
2976030Sjb150015 static uint32_t
smb_open_subr(smb_request_t * sr)2986030Sjb150015 smb_open_subr(smb_request_t *sr)
2995331Samw {
3009343SAfshin.Ardakani@Sun.COM 	boolean_t	created = B_FALSE;
3019343SAfshin.Ardakani@Sun.COM 	boolean_t	last_comp_found = B_FALSE;
3028934SJose.Borrego@Sun.COM 	smb_node_t	*node = NULL;
3038934SJose.Borrego@Sun.COM 	smb_node_t	*dnode = NULL;
3049343SAfshin.Ardakani@Sun.COM 	smb_node_t	*cur_node = NULL;
30512508Samw@Sun.COM 	smb_arg_open_t	*op = &sr->sr_open;
3068934SJose.Borrego@Sun.COM 	int		rc;
3078934SJose.Borrego@Sun.COM 	smb_ofile_t	*of;
3088934SJose.Borrego@Sun.COM 	smb_attr_t	new_attr;
3098934SJose.Borrego@Sun.COM 	int		max_requested = 0;
3108934SJose.Borrego@Sun.COM 	uint32_t	max_allowed;
3118934SJose.Borrego@Sun.COM 	uint32_t	status = NT_STATUS_SUCCESS;
3128934SJose.Borrego@Sun.COM 	int		is_dir;
3138934SJose.Borrego@Sun.COM 	smb_error_t	err;
3148934SJose.Borrego@Sun.COM 	boolean_t	is_stream = B_FALSE;
3158934SJose.Borrego@Sun.COM 	int		lookup_flags = SMB_FOLLOW_LINKS;
3168934SJose.Borrego@Sun.COM 	uint32_t	uniq_fid;
3179343SAfshin.Ardakani@Sun.COM 	smb_pathname_t	*pn = &op->fqi.fq_path;
318*12890SJoyce.McIntosh@Sun.COM 	smb_server_t	*sv = sr->sr_server;
3195331Samw 
3205331Samw 	is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0;
3215331Samw 
32210001SJoyce.McIntosh@Sun.COM 	/*
32310001SJoyce.McIntosh@Sun.COM 	 * If the object being created or opened is a directory
32410001SJoyce.McIntosh@Sun.COM 	 * the Disposition parameter must be one of FILE_CREATE,
32510001SJoyce.McIntosh@Sun.COM 	 * FILE_OPEN, or FILE_OPEN_IF
32610001SJoyce.McIntosh@Sun.COM 	 */
3275331Samw 	if (is_dir) {
3285331Samw 		if ((op->create_disposition != FILE_CREATE) &&
3295331Samw 		    (op->create_disposition != FILE_OPEN_IF) &&
3305331Samw 		    (op->create_disposition != FILE_OPEN)) {
3315772Sas200622 			smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
3325331Samw 			    ERRDOS, ERROR_INVALID_ACCESS);
3336030Sjb150015 			return (NT_STATUS_INVALID_PARAMETER);
3345331Samw 		}
3355331Samw 	}
3365331Samw 
3375331Samw 	if (op->desired_access & MAXIMUM_ALLOWED) {
3385331Samw 		max_requested = 1;
3395331Samw 		op->desired_access &= ~MAXIMUM_ALLOWED;
3405331Samw 	}
3415331Samw 	op->desired_access = smb_access_generic_to_file(op->desired_access);
3425331Samw 
3435331Samw 	if (sr->session->s_file_cnt >= SMB_SESSION_OFILE_MAX) {
3445331Samw 		ASSERT(sr->uid_user);
345*12890SJoyce.McIntosh@Sun.COM 		cmn_err(CE_NOTE, "smbsrv[%s\\%s]: TOO_MANY_OPENED_FILES",
34612508Samw@Sun.COM 		    sr->uid_user->u_domain, sr->uid_user->u_name);
3475331Samw 
3485772Sas200622 		smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
3495331Samw 		    ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
3506030Sjb150015 		return (NT_STATUS_TOO_MANY_OPENED_FILES);
3515331Samw 	}
3525331Samw 
3535331Samw 	/* This must be NULL at this point */
3545331Samw 	sr->fid_ofile = NULL;
3555331Samw 
3565331Samw 	op->devstate = 0;
3575331Samw 
3585331Samw 	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
3595331Samw 	case STYPE_DISKTREE:
36011447Samw@Sun.COM 	case STYPE_PRINTQ:
3615331Samw 		break;
3625331Samw 
3635331Samw 	case STYPE_IPC:
364*12890SJoyce.McIntosh@Sun.COM 
365*12890SJoyce.McIntosh@Sun.COM 		if ((rc = smb_threshold_enter(&sv->sv_opipe_ct)) != 0) {
366*12890SJoyce.McIntosh@Sun.COM 			status = RPC_NT_SERVER_TOO_BUSY;
367*12890SJoyce.McIntosh@Sun.COM 			smbsr_error(sr, status, 0, 0);
368*12890SJoyce.McIntosh@Sun.COM 			return (status);
369*12890SJoyce.McIntosh@Sun.COM 		}
370*12890SJoyce.McIntosh@Sun.COM 
3715331Samw 		/*
3725331Samw 		 * No further processing for IPC, we need to either
3735331Samw 		 * raise an exception or return success here.
3745331Samw 		 */
3757052Samw 		if ((status = smb_opipe_open(sr)) != NT_STATUS_SUCCESS)
3766030Sjb150015 			smbsr_error(sr, status, 0, 0);
377*12890SJoyce.McIntosh@Sun.COM 
378*12890SJoyce.McIntosh@Sun.COM 		smb_threshold_exit(&sv->sv_opipe_ct, sv);
3796030Sjb150015 		return (status);
3805331Samw 
3815331Samw 	default:
3826030Sjb150015 		smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE,
3836030Sjb150015 		    ERRDOS, ERROR_BAD_DEV_TYPE);
3846030Sjb150015 		return (NT_STATUS_BAD_DEVICE_TYPE);
3855331Samw 	}
3865331Samw 
38711337SWilliam.Krier@Sun.COM 	smb_pathname_init(sr, pn, pn->pn_path);
38811337SWilliam.Krier@Sun.COM 	if (!smb_pathname_validate(sr, pn))
38911337SWilliam.Krier@Sun.COM 		return (sr->smb_error.status);
39011337SWilliam.Krier@Sun.COM 
39111337SWilliam.Krier@Sun.COM 	if (strlen(pn->pn_path) >= MAXPATHLEN) {
3925772Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRfilespecs);
3936030Sjb150015 		return (NT_STATUS_NAME_TOO_LONG);
3945331Samw 	}
3955331Samw 
39611337SWilliam.Krier@Sun.COM 	if (is_dir) {
39711337SWilliam.Krier@Sun.COM 		if (!smb_validate_dirname(sr, pn))
39811337SWilliam.Krier@Sun.COM 			return (sr->smb_error.status);
39911337SWilliam.Krier@Sun.COM 	} else {
40011337SWilliam.Krier@Sun.COM 		if (!smb_validate_object_name(sr, pn))
40111337SWilliam.Krier@Sun.COM 			return (sr->smb_error.status);
4025331Samw 	}
4035331Samw 
4049343SAfshin.Ardakani@Sun.COM 	cur_node = op->fqi.fq_dnode ?
4059343SAfshin.Ardakani@Sun.COM 	    op->fqi.fq_dnode : sr->tid_tree->t_snode;
4069343SAfshin.Ardakani@Sun.COM 
4079343SAfshin.Ardakani@Sun.COM 	/*
4089343SAfshin.Ardakani@Sun.COM 	 * if no path or filename are specified the stream should be
4099343SAfshin.Ardakani@Sun.COM 	 * created on cur_node
4109343SAfshin.Ardakani@Sun.COM 	 */
4119343SAfshin.Ardakani@Sun.COM 	if (!is_dir && !pn->pn_pname && !pn->pn_fname && pn->pn_sname) {
41211963SAfshin.Ardakani@Sun.COM 		/*
41311963SAfshin.Ardakani@Sun.COM 		 * Can't currently handle a stream on the tree root.
41411963SAfshin.Ardakani@Sun.COM 		 * If a stream is being opened return "not found", otherwise
41511963SAfshin.Ardakani@Sun.COM 		 * return "access denied".
41611963SAfshin.Ardakani@Sun.COM 		 */
4179343SAfshin.Ardakani@Sun.COM 		if (cur_node == sr->tid_tree->t_snode) {
41811963SAfshin.Ardakani@Sun.COM 			if (op->create_disposition == FILE_OPEN) {
41911963SAfshin.Ardakani@Sun.COM 				smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
42011963SAfshin.Ardakani@Sun.COM 				    ERRDOS, ERROR_FILE_NOT_FOUND);
42111963SAfshin.Ardakani@Sun.COM 				return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
42211963SAfshin.Ardakani@Sun.COM 			}
4239343SAfshin.Ardakani@Sun.COM 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
4249343SAfshin.Ardakani@Sun.COM 			    ERROR_ACCESS_DENIED);
4259343SAfshin.Ardakani@Sun.COM 			return (NT_STATUS_ACCESS_DENIED);
4269343SAfshin.Ardakani@Sun.COM 		}
4279343SAfshin.Ardakani@Sun.COM 
4289343SAfshin.Ardakani@Sun.COM 		(void) snprintf(op->fqi.fq_last_comp,
4299343SAfshin.Ardakani@Sun.COM 		    sizeof (op->fqi.fq_last_comp),
4309343SAfshin.Ardakani@Sun.COM 		    "%s%s", cur_node->od_name, pn->pn_sname);
4319343SAfshin.Ardakani@Sun.COM 
43210122SJordan.Brown@Sun.COM 		op->fqi.fq_dnode = cur_node->n_dnode;
4339343SAfshin.Ardakani@Sun.COM 		smb_node_ref(op->fqi.fq_dnode);
4349343SAfshin.Ardakani@Sun.COM 	} else {
4359343SAfshin.Ardakani@Sun.COM 		if (rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
4369343SAfshin.Ardakani@Sun.COM 		    sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode,
4379343SAfshin.Ardakani@Sun.COM 		    op->fqi.fq_last_comp)) {
4389343SAfshin.Ardakani@Sun.COM 			smbsr_errno(sr, rc);
4399343SAfshin.Ardakani@Sun.COM 			return (sr->smb_error.status);
4409343SAfshin.Ardakani@Sun.COM 		}
4415331Samw 	}
4425331Samw 
4435331Samw 	/*
4445331Samw 	 * If the access mask has only DELETE set (ignore
4455331Samw 	 * FILE_READ_ATTRIBUTES), then assume that this
4465331Samw 	 * is a request to delete the link (if a link)
4475331Samw 	 * and do not follow links.  Otherwise, follow
4485331Samw 	 * the link to the target.
4495331Samw 	 */
45010001SJoyce.McIntosh@Sun.COM 	if ((op->desired_access & ~FILE_READ_ATTRIBUTES) == DELETE)
4515331Samw 		lookup_flags &= ~SMB_FOLLOW_LINKS;
4525331Samw 
4535331Samw 	rc = smb_fsop_lookup_name(sr, kcred, lookup_flags,
4549343SAfshin.Ardakani@Sun.COM 	    sr->tid_tree->t_snode, op->fqi.fq_dnode, op->fqi.fq_last_comp,
45510001SJoyce.McIntosh@Sun.COM 	    &op->fqi.fq_fnode);
4565331Samw 
4575331Samw 	if (rc == 0) {
4589343SAfshin.Ardakani@Sun.COM 		last_comp_found = B_TRUE;
45910001SJoyce.McIntosh@Sun.COM 		rc = smb_node_getattr(sr, op->fqi.fq_fnode,
46010001SJoyce.McIntosh@Sun.COM 		    &op->fqi.fq_fattr);
46110001SJoyce.McIntosh@Sun.COM 		if (rc != 0) {
46210001SJoyce.McIntosh@Sun.COM 			smb_node_release(op->fqi.fq_fnode);
46310001SJoyce.McIntosh@Sun.COM 			smb_node_release(op->fqi.fq_dnode);
46410001SJoyce.McIntosh@Sun.COM 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
46510001SJoyce.McIntosh@Sun.COM 			    ERRDOS, ERROR_INTERNAL_ERROR);
46610001SJoyce.McIntosh@Sun.COM 			return (sr->smb_error.status);
46710001SJoyce.McIntosh@Sun.COM 		}
4685331Samw 	} else if (rc == ENOENT) {
4699343SAfshin.Ardakani@Sun.COM 		last_comp_found = B_FALSE;
4709343SAfshin.Ardakani@Sun.COM 		op->fqi.fq_fnode = NULL;
4715331Samw 		rc = 0;
4725331Samw 	} else {
4739343SAfshin.Ardakani@Sun.COM 		smb_node_release(op->fqi.fq_dnode);
4745772Sas200622 		smbsr_errno(sr, rc);
4756030Sjb150015 		return (sr->smb_error.status);
4765331Samw 	}
4775331Samw 
47810001SJoyce.McIntosh@Sun.COM 
4795772Sas200622 	/*
4805772Sas200622 	 * The uniq_fid is a CIFS-server-wide unique identifier for an ofile
4815772Sas200622 	 * which is used to uniquely identify open instances for the
4827348SJose.Borrego@Sun.COM 	 * VFS share reservation and POSIX locks.
4835772Sas200622 	 */
4845772Sas200622 
4855772Sas200622 	uniq_fid = SMB_UNIQ_FID();
4865772Sas200622 
4879343SAfshin.Ardakani@Sun.COM 	if (last_comp_found) {
4886432Sas200622 
48911963SAfshin.Ardakani@Sun.COM 		node = op->fqi.fq_fnode;
49011963SAfshin.Ardakani@Sun.COM 		dnode = op->fqi.fq_dnode;
4916432Sas200622 
49211963SAfshin.Ardakani@Sun.COM 		if (!smb_node_is_file(node) && !smb_node_is_dir(node) &&
49311963SAfshin.Ardakani@Sun.COM 		    !smb_node_is_symlink(node)) {
49411963SAfshin.Ardakani@Sun.COM 			smb_node_release(node);
49511963SAfshin.Ardakani@Sun.COM 			smb_node_release(dnode);
4966432Sas200622 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS,
4976432Sas200622 			    ERRnoaccess);
4986432Sas200622 			return (NT_STATUS_ACCESS_DENIED);
4996432Sas200622 		}
5006432Sas200622 
5015331Samw 		/*
5027619SJose.Borrego@Sun.COM 		 * Reject this request if either:
5037619SJose.Borrego@Sun.COM 		 * - the target IS a directory and the client requires that
5047619SJose.Borrego@Sun.COM 		 *   it must NOT be (required by Lotus Notes)
5057619SJose.Borrego@Sun.COM 		 * - the target is NOT a directory and client requires that
5067619SJose.Borrego@Sun.COM 		 *   it MUST be.
5075331Samw 		 */
50811963SAfshin.Ardakani@Sun.COM 		if (smb_node_is_dir(node)) {
5097619SJose.Borrego@Sun.COM 			if (op->create_options & FILE_NON_DIRECTORY_FILE) {
5105331Samw 				smb_node_release(node);
5115331Samw 				smb_node_release(dnode);
5125772Sas200622 				smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY,
5135331Samw 				    ERRDOS, ERROR_ACCESS_DENIED);
5146030Sjb150015 				return (NT_STATUS_FILE_IS_A_DIRECTORY);
5155331Samw 			}
5167619SJose.Borrego@Sun.COM 		} else {
5177619SJose.Borrego@Sun.COM 			if ((op->create_options & FILE_DIRECTORY_FILE) ||
5188934SJose.Borrego@Sun.COM 			    (op->nt_flags & NT_CREATE_FLAG_OPEN_TARGET_DIR)) {
5197619SJose.Borrego@Sun.COM 				smb_node_release(node);
5207619SJose.Borrego@Sun.COM 				smb_node_release(dnode);
5217619SJose.Borrego@Sun.COM 				smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
5227619SJose.Borrego@Sun.COM 				    ERRDOS, ERROR_DIRECTORY);
5237619SJose.Borrego@Sun.COM 				return (NT_STATUS_NOT_A_DIRECTORY);
5247619SJose.Borrego@Sun.COM 			}
5255331Samw 		}
5265331Samw 
5275331Samw 		/*
5285331Samw 		 * No more open should be accepted when "Delete on close"
5295331Samw 		 * flag is set.
5305331Samw 		 */
5315331Samw 		if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
5325331Samw 			smb_node_release(node);
5335331Samw 			smb_node_release(dnode);
5345772Sas200622 			smbsr_error(sr, NT_STATUS_DELETE_PENDING,
5355331Samw 			    ERRDOS, ERROR_ACCESS_DENIED);
5366030Sjb150015 			return (NT_STATUS_DELETE_PENDING);
5375331Samw 		}
5385331Samw 
5395331Samw 		/*
5405331Samw 		 * Specified file already exists so the operation should fail.
5415331Samw 		 */
5425331Samw 		if (op->create_disposition == FILE_CREATE) {
5435331Samw 			smb_node_release(node);
5445331Samw 			smb_node_release(dnode);
5455772Sas200622 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION,
5467961SNatalie.Li@Sun.COM 			    ERRDOS, ERROR_FILE_EXISTS);
5476030Sjb150015 			return (NT_STATUS_OBJECT_NAME_COLLISION);
5485331Samw 		}
5495331Samw 
5505331Samw 		/*
5515331Samw 		 * Windows seems to check read-only access before file
5525331Samw 		 * sharing check.
5537348SJose.Borrego@Sun.COM 		 *
5547348SJose.Borrego@Sun.COM 		 * Check to see if the file is currently readonly (irrespective
5557348SJose.Borrego@Sun.COM 		 * of whether this open will make it readonly).
5565331Samw 		 */
5577348SJose.Borrego@Sun.COM 		if (SMB_PATHFILE_IS_READONLY(sr, node)) {
5585331Samw 			/* Files data only */
55910001SJoyce.McIntosh@Sun.COM 			if (!smb_node_is_dir(node)) {
5605331Samw 				if (op->desired_access & (FILE_WRITE_DATA |
5615331Samw 				    FILE_APPEND_DATA)) {
5625331Samw 					smb_node_release(node);
5635331Samw 					smb_node_release(dnode);
5645772Sas200622 					smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
5655772Sas200622 					    ERRDOS, ERRnoaccess);
5666030Sjb150015 					return (NT_STATUS_ACCESS_DENIED);
5675331Samw 				}
5685331Samw 			}
5695331Samw 		}
5705331Samw 
571*12890SJoyce.McIntosh@Sun.COM 		/*
572*12890SJoyce.McIntosh@Sun.COM 		 * Oplock break is done prior to sharing checks as the break
573*12890SJoyce.McIntosh@Sun.COM 		 * may cause other clients to close the file which would
574*12890SJoyce.McIntosh@Sun.COM 		 * affect the sharing checks.
575*12890SJoyce.McIntosh@Sun.COM 		 */
576*12890SJoyce.McIntosh@Sun.COM 		smb_node_inc_opening_count(node);
577*12890SJoyce.McIntosh@Sun.COM 		smb_open_oplock_break(sr, node);
5786600Sas200622 
5798934SJose.Borrego@Sun.COM 		smb_node_wrlock(node);
5805772Sas200622 
5815772Sas200622 		if ((op->create_disposition == FILE_SUPERSEDE) ||
5825772Sas200622 		    (op->create_disposition == FILE_OVERWRITE_IF) ||
5835772Sas200622 		    (op->create_disposition == FILE_OVERWRITE)) {
5845772Sas200622 
5857619SJose.Borrego@Sun.COM 			if ((!(op->desired_access &
5866600Sas200622 			    (FILE_WRITE_DATA | FILE_APPEND_DATA |
5877619SJose.Borrego@Sun.COM 			    FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA))) ||
58810001SJoyce.McIntosh@Sun.COM 			    (!smb_sattr_check(op->fqi.fq_fattr.sa_dosattr,
5898934SJose.Borrego@Sun.COM 			    op->dattr))) {
5908934SJose.Borrego@Sun.COM 				smb_node_unlock(node);
591*12890SJoyce.McIntosh@Sun.COM 				smb_node_dec_opening_count(node);
5925772Sas200622 				smb_node_release(node);
5935772Sas200622 				smb_node_release(dnode);
5945772Sas200622 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
5955772Sas200622 				    ERRDOS, ERRnoaccess);
5966030Sjb150015 				return (NT_STATUS_ACCESS_DENIED);
5975772Sas200622 			}
5985772Sas200622 		}
5995772Sas200622 
6005772Sas200622 		status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
6017348SJose.Borrego@Sun.COM 		    op->desired_access, op->share_access);
6025772Sas200622 
6035331Samw 		if (status == NT_STATUS_SHARING_VIOLATION) {
6048934SJose.Borrego@Sun.COM 			smb_node_unlock(node);
605*12890SJoyce.McIntosh@Sun.COM 			smb_node_dec_opening_count(node);
6065331Samw 			smb_node_release(node);
6075331Samw 			smb_node_release(dnode);
6085331Samw 			return (status);
6095331Samw 		}
6105331Samw 
6115331Samw 		status = smb_fsop_access(sr, sr->user_cr, node,
6125331Samw 		    op->desired_access);
6135331Samw 
6145331Samw 		if (status != NT_STATUS_SUCCESS) {
6155772Sas200622 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
6165772Sas200622 
6178934SJose.Borrego@Sun.COM 			smb_node_unlock(node);
618*12890SJoyce.McIntosh@Sun.COM 			smb_node_dec_opening_count(node);
6195331Samw 			smb_node_release(node);
6205331Samw 			smb_node_release(dnode);
6215772Sas200622 
6225331Samw 			if (status == NT_STATUS_PRIVILEGE_NOT_HELD) {
6235772Sas200622 				smbsr_error(sr, status,
6245772Sas200622 				    ERRDOS, ERROR_PRIVILEGE_NOT_HELD);
6256030Sjb150015 				return (status);
6265331Samw 			} else {
6275772Sas200622 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
6285772Sas200622 				    ERRDOS, ERROR_ACCESS_DENIED);
6296030Sjb150015 				return (NT_STATUS_ACCESS_DENIED);
6305331Samw 			}
6315331Samw 		}
6325331Samw 
6335331Samw 		switch (op->create_disposition) {
6345331Samw 		case FILE_SUPERSEDE:
6355331Samw 		case FILE_OVERWRITE_IF:
6365331Samw 		case FILE_OVERWRITE:
63710001SJoyce.McIntosh@Sun.COM 			if (smb_node_is_dir(node)) {
6385772Sas200622 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
6398934SJose.Borrego@Sun.COM 				smb_node_unlock(node);
640*12890SJoyce.McIntosh@Sun.COM 				smb_node_dec_opening_count(node);
6415331Samw 				smb_node_release(node);
6425331Samw 				smb_node_release(dnode);
6435772Sas200622 				smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
6445772Sas200622 				    ERRDOS, ERROR_ACCESS_DENIED);
6456030Sjb150015 				return (NT_STATUS_ACCESS_DENIED);
6465331Samw 			}
6475331Samw 
6487619SJose.Borrego@Sun.COM 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
64910001SJoyce.McIntosh@Sun.COM 			/* Don't apply readonly bit until smb_ofile_close */
6507619SJose.Borrego@Sun.COM 			if (op->dattr & FILE_ATTRIBUTE_READONLY) {
6517619SJose.Borrego@Sun.COM 				op->created_readonly = B_TRUE;
6527619SJose.Borrego@Sun.COM 				op->dattr &= ~FILE_ATTRIBUTE_READONLY;
6537619SJose.Borrego@Sun.COM 			}
6547619SJose.Borrego@Sun.COM 
65510001SJoyce.McIntosh@Sun.COM 			bzero(&new_attr, sizeof (new_attr));
65610001SJoyce.McIntosh@Sun.COM 			new_attr.sa_dosattr = op->dattr;
65710001SJoyce.McIntosh@Sun.COM 			new_attr.sa_vattr.va_size = op->dsize;
65810001SJoyce.McIntosh@Sun.COM 			new_attr.sa_mask = SMB_AT_DOSATTR | SMB_AT_SIZE;
65910001SJoyce.McIntosh@Sun.COM 			rc = smb_fsop_setattr(sr, sr->user_cr, node, &new_attr);
66010001SJoyce.McIntosh@Sun.COM 			if (rc != 0) {
66110001SJoyce.McIntosh@Sun.COM 				smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
66210001SJoyce.McIntosh@Sun.COM 				smb_node_unlock(node);
663*12890SJoyce.McIntosh@Sun.COM 				smb_node_dec_opening_count(node);
66410001SJoyce.McIntosh@Sun.COM 				smb_node_release(node);
66510001SJoyce.McIntosh@Sun.COM 				smb_node_release(dnode);
66610001SJoyce.McIntosh@Sun.COM 				smbsr_errno(sr, rc);
66710001SJoyce.McIntosh@Sun.COM 				return (sr->smb_error.status);
66810001SJoyce.McIntosh@Sun.COM 			}
6697619SJose.Borrego@Sun.COM 
6705331Samw 			/*
67110001SJoyce.McIntosh@Sun.COM 			 * If file is being replaced, remove existing streams
6725331Samw 			 */
6739343SAfshin.Ardakani@Sun.COM 			if (SMB_IS_STREAM(node) == 0) {
67410001SJoyce.McIntosh@Sun.COM 				rc = smb_fsop_remove_streams(sr, sr->user_cr,
67510001SJoyce.McIntosh@Sun.COM 				    node);
67610001SJoyce.McIntosh@Sun.COM 				if (rc != 0) {
6779343SAfshin.Ardakani@Sun.COM 					smb_fsop_unshrlock(sr->user_cr, node,
6789343SAfshin.Ardakani@Sun.COM 					    uniq_fid);
6799343SAfshin.Ardakani@Sun.COM 					smb_node_unlock(node);
680*12890SJoyce.McIntosh@Sun.COM 					smb_node_dec_opening_count(node);
6819343SAfshin.Ardakani@Sun.COM 					smb_node_release(node);
6829343SAfshin.Ardakani@Sun.COM 					smb_node_release(dnode);
6839343SAfshin.Ardakani@Sun.COM 					return (sr->smb_error.status);
6849343SAfshin.Ardakani@Sun.COM 				}
6859343SAfshin.Ardakani@Sun.COM 			}
6865331Samw 
6875331Samw 			op->action_taken = SMB_OACT_TRUNCATED;
6885331Samw 			break;
6895331Samw 
6905331Samw 		default:
6915331Samw 			/*
6925331Samw 			 * FILE_OPEN or FILE_OPEN_IF.
6935331Samw 			 */
6945331Samw 			op->action_taken = SMB_OACT_OPENED;
6955331Samw 			break;
6965331Samw 		}
6975331Samw 	} else {
6985331Samw 		/* Last component was not found. */
6999343SAfshin.Ardakani@Sun.COM 		dnode = op->fqi.fq_dnode;
7005331Samw 
7016030Sjb150015 		if (is_dir == 0)
7029343SAfshin.Ardakani@Sun.COM 			is_stream = smb_is_stream_name(pn->pn_path);
7036030Sjb150015 
7045331Samw 		if ((op->create_disposition == FILE_OPEN) ||
7055331Samw 		    (op->create_disposition == FILE_OVERWRITE)) {
7065331Samw 			smb_node_release(dnode);
7076139Sjb150015 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
7086139Sjb150015 			    ERRDOS, ERROR_FILE_NOT_FOUND);
7096030Sjb150015 			return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
7105331Samw 		}
7115331Samw 
71211963SAfshin.Ardakani@Sun.COM 		if (pn->pn_fname && smb_is_invalid_filename(pn->pn_fname)) {
7138934SJose.Borrego@Sun.COM 			smb_node_release(dnode);
7148934SJose.Borrego@Sun.COM 			smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
7158934SJose.Borrego@Sun.COM 			    ERRDOS, ERROR_INVALID_NAME);
7168934SJose.Borrego@Sun.COM 			return (NT_STATUS_OBJECT_NAME_INVALID);
7178934SJose.Borrego@Sun.COM 		}
7188934SJose.Borrego@Sun.COM 
7195331Samw 		/*
7205331Samw 		 * lock the parent dir node in case another create
7215331Samw 		 * request to the same parent directory comes in.
7225331Samw 		 */
7238934SJose.Borrego@Sun.COM 		smb_node_wrlock(dnode);
7245331Samw 
72510001SJoyce.McIntosh@Sun.COM 		/* Don't apply readonly bit until smb_ofile_close */
72610001SJoyce.McIntosh@Sun.COM 		if (op->dattr & FILE_ATTRIBUTE_READONLY) {
72710001SJoyce.McIntosh@Sun.COM 			op->dattr &= ~FILE_ATTRIBUTE_READONLY;
72810001SJoyce.McIntosh@Sun.COM 			op->created_readonly = B_TRUE;
72910001SJoyce.McIntosh@Sun.COM 		}
7307348SJose.Borrego@Sun.COM 
73110001SJoyce.McIntosh@Sun.COM 		bzero(&new_attr, sizeof (new_attr));
7327348SJose.Borrego@Sun.COM 		if ((op->crtime.tv_sec != 0) &&
7337348SJose.Borrego@Sun.COM 		    (op->crtime.tv_sec != UINT_MAX)) {
7347348SJose.Borrego@Sun.COM 
7357348SJose.Borrego@Sun.COM 			new_attr.sa_mask |= SMB_AT_CRTIME;
7367348SJose.Borrego@Sun.COM 			new_attr.sa_crtime = op->crtime;
7377348SJose.Borrego@Sun.COM 		}
7387348SJose.Borrego@Sun.COM 
7395331Samw 		if (is_dir == 0) {
74010001SJoyce.McIntosh@Sun.COM 			op->dattr |= FILE_ATTRIBUTE_ARCHIVE;
74110001SJoyce.McIntosh@Sun.COM 			new_attr.sa_dosattr = op->dattr;
7425331Samw 			new_attr.sa_vattr.va_type = VREG;
7436030Sjb150015 			new_attr.sa_vattr.va_mode = is_stream ? S_IRUSR :
7446030Sjb150015 			    S_IRUSR | S_IRGRP | S_IROTH |
7456030Sjb150015 			    S_IWUSR | S_IWGRP | S_IWOTH;
74610001SJoyce.McIntosh@Sun.COM 			new_attr.sa_mask |=
74710001SJoyce.McIntosh@Sun.COM 			    SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
7485772Sas200622 
7496432Sas200622 			if (op->dsize) {
7506432Sas200622 				new_attr.sa_vattr.va_size = op->dsize;
7516432Sas200622 				new_attr.sa_mask |= SMB_AT_SIZE;
7525772Sas200622 			}
7535772Sas200622 
7545331Samw 			rc = smb_fsop_create(sr, sr->user_cr, dnode,
75510001SJoyce.McIntosh@Sun.COM 			    op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
7565772Sas200622 
7575331Samw 			if (rc != 0) {
7588934SJose.Borrego@Sun.COM 				smb_node_unlock(dnode);
7595331Samw 				smb_node_release(dnode);
7605772Sas200622 				smbsr_errno(sr, rc);
7616030Sjb150015 				return (sr->smb_error.status);
7625331Samw 			}
7635331Samw 
7649343SAfshin.Ardakani@Sun.COM 			node = op->fqi.fq_fnode;
765*12890SJoyce.McIntosh@Sun.COM 			smb_node_inc_opening_count(node);
7668934SJose.Borrego@Sun.COM 			smb_node_wrlock(node);
7675772Sas200622 
7686139Sjb150015 			status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid,
7697348SJose.Borrego@Sun.COM 			    op->desired_access, op->share_access);
7705772Sas200622 
7715772Sas200622 			if (status == NT_STATUS_SHARING_VIOLATION) {
7728934SJose.Borrego@Sun.COM 				smb_node_unlock(node);
773*12890SJoyce.McIntosh@Sun.COM 				smb_node_dec_opening_count(node);
77410001SJoyce.McIntosh@Sun.COM 				smb_delete_new_object(sr);
7755772Sas200622 				smb_node_release(node);
7768934SJose.Borrego@Sun.COM 				smb_node_unlock(dnode);
7775772Sas200622 				smb_node_release(dnode);
7785772Sas200622 				return (status);
7795772Sas200622 			}
7805331Samw 		} else {
7817052Samw 			op->dattr |= FILE_ATTRIBUTE_DIRECTORY;
78210001SJoyce.McIntosh@Sun.COM 			new_attr.sa_dosattr = op->dattr;
7835331Samw 			new_attr.sa_vattr.va_type = VDIR;
7845331Samw 			new_attr.sa_vattr.va_mode = 0777;
78510001SJoyce.McIntosh@Sun.COM 			new_attr.sa_mask |=
78610001SJoyce.McIntosh@Sun.COM 			    SMB_AT_DOSATTR | SMB_AT_TYPE | SMB_AT_MODE;
7877348SJose.Borrego@Sun.COM 
7885331Samw 			rc = smb_fsop_mkdir(sr, sr->user_cr, dnode,
78910001SJoyce.McIntosh@Sun.COM 			    op->fqi.fq_last_comp, &new_attr, &op->fqi.fq_fnode);
7905331Samw 			if (rc != 0) {
7918934SJose.Borrego@Sun.COM 				smb_node_unlock(dnode);
7925331Samw 				smb_node_release(dnode);
7935772Sas200622 				smbsr_errno(sr, rc);
7946030Sjb150015 				return (sr->smb_error.status);
7955331Samw 			}
7965772Sas200622 
7979343SAfshin.Ardakani@Sun.COM 			node = op->fqi.fq_fnode;
798*12890SJoyce.McIntosh@Sun.COM 			smb_node_inc_opening_count(node);
7998934SJose.Borrego@Sun.COM 			smb_node_wrlock(node);
8005331Samw 		}
8015331Samw 
8029343SAfshin.Ardakani@Sun.COM 		created = B_TRUE;
8035331Samw 		op->action_taken = SMB_OACT_CREATED;
8047348SJose.Borrego@Sun.COM 	}
8057348SJose.Borrego@Sun.COM 
8067619SJose.Borrego@Sun.COM 	if (max_requested) {
8077619SJose.Borrego@Sun.COM 		smb_fsop_eaccess(sr, sr->user_cr, node, &max_allowed);
8087619SJose.Borrego@Sun.COM 		op->desired_access |= max_allowed;
8097619SJose.Borrego@Sun.COM 	}
8107619SJose.Borrego@Sun.COM 
81110001SJoyce.McIntosh@Sun.COM 	status = NT_STATUS_SUCCESS;
8127619SJose.Borrego@Sun.COM 
8137348SJose.Borrego@Sun.COM 	of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK,
8147348SJose.Borrego@Sun.COM 	    uniq_fid, &err);
81510001SJoyce.McIntosh@Sun.COM 	if (of == NULL) {
81610001SJoyce.McIntosh@Sun.COM 		smbsr_error(sr, err.status, err.errcls, err.errcode);
81710001SJoyce.McIntosh@Sun.COM 		status = err.status;
81810001SJoyce.McIntosh@Sun.COM 	}
8195331Samw 
82010001SJoyce.McIntosh@Sun.COM 	if (status == NT_STATUS_SUCCESS) {
82110001SJoyce.McIntosh@Sun.COM 		if (!smb_tree_is_connected(sr->tid_tree)) {
82210001SJoyce.McIntosh@Sun.COM 			smbsr_error(sr, 0, ERRSRV, ERRinvnid);
82310001SJoyce.McIntosh@Sun.COM 			status = NT_STATUS_UNSUCCESSFUL;
82410001SJoyce.McIntosh@Sun.COM 		}
82510001SJoyce.McIntosh@Sun.COM 	}
82610001SJoyce.McIntosh@Sun.COM 
82710001SJoyce.McIntosh@Sun.COM 	/*
82810001SJoyce.McIntosh@Sun.COM 	 * This MUST be done after ofile creation, so that explicitly
82910001SJoyce.McIntosh@Sun.COM 	 * set timestamps can be remembered on the ofile.
83010001SJoyce.McIntosh@Sun.COM 	 */
83110001SJoyce.McIntosh@Sun.COM 	if (status == NT_STATUS_SUCCESS) {
83210001SJoyce.McIntosh@Sun.COM 		if ((rc = smb_set_open_timestamps(sr, of, created)) != 0) {
83310001SJoyce.McIntosh@Sun.COM 			smbsr_errno(sr, rc);
83410001SJoyce.McIntosh@Sun.COM 			status = sr->smb_error.status;
83510001SJoyce.McIntosh@Sun.COM 		}
83610001SJoyce.McIntosh@Sun.COM 	}
83710001SJoyce.McIntosh@Sun.COM 
83810001SJoyce.McIntosh@Sun.COM 	if (status == NT_STATUS_SUCCESS) {
83910001SJoyce.McIntosh@Sun.COM 		if (smb_node_getattr(sr, node,  &op->fqi.fq_fattr) != 0) {
84010001SJoyce.McIntosh@Sun.COM 			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
84110001SJoyce.McIntosh@Sun.COM 			    ERRDOS, ERROR_INTERNAL_ERROR);
84210001SJoyce.McIntosh@Sun.COM 			status = NT_STATUS_INTERNAL_ERROR;
84310001SJoyce.McIntosh@Sun.COM 		}
84410001SJoyce.McIntosh@Sun.COM 	}
84510001SJoyce.McIntosh@Sun.COM 
84610001SJoyce.McIntosh@Sun.COM 	/*
84710001SJoyce.McIntosh@Sun.COM 	 * smb_fsop_unshrlock is a no-op if node is a directory
84810001SJoyce.McIntosh@Sun.COM 	 * smb_fsop_unshrlock is done in smb_ofile_close
84910001SJoyce.McIntosh@Sun.COM 	 */
85010001SJoyce.McIntosh@Sun.COM 	if (status != NT_STATUS_SUCCESS) {
85110001SJoyce.McIntosh@Sun.COM 		if (of == NULL) {
85210001SJoyce.McIntosh@Sun.COM 			smb_fsop_unshrlock(sr->user_cr, node, uniq_fid);
85310001SJoyce.McIntosh@Sun.COM 		} else {
85410001SJoyce.McIntosh@Sun.COM 			smb_ofile_close(of, 0);
85510001SJoyce.McIntosh@Sun.COM 			smb_ofile_release(of);
85610001SJoyce.McIntosh@Sun.COM 		}
8579231SAfshin.Ardakani@Sun.COM 		if (created)
8589231SAfshin.Ardakani@Sun.COM 			smb_delete_new_object(sr);
8598934SJose.Borrego@Sun.COM 		smb_node_unlock(node);
860*12890SJoyce.McIntosh@Sun.COM 		smb_node_dec_opening_count(node);
8615331Samw 		smb_node_release(node);
8625331Samw 		if (created)
8638934SJose.Borrego@Sun.COM 			smb_node_unlock(dnode);
8645331Samw 		smb_node_release(dnode);
86510001SJoyce.McIntosh@Sun.COM 		return (status);
8669231SAfshin.Ardakani@Sun.COM 	}
8679231SAfshin.Ardakani@Sun.COM 
8686600Sas200622 	/*
8696600Sas200622 	 * Propagate the write-through mode from the open params
8706600Sas200622 	 * to the node: see the notes in the function header.
8716600Sas200622 	 */
8726600Sas200622 	if (sr->sr_cfg->skc_sync_enable ||
8736600Sas200622 	    (op->create_options & FILE_WRITE_THROUGH))
8746600Sas200622 		node->flags |= NODE_FLAGS_WRITE_THROUGH;
8756600Sas200622 
87610001SJoyce.McIntosh@Sun.COM 	/*
87710001SJoyce.McIntosh@Sun.COM 	 * Set up the fileid and dosattr in open_param for response
87810001SJoyce.McIntosh@Sun.COM 	 */
8799343SAfshin.Ardakani@Sun.COM 	op->fileid = op->fqi.fq_fattr.sa_vattr.va_nodeid;
88010001SJoyce.McIntosh@Sun.COM 	op->dattr = op->fqi.fq_fattr.sa_dosattr;
8816600Sas200622 
8825331Samw 	/*
8835331Samw 	 * Set up the file type in open_param for the response
8845331Samw 	 */
8855331Samw 	op->ftype = SMB_FTYPE_DISK;
8865331Samw 	sr->smb_fid = of->f_fid;
8875331Samw 	sr->fid_ofile = of;
8885331Samw 
88911963SAfshin.Ardakani@Sun.COM 	if (smb_node_is_file(node)) {
890*12890SJoyce.McIntosh@Sun.COM 		smb_oplock_acquire(sr, node, of);
8919343SAfshin.Ardakani@Sun.COM 		op->dsize = op->fqi.fq_fattr.sa_vattr.va_size;
89211963SAfshin.Ardakani@Sun.COM 	} else {
89311963SAfshin.Ardakani@Sun.COM 		/* directory or symlink */
8948934SJose.Borrego@Sun.COM 		op->op_oplock_level = SMB_OPLOCK_NONE;
8958934SJose.Borrego@Sun.COM 		op->dsize = 0;
8968934SJose.Borrego@Sun.COM 	}
8975772Sas200622 
898*12890SJoyce.McIntosh@Sun.COM 	smb_node_dec_opening_count(node);
899*12890SJoyce.McIntosh@Sun.COM 
900*12890SJoyce.McIntosh@Sun.COM 	smb_node_unlock(node);
901*12890SJoyce.McIntosh@Sun.COM 	if (created)
902*12890SJoyce.McIntosh@Sun.COM 		smb_node_unlock(dnode);
903*12890SJoyce.McIntosh@Sun.COM 
9049231SAfshin.Ardakani@Sun.COM 	smb_node_release(node);
9055331Samw 	smb_node_release(dnode);
9065331Samw 
9075331Samw 	return (NT_STATUS_SUCCESS);
9085331Samw }
9095331Samw 
9105331Samw /*
911*12890SJoyce.McIntosh@Sun.COM  * smb_open_oplock_break
912*12890SJoyce.McIntosh@Sun.COM  *
913*12890SJoyce.McIntosh@Sun.COM  * If the node has an ofile opened with share access none,
914*12890SJoyce.McIntosh@Sun.COM  * (smb_node_share_check = FALSE) only break BATCH oplock.
915*12890SJoyce.McIntosh@Sun.COM  * Otherwise:
916*12890SJoyce.McIntosh@Sun.COM  * If overwriting, break to SMB_OPLOCK_NONE, else
917*12890SJoyce.McIntosh@Sun.COM  * If opening for anything other than attribute access,
918*12890SJoyce.McIntosh@Sun.COM  * break oplock to LEVEL_II.
919*12890SJoyce.McIntosh@Sun.COM  */
920*12890SJoyce.McIntosh@Sun.COM static void
smb_open_oplock_break(smb_request_t * sr,smb_node_t * node)921*12890SJoyce.McIntosh@Sun.COM smb_open_oplock_break(smb_request_t *sr, smb_node_t *node)
922*12890SJoyce.McIntosh@Sun.COM {
923*12890SJoyce.McIntosh@Sun.COM 	smb_arg_open_t	*op = &sr->sr_open;
924*12890SJoyce.McIntosh@Sun.COM 	uint32_t	flags = 0;
925*12890SJoyce.McIntosh@Sun.COM 
926*12890SJoyce.McIntosh@Sun.COM 	if (!smb_node_share_check(node))
927*12890SJoyce.McIntosh@Sun.COM 		flags |= SMB_OPLOCK_BREAK_BATCH;
928*12890SJoyce.McIntosh@Sun.COM 
929*12890SJoyce.McIntosh@Sun.COM 	if (smb_open_overwrite(op)) {
930*12890SJoyce.McIntosh@Sun.COM 		flags |= SMB_OPLOCK_BREAK_TO_NONE;
931*12890SJoyce.McIntosh@Sun.COM 		(void) smb_oplock_break(sr, node, flags);
932*12890SJoyce.McIntosh@Sun.COM 	} else if (!smb_open_attr_only(op)) {
933*12890SJoyce.McIntosh@Sun.COM 		flags |= SMB_OPLOCK_BREAK_TO_LEVEL_II;
934*12890SJoyce.McIntosh@Sun.COM 		(void) smb_oplock_break(sr, node, flags);
935*12890SJoyce.McIntosh@Sun.COM 	}
936*12890SJoyce.McIntosh@Sun.COM }
937*12890SJoyce.McIntosh@Sun.COM 
938*12890SJoyce.McIntosh@Sun.COM /*
939*12890SJoyce.McIntosh@Sun.COM  * smb_open_attr_only
940*12890SJoyce.McIntosh@Sun.COM  *
941*12890SJoyce.McIntosh@Sun.COM  * Determine if file is being opened for attribute access only.
942*12890SJoyce.McIntosh@Sun.COM  * This is used to determine whether it is necessary to break
943*12890SJoyce.McIntosh@Sun.COM  * existing oplocks on the file.
944*12890SJoyce.McIntosh@Sun.COM  */
945*12890SJoyce.McIntosh@Sun.COM static boolean_t
smb_open_attr_only(smb_arg_open_t * op)946*12890SJoyce.McIntosh@Sun.COM smb_open_attr_only(smb_arg_open_t *op)
947*12890SJoyce.McIntosh@Sun.COM {
948*12890SJoyce.McIntosh@Sun.COM 	if (((op->desired_access & ~(FILE_READ_ATTRIBUTES |
949*12890SJoyce.McIntosh@Sun.COM 	    FILE_WRITE_ATTRIBUTES | SYNCHRONIZE)) == 0) &&
950*12890SJoyce.McIntosh@Sun.COM 	    (op->create_disposition != FILE_SUPERSEDE) &&
951*12890SJoyce.McIntosh@Sun.COM 	    (op->create_disposition != FILE_OVERWRITE)) {
952*12890SJoyce.McIntosh@Sun.COM 		return (B_TRUE);
953*12890SJoyce.McIntosh@Sun.COM 	}
954*12890SJoyce.McIntosh@Sun.COM 	return (B_FALSE);
955*12890SJoyce.McIntosh@Sun.COM }
956*12890SJoyce.McIntosh@Sun.COM 
957*12890SJoyce.McIntosh@Sun.COM static boolean_t
smb_open_overwrite(smb_arg_open_t * op)958*12890SJoyce.McIntosh@Sun.COM smb_open_overwrite(smb_arg_open_t *op)
959*12890SJoyce.McIntosh@Sun.COM {
960*12890SJoyce.McIntosh@Sun.COM 	if ((op->create_disposition == FILE_SUPERSEDE) ||
961*12890SJoyce.McIntosh@Sun.COM 	    (op->create_disposition == FILE_OVERWRITE_IF) ||
962*12890SJoyce.McIntosh@Sun.COM 	    (op->create_disposition == FILE_OVERWRITE)) {
963*12890SJoyce.McIntosh@Sun.COM 		return (B_TRUE);
964*12890SJoyce.McIntosh@Sun.COM 	}
965*12890SJoyce.McIntosh@Sun.COM 	return (B_FALSE);
966*12890SJoyce.McIntosh@Sun.COM }
967*12890SJoyce.McIntosh@Sun.COM /*
96810001SJoyce.McIntosh@Sun.COM  * smb_set_open_timestamps
96910001SJoyce.McIntosh@Sun.COM  *
97010001SJoyce.McIntosh@Sun.COM  * Last write time:
97110001SJoyce.McIntosh@Sun.COM  * - If the last_write time specified in the open params is not 0 or -1,
97210001SJoyce.McIntosh@Sun.COM  *   use it as file's mtime. This will be considered an explicitly set
97310001SJoyce.McIntosh@Sun.COM  *   timestamps, not reset by subsequent writes.
97410001SJoyce.McIntosh@Sun.COM  *
97510001SJoyce.McIntosh@Sun.COM  * Opening existing file (not directory):
97610001SJoyce.McIntosh@Sun.COM  * - If opening an existing file for overwrite set initial ATIME, MTIME
97710001SJoyce.McIntosh@Sun.COM  *   & CTIME to now. (This is achieved by setting them as pending then forcing
97810001SJoyce.McIntosh@Sun.COM  *   an smb_node_setattr() to apply pending times.)
97910001SJoyce.McIntosh@Sun.COM  *
98010001SJoyce.McIntosh@Sun.COM  * - Note  If opening an existing file NOT for overwrite, windows would
98110001SJoyce.McIntosh@Sun.COM  *   set the atime on file close, however setting the atime would cause
98210001SJoyce.McIntosh@Sun.COM  *   the ARCHIVE attribute to be set, which does not occur on windows,
98310001SJoyce.McIntosh@Sun.COM  *   so we do not do the atime update.
98410001SJoyce.McIntosh@Sun.COM  *
98510001SJoyce.McIntosh@Sun.COM  * Returns: errno
98610001SJoyce.McIntosh@Sun.COM  */
98710001SJoyce.McIntosh@Sun.COM static int
smb_set_open_timestamps(smb_request_t * sr,smb_ofile_t * of,boolean_t created)98810001SJoyce.McIntosh@Sun.COM smb_set_open_timestamps(smb_request_t *sr, smb_ofile_t *of, boolean_t created)
98910001SJoyce.McIntosh@Sun.COM {
99010001SJoyce.McIntosh@Sun.COM 	int		rc = 0;
99112508Samw@Sun.COM 	smb_arg_open_t	*op = &sr->sr_open;
99210001SJoyce.McIntosh@Sun.COM 	smb_node_t	*node = of->f_node;
99310001SJoyce.McIntosh@Sun.COM 	boolean_t	existing_file, set_times;
99410001SJoyce.McIntosh@Sun.COM 	smb_attr_t	attr;
99510001SJoyce.McIntosh@Sun.COM 
99610001SJoyce.McIntosh@Sun.COM 	bzero(&attr, sizeof (smb_attr_t));
99710001SJoyce.McIntosh@Sun.COM 	set_times = B_FALSE;
99810001SJoyce.McIntosh@Sun.COM 
99910001SJoyce.McIntosh@Sun.COM 	if ((op->mtime.tv_sec != 0) && (op->mtime.tv_sec != UINT_MAX)) {
100010001SJoyce.McIntosh@Sun.COM 		attr.sa_mask = SMB_AT_MTIME;
100110001SJoyce.McIntosh@Sun.COM 		attr.sa_vattr.va_mtime = op->mtime;
100210001SJoyce.McIntosh@Sun.COM 		set_times = B_TRUE;
100310001SJoyce.McIntosh@Sun.COM 	}
100410001SJoyce.McIntosh@Sun.COM 
100510001SJoyce.McIntosh@Sun.COM 	existing_file = !(created || smb_node_is_dir(node));
100610001SJoyce.McIntosh@Sun.COM 	if (existing_file) {
100710001SJoyce.McIntosh@Sun.COM 		switch (op->create_disposition) {
100810001SJoyce.McIntosh@Sun.COM 		case FILE_SUPERSEDE:
100910001SJoyce.McIntosh@Sun.COM 		case FILE_OVERWRITE_IF:
101010001SJoyce.McIntosh@Sun.COM 		case FILE_OVERWRITE:
101110001SJoyce.McIntosh@Sun.COM 			smb_ofile_set_write_time_pending(of);
101210001SJoyce.McIntosh@Sun.COM 			set_times = B_TRUE;
101310001SJoyce.McIntosh@Sun.COM 			break;
101410001SJoyce.McIntosh@Sun.COM 		default:
101510001SJoyce.McIntosh@Sun.COM 			break;
101610001SJoyce.McIntosh@Sun.COM 		}
101710001SJoyce.McIntosh@Sun.COM 	}
101810001SJoyce.McIntosh@Sun.COM 
101910001SJoyce.McIntosh@Sun.COM 	if (set_times)
102010001SJoyce.McIntosh@Sun.COM 		rc = smb_node_setattr(sr, node, sr->user_cr, of, &attr);
102110001SJoyce.McIntosh@Sun.COM 
102210001SJoyce.McIntosh@Sun.COM 	return (rc);
102310001SJoyce.McIntosh@Sun.COM }
102410001SJoyce.McIntosh@Sun.COM 
102510001SJoyce.McIntosh@Sun.COM /*
10269231SAfshin.Ardakani@Sun.COM  * This function is used to delete a newly created object (file or
10279231SAfshin.Ardakani@Sun.COM  * directory) if an error occurs after creation of the object.
10285331Samw  */
10299231SAfshin.Ardakani@Sun.COM static void
smb_delete_new_object(smb_request_t * sr)10309231SAfshin.Ardakani@Sun.COM smb_delete_new_object(smb_request_t *sr)
10315331Samw {
103212508Samw@Sun.COM 	smb_arg_open_t	*op = &sr->sr_open;
10339231SAfshin.Ardakani@Sun.COM 	smb_fqi_t	*fqi = &(op->fqi);
10349231SAfshin.Ardakani@Sun.COM 	uint32_t	flags = 0;
10359231SAfshin.Ardakani@Sun.COM 
10369231SAfshin.Ardakani@Sun.COM 	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
10379231SAfshin.Ardakani@Sun.COM 		flags |= SMB_IGNORE_CASE;
10389231SAfshin.Ardakani@Sun.COM 	if (SMB_TREE_SUPPORTS_CATIA(sr))
10399231SAfshin.Ardakani@Sun.COM 		flags |= SMB_CATIA;
10409231SAfshin.Ardakani@Sun.COM 
10419231SAfshin.Ardakani@Sun.COM 	if (op->create_options & FILE_DIRECTORY_FILE)
10429343SAfshin.Ardakani@Sun.COM 		(void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
10439343SAfshin.Ardakani@Sun.COM 		    fqi->fq_last_comp, flags);
10449231SAfshin.Ardakani@Sun.COM 	else
10459343SAfshin.Ardakani@Sun.COM 		(void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode,
10469343SAfshin.Ardakani@Sun.COM 		    fqi->fq_last_comp, flags);
10475331Samw }
1048