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.
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.
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]
23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/systm.h>
44 #include <sys/errno.h>
49 #include <sys/vnode.h>
50 #include <sys/pathname.h>
52 #include <sys/vtrace.h>
53 #include <sys/sysmacros.h>
54 #include <sys/debug.h>
55 #include <sys/dirent.h>
58 #include <sys/fs/snode.h>
61 * Starting at current directory, translate pathname pnp to end.
62 * Leave pathname of final component in pnp, return the vnode
63 * for the final component in *compvpp, and return the vnode
64 * for the parent of the final component in dirvpp.
66 * This is the central routine in pathname translation and handles
67 * multiple components in pathnames, separating them at /'s. It also
68 * implements mounted file systems and processes symbolic links.
70 * vp is the vnode where the directory search should start.
72 * Reference counts: vp must be held prior to calling this function. rootvp
73 * should only be held if rootvp != rootdir.
77 struct pathname
*pnp
, /* pathname to lookup */
78 struct pathname
*rpnp
, /* if non-NULL, return resolved path */
79 int flags
, /* follow symlinks */
80 vnode_t
**dirvpp
, /* ptr for parent vnode */
81 vnode_t
**compvpp
, /* ptr for entry vnode */
82 vnode_t
*rootvp
, /* rootvp */
83 vnode_t
*vp
, /* directory to start search at */
84 cred_t
*cr
) /* user's credential */
86 vnode_t
*cvp
; /* current component vp */
87 vnode_t
*tvp
; /* addressable temp ptr */
88 char component
[MAXNAMELEN
]; /* buffer for component (incl null) */
92 struct pathname presrvd
; /* case preserved name */
93 struct pathname
*pp
= NULL
;
95 int must_be_directory
= 0;
96 boolean_t retry_with_kcred
;
101 rpnp
->pn_pathlen
= 0;
103 lookup_flags
= dirvpp
? LOOKUP_DIR
: 0;
104 if (flags
& FIGNORECASE
) {
105 lookup_flags
|= FIGNORECASE
;
111 * Eliminate any trailing slashes in the pathname.
112 * If there are any, we must follow all symlinks.
113 * Also, we must guarantee that the last component is a directory.
115 if (pn_fixslash(pnp
)) {
117 must_be_directory
= 1;
122 retry_with_kcred
= B_FALSE
;
125 * Make sure we have a directory.
127 if (vp
->v_type
!= VDIR
) {
132 if (rpnp
&& VN_CMP(vp
, rootvp
))
133 (void) pn_set(rpnp
, "/");
136 * Process the next component of the pathname.
138 if (error
= pn_getcomponent(pnp
, component
)) {
143 * Handle "..": two special cases.
144 * 1. If we're at the root directory (e.g. after chroot or
145 * zone_enter) then change ".." to "." so we can't get
146 * out of this subtree.
147 * 2. If this vnode is the root of a mounted file system,
148 * then replace it with the vnode that was mounted on
149 * so that we take the ".." in the other file system.
151 if (component
[0] == '.' && component
[1] == '.' && component
[2] == 0) {
153 if (VN_CMP(vp
, rootvp
)) {
155 } else if (vp
->v_flag
& VROOT
) {
160 * While we deal with the vfs pointer from the vnode
161 * the filesystem could have been forcefully unmounted
162 * and the vnode's v_vfsp could have been invalidated
163 * by VFS_UNMOUNT. Hence, we cache v_vfsp and use it
164 * with vfs_rlock_wait/vfs_unlock.
165 * It is safe to use the v_vfsp even it is freed by
166 * VFS_UNMOUNT because vfs_rlock_wait/vfs_unlock
167 * do not dereference v_vfsp. It is just used as a
169 * One more corner case here is the memory getting
170 * reused for another vfs structure. In this case
171 * lookuppnvp's vfs_rlock_wait will succeed, domount's
172 * vfs_lock will fail and domount will bail out with an
178 * This lock is used to synchronize
179 * mounts/unmounts and lookups.
180 * Threads doing mounts/unmounts hold the
181 * writers version vfs_lock_wait().
184 vfs_rlock_wait(vfsp
);
187 * If this vnode is on a file system that
188 * has been forcibly unmounted,
189 * we can't proceed. Cancel this operation
192 * vfs_vnodecovered is NULL if unmounted.
193 * Currently, nfs uses VFS_UNMOUNTED to
194 * check if it's a forced-umount. Keep the
195 * same checking here as well even though it
198 if (((vp
= cvp
->v_vfsp
->vfs_vnodecovered
) == NULL
) ||
199 (cvp
->v_vfsp
->vfs_flag
& VFS_UNMOUNTED
)) {
211 * Crossing mount points. For eg: We are doing
212 * a lookup of ".." for file systems root vnode
213 * mounted here, and VOP_LOOKUP() (with covered vnode)
214 * will be on underlying file systems mount point
215 * vnode. Set retry_with_kcred flag as we might end
216 * up doing VOP_LOOKUP() with kcred if required.
218 retry_with_kcred
= B_TRUE
;
224 * Perform a lookup in the current directory.
226 error
= VOP_LOOKUP(vp
, component
, &tvp
, pnp
, lookup_flags
,
227 rootvp
, cr
, NULL
, NULL
, pp
);
230 * Retry with kcred - If crossing mount points & error is EACCES.
232 * If we are crossing mount points here and doing ".." lookup,
233 * VOP_LOOKUP() might fail if the underlying file systems
234 * mount point has no execute permission. In cases like these,
235 * we retry VOP_LOOKUP() by giving as much privilage as possible
236 * by passing kcred credentials.
238 * In case of hierarchical file systems, passing kcred still may
240 * For eg: UFS FS --> Mount NFS FS --> Again mount UFS on some
241 * directory inside NFS FS.
243 if ((error
== EACCES
) && retry_with_kcred
)
244 error
= VOP_LOOKUP(vp
, component
, &tvp
, pnp
, lookup_flags
,
245 rootvp
, zone_kcred(), NULL
, NULL
, pp
);
251 * On error, return hard error if
252 * (a) we're not at the end of the pathname yet, or
253 * (b) the caller didn't want the parent directory, or
254 * (c) we failed for some reason other than a missing entry.
256 if (pn_pathleft(pnp
) || dirvpp
== NULL
|| error
!= ENOENT
)
261 * We inform the caller that the desired entry must be
262 * a directory by adding a '/' to the component name.
264 if (must_be_directory
&& (error
= pn_addslash(pnp
)) != 0)
269 if (rootvp
!= rootdir
)
277 * Traverse mount points.
279 if (vn_mountedvfs(cvp
) != NULL
) {
281 if ((error
= traverse(&tvp
)) != 0) {
283 * It is required to assign cvp here, because
284 * traverse() will return a held vnode which
285 * may different than the vnode that was passed
286 * in (even in the error case). If traverse()
287 * changes the vnode it releases the original,
288 * and holds the new one.
297 * If we hit a symbolic link and there is more path to be
298 * translated or this operation does not wish to apply
299 * to a link, then place the contents of the link at the
300 * front of the remaining pathname.
302 if (cvp
->v_type
== VLNK
&& ((flags
& FOLLOW
) || pn_pathleft(pnp
))) {
303 struct pathname linkpath
;
305 if (++nlink
> MAXSYMLINKS
) {
310 if (error
= pn_getsymlink(cvp
, &linkpath
, cr
)) {
315 if (pn_pathleft(&linkpath
) == 0)
316 (void) pn_set(&linkpath
, ".");
317 error
= pn_insert(pnp
, &linkpath
, strlen(component
));
323 if (pnp
->pn_pathlen
== 0) {
327 if (pnp
->pn_path
[0] == '/') {
331 } while (pnp
->pn_path
[0] == '/');
336 if (pn_fixslash(pnp
)) {
338 must_be_directory
= 1;
344 * If rpnp is non-NULL, remember the resolved path name therein.
345 * Do not include "." components. Collapse occurrences of
346 * "previous/..", so long as "previous" is not itself "..".
347 * Exhausting rpnp results in error ENAMETOOLONG.
349 if (rpnp
&& strcmp(component
, ".") != 0) {
352 if (strcmp(component
, "..") == 0 &&
353 rpnp
->pn_pathlen
!= 0 &&
354 !((rpnp
->pn_pathlen
> 2 &&
355 strncmp(rpnp
->pn_path
+rpnp
->pn_pathlen
-3, "/..", 3) == 0) ||
356 (rpnp
->pn_pathlen
== 2 &&
357 strncmp(rpnp
->pn_path
, "..", 2) == 0))) {
358 while (rpnp
->pn_pathlen
&&
359 rpnp
->pn_path
[rpnp
->pn_pathlen
-1] != '/')
361 if (rpnp
->pn_pathlen
> 1)
363 rpnp
->pn_path
[rpnp
->pn_pathlen
] = '\0';
365 if (rpnp
->pn_pathlen
!= 0 &&
366 rpnp
->pn_path
[rpnp
->pn_pathlen
-1] != '/')
367 rpnp
->pn_path
[rpnp
->pn_pathlen
++] = '/';
368 if (flags
& FIGNORECASE
) {
370 * Return the case-preserved name
371 * within the resolved path.
373 error
= copystr(pp
->pn_buf
,
374 rpnp
->pn_path
+ rpnp
->pn_pathlen
,
375 rpnp
->pn_bufsize
- rpnp
->pn_pathlen
, &len
);
377 error
= copystr(component
,
378 rpnp
->pn_path
+ rpnp
->pn_pathlen
,
379 rpnp
->pn_bufsize
- rpnp
->pn_pathlen
, &len
);
381 if (error
) /* copystr() returns ENAMETOOLONG */
383 rpnp
->pn_pathlen
+= (len
- 1);
384 ASSERT(rpnp
->pn_bufsize
> rpnp
->pn_pathlen
);
389 * If no more components, return last directory (if wanted) and
390 * last component (if wanted).
392 if (pn_pathleft(pnp
) == 0) {
394 * If there was a trailing slash in the pathname,
395 * make sure the last component is a directory.
397 if (must_be_directory
&& cvp
->v_type
!= VDIR
) {
401 if (dirvpp
!= NULL
) {
403 * Check that we have the real parent and not
404 * an alias of the last component.
406 if (vn_compare(vp
, cvp
)) {
410 if (rootvp
!= rootdir
)
419 if (pnp
->pn_path
== pnp
->pn_buf
)
420 (void) pn_set(pnp
, ".");
424 if (VN_CMP(cvp
, rootvp
))
425 (void) pn_set(rpnp
, "/");
426 else if (rpnp
->pn_pathlen
== 0)
427 (void) pn_set(rpnp
, ".");
434 if (rootvp
!= rootdir
)
442 * Skip over slashes from end of last component.
444 while (pnp
->pn_path
[0] == '/') {
450 * Searched through another level of directory:
451 * release previous directory handle and save new (result
452 * of lookup) as current directory.
461 * Error. Release vnodes and return.
466 * If the error was ESTALE and the current directory to look in
467 * was the root for this lookup, the root for a mounted file
468 * system, or the starting directory for lookups, then
469 * return ENOENT instead of ESTALE. In this case, no recovery
470 * is possible by the higher level. If ESTALE was returned for
471 * some intermediate directory along the path, then recovery
472 * is potentially possible and retrying from the higher level
473 * will either correct the situation by purging stale cache
474 * entries or eventually get back to the point where no recovery
477 if (error
== ESTALE
&&
478 (VN_CMP(vp
, rootvp
) || (vp
->v_flag
& VROOT
) || vp
== startvp
))
481 if (rootvp
!= rootdir
)
489 * Traverse a mount point. Routine accepts a vnode pointer as a reference
490 * parameter and performs the indirection, releasing the original vnode.
493 traverse(vnode_t
**cvpp
)
503 * If this vnode is mounted on, then we transparently indirect
504 * to the vnode which is the root of the mounted file system.
505 * Before we do this we must check that an unmount is not in
506 * progress on this vnode.
511 * Used to try to read lock the vnode here.
515 * Reached the end of the mount chain?
517 vfsp
= vn_mountedvfs(cvp
);
523 * The read lock must be held across the call to VFS_ROOT() to
524 * prevent a concurrent unmount from destroying the vfs.
526 error
= VFS_ROOT(vfsp
, &tvp
);
540 * Get the vnode path, relative to the passed rootvp.
541 * Our vncache always fills in v_path, so this is easy.
545 vnodetopath(vnode_t
*vrootp
, vnode_t
*vp
, char *buf
, size_t buflen
, cred_t
*cr
)
547 int len
, rvp_len
= 0;
548 const char *p
= vp
->v_path
;
551 rvp_len
= strlen(vrootp
->v_path
);
558 (void) strlcpy(buf
, p
, buflen
);