1da6c28aamw/*
2da6c28aamw * CDDL HEADER START
3da6c28aamw *
4da6c28aamw * The contents of this file are subject to the terms of the
5da6c28aamw * Common Development and Distribution License (the "License").
6da6c28aamw * You may not use this file except in compliance with the License.
7da6c28aamw *
8da6c28aamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aamw * or http://www.opensolaris.org/os/licensing.
10da6c28aamw * See the License for the specific language governing permissions
11da6c28aamw * and limitations under the License.
12da6c28aamw *
13da6c28aamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aamw *
19da6c28aamw * CDDL HEADER END
20da6c28aamw */
21da6c28aamw/*
22148c5f4Alan Wright * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
231bc6aeeMatt Barden * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
24da6c28aamw */
25da6c28aamw
26bbf6f00Jordan Brown#include <smbsrv/smb_kproto.h>
27da6c28aamw#include <smbsrv/smb_fsops.h>
28da6c28aamw#include <sys/pathname.h>
29da6c28aamw#include <sys/sdt.h>
30da6c28aamw
318b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic char *smb_pathname_catia_v5tov4(smb_request_t *, char *, char *, int);
328b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic char *smb_pathname_catia_v4tov5(smb_request_t *, char *, char *, int);
338b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic int smb_pathname_lookup(pathname_t *, pathname_t *, int,
349fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States    vnode_t **, vnode_t *, vnode_t *, smb_attr_t *attr, cred_t *);
35fe1c642Bill Krierstatic char *smb_pathname_strdup(smb_request_t *, const char *);
36fe1c642Bill Krierstatic char *smb_pathname_strcat(smb_request_t *, char *, const char *);
37fe1c642Bill Krierstatic void smb_pathname_preprocess(smb_request_t *, smb_pathname_t *);
389fb67eaafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic void smb_pathname_preprocess_quota(smb_request_t *, smb_pathname_t *);
399fb67eaafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic int smb_pathname_dfs_preprocess(smb_request_t *, char *, size_t);
409fb67eaafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic void smb_pathname_preprocess_adminshare(smb_request_t *,
419fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States    smb_pathname_t *);
429fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States
438b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
44da6c28aamwuint32_t
45da6c28aamwsmb_is_executable(char *path)
46da6c28aamw{
47da6c28aamw	char	extension[5];
48da6c28aamw	int	len = strlen(path);
49da6c28aamw
50da6c28aamw	if ((len >= 4) && (path[len - 4] == '.')) {
51da6c28aamw		(void) strcpy(extension, &path[len - 3]);
52bbf6f00Jordan Brown		(void) smb_strupr(extension);
53da6c28aamw
54da6c28aamw		if (strcmp(extension, "EXE") == 0)
55da6c28aamw			return (NODE_FLAGS_EXECUTABLE);
56da6c28aamw
57da6c28aamw		if (strcmp(extension, "COM") == 0)
58da6c28aamw			return (NODE_FLAGS_EXECUTABLE);
59da6c28aamw
60da6c28aamw		if (strcmp(extension, "DLL") == 0)
61da6c28aamw			return (NODE_FLAGS_EXECUTABLE);
62da6c28aamw
63da6c28aamw		if (strcmp(extension, "SYM") == 0)
64da6c28aamw			return (NODE_FLAGS_EXECUTABLE);
65da6c28aamw	}
66da6c28aamw
67da6c28aamw	return (0);
68da6c28aamw}
69da6c28aamw
70da6c28aamw/*
71da6c28aamw * smb_pathname_reduce
72da6c28aamw *
73da6c28aamw * smb_pathname_reduce() takes a path and returns the smb_node for the
74da6c28aamw * second-to-last component of the path.  It also returns the name of the last
75da6c28aamw * component.  Pointers for both of these fields must be supplied by the caller.
76da6c28aamw *
77da6c28aamw * Upon success, 0 is returned.
78da6c28aamw *
79da6c28aamw * Upon error, *dir_node will be set to 0.
80da6c28aamw *
81da6c28aamw * *sr (in)
82da6c28aamw * ---
83da6c28aamw * smb_request structure pointer
84da6c28aamw *
85da6c28aamw * *cred (in)
86da6c28aamw * -----
87da6c28aamw * credential
88da6c28aamw *
89da6c28aamw * *path (in)
90da6c28aamw * -----
91da6c28aamw * pathname to be looked up
92da6c28aamw *
93da6c28aamw * *share_root_node (in)
94da6c28aamw * ----------------
95da6c28aamw * File operations which are share-relative should pass sr->tid_tree->t_snode.
96da6c28aamw * If the call is not for a share-relative operation, this parameter must be 0
97da6c28aamw * (e.g. the call from smbsr_setup_share()).  (Such callers will have path
98da6c28aamw * operations done using root_smb_node.)  This parameter is used to determine
99da6c28aamw * whether mount points can be crossed.
100da6c28aamw *
101da6c28aamw * share_root_node should have at least one reference on it.  This reference
102da6c28aamw * will stay intact throughout this routine.
103da6c28aamw *
104da6c28aamw * *cur_node (in)
105da6c28aamw * ---------
106da6c28aamw * The smb_node for the current directory (for relative paths).
107da6c28aamw * cur_node should have at least one reference on it.
108da6c28aamw * This reference will stay intact throughout this routine.
109da6c28aamw *
110da6c28aamw * **dir_node (out)
111da6c28aamw * ----------
112da6c28aamw * Directory for the penultimate component of the original path.
113da6c28aamw * (Note that this is not the same as the parent directory of the ultimate
114da6c28aamw * target in the case of a link.)
115da6c28aamw *
116da6c28aamw * The directory smb_node is returned held.  The caller will need to release
117da6c28aamw * the hold or otherwise make sure it will get released (e.g. in a destroy
118da6c28aamw * routine if made part of a global structure).
119da6c28aamw *
120da6c28aamw * last_component (out)
121da6c28aamw * --------------
122da6c28aamw * The last component of the path.  (This may be different from the name of any
123da6c28aamw * link target to which the last component may resolve.)
124da6c28aamw *
125da6c28aamw *
126da6c28aamw * ____________________________
127da6c28aamw *
128da6c28aamw * The CIFS server lookup path needs to have logic equivalent to that of
129da6c28aamw * smb_fsop_lookup(), smb_vop_lookup() and other smb_vop_*() routines in the
130da6c28aamw * following areas:
131da6c28aamw *
1325f1ef25Aram Hăvărneanu *	- traversal of child mounts (handled by smb_pathname_reduce)
1335f1ef25Aram Hăvărneanu *	- unmangling                (handled in smb_pathname)
1345f1ef25Aram Hăvărneanu *	- "chroot" behavior of share root (handled by lookuppnvp)
135da6c28aamw *
136da6c28aamw * In addition, it needs to replace backslashes with forward slashes.  It also
137da6c28aamw * ensures that link processing is done correctly, and that directory
138da6c28aamw * information requested by the caller is correctly returned (i.e. for paths
139da6c28aamw * with a link in the last component, the directory information of the
140da6c28aamw * link and not the target needs to be returned).
141da6c28aamw */
142da6c28aamw
143da6c28aamwint
144da6c28aamwsmb_pathname_reduce(
145da6c28aamw    smb_request_t	*sr,
146da6c28aamw    cred_t		*cred,
147da6c28aamw    const char		*path,
148da6c28aamw    smb_node_t		*share_root_node,
149da6c28aamw    smb_node_t		*cur_node,
150da6c28aamw    smb_node_t		**dir_node,
151da6c28aamw    char		*last_component)
152da6c28aamw{
153da6c28aamw	smb_node_t	*root_node;
1541bc6aeeMatt Barden	pathname_t	ppn, mnt_pn;
155da6c28aamw	char		*usepath;
156da6c28aamw	int		lookup_flags = FOLLOW;
1578d94f65Gordon Ross	int		trailing_slash = 0;
158da6c28aamw	int		err = 0;
159da6c28aamw	int		len;
1601bc6aeeMatt Barden	smb_node_t	*vss_node;
16189dc44cjose borrego	smb_node_t	*local_cur_node;
16289dc44cjose borrego	smb_node_t	*local_root_node;
1631bc6aeeMatt Barden	boolean_t	chk_vss;
1641bc6aeeMatt Barden	char		*gmttoken;
165da6c28aamw
166da6c28aamw	ASSERT(dir_node);
167da6c28aamw	ASSERT(last_component);
168da6c28aamw
169da6c28aamw	*dir_node = NULL;
170da6c28aamw	*last_component = '\0';
1711bc6aeeMatt Barden	vss_node = NULL;
1721bc6aeeMatt Barden	gmttoken = NULL;
1731bc6aeeMatt Barden	chk_vss = B_FALSE;
174da6c28aamw
1757b59d02jb	if (sr && sr->tid_tree) {
176f96bd5cAlan Wright		if (STYPE_ISIPC(sr->tid_tree->t_res_type))
1777b59d02jb			return (EACCES);
1787b59d02jb	}
1797b59d02jb
180c8ec8eejose borrego	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
181da6c28aamw		lookup_flags |= FIGNORECASE;
182da6c28aamw
183da6c28aamw	if (path == NULL)
184da6c28aamw		return (EINVAL);
185da6c28aamw
186da6c28aamw	if (*path == '\0')
187da6c28aamw		return (ENOENT);
188da6c28aamw
189b24e356Peer Dampmann	usepath = kmem_alloc(SMB_MAXPATHLEN, KM_SLEEP);
190da6c28aamw
191b24e356Peer Dampmann	len = strlcpy(usepath, path, SMB_MAXPATHLEN);
192b24e356Peer Dampmann	if (len >= SMB_MAXPATHLEN) {
193b24e356Peer Dampmann		kmem_free(usepath, SMB_MAXPATHLEN);
194da6c28aamw		return (ENAMETOOLONG);
195da6c28aamw	}
196da6c28aamw
197da6c28aamw	(void) strsubst(usepath, '\\', '/');
198da6c28aamw
199da6c28aamw	if (share_root_node)
200da6c28aamw		root_node = share_root_node;
201da6c28aamw	else
202faa1795jb		root_node = sr->sr_server->si_root_smb_node;
203da6c28aamw
204da6c28aamw	if (cur_node == NULL)
205da6c28aamw		cur_node = root_node;
206da6c28aamw
20789dc44cjose borrego	local_cur_node = cur_node;
20889dc44cjose borrego	local_root_node = root_node;
20989dc44cjose borrego
210a90cf9fGordon Ross	if (SMB_TREE_IS_DFSROOT(sr)) {
211a90cf9fGordon Ross		int is_dfs;
212a90cf9fGordon Ross		if (sr->session->dialect >= SMB_VERS_2_BASE)
213a90cf9fGordon Ross			is_dfs = sr->smb2_hdr_flags &
214a90cf9fGordon Ross			    SMB2_FLAGS_DFS_OPERATIONS;
215a90cf9fGordon Ross		else
216a90cf9fGordon Ross			is_dfs = sr->smb_flg2 & SMB_FLAGS2_DFS;
217a90cf9fGordon Ross		if (is_dfs != 0) {
218a90cf9fGordon Ross			err = smb_pathname_dfs_preprocess(sr, usepath,
219a90cf9fGordon Ross			    SMB_MAXPATHLEN);
220a90cf9fGordon Ross			if (err != 0) {
221a90cf9fGordon Ross				kmem_free(usepath, SMB_MAXPATHLEN);
222a90cf9fGordon Ross				return (err);
223a90cf9fGordon Ross			}
224a90cf9fGordon Ross			len = strlen(usepath);
2259fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		}
2269fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States	}
2279fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States
228a90cf9fGordon Ross	if (sr != NULL) {
2291bc6aeeMatt Barden		if (sr->session->dialect >= SMB_VERS_2_BASE) {
230a90cf9fGordon Ross			chk_vss = sr->arg.open.create_timewarp;
2311bc6aeeMatt Barden		} else {
232a90cf9fGordon Ross			chk_vss = (sr->smb_flg2 &
233a90cf9fGordon Ross			    SMB_FLAGS2_REPARSE_PATH) != 0;
23489dc44cjose borrego
2351bc6aeeMatt Barden			if (chk_vss) {
2361bc6aeeMatt Barden				gmttoken = kmem_alloc(SMB_VSS_GMT_SIZE,
2371bc6aeeMatt Barden				    KM_SLEEP);
2381bc6aeeMatt Barden				err = smb_vss_extract_gmttoken(usepath,
2391bc6aeeMatt Barden				    gmttoken);
2401bc6aeeMatt Barden				if (err != 0) {
2411bc6aeeMatt Barden					kmem_free(usepath, SMB_MAXPATHLEN);
2421bc6aeeMatt Barden					kmem_free(gmttoken, SMB_VSS_GMT_SIZE);
2431bc6aeeMatt Barden					return (err);
2441bc6aeeMatt Barden				}
2451bc6aeeMatt Barden				len = strlen(usepath);
2461bc6aeeMatt Barden			}
24789dc44cjose borrego		}
2481bc6aeeMatt Barden		if (chk_vss)
2491bc6aeeMatt Barden			(void) pn_alloc(&mnt_pn);
25089dc44cjose borrego	}
25189dc44cjose borrego
25289dc44cjose borrego	if (usepath[len - 1] == '/')
25389dc44cjose borrego		trailing_slash = 1;
25489dc44cjose borrego
25589dc44cjose borrego	(void) strcanon(usepath, "/");
25689dc44cjose borrego
257b24e356Peer Dampmann	(void) pn_alloc_sz(&ppn, SMB_MAXPATHLEN);
258da6c28aamw
259da6c28aamw	if ((err = pn_set(&ppn, usepath)) != 0) {
260da6c28aamw		(void) pn_free(&ppn);
261b24e356Peer Dampmann		kmem_free(usepath, SMB_MAXPATHLEN);
2621bc6aeeMatt Barden		if (chk_vss)
2631bc6aeeMatt Barden			(void) pn_free(&mnt_pn);
2641bc6aeeMatt Barden		if (gmttoken != NULL)
2651bc6aeeMatt Barden			kmem_free(gmttoken, SMB_VSS_GMT_SIZE);
266da6c28aamw		return (err);
267da6c28aamw	}
268da6c28aamw
269da6c28aamw	/*
270da6c28aamw	 * If a path does not have a trailing slash, strip off the
271da6c28aamw	 * last component.  (We only need to return an smb_node for
272da6c28aamw	 * the second to last component; a name is returned for the
273da6c28aamw	 * last component.)
2741bc6aeeMatt Barden	 *
2751bc6aeeMatt Barden	 * For VSS requests, the last component might be a filesystem of its
2761bc6aeeMatt Barden	 * own, and we need to discover that before exiting this function,
2771bc6aeeMatt Barden	 * so allow the lookup to happen on the last component.
2781bc6aeeMatt Barden	 * We'll correct this later when we convert to the snapshot.
279da6c28aamw	 */
280da6c28aamw
2811bc6aeeMatt Barden	if (!chk_vss) {
2821bc6aeeMatt Barden		if (trailing_slash) {
2831bc6aeeMatt Barden			(void) strlcpy(last_component, ".", MAXNAMELEN);
2841bc6aeeMatt Barden		} else {
2851bc6aeeMatt Barden			(void) pn_setlast(&ppn);
2861bc6aeeMatt Barden			(void) strlcpy(last_component, ppn.pn_path, MAXNAMELEN);
2871bc6aeeMatt Barden			ppn.pn_path[0] = '\0';
2881bc6aeeMatt Barden		}
289da6c28aamw	}
290da6c28aamw
291fc72463Alan Wright	if ((strcmp(ppn.pn_buf, "/") == 0) || (ppn.pn_buf[0] == '\0')) {
29289dc44cjose borrego		smb_node_ref(local_cur_node);
29389dc44cjose borrego		*dir_node = local_cur_node;
294da6c28aamw	} else {
29589dc44cjose borrego		err = smb_pathname(sr, ppn.pn_buf, lookup_flags,
2961bc6aeeMatt Barden		    local_root_node, local_cur_node, NULL, dir_node, cred,
2971bc6aeeMatt Barden		    chk_vss ? &mnt_pn : NULL);
298da6c28aamw	}
299da6c28aamw
300da6c28aamw	(void) pn_free(&ppn);
301b24e356Peer Dampmann	kmem_free(usepath, SMB_MAXPATHLEN);
302da6c28aamw
303da6c28aamw	/*
3041bc6aeeMatt Barden	 * We need to try and convert to snapshots, even on error.
3051bc6aeeMatt Barden	 * This is to handle the following cases:
3061bc6aeeMatt Barden	 * - We're on the lowest level filesystem, but a directory got renamed
3071bc6aeeMatt Barden	 *   on the live version. We'll get ENOENT, but can still find it in
3081bc6aeeMatt Barden	 *   the snapshot.
3091bc6aeeMatt Barden	 * - The last component was actually a file. We need to leave the last
3101bc6aeeMatt Barden	 *   component in in case it is, itself, a mountpoint, but that means
3111bc6aeeMatt Barden	 *   we might get ENOTDIR if it's not actually a directory.
3121bc6aeeMatt Barden	 *
3131bc6aeeMatt Barden	 * Note that if you change the share-relative name of a mountpoint,
3141bc6aeeMatt Barden	 * you won't be able to access previous versions of files under it.
3151bc6aeeMatt Barden	 */
3161bc6aeeMatt Barden	if (chk_vss && *dir_node != NULL) {
3171bc6aeeMatt Barden		if ((err = smb_vss_lookup_nodes(sr, *dir_node, &vss_node,
3181bc6aeeMatt Barden		    gmttoken)) == 0) {
3191bc6aeeMatt Barden			char *p = mnt_pn.pn_path;
3201bc6aeeMatt Barden			size_t pathleft;
3211bc6aeeMatt Barden
3221bc6aeeMatt Barden			smb_node_release(*dir_node);
3231bc6aeeMatt Barden			*dir_node = NULL;
3241bc6aeeMatt Barden			pathleft = pn_pathleft(&mnt_pn);
3251bc6aeeMatt Barden
3261bc6aeeMatt Barden			if (pathleft == 0 || trailing_slash) {
3271bc6aeeMatt Barden				(void) strlcpy(last_component, ".", MAXNAMELEN);
3281bc6aeeMatt Barden			} else {
3291bc6aeeMatt Barden				(void) pn_setlast(&mnt_pn);
3301bc6aeeMatt Barden				(void) strlcpy(last_component, mnt_pn.pn_path,
3311bc6aeeMatt Barden				    MAXNAMELEN);
3321bc6aeeMatt Barden				mnt_pn.pn_path[0] = '\0';
3331bc6aeeMatt Barden				pathleft -= strlen(last_component);
3341bc6aeeMatt Barden			}
3351bc6aeeMatt Barden
3361bc6aeeMatt Barden			if (pathleft != 0) {
3371bc6aeeMatt Barden				err = smb_pathname(sr, p, lookup_flags,
3381bc6aeeMatt Barden				    vss_node, vss_node, NULL, dir_node, cred,
3391bc6aeeMatt Barden				    NULL);
3401bc6aeeMatt Barden			} else {
3411bc6aeeMatt Barden				*dir_node = vss_node;
3421bc6aeeMatt Barden				vss_node = NULL;
3431bc6aeeMatt Barden			}
3441bc6aeeMatt Barden		}
3451bc6aeeMatt Barden	}
3461bc6aeeMatt Barden
3471bc6aeeMatt Barden	if (chk_vss)
3481bc6aeeMatt Barden		(void) pn_free(&mnt_pn);
3491bc6aeeMatt Barden	if (gmttoken != NULL)
3501bc6aeeMatt Barden		kmem_free(gmttoken, SMB_VSS_GMT_SIZE);
3511bc6aeeMatt Barden
3521bc6aeeMatt Barden	/*
3535f1ef25Aram Hăvărneanu	 * Prevent traversal to another file system if mount point
3545f1ef25Aram Hăvărneanu	 * traversal is disabled.
355da6c28aamw	 *
356da6c28aamw	 * Note that we disregard whether the traversal of the path went
357da6c28aamw	 * outside of the file system and then came back (say via a link).
3585f1ef25Aram Hăvărneanu	 * This means that only symlinks that are expressed relatively to
3595f1ef25Aram Hăvărneanu	 * the share root work.
3605f1ef25Aram Hăvărneanu	 *
3615f1ef25Aram Hăvărneanu	 * share_root_node is NULL when mapping a share, so we disregard
3625f1ef25Aram Hăvărneanu	 * that case.
363da6c28aamw	 */
364da6c28aamw
365da6c28aamw	if ((err == 0) && share_root_node) {
3665f1ef25Aram Hăvărneanu		if (share_root_node->vp->v_vfsp != (*dir_node)->vp->v_vfsp) {
367da6c28aamw			err = EACCES;
3685f1ef25Aram Hăvărneanu			if ((sr) && (sr)->tid_tree &&
3695f1ef25Aram Hăvărneanu			    smb_tree_has_feature((sr)->tid_tree,
3705f1ef25Aram Hăvărneanu			    SMB_TREE_TRAVERSE_MOUNTS))
3715f1ef25Aram Hăvărneanu				err = 0;
3725f1ef25Aram Hăvărneanu		}
373da6c28aamw	}
374da6c28aamw
375da6c28aamw	if (err) {
376da6c28aamw		if (*dir_node) {
377da6c28aamw			(void) smb_node_release(*dir_node);
378da6c28aamw			*dir_node = NULL;
379da6c28aamw		}
380da6c28aamw		*last_component = 0;
381da6c28aamw	}
382da6c28aamw
3831bc6aeeMatt Barden	if (vss_node != NULL)
3841bc6aeeMatt Barden		(void) smb_node_release(vss_node);
385da6c28aamw	return (err);
386da6c28aamw}
387da6c28aamw
388da6c28aamw/*
3898b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * smb_pathname()
3908b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * wrapper to lookuppnvp().  Handles name unmangling.
391da6c28aamw *
392da6c28aamw * *dir_node is the true directory of the target *node.
393da6c28aamw *
394da6c28aamw * If any component but the last in the path is not found, ENOTDIR instead of
395da6c28aamw * ENOENT will be returned.
396da6c28aamw *
397da6c28aamw * Path components are processed one at a time so that smb_nodes can be
3981fcced4Jordan Brown * created for each component.  This allows the n_dnode field in the
399da6c28aamw * smb_node to be properly populated.
400da6c28aamw *
4018b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * Because of the above, links are also processed in this routine
4028b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * (i.e., we do not pass the FOLLOW flag to lookuppnvp()).  This
4038b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * will allow smb_nodes to be created for each component of a link.
4048b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States *
4058b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * Mangle checking is per component. If a name is mangled, when the
4068b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * unmangled name is passed to smb_pathname_lookup() do not pass
4078b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * FIGNORECASE, since the unmangled name is the real on-disk name.
4088b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * Otherwise pass FIGNORECASE if it's set in flags. This will cause the
4098b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * file system to return "first match" in the event of a case collision.
4108b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States *
4118b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * If CATIA character translation is enabled it is applied to each
4128b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * component before passing the component to smb_pathname_lookup().
4138b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * After smb_pathname_lookup() the reverse translation is applied.
414da6c28aamw */
415da6c28aamw
416da6c28aamwint
4178b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statessmb_pathname(smb_request_t *sr, char *path, int flags,
4188b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States    smb_node_t *root_node, smb_node_t *cur_node, smb_node_t **dir_node,
4191bc6aeeMatt Barden    smb_node_t **ret_node, cred_t *cred, pathname_t *mnt_pn)
420da6c28aamw{
4218b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	char		*component, *real_name, *namep;
4228b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	pathname_t	pn, rpn, upn, link_pn;
4231bc6aeeMatt Barden	smb_node_t	*dnode, *fnode, *mnt_node;
4249fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States	smb_attr_t	attr;
4258b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	vnode_t		*rootvp, *vp;
426da6c28aamw	size_t		pathleft;
427da6c28aamw	int		err = 0;
428da6c28aamw	int		nlink = 0;
429da6c28aamw	int		local_flags;
430e3f2c99Keyur Desai	uint32_t	abe_flag = 0;
4318b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	char		namebuf[MAXNAMELEN];
4321bc6aeeMatt Barden	vnode_t *fsrootvp = NULL;
433da6c28aamw
434da6c28aamw	if (path == NULL)
435da6c28aamw		return (EINVAL);
436da6c28aamw
437da6c28aamw	ASSERT(root_node);
438da6c28aamw	ASSERT(cur_node);
439da6c28aamw	ASSERT(ret_node);
440da6c28aamw
441da6c28aamw	*ret_node = NULL;
442da6c28aamw
443da6c28aamw	if (dir_node)
444da6c28aamw		*dir_node = NULL;
445da6c28aamw
446b24e356Peer Dampmann	(void) pn_alloc_sz(&upn, SMB_MAXPATHLEN);
447da6c28aamw
448da6c28aamw	if ((err = pn_set(&upn, path)) != 0) {
449da6c28aamw		(void) pn_free(&upn);
450da6c28aamw		return (err);
451da6c28aamw	}
452da6c28aamw
4531bc6aeeMatt Barden	if (mnt_pn != NULL && (err = pn_set(mnt_pn, path) != 0)) {
4541bc6aeeMatt Barden		(void) pn_free(&upn);
4551bc6aeeMatt Barden		return (err);
4561bc6aeeMatt Barden	}
4571bc6aeeMatt Barden
458e3f2c99Keyur Desai	if (SMB_TREE_SUPPORTS_ABE(sr))
459e3f2c99Keyur Desai		abe_flag = SMB_ABE;
460e3f2c99Keyur Desai
461da6c28aamw	(void) pn_alloc(&pn);
462da6c28aamw	(void) pn_alloc(&rpn);
463da6c28aamw
464da6c28aamw	component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
465da6c28aamw	real_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
466da6c28aamw
4671bc6aeeMatt Barden	if (mnt_pn != NULL) {
4681bc6aeeMatt Barden		mnt_node = cur_node;
4691bc6aeeMatt Barden		smb_node_ref(cur_node);
4701bc6aeeMatt Barden	} else
4711bc6aeeMatt Barden		mnt_node = NULL;
4728b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	fnode = NULL;
473da6c28aamw	dnode = cur_node;
474da6c28aamw	smb_node_ref(dnode);
4758b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	rootvp = root_node->vp;
47655bf511as
477da6c28aamw	while ((pathleft = pn_pathleft(&upn)) != 0) {
478da6c28aamw		if (fnode) {
479da6c28aamw			smb_node_release(dnode);
480da6c28aamw			dnode = fnode;
481da6c28aamw			fnode = NULL;
482da6c28aamw		}
483da6c28aamw
484da6c28aamw		if ((err = pn_getcomponent(&upn, component)) != 0)
485da6c28aamw			break;
486da6c28aamw
4878b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		if ((namep = smb_pathname_catia_v5tov4(sr, component,
4888b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		    namebuf, sizeof (namebuf))) == NULL) {
4898b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			err = EILSEQ;
4908b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			break;
491da6c28aamw		}
492da6c28aamw
493da6c28aamw		if ((err = pn_set(&pn, namep)) != 0)
494da6c28aamw			break;
495da6c28aamw
4968d94f65Gordon Ross		/* We want the DOS attributes. */
4978d94f65Gordon Ross		bzero(&attr, sizeof (attr));
4988d94f65Gordon Ross		attr.sa_mask = SMB_AT_DOSATTR;
4998d94f65Gordon Ross
5008b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		local_flags = flags & FIGNORECASE;
5018b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		err = smb_pathname_lookup(&pn, &rpn, local_flags,
5029fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		    &vp, rootvp, dnode->vp, &attr, cred);
503da6c28aamw
5048b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		if (err) {
505cb17486joyce mcintosh			if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
506cb17486joyce mcintosh			    !smb_maybe_mangled(component))
5078b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				break;
5088b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
509148c5f4Alan Wright			if ((err = smb_unmangle(dnode, component,
510e3f2c99Keyur Desai			    real_name, MAXNAMELEN, abe_flag)) != 0)
5118b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				break;
512da6c28aamw
5138b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			if ((namep = smb_pathname_catia_v5tov4(sr, real_name,
5148b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			    namebuf, sizeof (namebuf))) == NULL) {
5158b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				err = EILSEQ;
5168b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				break;
5178b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			}
518da6c28aamw
5198b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			if ((err = pn_set(&pn, namep)) != 0)
5208b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				break;
5218b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
5228b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			local_flags = 0;
5238b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			err = smb_pathname_lookup(&pn, &rpn, local_flags,
5249fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States			    &vp, rootvp, dnode->vp, &attr, cred);
5258b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			if (err)
5268b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				break;
5278b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		}
528da6c28aamw
5299fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		/*
5309fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		 * This check MUST be done before symlink check
5319fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		 * since a reparse point is of type VLNK but should
5329fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		 * not be handled like a regular symlink.
5339fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		 */
5349fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		if (attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) {
5359fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States			err = EREMOTE;
5369fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States			VN_RELE(vp);
5379fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States			break;
5389fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		}
5399fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States
540da6c28aamw		if ((vp->v_type == VLNK) &&
541da6c28aamw		    ((flags & FOLLOW) || pn_pathleft(&upn))) {
542da6c28aamw
543da6c28aamw			if (++nlink > MAXSYMLINKS) {
544da6c28aamw				err = ELOOP;
5457f667e7jose borrego				VN_RELE(vp);
546da6c28aamw				break;
547da6c28aamw			}
548da6c28aamw
549da6c28aamw			(void) pn_alloc(&link_pn);
550da6c28aamw			err = pn_getsymlink(vp, &link_pn, cred);
5517f667e7jose borrego			VN_RELE(vp);
552da6c28aamw
5538b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			if (err == 0) {
5548b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				if (pn_pathleft(&link_pn) == 0)
5558b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States					(void) pn_set(&link_pn, ".");
5568b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				err = pn_insert(&upn, &link_pn,
5578b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States				    strlen(component));
558da6c28aamw			}
559da6c28aamw			pn_free(&link_pn);
560da6c28aamw
561da6c28aamw			if (err)
562da6c28aamw				break;
563da6c28aamw
564da6c28aamw			if (upn.pn_pathlen == 0) {
565da6c28aamw				err = ENOENT;
566da6c28aamw				break;
567da6c28aamw			}
568da6c28aamw
569da6c28aamw			if (upn.pn_path[0] == '/') {
570da6c28aamw				fnode = root_node;
571da6c28aamw				smb_node_ref(fnode);
572da6c28aamw			}
573da6c28aamw
574da6c28aamw			if (pn_fixslash(&upn))
575da6c28aamw				flags |= FOLLOW;
576da6c28aamw
577da6c28aamw		} else {
578da6c28aamw			if (flags & FIGNORECASE) {
579da6c28aamw				if (strcmp(rpn.pn_path, "/") != 0)
580da6c28aamw					pn_setlast(&rpn);
581da6c28aamw				namep = rpn.pn_path;
5828b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			} else {
583da6c28aamw				namep = pn.pn_path;
5848b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			}
5858b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
5868b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			namep = smb_pathname_catia_v4tov5(sr, namep,
5878b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			    namebuf, sizeof (namebuf));
588da6c28aamw
589da6c28aamw			fnode = smb_node_lookup(sr, NULL, cred, vp, namep,
590037cac0joyce mcintosh			    dnode, NULL);
5917f667e7jose borrego			VN_RELE(vp);
592da6c28aamw
593da6c28aamw			if (fnode == NULL) {
594da6c28aamw				err = ENOMEM;
595da6c28aamw				break;
596da6c28aamw			}
597da6c28aamw		}
598da6c28aamw
599da6c28aamw		while (upn.pn_path[0] == '/') {
600da6c28aamw			upn.pn_path++;
601da6c28aamw			upn.pn_pathlen--;
602da6c28aamw		}
6037f667e7jose borrego
6041bc6aeeMatt Barden		/*
6051bc6aeeMatt Barden		 * If the node we looked up is the root of a filesystem,
6061bc6aeeMatt Barden		 * snapshot the lookup so we can replay this after discovering
6071bc6aeeMatt Barden		 * the lowest mounted filesystem.
6081bc6aeeMatt Barden		 */
6091bc6aeeMatt Barden		if (mnt_pn != NULL &&
6101bc6aeeMatt Barden		    fnode != NULL &&
6111bc6aeeMatt Barden		    (err = VFS_ROOT(fnode->vp->v_vfsp, &fsrootvp)) == 0) {
6121bc6aeeMatt Barden			if (fsrootvp == fnode->vp) {
6131bc6aeeMatt Barden				mnt_pn->pn_pathlen = pn_pathleft(&upn);
6141bc6aeeMatt Barden				mnt_pn->pn_path = mnt_pn->pn_buf +
6151bc6aeeMatt Barden				    ((ptrdiff_t)upn.pn_path -
6161bc6aeeMatt Barden				    (ptrdiff_t)upn.pn_buf);
6171bc6aeeMatt Barden
6181bc6aeeMatt Barden				smb_node_ref(fnode);
6191bc6aeeMatt Barden				if (mnt_node != NULL)
6201bc6aeeMatt Barden					smb_node_release(mnt_node);
6211bc6aeeMatt Barden				mnt_node = fnode;
6221bc6aeeMatt Barden
6231bc6aeeMatt Barden			}
6241bc6aeeMatt Barden			VN_RELE(fsrootvp);
6251bc6aeeMatt Barden		}
626da6c28aamw	}
627da6c28aamw
628da6c28aamw	if ((pathleft) && (err == ENOENT))
629da6c28aamw		err = ENOTDIR;
630da6c28aamw
6311bc6aeeMatt Barden	if (mnt_node == NULL)
6321bc6aeeMatt Barden		mnt_pn = NULL;
6331bc6aeeMatt Barden
6341bc6aeeMatt Barden	/*
6351bc6aeeMatt Barden	 * We always want to return a node when we're doing VSS
6361bc6aeeMatt Barden	 * (mnt_pn != NULL)
6371bc6aeeMatt Barden	 */
6381bc6aeeMatt Barden	if (mnt_pn == NULL && err != 0) {
639da6c28aamw		if (fnode)
640da6c28aamw			smb_node_release(fnode);
641da6c28aamw		if (dnode)
642da6c28aamw			smb_node_release(dnode);
643da6c28aamw	} else {
6441bc6aeeMatt Barden		if (mnt_pn != NULL) {
6451bc6aeeMatt Barden			*ret_node = mnt_node;
6461bc6aeeMatt Barden			if (fnode != NULL)
6471bc6aeeMatt Barden				smb_node_release(fnode);
6481bc6aeeMatt Barden		} else {
6491bc6aeeMatt Barden			*ret_node = fnode;
6501bc6aeeMatt Barden		}
651da6c28aamw
652da6c28aamw		if (dir_node)
653da6c28aamw			*dir_node = dnode;
654da6c28aamw		else
655da6c28aamw			smb_node_release(dnode);
656da6c28aamw	}
657da6c28aamw
658da6c28aamw	kmem_free(component, MAXNAMELEN);
659da6c28aamw	kmem_free(real_name, MAXNAMELEN);
660da6c28aamw	(void) pn_free(&pn);
661da6c28aamw	(void) pn_free(&rpn);
662da6c28aamw	(void) pn_free(&upn);
663da6c28aamw
664da6c28aamw	return (err);
665da6c28aamw}
66689dc44cjose borrego
66789dc44cjose borrego/*
6688b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * Holds on dvp and rootvp (if not rootdir) are required by lookuppnvp()
6698b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * and will be released within lookuppnvp().
6708b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States */
6718b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic int
6728b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statessmb_pathname_lookup(pathname_t *pn, pathname_t *rpn, int flags,
6739fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States    vnode_t **vp, vnode_t *rootvp, vnode_t *dvp, smb_attr_t *attr, cred_t *cred)
6748b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States{
6758b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	int err;
6768b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
6778b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	*vp = NULL;
6788b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	VN_HOLD(dvp);
6798b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	if (rootvp != rootdir)
6808b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		VN_HOLD(rootvp);
6818b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
6828b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	err = lookuppnvp(pn, rpn, flags, NULL, vp, rootvp, dvp, cred);
6839fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States	if ((err == 0) && (attr != NULL))
6848622ec4Gordon Ross		(void) smb_vop_getattr(*vp, NULL, attr, 0, zone_kcred());
6859fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States
6868b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	return (err);
6878b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States}
6888b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
6898b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States/*
6908b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * CATIA Translation of a pathname component prior to passing it to lookuppnvp
6918b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States *
6928b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * If the translated component name contains a '/' NULL is returned.
6938b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * The caller should treat this as error EILSEQ. It is not valid to
6948b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * have a directory name with a '/'.
6958b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States */
6968b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic char *
6978b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statessmb_pathname_catia_v5tov4(smb_request_t *sr, char *name,
6988b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States    char *namebuf, int buflen)
6998b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States{
7008b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	char *namep;
7018b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
7028b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	if (SMB_TREE_SUPPORTS_CATIA(sr)) {
7038b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		namep = smb_vop_catia_v5tov4(name, namebuf, buflen);
7048b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		if (strchr(namep, '/') != NULL)
7058b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States			return (NULL);
7068b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		return (namep);
7078b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	}
7088b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
7098b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	return (name);
7108b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States}
7118b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
7128b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States/*
7138b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States * CATIA translation of a pathname component after returning from lookuppnvp
7148b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States */
7158b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statesstatic char *
7168b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United Statessmb_pathname_catia_v4tov5(smb_request_t *sr, char *name,
7178b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States    char *namebuf, int buflen)
7188b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States{
7198b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	if (SMB_TREE_SUPPORTS_CATIA(sr)) {
7208b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		smb_vop_catia_v4tov5(name, namebuf, buflen);
7218b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States		return (namebuf);
7228b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	}
7238b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
7248b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States	return (name);
7258b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States}
7268b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States
7278b2cc8aafshin salek ardakani - Sun Microsystems - Irvine United States/*
72889dc44cjose borrego * sr - needed to check for case sense
72989dc44cjose borrego * path - non mangled path needed to be looked up from the startvp
73089dc44cjose borrego * startvp - the vnode to start the lookup from
73189dc44cjose borrego * rootvp - the vnode of the root of the filesystem
73289dc44cjose borrego * returns the vnode found when starting at startvp and using the path
73389dc44cjose borrego *
73489dc44cjose borrego * Finds a vnode starting at startvp and parsing the non mangled path
73589dc44cjose borrego */
73689dc44cjose borrego
73789dc44cjose borregovnode_t *
73889dc44cjose borregosmb_lookuppathvptovp(smb_request_t *sr, char *path, vnode_t *startvp,
73989dc44cjose borrego    vnode_t *rootvp)
74089dc44cjose borrego{
74189dc44cjose borrego	pathname_t pn;
74289dc44cjose borrego	vnode_t *vp = NULL;
74389dc44cjose borrego	int lookup_flags = FOLLOW;
74489dc44cjose borrego
74589dc44cjose borrego	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
74689dc44cjose borrego		lookup_flags |= FIGNORECASE;
74789dc44cjose borrego
74889dc44cjose borrego	(void) pn_alloc(&pn);
74989dc44cjose borrego
75089dc44cjose borrego	if (pn_set(&pn, path) == 0) {
751037cac0joyce mcintosh		VN_HOLD(startvp);
75289dc44cjose borrego		if (rootvp != rootdir)
75389dc44cjose borrego			VN_HOLD(rootvp);
75489dc44cjose borrego
75589dc44cjose borrego		/* lookuppnvp should release the holds */
75689dc44cjose borrego		if (lookuppnvp(&pn, NULL, lookup_flags, NULL, &vp,
7578622ec4Gordon Ross		    rootvp, startvp, zone_kcred()) != 0) {
75889dc44cjose borrego			pn_free(&pn);
75989dc44cjose borrego			return (NULL);
76089dc44cjose borrego		}
76189dc44cjose borrego	}
76289dc44cjose borrego
76389dc44cjose borrego	pn_free(&pn);
76489dc44cjose borrego	return (vp);
76589dc44cjose borrego}
766fe1c642Bill Krier
767fe1c642Bill Krier/*
768fe1c642Bill Krier * smb_pathname_init
769fe1c642Bill Krier * Parse path: pname\\fname:sname:stype
770fe1c642Bill Krier *
771fe1c642Bill Krier * Elements of the smb_pathname_t structure are allocated using request
772fe1c642Bill Krier * specific storage and will be free'd when the sr is destroyed.
773fe1c642Bill Krier *
774fe1c642Bill Krier * Populate pn structure elements with the individual elements
775fe1c642Bill Krier * of pn->pn_path. pn->pn_sname will contain the whole stream name
776fe1c642Bill Krier * including the stream type and preceding colon: :sname:%DATA
777fe1c642Bill Krier * pn_stype will point to the stream type within pn_sname.
778fe1c642Bill Krier *
7799fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States * If the pname element is missing pn_pname will be set to NULL.
780fe1c642Bill Krier * If any other element is missing the pointer in pn will be NULL.
781fe1c642Bill Krier */
782fe1c642Bill Kriervoid
783fe1c642Bill Kriersmb_pathname_init(smb_request_t *sr, smb_pathname_t *pn, char *path)
784fe1c642Bill Krier{
785fe1c642Bill Krier	char *pname, *fname, *sname;
786fe1c642Bill Krier	int len;
787fe1c642Bill Krier
788fe1c642Bill Krier	bzero(pn, sizeof (smb_pathname_t));
789fe1c642Bill Krier	pn->pn_path = smb_pathname_strdup(sr, path);
790fe1c642Bill Krier
791fe1c642Bill Krier	smb_pathname_preprocess(sr, pn);
792fe1c642Bill Krier
793fe1c642Bill Krier	/* parse pn->pn_path into its constituent parts */
794fe1c642Bill Krier	pname = pn->pn_path;
795fe1c642Bill Krier	fname = strrchr(pn->pn_path, '\\');
796fe1c642Bill Krier
797fe1c642Bill Krier	if (fname) {
798fe1c642Bill Krier		if (fname == pname) {
7999fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States			pn->pn_pname = NULL;
800fe1c642Bill Krier		} else {
801fe1c642Bill Krier			*fname = '\0';
802fe1c642Bill Krier			pn->pn_pname =
803fe1c642Bill Krier			    smb_pathname_strdup(sr, pname);
804fe1c642Bill Krier			*fname = '\\';
805fe1c642Bill Krier		}
806fe1c642Bill Krier		++fname;
807fe1c642Bill Krier	} else {
808fe1c642Bill Krier		fname = pname;
8099fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States		pn->pn_pname = NULL;
810fe1c642Bill Krier	}
811fe1c642Bill Krier
812fe1c642Bill Krier	if (fname[0] == '\0') {
813fe1c642Bill Krier		pn->pn_fname = NULL;
814fe1c642Bill Krier		return;
815fe1c642Bill Krier	}
816fe1c642Bill Krier
817fe1c642Bill Krier	if (!smb_is_stream_name(fname)) {
818fe1c642Bill Krier		pn->pn_fname = smb_pathname_strdup(sr, fname);
819fe1c642Bill Krier		return;
820fe1c642Bill Krier	}
821fe1c642Bill Krier
822fe1c642Bill Krier	/*
823fe1c642Bill Krier	 * find sname and stype in fname.
824fe1c642Bill Krier	 * sname can't be NULL smb_is_stream_name checks this
825fe1c642Bill Krier	 */
826fe1c642Bill Krier	sname = strchr(fname, ':');
827fe1c642Bill Krier	if (sname == fname)
828fe1c642Bill Krier		fname = NULL;
829fe1c642Bill Krier	else {
830fe1c642Bill Krier		*sname = '\0';
831fe1c642Bill Krier		pn->pn_fname =
832fe1c642Bill Krier		    smb_pathname_strdup(sr, fname);
833fe1c642Bill Krier		*sname = ':';
834fe1c642Bill Krier	}
835fe1c642Bill Krier
836fe1c642Bill Krier	pn->pn_sname = smb_pathname_strdup(sr, sname);
837fe1c642Bill Krier	pn->pn_stype = strchr(pn->pn_sname + 1, ':');
838fe1c642Bill Krier	if (pn->pn_stype) {
839fe1c642Bill Krier		(void) smb_strupr(pn->pn_stype);
840fe1c642Bill Krier	} else {
841fe1c642Bill Krier		len = strlen(pn->pn_sname);
842fe1c642Bill Krier		pn->pn_sname = smb_pathname_strcat(sr, pn->pn_sname, ":$DATA");
843fe1c642Bill Krier		pn->pn_stype = pn->pn_sname + len;
844fe1c642Bill Krier	}
845fe1c642Bill Krier	++pn->pn_stype;
846fe1c642Bill Krier}
847fe1c642Bill Krier
848fe1c642Bill Krier/*
849fe1c642Bill Krier * smb_pathname_preprocess
850fe1c642Bill Krier *
851fe1c642Bill Krier * Perform common pre-processing of pn->pn_path:
852fe1c642Bill Krier * - if the pn_path is blank, set it to '\\'
853fe1c642Bill Krier * - perform unicode wildcard converstion.
854fe1c642Bill Krier * - convert any '/' to '\\'
855fe1c642Bill Krier * - eliminate duplicate slashes
856fe1c642Bill Krier * - remove trailing slashes
8579fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States * - quota directory specific pre-processing
858fe1c642Bill Krier */
859fe1c642Bill Krierstatic void
860fe1c642Bill Kriersmb_pathname_preprocess(smb_request_t *sr, smb_pathname_t *pn)
861fe1c642Bill Krier{
862fe1c642Bill Krier	char *p;
863fe1c642Bill Krier
864fe1c642Bill Krier	/* treat empty path as "\\" */
865fe1c642Bill Krier	if (strlen(pn->pn_path) == 0) {
866fe1c642Bill Krier		pn->pn_path = smb_pathname_strdup(sr, "\\");
867fe1c642Bill Krier		return;
868fe1c642Bill Krier	}
869fe1c642Bill Krier
870c13be35Gordon Ross	if (sr->session->dialect < NT_LM_0_12)
871c13be35Gordon Ross		smb_convert_wildcards(pn->pn_path);
872fe1c642Bill Krier
873fe1c642Bill Krier	/* treat '/' as '\\' */
874fe1c642Bill Krier	(void) strsubst(pn->pn_path, '/', '\\');
875fe1c642Bill Krier
876fe1c642Bill Krier	(void) strcanon(pn->pn_path, "\\");
877fe1c642Bill Krier
878fe1c642Bill Krier	/* remove trailing '\\' */
879fe1c642Bill Krier	p = pn->pn_path + strlen(pn->pn_path) - 1;
880fe1c642Bill Krier	if ((p != pn->pn_path) && (*p == '\\'))
881fe1c642Bill Krier		*p = '\0';
8829fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States
8839fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States	smb_pathname_preprocess_quota(sr, pn);
8849fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States	smb_pathname_preprocess_adminshare(sr, pn);
8859fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States}
8869fb67eaafshin salek ardakani - Sun Microsystems - Irvine United States
887