]> git.saurik.com Git - apple/xnu.git/blame - bsd/vfs/vfs_lookup.c
xnu-2782.40.9.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_lookup.c
CommitLineData
1c79356b 1/*
316670eb 2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29/*
30 * Copyright (c) 1982, 1986, 1989, 1993
31 * The Regents of the University of California. All rights reserved.
32 * (c) UNIX System Laboratories, Inc.
33 * All or some portions of this file are derived from material licensed
34 * to the University of California by American Telephone and Telegraph
35 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
36 * the permission of UNIX System Laboratories, Inc.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95
67 */
2d21ac55
A
68/*
69 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
70 * support for mandatory and extensible security protections. This notice
71 * is included in support of clause 2.2 (b) of the Apple Public License,
72 * Version 2.0.
73 */
1c79356b
A
74
75#include <sys/param.h>
55e303ae 76#include <sys/systm.h>
1c79356b
A
77#include <sys/syslimits.h>
78#include <sys/time.h>
79#include <sys/namei.h>
80#include <sys/vm.h>
91447636
A
81#include <sys/vnode_internal.h>
82#include <sys/mount_internal.h>
1c79356b
A
83#include <sys/errno.h>
84#include <sys/malloc.h>
85#include <sys/filedesc.h>
91447636 86#include <sys/proc_internal.h>
1c79356b
A
87#include <sys/kdebug.h>
88#include <sys/unistd.h> /* For _PC_NAME_MAX */
91447636
A
89#include <sys/uio_internal.h>
90#include <sys/kauth.h>
39236c6e 91#include <kern/kalloc.h>
b0d623f7 92#include <security/audit/audit.h>
1c79356b 93
2d21ac55
A
94#if CONFIG_MACF
95#include <security/mac_framework.h>
96#endif
97
98#if NAMEDRSRCFORK
99#include <sys/xattr.h>
1c79356b 100#endif
2d21ac55
A
101/*
102 * The minimum volfs-style pathname is 9.
103 * Example: "/.vol/1/2"
104 */
105#define VOLFS_MIN_PATH_LEN 9
1c79356b 106
91447636
A
107
108static void kdebug_lookup(struct vnode *dp, struct componentname *cnp);
55e303ae 109
2d21ac55
A
110#if CONFIG_VOLFS
111static int vfs_getrealpath(const char * path, char * realpath, size_t bufsize, vfs_context_t ctx);
39236c6e 112#define MAX_VOLFS_RESTARTS 5
2d21ac55
A
113#endif
114
fe8ab488
A
115static int lookup_traverse_mountpoints(struct nameidata *ndp, struct componentname *cnp, vnode_t dp, int vbusyflags, vfs_context_t ctx);
116static int lookup_handle_symlink(struct nameidata *ndp, vnode_t *new_dp, vfs_context_t ctx);
117static int lookup_authorize_search(vnode_t dp, struct componentname *cnp, int dp_authorized_in_cache, vfs_context_t ctx);
118static void lookup_consider_update_cache(vnode_t dvp, vnode_t vp, struct componentname *cnp, int nc_generation);
119static int lookup_handle_found_vnode(struct nameidata *ndp, struct componentname *cnp, int rdonly,
6d2010ae
A
120 int vbusyflags, int *keep_going, int nc_generation,
121 int wantparent, int atroot, vfs_context_t ctx);
fe8ab488 122static int lookup_handle_emptyname(struct nameidata *ndp, struct componentname *cnp, int wantparent);
6d2010ae 123
fe8ab488
A
124#if NAMEDRSRCFORK
125static int lookup_handle_rsrc_fork(vnode_t dp, struct nameidata *ndp, struct componentname *cnp, int wantparent, vfs_context_t ctx);
126#endif
39236c6e
A
127
128
129
1c79356b
A
130/*
131 * Convert a pathname into a pointer to a locked inode.
132 *
133 * The FOLLOW flag is set when symbolic links are to be followed
134 * when they occur at the end of the name translation process.
135 * Symbolic links are always followed for all other pathname
136 * components other than the last.
137 *
138 * The segflg defines whether the name is to be copied from user
139 * space or kernel space.
140 *
141 * Overall outline of namei:
142 *
143 * copy in name
144 * get starting directory
145 * while (!done && !error) {
146 * call lookup to search path.
147 * if symbolic link, massage name in buffer and continue
148 * }
2d21ac55
A
149 *
150 * Returns: 0 Success
151 * ENOENT No such file or directory
152 * ELOOP Too many levels of symbolic links
153 * ENAMETOOLONG Filename too long
154 * copyinstr:EFAULT Bad address
155 * copyinstr:ENAMETOOLONG Filename too long
156 * lookup:EBADF Bad file descriptor
157 * lookup:EROFS
158 * lookup:EACCES
159 * lookup:EPERM
4a3eedf9
A
160 * lookup:ERECYCLE vnode was recycled from underneath us in lookup.
161 * This means we should re-drive lookup from this point.
162 * lookup: ???
2d21ac55 163 * VNOP_READLINK:???
1c79356b
A
164 */
165int
2d21ac55 166namei(struct nameidata *ndp)
1c79356b 167{
2d21ac55 168 struct filedesc *fdp; /* pointer to file descriptor state */
2d21ac55 169 struct vnode *dp; /* the directory we are searching */
4a3eedf9
A
170 struct vnode *usedvp = ndp->ni_dvp; /* store pointer to vp in case we must loop due to
171 heavy vnode pressure */
172 u_long cnpflags = ndp->ni_cnd.cn_flags; /* store in case we have to restore after loop */
91447636 173 int error;
1c79356b 174 struct componentname *cnp = &ndp->ni_cnd;
91447636 175 vfs_context_t ctx = cnp->cn_context;
2d21ac55 176 proc_t p = vfs_context_proc(ctx);
b0d623f7 177#if CONFIG_AUDIT
2d21ac55
A
178/* XXX ut should be from context */
179 uthread_t ut = (struct uthread *)get_bsdthread_info(current_thread());
b0d623f7 180#endif
6d2010ae 181
39236c6e
A
182#if CONFIG_VOLFS
183 int volfs_restarts = 0;
184#endif
185
6d2010ae 186 fdp = p->p_fd;
1c79356b 187
1c79356b 188#if DIAGNOSTIC
91447636 189 if (!vfs_context_ucred(ctx) || !p)
1c79356b
A
190 panic ("namei: bad cred/proc");
191 if (cnp->cn_nameiop & (~OPMASK))
192 panic ("namei: nameiop contaminated with flags");
193 if (cnp->cn_flags & OPMASK)
194 panic ("namei: flags contaminated with nameiops");
195#endif
6d2010ae
A
196
197 /*
198 * A compound VNOP found something that needs further processing:
199 * either a trigger vnode, a covered directory, or a symlink.
200 */
201 if (ndp->ni_flag & NAMEI_CONTLOOKUP) {
202 int rdonly, vbusyflags, keep_going, wantparent;
203
204 rdonly = cnp->cn_flags & RDONLY;
205 vbusyflags = ((cnp->cn_flags & CN_NBMOUNTLOOK) != 0) ? LK_NOWAIT : 0;
206 keep_going = 0;
207 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
208
209 ndp->ni_flag &= ~(NAMEI_CONTLOOKUP);
210
211 error = lookup_handle_found_vnode(ndp, &ndp->ni_cnd, rdonly, vbusyflags,
212 &keep_going, ndp->ni_ncgeneration, wantparent, 0, ctx);
213 if (error)
214 goto out_drop;
215 if (keep_going) {
216 if ((cnp->cn_flags & ISSYMLINK) == 0) {
217 panic("We need to keep going on a continued lookup, but for vp type %d (tag %d)\n", ndp->ni_vp->v_type, ndp->ni_vp->v_tag);
218 }
219 goto continue_symlink;
220 }
221
222 return 0;
223
224 }
1c79356b 225
4a3eedf9
A
226vnode_recycled:
227
1c79356b
A
228 /*
229 * Get a buffer for the name to be translated, and copy the
230 * name into the buffer.
231 */
232 if ((cnp->cn_flags & HASBUF) == 0) {
2d21ac55 233 cnp->cn_pnbuf = ndp->ni_pathbuf;
91447636 234 cnp->cn_pnlen = PATHBUFLEN;
1c79356b 235 }
91447636 236#if LP64_DEBUG
b0d623f7
A
237 if ((UIO_SEG_IS_USER_SPACE(ndp->ni_segflg) == 0)
238 && (ndp->ni_segflg != UIO_SYSSPACE)
239 && (ndp->ni_segflg != UIO_SYSSPACE32)) {
91447636
A
240 panic("%s :%d - invalid ni_segflg\n", __FILE__, __LINE__);
241 }
242#endif /* LP64_DEBUG */
243
244retry_copy:
2d21ac55 245 if (UIO_SEG_IS_USER_SPACE(ndp->ni_segflg)) {
1c79356b 246 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
91447636 247 cnp->cn_pnlen, (size_t *)&ndp->ni_pathlen);
2d21ac55 248 } else {
91447636
A
249 error = copystr(CAST_DOWN(void *, ndp->ni_dirp), cnp->cn_pnbuf,
250 cnp->cn_pnlen, (size_t *)&ndp->ni_pathlen);
2d21ac55 251 }
91447636 252 if (error == ENAMETOOLONG && !(cnp->cn_flags & HASBUF)) {
2d21ac55
A
253 MALLOC_ZONE(cnp->cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
254 if (cnp->cn_pnbuf == NULL) {
255 error = ENOMEM;
256 goto error_out;
257 }
91447636
A
258
259 cnp->cn_flags |= HASBUF;
260 cnp->cn_pnlen = MAXPATHLEN;
261
262 goto retry_copy;
263 }
264 if (error)
265 goto error_out;
55e303ae 266
39236c6e
A
267 /*
268 * Since the name cache may contain positive entries of
269 * the incorrect case, force lookup() to bypass the cache
270 * and call directly into the filesystem for each path
271 * component. Note: the FS may still consult the cache,
272 * but can apply rules to validate the results.
273 */
274 if (proc_is_forcing_hfs_case_sensitivity(p))
275 cnp->cn_flags |= CN_SKIPNAMECACHE;
276
2d21ac55
A
277#if CONFIG_VOLFS
278 /*
279 * Check for legacy volfs style pathnames.
280 *
281 * For compatibility reasons we currently allow these paths,
282 * but future versions of the OS may not support them.
283 */
284 if (ndp->ni_pathlen >= VOLFS_MIN_PATH_LEN &&
285 cnp->cn_pnbuf[0] == '/' &&
286 cnp->cn_pnbuf[1] == '.' &&
287 cnp->cn_pnbuf[2] == 'v' &&
288 cnp->cn_pnbuf[3] == 'o' &&
289 cnp->cn_pnbuf[4] == 'l' &&
290 cnp->cn_pnbuf[5] == '/' ) {
291 char * realpath;
292 int realpath_err;
293 /* Attempt to resolve a legacy volfs style pathname. */
294 MALLOC_ZONE(realpath, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
295 if (realpath) {
b0d623f7
A
296 /*
297 * We only error out on the ENAMETOOLONG cases where we know that
298 * vfs_getrealpath translation succeeded but the path could not fit into
299 * MAXPATHLEN characters. In other failure cases, we may be dealing with a path
300 * that legitimately looks like /.vol/1234/567 and is not meant to be translated
301 */
2d21ac55
A
302 if ((realpath_err= vfs_getrealpath(&cnp->cn_pnbuf[6], realpath, MAXPATHLEN, ctx))) {
303 FREE_ZONE(realpath, MAXPATHLEN, M_NAMEI);
b0d623f7 304 if (realpath_err == ENOSPC || realpath_err == ENAMETOOLONG){
2d21ac55
A
305 error = ENAMETOOLONG;
306 goto error_out;
307 }
308 } else {
309 if (cnp->cn_flags & HASBUF) {
310 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
311 }
312 cnp->cn_pnbuf = realpath;
313 cnp->cn_pnlen = MAXPATHLEN;
314 ndp->ni_pathlen = strlen(realpath) + 1;
315 cnp->cn_flags |= HASBUF | CN_VOLFSPATH;
316 }
317 }
318 }
b0d623f7 319#endif /* CONFIG_VOLFS */
2d21ac55 320
b0d623f7 321#if CONFIG_AUDIT
55e303ae
A
322 /* If we are auditing the kernel pathname, save the user pathname */
323 if (cnp->cn_flags & AUDITVNPATH1)
2d21ac55 324 AUDIT_ARG(upath, ut->uu_cdir, cnp->cn_pnbuf, ARG_UPATH1);
55e303ae 325 if (cnp->cn_flags & AUDITVNPATH2)
2d21ac55 326 AUDIT_ARG(upath, ut->uu_cdir, cnp->cn_pnbuf, ARG_UPATH2);
b0d623f7 327#endif /* CONFIG_AUDIT */
55e303ae 328
1c79356b
A
329 /*
330 * Do not allow empty pathnames
331 */
91447636 332 if (*cnp->cn_pnbuf == '\0') {
1c79356b 333 error = ENOENT;
2d21ac55 334 goto error_out;
1c79356b
A
335 }
336 ndp->ni_loopcnt = 0;
1c79356b
A
337
338 /*
91447636 339 * determine the starting point for the translation.
1c79356b 340 */
91447636
A
341 if ((ndp->ni_rootdir = fdp->fd_rdir) == NULLVP) {
342 if ( !(fdp->fd_flags & FD_CHROOT))
343 ndp->ni_rootdir = rootvnode;
55e303ae 344 }
91447636 345 cnp->cn_nameptr = cnp->cn_pnbuf;
55e303ae 346
91447636
A
347 ndp->ni_usedvp = NULLVP;
348
349 if (*(cnp->cn_nameptr) == '/') {
350 while (*(cnp->cn_nameptr) == '/') {
351 cnp->cn_nameptr++;
352 ndp->ni_pathlen--;
1c79356b 353 }
91447636
A
354 dp = ndp->ni_rootdir;
355 } else if (cnp->cn_flags & USEDVP) {
356 dp = ndp->ni_dvp;
357 ndp->ni_usedvp = dp;
358 } else
2d21ac55 359 dp = vfs_context_cwd(ctx);
91447636 360
2d21ac55 361 if (dp == NULLVP || (dp->v_lflag & VL_DEAD)) {
91447636
A
362 error = ENOENT;
363 goto error_out;
364 }
365 ndp->ni_dvp = NULLVP;
366 ndp->ni_vp = NULLVP;
367
368 for (;;) {
1c79356b 369 ndp->ni_startdir = dp;
91447636
A
370
371 if ( (error = lookup(ndp)) ) {
372 goto error_out;
1c79356b
A
373 }
374 /*
375 * Check for symbolic link
376 */
377 if ((cnp->cn_flags & ISSYMLINK) == 0) {
1c79356b
A
378 return (0);
379 }
91447636 380
6d2010ae
A
381continue_symlink:
382 /* Gives us a new path to process, and a starting dir */
383 error = lookup_handle_symlink(ndp, &dp, ctx);
384 if (error != 0) {
1c79356b
A
385 break;
386 }
91447636
A
387 }
388 /*
389 * only come here if we fail to handle a SYMLINK...
390 * if either ni_dvp or ni_vp is non-NULL, then
391 * we need to drop the iocount that was picked
392 * up in the lookup routine
393 */
6d2010ae 394out_drop:
91447636
A
395 if (ndp->ni_dvp)
396 vnode_put(ndp->ni_dvp);
397 if (ndp->ni_vp)
398 vnode_put(ndp->ni_vp);
399 error_out:
400 if ( (cnp->cn_flags & HASBUF) ) {
2d21ac55 401 cnp->cn_flags &= ~HASBUF;
91447636
A
402 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
403 }
55e303ae 404 cnp->cn_pnbuf = NULL;
91447636 405 ndp->ni_vp = NULLVP;
6d2010ae 406 ndp->ni_dvp = NULLVP;
39236c6e
A
407
408#if CONFIG_VOLFS
409 /*
410 * Deal with volfs fallout.
411 *
412 * At this point, if we were originally given a volfs path that
413 * looks like /.vol/123/456, then we would have had to convert it into
414 * a full path. Assuming that part worked properly, we will now attempt
415 * to conduct a lookup of the item in the namespace. Under normal
416 * circumstances, if a user looked up /tmp/foo and it was not there, it
417 * would be permissible to return ENOENT.
418 *
419 * However, we may not want to do that here. Specifically, the volfs path
420 * uniquely identifies a certain item in the namespace regardless of where it
421 * lives. If the item has moved in between the time we constructed the
422 * path and now, when we're trying to do a lookup/authorization on the full
423 * path, we may have gotten an ENOENT.
424 *
425 * At this point we can no longer tell if the path no longer exists
426 * or if the item in question no longer exists. It could have been renamed
427 * away, in which case the /.vol identifier is still valid.
428 *
429 * Do this dance a maximum of MAX_VOLFS_RESTARTS times.
430 */
431 if ((error == ENOENT) && (ndp->ni_cnd.cn_flags & CN_VOLFSPATH)) {
432 if (volfs_restarts < MAX_VOLFS_RESTARTS) {
433 volfs_restarts++;
434 goto vnode_recycled;
435 }
436 }
437#endif
438
4a3eedf9
A
439 if (error == ERECYCLE){
440 /* vnode was recycled underneath us. re-drive lookup to start at
441 the beginning again, since recycling invalidated last lookup*/
442 ndp->ni_cnd.cn_flags = cnpflags;
443 ndp->ni_dvp = usedvp;
444 goto vnode_recycled;
445 }
446
55e303ae 447
1c79356b
A
448 return (error);
449}
450
6d2010ae
A
451int
452namei_compound_available(vnode_t dp, struct nameidata *ndp)
453{
454 if ((ndp->ni_flag & NAMEI_COMPOUNDOPEN) != 0) {
455 return vnode_compound_open_available(dp);
456 }
91447636 457
6d2010ae
A
458 return 0;
459}
fe8ab488 460static int
6d2010ae 461lookup_authorize_search(vnode_t dp, struct componentname *cnp, int dp_authorized_in_cache, vfs_context_t ctx)
1c79356b 462{
39236c6e
A
463#if !CONFIG_MACF
464#pragma unused(cnp)
465#endif
466
6d2010ae 467 int error;
1c79356b 468
6d2010ae
A
469 if (!dp_authorized_in_cache) {
470 error = vnode_authorize(dp, NULL, KAUTH_VNODE_SEARCH, ctx);
471 if (error)
472 return error;
91447636 473 }
6d2010ae
A
474#if CONFIG_MACF
475 error = mac_vnode_check_lookup(ctx, dp, cnp);
476 if (error)
477 return error;
478#endif /* CONFIG_MACF */
91447636 479
6d2010ae
A
480 return 0;
481}
1c79356b 482
fe8ab488 483static void
6d2010ae
A
484lookup_consider_update_cache(vnode_t dvp, vnode_t vp, struct componentname *cnp, int nc_generation)
485{
486 int isdot_or_dotdot;
487 isdot_or_dotdot = (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') || (cnp->cn_flags & ISDOTDOT);
55e303ae 488
6d2010ae
A
489 if (vp->v_name == NULL || vp->v_parent == NULLVP) {
490 int update_flags = 0;
491
492 if (isdot_or_dotdot == 0) {
493 if (vp->v_name == NULL)
494 update_flags |= VNODE_UPDATE_NAME;
495 if (dvp != NULLVP && vp->v_parent == NULLVP)
496 update_flags |= VNODE_UPDATE_PARENT;
497
498 if (update_flags)
499 vnode_update_identity(vp, dvp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_hash, update_flags);
55e303ae 500 }
1c79356b 501 }
6d2010ae
A
502 if ( (cnp->cn_flags & MAKEENTRY) && (vp->v_flag & VNCACHEABLE) && LIST_FIRST(&vp->v_nclinks) == NULL) {
503 /*
504 * missing from name cache, but should
505 * be in it... this can happen if volfs
506 * causes the vnode to be created or the
507 * name cache entry got recycled but the
508 * vnode didn't...
509 * check to make sure that ni_dvp is valid
510 * cache_lookup_path may return a NULL
511 * do a quick check to see if the generation of the
512 * directory matches our snapshot... this will get
513 * rechecked behind the name cache lock, but if it
514 * already fails to match, no need to go any further
515 */
516 if (dvp != NULLVP && (nc_generation == dvp->v_nc_generation) && (!isdot_or_dotdot))
517 cache_enter_with_gen(dvp, vp, cnp, nc_generation);
518 }
9bccf70c 519
6d2010ae
A
520}
521
522#if NAMEDRSRCFORK
523/*
524 * Can change ni_dvp and ni_vp. On success, returns with iocounts on stream vnode (always) and
525 * data fork if requested. On failure, returns with iocount data fork (always) and its parent directory
526 * (if one was provided).
527 */
fe8ab488 528static int
6d2010ae
A
529lookup_handle_rsrc_fork(vnode_t dp, struct nameidata *ndp, struct componentname *cnp, int wantparent, vfs_context_t ctx)
530{
531 vnode_t svp = NULLVP;
532 enum nsoperation nsop;
533 int error;
534
535 if (dp->v_type != VREG) {
536 error = ENOENT;
537 goto out;
91447636 538 }
6d2010ae
A
539 switch (cnp->cn_nameiop) {
540 case DELETE:
541 if (cnp->cn_flags & CN_ALLOWRSRCFORK) {
542 nsop = NS_DELETE;
543 } else {
544 error = EPERM;
545 goto out;
546 }
547 break;
548 case CREATE:
549 if (cnp->cn_flags & CN_ALLOWRSRCFORK) {
550 nsop = NS_CREATE;
551 } else {
552 error = EPERM;
553 goto out;
554 }
555 break;
556 case LOOKUP:
557 /* Make sure our lookup of "/..namedfork/rsrc" is allowed. */
558 if (cnp->cn_flags & CN_ALLOWRSRCFORK) {
559 nsop = NS_OPEN;
560 } else {
561 error = EPERM;
562 goto out;
563 }
564 break;
565 default:
566 error = EPERM;
567 goto out;
568 }
569 /* Ask the file system for the resource fork. */
570 error = vnode_getnamedstream(dp, &svp, XATTR_RESOURCEFORK_NAME, nsop, 0, ctx);
91447636 571
6d2010ae
A
572 /* During a create, it OK for stream vnode to be missing. */
573 if (error == ENOATTR || error == ENOENT) {
574 error = (nsop == NS_CREATE) ? 0 : ENOENT;
575 }
576 if (error) {
577 goto out;
578 }
579 /* The "parent" of the stream is the file. */
580 if (wantparent) {
581 if (ndp->ni_dvp) {
6d2010ae
A
582 vnode_put(ndp->ni_dvp);
583 }
584 ndp->ni_dvp = dp;
585 } else {
586 vnode_put(dp);
587 }
588 ndp->ni_vp = svp; /* on create this may be null */
91447636 589
6d2010ae
A
590 /* Restore the truncated pathname buffer (for audits). */
591 if (ndp->ni_pathlen == 1 && ndp->ni_next[0] == '\0') {
592 ndp->ni_next[0] = '/';
593 }
594 cnp->cn_flags &= ~MAKEENTRY;
2d21ac55 595
6d2010ae
A
596 return 0;
597out:
598 return error;
599}
600#endif /* NAMEDRSRCFORK */
601
602/*
603 * iocounts in:
604 * --One on ni_vp. One on ni_dvp if there is more path, or we didn't come through the
605 * cache, or we came through the cache and the caller doesn't want the parent.
606 *
607 * iocounts out:
608 * --Leaves us in the correct state for the next step, whatever that might be.
609 * --If we find a symlink, returns with iocounts on both ni_vp and ni_dvp.
610 * --If we are to look up another component, then we have an iocount on ni_vp and
611 * nothing else.
612 * --If we are done, returns an iocount on ni_vp, and possibly on ni_dvp depending on nameidata flags.
613 * --In the event of an error, may return with ni_dvp NULL'ed out (in which case, iocount
614 * was dropped).
615 */
fe8ab488 616static int
6d2010ae
A
617lookup_handle_found_vnode(struct nameidata *ndp, struct componentname *cnp, int rdonly,
618 int vbusyflags, int *keep_going, int nc_generation,
619 int wantparent, int atroot, vfs_context_t ctx)
620{
621 vnode_t dp;
622 int error;
623 char *cp;
624
625 dp = ndp->ni_vp;
626 *keep_going = 0;
627
628 if (ndp->ni_vp == NULLVP) {
629 panic("NULL ni_vp in %s\n", __FUNCTION__);
630 }
631
632 if (atroot) {
633 goto nextname;
634 }
635
636#if CONFIG_TRIGGERS
637 if (dp->v_resolve) {
638 error = vnode_trigger_resolve(dp, ndp, ctx);
639 if (error) {
640 goto out;
641 }
642 }
643#endif /* CONFIG_TRIGGERS */
644
645 /*
646 * Take into account any additional components consumed by
647 * the underlying filesystem.
648 */
649 if (cnp->cn_consume > 0) {
650 cnp->cn_nameptr += cnp->cn_consume;
651 ndp->ni_next += cnp->cn_consume;
652 ndp->ni_pathlen -= cnp->cn_consume;
653 cnp->cn_consume = 0;
654 } else {
655 lookup_consider_update_cache(ndp->ni_dvp, dp, cnp, nc_generation);
656 }
657
658 /*
659 * Check to see if the vnode has been mounted on...
660 * if so find the root of the mounted file system.
661 * Updates ndp->ni_vp.
662 */
663 error = lookup_traverse_mountpoints(ndp, cnp, dp, vbusyflags, ctx);
664 dp = ndp->ni_vp;
665 if (error) {
666 goto out;
667 }
668
669#if CONFIG_MACF
670 if (vfs_flags(vnode_mount(dp)) & MNT_MULTILABEL) {
671 error = vnode_label(vnode_mount(dp), NULL, dp, NULL, 0, ctx);
672 if (error)
673 goto out;
674 }
675#endif
676
677 /*
678 * Check for symbolic link
679 */
680 if ((dp->v_type == VLNK) &&
681 ((cnp->cn_flags & FOLLOW) || (ndp->ni_flag & NAMEI_TRAILINGSLASH) || *ndp->ni_next == '/')) {
682 cnp->cn_flags |= ISSYMLINK;
683 *keep_going = 1;
684 return (0);
685 }
686
687 /*
688 * Check for bogus trailing slashes.
689 */
690 if ((ndp->ni_flag & NAMEI_TRAILINGSLASH)) {
691 if (dp->v_type != VDIR) {
692 error = ENOTDIR;
693 goto out;
694 }
695 ndp->ni_flag &= ~(NAMEI_TRAILINGSLASH);
696 }
4b17d6b6
A
697
698#if NAMEDSTREAMS
699 /*
700 * Deny namei/lookup requests to resolve paths that point to shadow files.
701 * Access to shadow files must be conducted by explicit calls to VNOP_LOOKUP
702 * directly, and not use lookup/namei
703 */
704 if (vnode_isshadow (dp)) {
705 error = ENOENT;
706 goto out;
707 }
708#endif
709
6d2010ae
A
710nextname:
711 /*
712 * Not a symbolic link. If more pathname,
713 * continue at next component, else return.
714 *
715 * Definitely have a dvp if there's another slash
716 */
717 if (*ndp->ni_next == '/') {
718 cnp->cn_nameptr = ndp->ni_next + 1;
719 ndp->ni_pathlen--;
720 while (*cnp->cn_nameptr == '/') {
721 cnp->cn_nameptr++;
722 ndp->ni_pathlen--;
723 }
724
725 cp = cnp->cn_nameptr;
726 vnode_put(ndp->ni_dvp);
727 ndp->ni_dvp = NULLVP;
728
729 if (*cp == '\0') {
730 goto emptyname;
731 }
732
733 *keep_going = 1;
734 return 0;
735 }
736
737 /*
738 * Disallow directory write attempts on read-only file systems.
739 */
740 if (rdonly &&
741 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
742 error = EROFS;
743 goto out;
744 }
745
746 /* If SAVESTART is set, we should have a dvp */
747 if (cnp->cn_flags & SAVESTART) {
748 /*
749 * note that we already hold a reference
750 * on both dp and ni_dvp, but for some reason
751 * can't get another one... in this case we
752 * need to do vnode_put on dp in 'bad2'
753 */
754 if ( (vnode_get(ndp->ni_dvp)) ) {
755 error = ENOENT;
756 goto out;
757 }
758 ndp->ni_startdir = ndp->ni_dvp;
759 }
760 if (!wantparent && ndp->ni_dvp) {
761 vnode_put(ndp->ni_dvp);
762 ndp->ni_dvp = NULLVP;
763 }
764
765 if (cnp->cn_flags & AUDITVNPATH1)
766 AUDIT_ARG(vnpath, dp, ARG_VNODE1);
767 else if (cnp->cn_flags & AUDITVNPATH2)
768 AUDIT_ARG(vnpath, dp, ARG_VNODE2);
769
770#if NAMEDRSRCFORK
771 /*
772 * Caller wants the resource fork.
773 */
774 if ((cnp->cn_flags & CN_WANTSRSRCFORK) && (dp != NULLVP)) {
775 error = lookup_handle_rsrc_fork(dp, ndp, cnp, wantparent, ctx);
776 if (error != 0)
777 goto out;
778
779 dp = ndp->ni_vp;
780 }
781#endif
782 if (kdebug_enable)
39236c6e 783 kdebug_lookup(ndp->ni_vp, cnp);
6d2010ae
A
784
785 return 0;
786
787emptyname:
788 error = lookup_handle_emptyname(ndp, cnp, wantparent);
789 if (error != 0)
790 goto out;
791
792 return 0;
793out:
794 return error;
795
796}
797
798/*
799 * Comes in iocount on ni_vp. May overwrite ni_dvp, but doesn't interpret incoming value.
800 */
fe8ab488 801static int
6d2010ae
A
802lookup_handle_emptyname(struct nameidata *ndp, struct componentname *cnp, int wantparent)
803{
804 vnode_t dp;
805 int error = 0;
806
807 dp = ndp->ni_vp;
808 cnp->cn_namelen = 0;
809 /*
810 * A degenerate name (e.g. / or "") which is a way of
811 * talking about a directory, e.g. like "/." or ".".
812 */
813 if (dp->v_type != VDIR) {
814 error = ENOTDIR;
815 goto out;
816 }
817 if (cnp->cn_nameiop != LOOKUP) {
818 error = EISDIR;
819 goto out;
820 }
821 if (wantparent) {
822 /*
823 * note that we already hold a reference
824 * on dp, but for some reason can't
825 * get another one... in this case we
826 * need to do vnode_put on dp in 'bad'
827 */
828 if ( (vnode_get(dp)) ) {
829 error = ENOENT;
830 goto out;
831 }
832 ndp->ni_dvp = dp;
833 }
834 cnp->cn_flags &= ~ISDOTDOT;
835 cnp->cn_flags |= ISLASTCN;
836 ndp->ni_next = cnp->cn_nameptr;
837 ndp->ni_vp = dp;
838
839 if (cnp->cn_flags & AUDITVNPATH1)
840 AUDIT_ARG(vnpath, dp, ARG_VNODE1);
841 else if (cnp->cn_flags & AUDITVNPATH2)
842 AUDIT_ARG(vnpath, dp, ARG_VNODE2);
843 if (cnp->cn_flags & SAVESTART)
844 panic("lookup: SAVESTART");
845
846 return 0;
847out:
848 return error;
849}
850/*
851 * Search a pathname.
852 * This is a very central and rather complicated routine.
853 *
854 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
855 * The starting directory is taken from ni_startdir. The pathname is
856 * descended until done, or a symbolic link is encountered. The variable
857 * ni_more is clear if the path is completed; it is set to one if a
858 * symbolic link needing interpretation is encountered.
859 *
860 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
861 * whether the name is to be looked up, created, renamed, or deleted.
862 * When CREATE, RENAME, or DELETE is specified, information usable in
863 * creating, renaming, or deleting a directory entry may be calculated.
864 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
865 * locked. If flag has WANTPARENT or'ed into it, the parent directory is
866 * returned unlocked. Otherwise the parent directory is not returned. If
867 * the target of the pathname exists and LOCKLEAF is or'ed into the flag
868 * the target is returned locked, otherwise it is returned unlocked.
869 * When creating or renaming and LOCKPARENT is specified, the target may not
870 * be ".". When deleting and LOCKPARENT is specified, the target may be ".".
871 *
872 * Overall outline of lookup:
873 *
874 * dirloop:
875 * identify next component of name at ndp->ni_ptr
876 * handle degenerate case where name is null string
877 * if .. and crossing mount points and on mounted filesys, find parent
878 * call VNOP_LOOKUP routine for next component name
879 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
880 * component vnode returned in ni_vp (if it exists), locked.
881 * if result vnode is mounted on and crossing mount points,
882 * find mounted on vnode
883 * if more components of name, do next level at dirloop
884 * return the answer in ni_vp, locked if LOCKLEAF set
885 * if LOCKPARENT set, return locked parent in ni_dvp
886 * if WANTPARENT set, return unlocked parent in ni_dvp
887 *
888 * Returns: 0 Success
889 * ENOENT No such file or directory
890 * EBADF Bad file descriptor
891 * ENOTDIR Not a directory
892 * EROFS Read-only file system [CREATE]
893 * EISDIR Is a directory [CREATE]
894 * cache_lookup_path:ERECYCLE (vnode was recycled from underneath us, redrive lookup again)
895 * vnode_authorize:EROFS
896 * vnode_authorize:EACCES
897 * vnode_authorize:EPERM
898 * vnode_authorize:???
899 * VNOP_LOOKUP:ENOENT No such file or directory
900 * VNOP_LOOKUP:EJUSTRETURN Restart system call (INTERNAL)
901 * VNOP_LOOKUP:???
902 * VFS_ROOT:ENOTSUP
903 * VFS_ROOT:ENOENT
904 * VFS_ROOT:???
905 */
906int
907lookup(struct nameidata *ndp)
908{
909 char *cp; /* pointer into pathname argument */
910 vnode_t tdp; /* saved dp */
911 vnode_t dp; /* the directory we are searching */
912 int docache = 1; /* == 0 do not cache last component */
913 int wantparent; /* 1 => wantparent or lockparent flag */
914 int rdonly; /* lookup read-only flag bit */
915 int dp_authorized = 0;
916 int error = 0;
917 struct componentname *cnp = &ndp->ni_cnd;
918 vfs_context_t ctx = cnp->cn_context;
919 int vbusyflags = 0;
920 int nc_generation = 0;
921 vnode_t last_dp = NULLVP;
922 int keep_going;
923 int atroot;
924
925 /*
926 * Setup: break out flag bits into variables.
927 */
fe8ab488
A
928 if (cnp->cn_flags & NOCACHE) {
929 docache = 0;
6d2010ae
A
930 }
931 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
932 rdonly = cnp->cn_flags & RDONLY;
933 cnp->cn_flags &= ~ISSYMLINK;
934 cnp->cn_consume = 0;
935
936 dp = ndp->ni_startdir;
937 ndp->ni_startdir = NULLVP;
938
939 if ((cnp->cn_flags & CN_NBMOUNTLOOK) != 0)
940 vbusyflags = LK_NOWAIT;
941 cp = cnp->cn_nameptr;
942
943 if (*cp == '\0') {
944 if ( (vnode_getwithref(dp)) ) {
945 dp = NULLVP;
946 error = ENOENT;
947 goto bad;
948 }
949 ndp->ni_vp = dp;
950 error = lookup_handle_emptyname(ndp, cnp, wantparent);
951 if (error) {
952 goto bad;
953 }
954
955 return 0;
956 }
957dirloop:
958 atroot = 0;
959 ndp->ni_vp = NULLVP;
960
961 if ( (error = cache_lookup_path(ndp, cnp, dp, ctx, &dp_authorized, last_dp)) ) {
962 dp = NULLVP;
963 goto bad;
964 }
965 if ((cnp->cn_flags & ISLASTCN)) {
966 if (docache)
967 cnp->cn_flags |= MAKEENTRY;
968 } else
969 cnp->cn_flags |= MAKEENTRY;
970
971 dp = ndp->ni_dvp;
972
973 if (ndp->ni_vp != NULLVP) {
974 /*
975 * cache_lookup_path returned a non-NULL ni_vp then,
976 * we're guaranteed that the dp is a VDIR, it's
977 * been authorized, and vp is not ".."
978 *
979 * make sure we don't try to enter the name back into
980 * the cache if this vp is purged before we get to that
981 * check since we won't have serialized behind whatever
982 * activity is occurring in the FS that caused the purge
983 */
984 if (dp != NULLVP)
985 nc_generation = dp->v_nc_generation - 1;
986
987 goto returned_from_lookup_path;
9bccf70c 988 }
1c79356b 989
1c79356b
A
990 /*
991 * Handle "..": two special cases.
992 * 1. If at root directory (e.g. after chroot)
993 * or at absolute root directory
994 * then ignore it so can't get out.
995 * 2. If this vnode is the root of a mounted
996 * filesystem, then replace it with the
997 * vnode which was mounted on so we take the
998 * .. in the other file system.
999 */
91447636 1000 if ( (cnp->cn_flags & ISDOTDOT) ) {
1c79356b 1001 for (;;) {
91447636
A
1002 if (dp == ndp->ni_rootdir || dp == rootvnode) {
1003 ndp->ni_dvp = dp;
1c79356b 1004 ndp->ni_vp = dp;
91447636
A
1005 /*
1006 * we're pinned at the root
1007 * we've already got one reference on 'dp'
1008 * courtesy of cache_lookup_path... take
1009 * another one for the ".."
1010 * if we fail to get the new reference, we'll
1011 * drop our original down in 'bad'
1012 */
1013 if ( (vnode_get(dp)) ) {
1014 error = ENOENT;
1015 goto bad;
1016 }
6d2010ae
A
1017 atroot = 1;
1018 goto returned_from_lookup_path;
1c79356b
A
1019 }
1020 if ((dp->v_flag & VROOT) == 0 ||
1021 (cnp->cn_flags & NOCROSSMOUNT))
91447636 1022 break;
0b4e3aa0 1023 if (dp->v_mount == NULL) { /* forced umount */
91447636 1024 error = EBADF;
0b4e3aa0
A
1025 goto bad;
1026 }
1c79356b 1027 tdp = dp;
91447636
A
1028 dp = tdp->v_mount->mnt_vnodecovered;
1029
1030 vnode_put(tdp);
1031
1032 if ( (vnode_getwithref(dp)) ) {
1033 dp = NULLVP;
1034 error = ENOENT;
1035 goto bad;
1036 }
1037 ndp->ni_dvp = dp;
1038 dp_authorized = 0;
1c79356b
A
1039 }
1040 }
1041
1042 /*
1043 * We now have a segment name to search for, and a directory to search.
1044 */
1045unionlookup:
91447636
A
1046 ndp->ni_vp = NULLVP;
1047
1048 if (dp->v_type != VDIR) {
1049 error = ENOTDIR;
1050 goto lookup_error;
1051 }
2d21ac55 1052 if ( (cnp->cn_flags & DONOTAUTH) != DONOTAUTH ) {
6d2010ae
A
1053 error = lookup_authorize_search(dp, cnp, dp_authorized, ctx);
1054 if (error) {
2d21ac55 1055 goto lookup_error;
6d2010ae
A
1056 }
1057 }
1058
1059 /*
1060 * Now that we've authorized a lookup, can bail out if the filesystem
1061 * will be doing a batched operation. Return an iocount on dvp.
1062 */
1063#if NAMEDRSRCFORK
39236c6e 1064 if ((cnp->cn_flags & ISLASTCN) && namei_compound_available(dp, ndp) && !(cnp->cn_flags & CN_WANTSRSRCFORK)) {
6d2010ae
A
1065#else
1066 if ((cnp->cn_flags & ISLASTCN) && namei_compound_available(dp, ndp)) {
1067#endif /* NAMEDRSRCFORK */
1068 ndp->ni_flag |= NAMEI_UNFINISHED;
1069 ndp->ni_ncgeneration = dp->v_nc_generation;
1070 return 0;
91447636 1071 }
2d21ac55
A
1072
1073 nc_generation = dp->v_nc_generation;
1074
39236c6e
A
1075 /*
1076 * Note:
1077 * Filesystems that support hardlinks may want to call vnode_update_identity
1078 * if the lookup operation below will modify the in-core vnode to belong to a new point
1079 * in the namespace. VFS cannot infer whether or not the look up operation makes the vnode
1080 * name change or change parents. Without this, the lookup may make update
1081 * filesystem-specific in-core metadata but fail to update the v_parent or v_name
1082 * fields in the vnode. If VFS were to do this, it would be necessary to call
1083 * vnode_update_identity on every lookup operation -- expensive!
1084 *
1085 * However, even with this in place, multiple lookups may occur in between this lookup
1086 * and the subsequent vnop, so, at best, we could only guarantee that you would get a
1087 * valid path back, and not necessarily the one that you wanted.
1088 *
1089 * Example:
1090 * /tmp/a == /foo/b
1091 *
1092 * If you are now looking up /foo/b and the vnode for this link represents /tmp/a,
1093 * vnode_update_identity will fix the parentage so that you can get /foo/b back
1094 * through the v_parent chain (preventing you from getting /tmp/b back). It would
1095 * not fix whether or not you should or should not get /tmp/a vs. /foo/b.
1096 */
6d2010ae 1097
39236c6e 1098 error = VNOP_LOOKUP(dp, &ndp->ni_vp, cnp, ctx);
6d2010ae
A
1099
1100 if ( error ) {
91447636 1101lookup_error:
1c79356b 1102 if ((error == ENOENT) &&
39236c6e 1103 (dp->v_mount != NULL) &&
1c79356b
A
1104 (dp->v_mount->mnt_flag & MNT_UNION)) {
1105 tdp = dp;
39236c6e 1106 error = lookup_traverse_union(tdp, &dp, ctx);
91447636 1107 vnode_put(tdp);
39236c6e 1108 if (error) {
91447636 1109 dp = NULLVP;
91447636
A
1110 goto bad;
1111 }
39236c6e 1112
91447636
A
1113 ndp->ni_dvp = dp;
1114 dp_authorized = 0;
1c79356b
A
1115 goto unionlookup;
1116 }
1117
1118 if (error != EJUSTRETURN)
1119 goto bad;
91447636
A
1120
1121 if (ndp->ni_vp != NULLVP)
1122 panic("leaf should be empty");
1123
39236c6e
A
1124#if NAMEDRSRCFORK
1125 /*
1126 * At this point, error should be EJUSTRETURN.
1127 *
1128 * If CN_WANTSRSRCFORK is set, that implies that the
1129 * underlying filesystem could not find the "parent" of the
1130 * resource fork (the data fork), and we are doing a lookup
1131 * for a CREATE event.
1132 *
1133 * However, this should be converted to an error, as the
1134 * failure to find this parent should disallow further
1135 * progress to try and acquire a resource fork vnode.
1136 */
1137 if (cnp->cn_flags & CN_WANTSRSRCFORK) {
1138 error = ENOENT;
1139 goto bad;
1140 }
1141#endif
1142
6d2010ae
A
1143 error = lookup_validate_creation_path(ndp);
1144 if (error)
9bccf70c 1145 goto bad;
1c79356b
A
1146 /*
1147 * We return with ni_vp NULL to indicate that the entry
1148 * doesn't currently exist, leaving a pointer to the
91447636 1149 * referenced directory vnode in ndp->ni_dvp.
1c79356b
A
1150 */
1151 if (cnp->cn_flags & SAVESTART) {
91447636
A
1152 if ( (vnode_get(ndp->ni_dvp)) ) {
1153 error = ENOENT;
1154 goto bad;
1155 }
1c79356b 1156 ndp->ni_startdir = ndp->ni_dvp;
1c79356b 1157 }
91447636
A
1158 if (!wantparent)
1159 vnode_put(ndp->ni_dvp);
1160
1c79356b
A
1161 if (kdebug_enable)
1162 kdebug_lookup(ndp->ni_dvp, cnp);
1163 return (0);
1164 }
91447636 1165returned_from_lookup_path:
6d2010ae
A
1166 /* We'll always have an iocount on ni_vp when this finishes. */
1167 error = lookup_handle_found_vnode(ndp, cnp, rdonly, vbusyflags, &keep_going, nc_generation, wantparent, atroot, ctx);
1168 if (error != 0) {
1169 goto bad2;
1c79356b
A
1170 }
1171
6d2010ae
A
1172 if (keep_going) {
1173 dp = ndp->ni_vp;
2d21ac55 1174
6d2010ae
A
1175 /* namei() will handle symlinks */
1176 if ((dp->v_type == VLNK) &&
1177 ((cnp->cn_flags & FOLLOW) || (ndp->ni_flag & NAMEI_TRAILINGSLASH) || *ndp->ni_next == '/')) {
1178 return 0;
2d21ac55 1179 }
1c79356b 1180
6d2010ae
A
1181 /*
1182 * Otherwise, there's more path to process.
1183 * cache_lookup_path is now responsible for dropping io ref on dp
1184 * when it is called again in the dirloop. This ensures we hold
1185 * a ref on dp until we complete the next round of lookup.
91447636 1186 */
6d2010ae
A
1187 last_dp = dp;
1188
1189 goto dirloop;
55e303ae 1190 }
91447636 1191
55e303ae 1192 return (0);
1c79356b 1193bad2:
91447636 1194 if (ndp->ni_dvp)
6d2010ae
A
1195 vnode_put(ndp->ni_dvp);
1196
1197 vnode_put(ndp->ni_vp);
91447636
A
1198 ndp->ni_vp = NULLVP;
1199
1200 if (kdebug_enable)
1201 kdebug_lookup(dp, cnp);
1202 return (error);
1203
1c79356b 1204bad:
91447636
A
1205 if (dp)
1206 vnode_put(dp);
1207 ndp->ni_vp = NULLVP;
1208
1c79356b
A
1209 if (kdebug_enable)
1210 kdebug_lookup(dp, cnp);
1211 return (error);
1212}
1213
39236c6e
A
1214/*
1215 * Given a vnode in a union mount, traverse to the equivalent
1216 * vnode in the underlying mount.
1217 */
1218int
1219lookup_traverse_union(vnode_t dvp, vnode_t *new_dvp, vfs_context_t ctx)
1220{
1221 char *path = NULL, *pp;
1222 const char *name, *np;
1223 int len;
1224 int error = 0;
1225 struct nameidata nd;
1226 vnode_t vp = dvp;
1227
1228 *new_dvp = NULL;
1229
1230 if (vp && vp->v_flag & VROOT) {
1231 *new_dvp = vp->v_mount->mnt_vnodecovered;
1232 if (vnode_getwithref(*new_dvp))
1233 return ENOENT;
1234 return 0;
1235 }
1236
1237 path = (char *) kalloc(MAXPATHLEN);
1238 if (path == NULL) {
1239 error = ENOMEM;
1240 goto done;
1241 }
1242
1243 /*
1244 * Walk back up to the mountpoint following the
1245 * v_parent chain and build a slash-separated path.
1246 * Then lookup that path starting with the covered vnode.
1247 */
1248 pp = path + (MAXPATHLEN - 1);
1249 *pp = '\0';
1250
1251 while (1) {
1252 name = vnode_getname(vp);
1253 if (name == NULL) {
1254 printf("lookup_traverse_union: null parent name: .%s\n", pp);
1255 error = ENOENT;
1256 goto done;
1257 }
1258 len = strlen(name);
1259 if ((len + 1) > (pp - path)) { // Enough space for this name ?
1260 error = ENAMETOOLONG;
1261 vnode_putname(name);
1262 goto done;
1263 }
1264 for (np = name + len; len > 0; len--) // Copy name backwards
1265 *--pp = *--np;
1266 vnode_putname(name);
1267 vp = vp->v_parent;
1268 if (vp == NULLVP || vp->v_flag & VROOT)
1269 break;
1270 *--pp = '/';
1271 }
1272
1273 /* Evaluate the path in the underlying mount */
1274 NDINIT(&nd, LOOKUP, OP_LOOKUP, USEDVP, UIO_SYSSPACE, CAST_USER_ADDR_T(pp), ctx);
1275 nd.ni_dvp = dvp->v_mount->mnt_vnodecovered;
1276 error = namei(&nd);
1277 if (error == 0)
1278 *new_dvp = nd.ni_vp;
1279 nameidone(&nd);
1280done:
1281 if (path)
1282 kfree(path, MAXPATHLEN);
1283 return error;
1284}
1285
6d2010ae
A
1286int
1287lookup_validate_creation_path(struct nameidata *ndp)
1288{
1289 struct componentname *cnp = &ndp->ni_cnd;
1290
1291 /*
1292 * If creating and at end of pathname, then can consider
1293 * allowing file to be created.
1294 */
1295 if (cnp->cn_flags & RDONLY) {
1296 return EROFS;
1297 }
1298 if ((cnp->cn_flags & ISLASTCN) && (ndp->ni_flag & NAMEI_TRAILINGSLASH) && !(cnp->cn_flags & WILLBEDIR)) {
1299 return ENOENT;
1300 }
1301
1302 return 0;
1303}
1304
1305/*
1306 * Modifies only ni_vp. Always returns with ni_vp still valid (iocount held).
1307 */
fe8ab488 1308static int
6d2010ae
A
1309lookup_traverse_mountpoints(struct nameidata *ndp, struct componentname *cnp, vnode_t dp,
1310 int vbusyflags, vfs_context_t ctx)
1311{
1312 mount_t mp;
1313 vnode_t tdp;
1314 int error = 0;
6d2010ae 1315 uint32_t depth = 0;
6d2010ae
A
1316 vnode_t mounted_on_dp;
1317 int current_mount_generation = 0;
1318
1319 mounted_on_dp = dp;
1320 current_mount_generation = mount_generation;
1321
1322 while ((dp->v_type == VDIR) && dp->v_mountedhere &&
1323 ((cnp->cn_flags & NOCROSSMOUNT) == 0)) {
39236c6e
A
1324
1325 if (dp->v_mountedhere->mnt_lflag & MNT_LFORCE) {
1326 break; // don't traverse into a forced unmount
1327 }
6d2010ae
A
1328#if CONFIG_TRIGGERS
1329 /*
1330 * For a trigger vnode, call its resolver when crossing its mount (if requested)
1331 */
1332 if (dp->v_resolve) {
1333 (void) vnode_trigger_resolve(dp, ndp, ctx);
1334 }
1335#endif
1336 vnode_lock(dp);
1337
1338 if ((dp->v_type == VDIR) && (mp = dp->v_mountedhere)) {
1339
1340 mp->mnt_crossref++;
1341 vnode_unlock(dp);
1342
1343
1344 if (vfs_busy(mp, vbusyflags)) {
1345 mount_dropcrossref(mp, dp, 0);
1346 if (vbusyflags == LK_NOWAIT) {
1347 error = ENOENT;
1348 goto out;
1349 }
1350
1351 continue;
1352 }
1353
6d2010ae 1354 error = VFS_ROOT(mp, &tdp, ctx);
6d2010ae
A
1355
1356 mount_dropcrossref(mp, dp, 0);
1357 vfs_unbusy(mp);
1358
1359 if (error) {
1360 goto out;
1361 }
1362
1363 vnode_put(dp);
1364 ndp->ni_vp = dp = tdp;
1365 depth++;
1366
1367#if CONFIG_TRIGGERS
1368 /*
1369 * Check if root dir is a trigger vnode
1370 */
1371 if (dp->v_resolve) {
1372 error = vnode_trigger_resolve(dp, ndp, ctx);
1373 if (error) {
1374 goto out;
1375 }
1376 }
1377#endif
1378
1379 } else {
1380 vnode_unlock(dp);
1381 break;
1382 }
1383 }
1384
fe8ab488 1385 if (depth) {
6d2010ae
A
1386 mp = mounted_on_dp->v_mountedhere;
1387
1388 if (mp) {
1389 mount_lock_spin(mp);
1390 mp->mnt_realrootvp_vid = dp->v_id;
1391 mp->mnt_realrootvp = dp;
1392 mp->mnt_generation = current_mount_generation;
1393 mount_unlock(mp);
1394 }
1395 }
1396
1397 return 0;
1398
1399out:
1400 return error;
1401}
1402
1403/*
1404 * Takes ni_vp and ni_dvp non-NULL. Returns with *new_dp set to the location
1405 * at which to start a lookup with a resolved path, and all other iocounts dropped.
1406 */
fe8ab488 1407static int
6d2010ae
A
1408lookup_handle_symlink(struct nameidata *ndp, vnode_t *new_dp, vfs_context_t ctx)
1409{
1410 int error;
1411 char *cp; /* pointer into pathname argument */
1412 uio_t auio;
1413 char uio_buf[ UIO_SIZEOF(1) ];
1414 int need_newpathbuf;
1415 u_int linklen;
1416 struct componentname *cnp = &ndp->ni_cnd;
1417 vnode_t dp;
1418 char *tmppn;
1419
6d2010ae
A
1420 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
1421 return ELOOP;
1422 }
1423#if CONFIG_MACF
1424 if ((error = mac_vnode_check_readlink(ctx, ndp->ni_vp)) != 0)
1425 return error;
1426#endif /* MAC */
1427 if (ndp->ni_pathlen > 1 || !(cnp->cn_flags & HASBUF))
1428 need_newpathbuf = 1;
1429 else
1430 need_newpathbuf = 0;
1431
1432 if (need_newpathbuf) {
1433 MALLOC_ZONE(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1434 if (cp == NULL) {
1435 return ENOMEM;
1436 }
1437 } else {
1438 cp = cnp->cn_pnbuf;
1439 }
1440 auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_READ, &uio_buf[0], sizeof(uio_buf));
1441
1442 uio_addiov(auio, CAST_USER_ADDR_T(cp), MAXPATHLEN);
1443
1444 error = VNOP_READLINK(ndp->ni_vp, auio, ctx);
1445 if (error) {
1446 if (need_newpathbuf)
1447 FREE_ZONE(cp, MAXPATHLEN, M_NAMEI);
1448 return error;
1449 }
1450
1451 /*
1452 * Safe to set unsigned with a [larger] signed type here
1453 * because 0 <= uio_resid <= MAXPATHLEN and MAXPATHLEN
1454 * is only 1024.
1455 */
1456 linklen = MAXPATHLEN - (u_int)uio_resid(auio);
1457 if (linklen + ndp->ni_pathlen > MAXPATHLEN) {
1458 if (need_newpathbuf)
1459 FREE_ZONE(cp, MAXPATHLEN, M_NAMEI);
1460
1461 return ENAMETOOLONG;
1462 }
1463 if (need_newpathbuf) {
1464 long len = cnp->cn_pnlen;
1465
1466 tmppn = cnp->cn_pnbuf;
1467 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
1468 cnp->cn_pnbuf = cp;
1469 cnp->cn_pnlen = MAXPATHLEN;
1470
1471 if ( (cnp->cn_flags & HASBUF) )
1472 FREE_ZONE(tmppn, len, M_NAMEI);
1473 else
1474 cnp->cn_flags |= HASBUF;
1475 } else
1476 cnp->cn_pnbuf[linklen] = '\0';
1477
1478 ndp->ni_pathlen += linklen;
1479 cnp->cn_nameptr = cnp->cn_pnbuf;
1480
1481 /*
1482 * starting point for 'relative'
1483 * symbolic link path
1484 */
1485 dp = ndp->ni_dvp;
1486
1487 /*
1488 * get rid of references returned via 'lookup'
1489 */
1490 vnode_put(ndp->ni_vp);
1491 vnode_put(ndp->ni_dvp); /* ALWAYS have a dvp for a symlink */
1492
1493 ndp->ni_vp = NULLVP;
1494 ndp->ni_dvp = NULLVP;
1495
1496 /*
1497 * Check if symbolic link restarts us at the root
1498 */
1499 if (*(cnp->cn_nameptr) == '/') {
1500 while (*(cnp->cn_nameptr) == '/') {
1501 cnp->cn_nameptr++;
1502 ndp->ni_pathlen--;
1503 }
1504 if ((dp = ndp->ni_rootdir) == NULLVP) {
1505 return ENOENT;
1506 }
1507 }
1508
1509 *new_dp = dp;
1510
1511 return 0;
1512}
1513
1c79356b
A
1514/*
1515 * relookup - lookup a path name component
1516 * Used by lookup to re-aquire things.
1517 */
1518int
2d21ac55 1519relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
1c79356b 1520{
2d21ac55 1521 struct vnode *dp = NULL; /* the directory we are searching */
1c79356b
A
1522 int wantparent; /* 1 => wantparent or lockparent flag */
1523 int rdonly; /* lookup read-only flag bit */
1524 int error = 0;
1525#ifdef NAMEI_DIAGNOSTIC
55e303ae 1526 int i, newhash; /* DEBUG: check name hash */
1c79356b
A
1527 char *cp; /* DEBUG: check name ptr/len */
1528#endif
91447636 1529 vfs_context_t ctx = cnp->cn_context;;
1c79356b
A
1530
1531 /*
1532 * Setup: break out flag bits into variables.
1533 */
1534 wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
1c79356b
A
1535 rdonly = cnp->cn_flags & RDONLY;
1536 cnp->cn_flags &= ~ISSYMLINK;
1c79356b 1537
91447636
A
1538 if (cnp->cn_flags & NOCACHE)
1539 cnp->cn_flags &= ~MAKEENTRY;
1540 else
1541 cnp->cn_flags |= MAKEENTRY;
1542
1543 dp = dvp;
1c79356b
A
1544
1545 /*
1546 * Check for degenerate name (e.g. / or "")
1547 * which is a way of talking about a directory,
1548 * e.g. like "/." or ".".
1549 */
1550 if (cnp->cn_nameptr[0] == '\0') {
1551 if (cnp->cn_nameiop != LOOKUP || wantparent) {
1552 error = EISDIR;
1553 goto bad;
1554 }
1555 if (dp->v_type != VDIR) {
1556 error = ENOTDIR;
1557 goto bad;
1558 }
91447636
A
1559 if ( (vnode_get(dp)) ) {
1560 error = ENOENT;
1561 goto bad;
1562 }
1c79356b 1563 *vpp = dp;
91447636 1564
1c79356b
A
1565 if (cnp->cn_flags & SAVESTART)
1566 panic("lookup: SAVESTART");
1567 return (0);
1568 }
1c79356b
A
1569 /*
1570 * We now have a segment name to search for, and a directory to search.
1571 */
91447636
A
1572 if ( (error = VNOP_LOOKUP(dp, vpp, cnp, ctx)) ) {
1573 if (error != EJUSTRETURN)
1574 goto bad;
1c79356b
A
1575#if DIAGNOSTIC
1576 if (*vpp != NULL)
1577 panic("leaf should be empty");
1578#endif
1c79356b
A
1579 /*
1580 * If creating and at end of pathname, then can consider
1581 * allowing file to be created.
1582 */
1583 if (rdonly) {
1584 error = EROFS;
1585 goto bad;
1586 }
1c79356b
A
1587 /*
1588 * We return with ni_vp NULL to indicate that the entry
1589 * doesn't currently exist, leaving a pointer to the
1590 * (possibly locked) directory inode in ndp->ni_dvp.
1591 */
1592 return (0);
1593 }
1594 dp = *vpp;
1595
1596#if DIAGNOSTIC
1597 /*
1598 * Check for symbolic link
1599 */
1600 if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW))
1601 panic ("relookup: symlink found.\n");
1602#endif
1603
1604 /*
1605 * Disallow directory write attempts on read-only file systems.
1606 */
1607 if (rdonly &&
1608 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
1609 error = EROFS;
1610 goto bad2;
1611 }
1612 /* ASSERT(dvp == ndp->ni_startdir) */
1c79356b 1613
1c79356b
A
1614 return (0);
1615
1616bad2:
91447636
A
1617 vnode_put(dp);
1618bad:
1c79356b 1619 *vpp = NULL;
91447636 1620
1c79356b
A
1621 return (error);
1622}
1623
6d2010ae
A
1624/*
1625 * Free pathname buffer
1626 */
1627void
1628nameidone(struct nameidata *ndp)
1629{
91447636
A
1630 if (ndp->ni_cnd.cn_flags & HASBUF) {
1631 char *tmp = ndp->ni_cnd.cn_pnbuf;
1632
1633 ndp->ni_cnd.cn_pnbuf = NULL;
1634 ndp->ni_cnd.cn_flags &= ~HASBUF;
1635 FREE_ZONE(tmp, ndp->ni_cnd.cn_pnlen, M_NAMEI);
1636 }
1637}
1638
1c79356b 1639
2d21ac55
A
1640/*
1641 * Log (part of) a pathname using the KERNEL_DEBUG_CONSTANT mechanism, as used
1642 * by fs_usage. The path up to and including the current component name are
1643 * logged. Up to NUMPARMS*4 bytes of pathname will be logged. If the path
1644 * to be logged is longer than that, then the last NUMPARMS*4 bytes are logged.
1645 * That is, the truncation removes the leading portion of the path.
1646 *
1647 * The logging is done via multiple KERNEL_DEBUG_CONSTANT calls. The first one
1648 * is marked with DBG_FUNC_START. The last one is marked with DBG_FUNC_END
1649 * (in addition to DBG_FUNC_START if it is also the first). There may be
1650 * intermediate ones with neither DBG_FUNC_START nor DBG_FUNC_END.
1651 *
1652 * The first KERNEL_DEBUG_CONSTANT passes the vnode pointer and 12 bytes of
1653 * pathname. The remaining KERNEL_DEBUG_CONSTANT calls add 16 bytes of pathname
1654 * each. The minimum number of KERNEL_DEBUG_CONSTANT calls required to pass
1655 * the path are used. Any excess padding in the final KERNEL_DEBUG_CONSTANT
1656 * (because not all of the 12 or 16 bytes are needed for the remainder of the
1657 * path) is set to zero bytes, or '>' if there is more path beyond the
1658 * current component name (usually because an intermediate component was not
1659 * found).
1660 *
1661 * NOTE: If the path length is greater than NUMPARMS*4, or is not of the form
1662 * 12+N*16, there will be no padding.
1663 *
1664 * TODO: If there is more path beyond the current component name, should we
1665 * force some padding? For example, a lookup for /foo_bar_baz/spam that
1666 * fails because /foo_bar_baz is not found will only log "/foo_bar_baz", with
1667 * no '>' padding. But /foo_bar/spam would log "/foo_bar>>>>".
1668 */
316670eb 1669#if (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST)
39236c6e
A
1670
1671void
1672kdebug_lookup_gen_events(long *dbg_parms, int dbg_namelen, void *dp, boolean_t lookup)
1c79356b 1673{
2d21ac55 1674 int code;
39236c6e
A
1675 unsigned int i;
1676
1677 /*
1678 * In the event that we collect multiple, consecutive pathname
1679 * entries, we must mark the start of the path's string and the end.
1680 */
1681 if (lookup == TRUE)
04b8595b 1682 code = VFS_LOOKUP | DBG_FUNC_START;
39236c6e 1683 else
04b8595b 1684 code = VFS_LOOKUP_DONE | DBG_FUNC_START;
39236c6e
A
1685
1686 if (dbg_namelen <= (int)(3 * sizeof(long)))
1687 code |= DBG_FUNC_END;
1688
1689 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, VM_KERNEL_ADDRPERM(dp), dbg_parms[0], dbg_parms[1], dbg_parms[2], 0);
1690
1691 code &= ~DBG_FUNC_START;
1692
1693 for (i=3, dbg_namelen -= (3 * sizeof(long)); dbg_namelen > 0; i+=4, dbg_namelen -= (4 * sizeof(long))) {
1694 if (dbg_namelen <= (int)(4 * sizeof(long)))
1695 code |= DBG_FUNC_END;
1696
1697 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, code, dbg_parms[i], dbg_parms[i+1], dbg_parms[i+2], dbg_parms[i+3], 0);
1698 }
1699}
1700
1701static void
1702kdebug_lookup(vnode_t dp, struct componentname *cnp)
1703{
2d21ac55
A
1704 int dbg_namelen;
1705 char *dbg_nameptr;
1c79356b 1706 long dbg_parms[NUMPARMS];
1c79356b
A
1707
1708 /* Collect the pathname for tracing */
1709 dbg_namelen = (cnp->cn_nameptr - cnp->cn_pnbuf) + cnp->cn_namelen;
1710 dbg_nameptr = cnp->cn_nameptr + cnp->cn_namelen;
1711
2d21ac55
A
1712 if (dbg_namelen > (int)sizeof(dbg_parms))
1713 dbg_namelen = sizeof(dbg_parms);
1c79356b 1714 dbg_nameptr -= dbg_namelen;
2d21ac55
A
1715
1716 /* Copy the (possibly truncated) path itself */
1717 memcpy(dbg_parms, dbg_nameptr, dbg_namelen);
1718
1719 /* Pad with '\0' or '>' */
1720 if (dbg_namelen < (int)sizeof(dbg_parms)) {
1721 memset((char *)dbg_parms + dbg_namelen,
1722 *(cnp->cn_nameptr + cnp->cn_namelen) ? '>' : 0,
1723 sizeof(dbg_parms) - dbg_namelen);
1c79356b 1724 }
39236c6e
A
1725 kdebug_lookup_gen_events(dbg_parms, dbg_namelen, (void *)dp, TRUE);
1726}
0c530ab8 1727
39236c6e 1728#else /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */
0c530ab8 1729
39236c6e
A
1730void
1731kdebug_lookup_gen_events(long *dbg_parms __unused, int dbg_namelen __unused, void *dp __unused)
1732{
2d21ac55 1733}
39236c6e 1734
6d2010ae
A
1735static void
1736kdebug_lookup(struct vnode *dp __unused, struct componentname *cnp __unused)
1737{
1738}
316670eb 1739#endif /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */
6d2010ae
A
1740
1741int
1742vfs_getbyid(fsid_t *fsid, ino64_t ino, vnode_t *vpp, vfs_context_t ctx)
1743{
1744 mount_t mp;
1745 int error;
1746
1747 mp = mount_lookupby_volfsid(fsid->val[0], 1);
1748 if (mp == NULL) {
1749 return EINVAL;
1750 }
1751
1752 /* Get the target vnode. */
1753 if (ino == 2) {
1754 error = VFS_ROOT(mp, vpp, ctx);
1755 } else {
1756 error = VFS_VGET(mp, ino, vpp, ctx);
1757 }
0c530ab8 1758
6d2010ae
A
1759 vfs_unbusy(mp);
1760 return error;
1761}
2d21ac55
A
1762/*
1763 * Obtain the real path from a legacy volfs style path.
1764 *
1765 * Valid formats of input path:
1766 *
1767 * "555/@"
1768 * "555/2"
1769 * "555/123456"
1770 * "555/123456/foobar"
1771 *
1772 * Where:
1773 * 555 represents the volfs file system id
1774 * '@' and '2' are aliases to the root of a file system
1775 * 123456 represents a file id
1776 * "foobar" represents a file name
1777 */
1778#if CONFIG_VOLFS
1779static int
1780vfs_getrealpath(const char * path, char * realpath, size_t bufsize, vfs_context_t ctx)
1781{
1782 vnode_t vp;
1783 struct mount *mp = NULL;
1784 char *str;
1785 char ch;
b0d623f7 1786 uint32_t id;
2d21ac55
A
1787 ino64_t ino;
1788 int error;
1789 int length;
1790
1791 /* Get file system id and move str to next component. */
1792 id = strtoul(path, &str, 10);
1793 if (id == 0 || str[0] != '/') {
1794 return (EINVAL);
1795 }
1796 while (*str == '/') {
1797 str++;
0c530ab8 1798 }
2d21ac55
A
1799 ch = *str;
1800
1801 mp = mount_lookupby_volfsid(id, 1);
1802 if (mp == NULL) {
1803 return (EINVAL); /* unexpected failure */
1804 }
1805 /* Check for an alias to a file system root. */
1806 if (ch == '@' && str[1] == '\0') {
1807 ino = 2;
1808 str++;
1809 } else {
1810 /* Get file id and move str to next component. */
1811 ino = strtouq(str, &str, 10);
1812 }
1813
1814 /* Get the target vnode. */
1815 if (ino == 2) {
1816 error = VFS_ROOT(mp, &vp, ctx);
1817 } else {
1818 error = VFS_VGET(mp, ino, &vp, ctx);
1819 }
1820 vfs_unbusy(mp);
1821 if (error) {
1822 goto out;
1823 }
1824 realpath[0] = '\0';
1825
1826 /* Get the absolute path to this vnode. */
1827 error = build_path(vp, realpath, bufsize, &length, 0, ctx);
1828 vnode_put(vp);
1829
1830 if (error == 0 && *str != '\0') {
1831 int attempt = strlcat(realpath, str, MAXPATHLEN);
1832 if (attempt > MAXPATHLEN){
1833 error = ENAMETOOLONG;
1834 }
1835 }
1836out:
1837 return (error);
1c79356b 1838}
2d21ac55 1839#endif
6d2010ae
A
1840
1841void
1842lookup_compound_vnop_post_hook(int error, vnode_t dvp, vnode_t vp, struct nameidata *ndp, int did_create)
1843{
1844 if (error == 0 && vp == NULLVP) {
1845 panic("NULL vp with error == 0.\n");
1846 }
1847
1848 /*
1849 * We don't want to do any of this if we didn't use the compound vnop
1850 * to perform the lookup... i.e. if we're allowing and using the legacy pattern,
1851 * where we did a full lookup.
1852 */
1853 if ((ndp->ni_flag & NAMEI_COMPOUND_OP_MASK) == 0) {
1854 return;
1855 }
1856
1857 /*
1858 * If we're going to continue the lookup, we'll handle
1859 * all lookup-related updates at that time.
1860 */
1861 if (error == EKEEPLOOKING) {
1862 return;
1863 }
1864
1865 /*
1866 * Only audit or update cache for *found* vnodes. For creation
1867 * neither would happen in the non-compound-vnop case.
1868 */
1869 if ((vp != NULLVP) && !did_create) {
1870 /*
1871 * If MAKEENTRY isn't set, and we've done a successful compound VNOP,
1872 * then we certainly don't want to update cache or identity.
1873 */
1874 if ((error != 0) || (ndp->ni_cnd.cn_flags & MAKEENTRY)) {
1875 lookup_consider_update_cache(dvp, vp, &ndp->ni_cnd, ndp->ni_ncgeneration);
1876 }
1877 if (ndp->ni_cnd.cn_flags & AUDITVNPATH1)
1878 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
1879 else if (ndp->ni_cnd.cn_flags & AUDITVNPATH2)
1880 AUDIT_ARG(vnpath, vp, ARG_VNODE2);
1881 }
1882
1883 /*
1884 * If you created (whether you opened or not), cut a lookup tracepoint
1885 * for the parent dir (as would happen without a compound vnop). Note: we may need
1886 * a vnode despite failure in this case!
1887 *
1888 * If you did not create:
1889 * Found child (succeeded or not): cut a tracepoint for the child.
1890 * Did not find child: cut a tracepoint with the parent.
1891 */
1892 if (kdebug_enable) {
1893 kdebug_lookup(vp ? vp : dvp, &ndp->ni_cnd);
1894 }
1895}