1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2016 Joyent, Inc.
25  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
26  */
27 
28 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
29 /*	  All Rights Reserved	*/
30 
31 /*
32  * University Copyright- Copyright (c) 1982, 1986, 1988
33  * The Regents of the University of California
34  * All Rights Reserved
35  *
36  * University Acknowledgment- Portions of this document are derived from
37  * software developed by the University of California, Berkeley, and its
38  * contributors.
39  */
40 
41 #include <sys/types.h>
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/errno.h>
45 #include <sys/cred.h>
46 #include <sys/user.h>
47 #include <sys/uio.h>
48 #include <sys/vfs.h>
49 #include <sys/vnode.h>
50 #include <sys/pathname.h>
51 #include <sys/proc.h>
52 #include <sys/vtrace.h>
53 #include <sys/sysmacros.h>
54 #include <sys/debug.h>
55 #include <sys/dirent.h>
56 #include <sys/zone.h>
57 #include <sys/fs/snode.h>
58 
59 #include <libfksmbfs.h>
60 
61 extern vnode_t *rootdir;
62 
63 /*
64  * Simplified variation on lookuppnvp()
65  */
66 int
fake_lookup(vnode_t * dvp,char * path,vnode_t ** vpp)67 fake_lookup(vnode_t *dvp, char *path, vnode_t **vpp)
68 {
69 	char component[MAXNAMELEN];	/* buffer for component */
70 	pathname_t pn;
71 	cred_t *cr;
72 	vnode_t *cvp;	/* current component vp */
73 	vnode_t *nvp;	/* next component vp */
74 	char *p;
75 	int flags = 0;
76 	int error, len;
77 
78 	bzero(&pn, sizeof (pn));
79 	pn.pn_buf = path;
80 	pn.pn_path = path;
81 	pn.pn_pathlen = strlen(path);
82 	pn.pn_bufsize = pn.pn_pathlen + 1;
83 	p = path;
84 
85 	cr = CRED();
86 	cvp = (dvp != NULL) ? dvp : rootdir;
87 	VN_HOLD(cvp);
88 	nvp = NULL;
89 
90 	while (*p != '\0') {
91 		if (*p == '/') {
92 			p++;
93 			continue;
94 		}
95 
96 		len = strcspn(p, "/");
97 		ASSERT(len > 0);
98 		if (len >= MAXNAMELEN)
99 			return (EINVAL);
100 		(void) strncpy(component, p, len);
101 		component[len] = '\0';
102 		pn.pn_path = p;
103 		pn.pn_pathlen = strlen(p);
104 
105 		error = VOP_LOOKUP(cvp, component, &nvp, &pn, flags,
106 		    rootdir, cr, NULL, NULL, NULL);
107 		VN_RELE(cvp);
108 		if (error != 0)
109 			return (error);
110 
111 		/* Lookup gave us a hold on nvp */
112 		cvp = nvp;
113 		nvp = NULL;
114 		p += len;
115 	}
116 
117 	*vpp = cvp;
118 	return (0);
119 }
120 
121 /*
122  * Lookup the directory and find the start of the
123  * last component of the given path.
124  */
125 int
fake_lookup_dir(char * path,vnode_t ** vpp,char ** lastcomp)126 fake_lookup_dir(char *path, vnode_t **vpp, char **lastcomp)
127 {
128 	vnode_t *dvp;
129 	char *last;
130 	char *tpn = NULL;
131 	int tpn_sz;
132 	int lc_off;
133 	int error;
134 
135 	*vpp = NULL;
136 	*lastcomp = NULL;
137 
138 	tpn_sz = strlen(path) + 1;
139 	tpn = kmem_alloc(tpn_sz, KM_SLEEP);
140 
141 	/*
142 	 * Get a copy of the path, and zap the last /
143 	 */
144 	bcopy(path, tpn, tpn_sz);
145 	last = strrchr(tpn, '/');
146 	if (last == NULL) {
147 		lc_off = 0;
148 		dvp = rootdir;
149 		VN_HOLD(dvp);
150 		error = 0;
151 	} else {
152 		*last++ = '\0';
153 		if (*last == '\0') {
154 			error = EINVAL;
155 			goto out;
156 		}
157 		error = fake_lookup(rootdir, tpn, &dvp);
158 		if (error != 0) {
159 			/* dir not found */
160 			goto out;
161 		}
162 		lc_off = last - tpn;
163 		ASSERT(lc_off >= 0 && lc_off < tpn_sz);
164 	}
165 	*vpp = dvp;
166 	*lastcomp = path + lc_off;
167 
168 out:
169 	if (tpn != NULL)
170 		kmem_free(tpn, tpn_sz);
171 
172 	return (error);
173 }
174