]> git.saurik.com Git - apple/xnu.git/blame - bsd/vfs/vfs_lookup.c
xnu-792.6.56.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_lookup.c
CommitLineData
1c79356b 1/*
e5568f75 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
ff6e181a
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
1c79356b 12 *
ff6e181a
A
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
ff6e181a
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
1c79356b
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24/*
25 * Copyright (c) 1982, 1986, 1989, 1993
26 * The Regents of the University of California. All rights reserved.
27 * (c) UNIX System Laboratories, Inc.
28 * All or some portions of this file are derived from material licensed
29 * to the University of California by American Telephone and Telegraph
30 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
31 * the permission of UNIX System Laboratories, Inc.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95
62 */
63
64#include <sys/param.h>
55e303ae 65#include <sys/systm.h>
1c79356b
A
66#include <sys/syslimits.h>
67#include <sys/time.h>
68#include <sys/namei.h>
69#include <sys/vm.h>
91447636
A
70#include <sys/vnode_internal.h>
71#include <sys/mount_internal.h>
1c79356b
A
72#include <sys/errno.h>
73#include <sys/malloc.h>
74#include <sys/filedesc.h>
91447636 75#include <sys/proc_internal.h>
1c79356b
A
76#include <sys/kdebug.h>
77#include <sys/unistd.h> /* For _PC_NAME_MAX */
91447636
A
78#include <sys/uio_internal.h>
79#include <sys/kauth.h>
e5568f75
A
80
81#include <bsm/audit_kernel.h>
1c79356b
A
82
83#if KTRACE
84#include <sys/ktrace.h>
85#endif
86
91447636
A
87
88static void kdebug_lookup(struct vnode *dp, struct componentname *cnp);
55e303ae 89
1c79356b
A
90/*
91 * Convert a pathname into a pointer to a locked inode.
92 *
93 * The FOLLOW flag is set when symbolic links are to be followed
94 * when they occur at the end of the name translation process.
95 * Symbolic links are always followed for all other pathname
96 * components other than the last.
97 *
98 * The segflg defines whether the name is to be copied from user
99 * space or kernel space.
100 *
101 * Overall outline of namei:
102 *
103 * copy in name
104 * get starting directory
105 * while (!done && !error) {
106 * call lookup to search path.
107 * if symbolic link, massage name in buffer and continue
108 * }
109 */
91447636 110
1c79356b
A
111int
112namei(ndp)
113 register struct nameidata *ndp;
114{
115 register struct filedesc *fdp; /* pointer to file descriptor state */
116 register char *cp; /* pointer into pathname argument */
117 register struct vnode *dp; /* the directory we are searching */
91447636
A
118 uio_t auio;
119 int error;
1c79356b 120 struct componentname *cnp = &ndp->ni_cnd;
91447636
A
121 vfs_context_t ctx = cnp->cn_context;
122 struct proc *p = vfs_context_proc(ctx);
55e303ae 123 char *tmppn;
91447636 124 char uio_buf[ UIO_SIZEOF(1) ];
1c79356b 125
1c79356b 126#if DIAGNOSTIC
91447636 127 if (!vfs_context_ucred(ctx) || !p)
1c79356b
A
128 panic ("namei: bad cred/proc");
129 if (cnp->cn_nameiop & (~OPMASK))
130 panic ("namei: nameiop contaminated with flags");
131 if (cnp->cn_flags & OPMASK)
132 panic ("namei: flags contaminated with nameiops");
133#endif
55e303ae 134 fdp = p->p_fd;
1c79356b
A
135
136 /*
137 * Get a buffer for the name to be translated, and copy the
138 * name into the buffer.
139 */
140 if ((cnp->cn_flags & HASBUF) == 0) {
91447636
A
141 cnp->cn_pnbuf = &ndp->ni_pathbuf;
142 cnp->cn_pnlen = PATHBUFLEN;
1c79356b 143 }
91447636
A
144#if LP64_DEBUG
145 if (IS_VALID_UIO_SEGFLG(ndp->ni_segflg) == 0) {
146 panic("%s :%d - invalid ni_segflg\n", __FILE__, __LINE__);
147 }
148#endif /* LP64_DEBUG */
149
150retry_copy:
151 if (UIO_SEG_IS_USER_SPACE(ndp->ni_segflg))
1c79356b 152 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
91447636
A
153 cnp->cn_pnlen, (size_t *)&ndp->ni_pathlen);
154 else
155 error = copystr(CAST_DOWN(void *, ndp->ni_dirp), cnp->cn_pnbuf,
156 cnp->cn_pnlen, (size_t *)&ndp->ni_pathlen);
157
158 if (error == ENAMETOOLONG && !(cnp->cn_flags & HASBUF)) {
159 MALLOC_ZONE(cnp->cn_pnbuf, caddr_t,
160 MAXPATHLEN, M_NAMEI, M_WAITOK);
161
162 cnp->cn_flags |= HASBUF;
163 cnp->cn_pnlen = MAXPATHLEN;
164
165 goto retry_copy;
166 }
167 if (error)
168 goto error_out;
55e303ae
A
169
170 /* If we are auditing the kernel pathname, save the user pathname */
171 if (cnp->cn_flags & AUDITVNPATH1)
172 AUDIT_ARG(upath, p, cnp->cn_pnbuf, ARG_UPATH1);
173 if (cnp->cn_flags & AUDITVNPATH2)
174 AUDIT_ARG(upath, p, cnp->cn_pnbuf, ARG_UPATH2);
175
1c79356b
A
176 /*
177 * Do not allow empty pathnames
178 */
91447636 179 if (*cnp->cn_pnbuf == '\0') {
1c79356b 180 error = ENOENT;
91447636 181 goto error_out;
1c79356b
A
182 }
183 ndp->ni_loopcnt = 0;
184#if KTRACE
55e303ae
A
185 if (KTRPOINT(p, KTR_NAMEI))
186 ktrnamei(p->p_tracep, cnp->cn_pnbuf);
1c79356b
A
187#endif
188
189 /*
91447636 190 * determine the starting point for the translation.
1c79356b 191 */
91447636
A
192 if ((ndp->ni_rootdir = fdp->fd_rdir) == NULLVP) {
193 if ( !(fdp->fd_flags & FD_CHROOT))
194 ndp->ni_rootdir = rootvnode;
55e303ae 195 }
91447636 196 cnp->cn_nameptr = cnp->cn_pnbuf;
55e303ae 197
91447636
A
198 ndp->ni_usedvp = NULLVP;
199
200 if (*(cnp->cn_nameptr) == '/') {
201 while (*(cnp->cn_nameptr) == '/') {
202 cnp->cn_nameptr++;
203 ndp->ni_pathlen--;
1c79356b 204 }
91447636
A
205 dp = ndp->ni_rootdir;
206 } else if (cnp->cn_flags & USEDVP) {
207 dp = ndp->ni_dvp;
208 ndp->ni_usedvp = dp;
209 } else
210 dp = fdp->fd_cdir;
211
212 if (dp == NULLVP) {
213 error = ENOENT;
214 goto error_out;
215 }
216 ndp->ni_dvp = NULLVP;
217 ndp->ni_vp = NULLVP;
218
219 for (;;) {
220 int need_newpathbuf;
221 int linklen;
222
1c79356b 223 ndp->ni_startdir = dp;
91447636
A
224
225 if ( (error = lookup(ndp)) ) {
226 goto error_out;
1c79356b
A
227 }
228 /*
229 * Check for symbolic link
230 */
231 if ((cnp->cn_flags & ISSYMLINK) == 0) {
1c79356b
A
232 return (0);
233 }
91447636
A
234 if ((cnp->cn_flags & FSNODELOCKHELD)) {
235 cnp->cn_flags &= ~FSNODELOCKHELD;
236 unlock_fsnode(ndp->ni_dvp, NULL);
237 }
1c79356b
A
238 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
239 error = ELOOP;
240 break;
241 }
91447636
A
242 if (ndp->ni_pathlen > 1 || !(cnp->cn_flags & HASBUF))
243 need_newpathbuf = 1;
244 else
245 need_newpathbuf = 0;
246
247 if (need_newpathbuf) {
1c79356b
A
248 MALLOC_ZONE(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
249 } else {
250 cp = cnp->cn_pnbuf;
251 }
91447636
A
252 auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_READ, &uio_buf[0], sizeof(uio_buf));
253
254 uio_addiov(auio, CAST_USER_ADDR_T(cp), MAXPATHLEN);
255
256 error = VNOP_READLINK(ndp->ni_vp, auio, ctx);
257 if (error) {
258 if (need_newpathbuf)
55e303ae 259 FREE_ZONE(cp, MAXPATHLEN, M_NAMEI);
1c79356b
A
260 break;
261 }
91447636
A
262 // LP64todo - fix this
263 linklen = MAXPATHLEN - uio_resid(auio);
264 if (linklen + ndp->ni_pathlen > MAXPATHLEN) {
265 if (need_newpathbuf)
55e303ae 266 FREE_ZONE(cp, MAXPATHLEN, M_NAMEI);
91447636 267
1c79356b
A
268 error = ENAMETOOLONG;
269 break;
270 }
91447636 271 if (need_newpathbuf) {
55e303ae 272 long len = cnp->cn_pnlen;
91447636 273
55e303ae 274 tmppn = cnp->cn_pnbuf;
1c79356b 275 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
1c79356b
A
276 cnp->cn_pnbuf = cp;
277 cnp->cn_pnlen = MAXPATHLEN;
91447636
A
278
279 if ( (cnp->cn_flags & HASBUF) )
280 FREE_ZONE(tmppn, len, M_NAMEI);
281 else
282 cnp->cn_flags |= HASBUF;
1c79356b
A
283 } else
284 cnp->cn_pnbuf[linklen] = '\0';
91447636 285
1c79356b 286 ndp->ni_pathlen += linklen;
91447636
A
287 cnp->cn_nameptr = cnp->cn_pnbuf;
288
289 /*
290 * starting point for 'relative'
291 * symbolic link path
292 */
1c79356b 293 dp = ndp->ni_dvp;
91447636
A
294 /*
295 * get rid of references returned via 'lookup'
296 */
297 vnode_put(ndp->ni_vp);
298 vnode_put(ndp->ni_dvp);
299
300 ndp->ni_vp = NULLVP;
301 ndp->ni_dvp = NULLVP;
55e303ae 302
91447636
A
303 /*
304 * Check if symbolic link restarts us at the root
305 */
306 if (*(cnp->cn_nameptr) == '/') {
307 while (*(cnp->cn_nameptr) == '/') {
308 cnp->cn_nameptr++;
309 ndp->ni_pathlen--;
310 }
311 if ((dp = ndp->ni_rootdir) == NULLVP) {
312 error = ENOENT;
313 goto error_out;
314 }
315 }
316 }
317 /*
318 * only come here if we fail to handle a SYMLINK...
319 * if either ni_dvp or ni_vp is non-NULL, then
320 * we need to drop the iocount that was picked
321 * up in the lookup routine
322 */
323 if (ndp->ni_dvp)
324 vnode_put(ndp->ni_dvp);
325 if (ndp->ni_vp)
326 vnode_put(ndp->ni_vp);
327 error_out:
328 if ( (cnp->cn_flags & HASBUF) ) {
329 cnp->cn_flags &= ~HASBUF;
330 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
331 }
55e303ae 332 cnp->cn_pnbuf = NULL;
91447636 333 ndp->ni_vp = NULLVP;
55e303ae 334
1c79356b
A
335 return (error);
336}
337
91447636 338
1c79356b
A
339/*
340 * Search a pathname.
341 * This is a very central and rather complicated routine.
342 *
343 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
344 * The starting directory is taken from ni_startdir. The pathname is
345 * descended until done, or a symbolic link is encountered. The variable
346 * ni_more is clear if the path is completed; it is set to one if a
347 * symbolic link needing interpretation is encountered.
348 *
349 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
350 * whether the name is to be looked up, created, renamed, or deleted.
351 * When CREATE, RENAME, or DELETE is specified, information usable in
352 * creating, renaming, or deleting a directory entry may be calculated.
353 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
354 * locked. If flag has WANTPARENT or'ed into it, the parent directory is
355 * returned unlocked. Otherwise the parent directory is not returned. If
356 * the target of the pathname exists and LOCKLEAF is or'ed into the flag
357 * the target is returned locked, otherwise it is returned unlocked.
358 * When creating or renaming and LOCKPARENT is specified, the target may not
359 * be ".". When deleting and LOCKPARENT is specified, the target may be ".".
360 *
361 * Overall outline of lookup:
362 *
363 * dirloop:
364 * identify next component of name at ndp->ni_ptr
365 * handle degenerate case where name is null string
366 * if .. and crossing mount points and on mounted filesys, find parent
91447636 367 * call VNOP_LOOKUP routine for next component name
1c79356b
A
368 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
369 * component vnode returned in ni_vp (if it exists), locked.
370 * if result vnode is mounted on and crossing mount points,
371 * find mounted on vnode
372 * if more components of name, do next level at dirloop
373 * return the answer in ni_vp, locked if LOCKLEAF set
374 * if LOCKPARENT set, return locked parent in ni_dvp
375 * if WANTPARENT set, return unlocked parent in ni_dvp
376 */
377int
378lookup(ndp)
379 register struct nameidata *ndp;
380{
91447636
A
381 register char *cp; /* pointer into pathname argument */
382 vnode_t tdp; /* saved dp */
383 vnode_t dp; /* the directory we are searching */
384 mount_t mp; /* mount table entry */
385 int docache = 1; /* == 0 do not cache last component */
1c79356b
A
386 int wantparent; /* 1 => wantparent or lockparent flag */
387 int rdonly; /* lookup read-only flag bit */
55e303ae 388 int trailing_slash = 0;
91447636 389 int dp_authorized = 0;
1c79356b
A
390 int error = 0;
391 struct componentname *cnp = &ndp->ni_cnd;
91447636 392 vfs_context_t ctx = cnp->cn_context;
1c79356b
A
393
394 /*
395 * Setup: break out flag bits into variables.
396 */
91447636
A
397 if (cnp->cn_flags & (NOCACHE | DOWHITEOUT)) {
398 if ((cnp->cn_flags & NOCACHE) || (cnp->cn_nameiop == DELETE))
399 docache = 0;
400 }
1c79356b 401 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
1c79356b 402 rdonly = cnp->cn_flags & RDONLY;
1c79356b 403 cnp->cn_flags &= ~ISSYMLINK;
91447636
A
404 cnp->cn_consume = 0;
405
1c79356b
A
406 dp = ndp->ni_startdir;
407 ndp->ni_startdir = NULLVP;
1c79356b 408
91447636 409 cp = cnp->cn_nameptr;
55e303ae 410
91447636
A
411 if (*cp == '\0') {
412 if ( (vnode_getwithref(dp)) ) {
413 dp = NULLVP;
414 error = ENOENT;
55e303ae
A
415 goto bad;
416 }
91447636 417 goto emptyname;
1c79356b 418 }
91447636
A
419dirloop:
420 ndp->ni_vp = NULLVP;
9bccf70c 421
91447636
A
422 if ( (error = cache_lookup_path(ndp, cnp, dp, ctx, &trailing_slash, &dp_authorized)) ) {
423 dp = NULLVP;
424 goto bad;
425 }
426 if ((cnp->cn_flags & ISLASTCN)) {
427 if (docache)
428 cnp->cn_flags |= MAKEENTRY;
429 } else
430 cnp->cn_flags |= MAKEENTRY;
431
432 dp = ndp->ni_dvp;
433
434 if (ndp->ni_vp != NULLVP) {
435 /*
436 * cache_lookup_path returned a non-NULL ni_vp then,
437 * we're guaranteed that the dp is a VDIR, it's
438 * been authorized, and vp is not ".."
439 */
440 goto returned_from_lookup_path;
9bccf70c 441 }
1c79356b 442
1c79356b
A
443 /*
444 * Handle "..": two special cases.
445 * 1. If at root directory (e.g. after chroot)
446 * or at absolute root directory
447 * then ignore it so can't get out.
448 * 2. If this vnode is the root of a mounted
449 * filesystem, then replace it with the
450 * vnode which was mounted on so we take the
451 * .. in the other file system.
452 */
91447636 453 if ( (cnp->cn_flags & ISDOTDOT) ) {
1c79356b 454 for (;;) {
91447636
A
455 if (dp == ndp->ni_rootdir || dp == rootvnode) {
456 ndp->ni_dvp = dp;
1c79356b 457 ndp->ni_vp = dp;
91447636
A
458 /*
459 * we're pinned at the root
460 * we've already got one reference on 'dp'
461 * courtesy of cache_lookup_path... take
462 * another one for the ".."
463 * if we fail to get the new reference, we'll
464 * drop our original down in 'bad'
465 */
466 if ( (vnode_get(dp)) ) {
467 error = ENOENT;
468 goto bad;
469 }
1c79356b
A
470 goto nextname;
471 }
472 if ((dp->v_flag & VROOT) == 0 ||
473 (cnp->cn_flags & NOCROSSMOUNT))
91447636 474 break;
0b4e3aa0 475 if (dp->v_mount == NULL) { /* forced umount */
91447636 476 error = EBADF;
0b4e3aa0
A
477 goto bad;
478 }
1c79356b 479 tdp = dp;
91447636
A
480 dp = tdp->v_mount->mnt_vnodecovered;
481
482 vnode_put(tdp);
483
484 if ( (vnode_getwithref(dp)) ) {
485 dp = NULLVP;
486 error = ENOENT;
487 goto bad;
488 }
489 ndp->ni_dvp = dp;
490 dp_authorized = 0;
1c79356b
A
491 }
492 }
493
494 /*
495 * We now have a segment name to search for, and a directory to search.
496 */
497unionlookup:
91447636
A
498 ndp->ni_vp = NULLVP;
499
500 if (dp->v_type != VDIR) {
501 error = ENOTDIR;
502 goto lookup_error;
503 }
504 if ( !(dp_authorized || (cnp->cn_flags & DONOTAUTH)) ) {
505 if ( (error = vnode_authorize(dp, NULL, KAUTH_VNODE_SEARCH, ctx)) )
506 goto lookup_error;
507 }
508 if ( (error = VNOP_LOOKUP(dp, &ndp->ni_vp, cnp, ctx)) ) {
509lookup_error:
1c79356b 510 if ((error == ENOENT) &&
0b4e3aa0 511 (dp->v_flag & VROOT) && (dp->v_mount != NULL) &&
1c79356b 512 (dp->v_mount->mnt_flag & MNT_UNION)) {
91447636
A
513 if ((cnp->cn_flags & FSNODELOCKHELD)) {
514 cnp->cn_flags &= ~FSNODELOCKHELD;
515 unlock_fsnode(dp, NULL);
516 }
1c79356b 517 tdp = dp;
91447636
A
518 dp = tdp->v_mount->mnt_vnodecovered;
519
520 vnode_put(tdp);
521
522 if ( (vnode_getwithref(dp)) ) {
523 dp = NULLVP;
524 error = ENOENT;
525 goto bad;
526 }
527 ndp->ni_dvp = dp;
528 dp_authorized = 0;
1c79356b
A
529 goto unionlookup;
530 }
531
532 if (error != EJUSTRETURN)
533 goto bad;
91447636
A
534
535 if (ndp->ni_vp != NULLVP)
536 panic("leaf should be empty");
537
1c79356b
A
538 /*
539 * If creating and at end of pathname, then can consider
540 * allowing file to be created.
541 */
542 if (rdonly) {
543 error = EROFS;
544 goto bad;
545 }
91447636 546 if ((cnp->cn_flags & ISLASTCN) && trailing_slash && !(cnp->cn_flags & WILLBEDIR)) {
9bccf70c
A
547 error = ENOENT;
548 goto bad;
549 }
1c79356b
A
550 /*
551 * We return with ni_vp NULL to indicate that the entry
552 * doesn't currently exist, leaving a pointer to the
91447636 553 * referenced directory vnode in ndp->ni_dvp.
1c79356b
A
554 */
555 if (cnp->cn_flags & SAVESTART) {
91447636
A
556 if ( (vnode_get(ndp->ni_dvp)) ) {
557 error = ENOENT;
558 goto bad;
559 }
1c79356b 560 ndp->ni_startdir = ndp->ni_dvp;
1c79356b 561 }
91447636
A
562 if (!wantparent)
563 vnode_put(ndp->ni_dvp);
564
1c79356b
A
565 if (kdebug_enable)
566 kdebug_lookup(ndp->ni_dvp, cnp);
567 return (0);
568 }
91447636
A
569returned_from_lookup_path:
570 dp = ndp->ni_vp;
1c79356b
A
571
572 /*
573 * Take into account any additional components consumed by
574 * the underlying filesystem.
575 */
576 if (cnp->cn_consume > 0) {
577 cnp->cn_nameptr += cnp->cn_consume;
578 ndp->ni_next += cnp->cn_consume;
579 ndp->ni_pathlen -= cnp->cn_consume;
580 cnp->cn_consume = 0;
55e303ae 581 } else {
91447636
A
582 if (dp->v_name == NULL || dp->v_parent == NULLVP) {
583 int isdot_or_dotdot;
584 int update_flags = 0;
55e303ae 585
91447636 586 isdot_or_dotdot = (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') || (cnp->cn_flags & ISDOTDOT);
55e303ae 587
91447636
A
588 if (isdot_or_dotdot == 0) {
589 if (dp->v_name == NULL)
590 update_flags |= VNODE_UPDATE_NAME;
591 if (ndp->ni_dvp != NULLVP && dp->v_parent == NULLVP)
592 update_flags |= VNODE_UPDATE_PARENT;
593
594 if (update_flags)
595 vnode_update_identity(dp, ndp->ni_dvp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_hash, update_flags);
596 }
597 }
598
599 if ( (cnp->cn_flags & MAKEENTRY) && (dp->v_flag & VNCACHEABLE) && LIST_FIRST(&dp->v_nclinks) == NULL) {
600 /*
601 * missing from name cache, but should
602 * be in it... this can happen if volfs
603 * causes the vnode to be created or the
604 * name cache entry got recycled but the
605 * vnode didn't...
606 * check to make sure that ni_dvp is valid
607 * cache_lookup_path may return a NULL
608 */
609 if (ndp->ni_dvp != NULL)
610 cache_enter(ndp->ni_dvp, dp, cnp);
55e303ae 611 }
1c79356b
A
612 }
613
1c79356b 614 /*
91447636 615 * Check to see if the vnode has been mounted on...
1c79356b
A
616 * if so find the root of the mounted file system.
617 */
91447636
A
618check_mounted_on:
619 if ((dp->v_type == VDIR) && dp->v_mountedhere &&
620 ((cnp->cn_flags & NOCROSSMOUNT) == 0)) {
621
622 vnode_lock(dp);
623
624 if ((dp->v_type == VDIR) && (mp = dp->v_mountedhere)) {
625
626 mp->mnt_crossref++;
627 vnode_unlock(dp);
628
629 if (vfs_busy(mp, 0)) {
630 mount_dropcrossref(mp, dp, 0);
631 goto check_mounted_on;
632 }
633 error = VFS_ROOT(mp, &tdp, ctx);
634 /*
635 * mount_dropcrossref does a vnode_put
636 * on dp if the 3rd arg is non-zero
637 */
638 mount_dropcrossref(mp, dp, 1);
639 dp = NULL;
640 vfs_unbusy(mp);
641
642 if (error) {
643 goto bad2;
644 }
645 ndp->ni_vp = dp = tdp;
646
647 goto check_mounted_on;
648 }
649 vnode_unlock(dp);
1c79356b
A
650 }
651
652 /*
653 * Check for symbolic link
654 */
655 if ((dp->v_type == VLNK) &&
91447636 656 ((cnp->cn_flags & FOLLOW) || trailing_slash || *ndp->ni_next == '/')) {
1c79356b
A
657 cnp->cn_flags |= ISSYMLINK;
658 return (0);
659 }
660
9bccf70c
A
661 /*
662 * Check for bogus trailing slashes.
663 */
55e303ae
A
664 if (trailing_slash) {
665 if (dp->v_type != VDIR) {
666 error = ENOTDIR;
667 goto bad2;
668 }
669 trailing_slash = 0;
91447636 670 }
9bccf70c 671
1c79356b
A
672nextname:
673 /*
674 * Not a symbolic link. If more pathname,
675 * continue at next component, else return.
676 */
677 if (*ndp->ni_next == '/') {
55e303ae
A
678 cnp->cn_nameptr = ndp->ni_next + 1;
679 ndp->ni_pathlen--;
1c79356b
A
680 while (*cnp->cn_nameptr == '/') {
681 cnp->cn_nameptr++;
682 ndp->ni_pathlen--;
683 }
91447636
A
684 vnode_put(ndp->ni_dvp);
685
686 cp = cnp->cn_nameptr;
687
688 if (*cp == '\0')
689 goto emptyname;
690
691 vnode_put(dp);
1c79356b
A
692 goto dirloop;
693 }
694
695 /*
696 * Disallow directory write attempts on read-only file systems.
697 */
698 if (rdonly &&
699 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
700 error = EROFS;
701 goto bad2;
702 }
703 if (cnp->cn_flags & SAVESTART) {
91447636
A
704 /*
705 * note that we already hold a reference
706 * on both dp and ni_dvp, but for some reason
707 * can't get another one... in this case we
708 * need to do vnode_put on dp in 'bad2'
709 */
710 if ( (vnode_get(ndp->ni_dvp)) ) {
711 error = ENOENT;
712 goto bad2;
713 }
1c79356b 714 ndp->ni_startdir = ndp->ni_dvp;
1c79356b 715 }
91447636
A
716 if (!wantparent && ndp->ni_dvp)
717 vnode_put(ndp->ni_dvp);
718
55e303ae
A
719 if (cnp->cn_flags & AUDITVNPATH1)
720 AUDIT_ARG(vnpath, dp, ARG_VNODE1);
721 else if (cnp->cn_flags & AUDITVNPATH2)
722 AUDIT_ARG(vnpath, dp, ARG_VNODE2);
91447636 723
1c79356b
A
724 if (kdebug_enable)
725 kdebug_lookup(dp, cnp);
726 return (0);
727
55e303ae 728emptyname:
91447636 729 cnp->cn_namelen = 0;
55e303ae
A
730 /*
731 * A degenerate name (e.g. / or "") which is a way of
732 * talking about a directory, e.g. like "/." or ".".
733 */
734 if (dp->v_type != VDIR) {
735 error = ENOTDIR;
736 goto bad;
737 }
738 if (cnp->cn_nameiop != LOOKUP) {
739 error = EISDIR;
740 goto bad;
741 }
742 if (wantparent) {
91447636
A
743 /*
744 * note that we already hold a reference
745 * on dp, but for some reason can't
746 * get another one... in this case we
747 * need to do vnode_put on dp in 'bad'
748 */
749 if ( (vnode_get(dp)) ) {
750 error = ENOENT;
751 goto bad;
752 }
55e303ae 753 ndp->ni_dvp = dp;
55e303ae
A
754 }
755 cnp->cn_flags &= ~ISDOTDOT;
756 cnp->cn_flags |= ISLASTCN;
757 ndp->ni_next = cp;
758 ndp->ni_vp = dp;
91447636 759
55e303ae
A
760 if (cnp->cn_flags & AUDITVNPATH1)
761 AUDIT_ARG(vnpath, dp, ARG_VNODE1);
762 else if (cnp->cn_flags & AUDITVNPATH2)
763 AUDIT_ARG(vnpath, dp, ARG_VNODE2);
55e303ae
A
764 if (cnp->cn_flags & SAVESTART)
765 panic("lookup: SAVESTART");
766 return (0);
767
1c79356b 768bad2:
91447636
A
769 if ((cnp->cn_flags & FSNODELOCKHELD)) {
770 cnp->cn_flags &= ~FSNODELOCKHELD;
771 unlock_fsnode(ndp->ni_dvp, NULL);
772 }
773 if (ndp->ni_dvp)
774 vnode_put(ndp->ni_dvp);
775 if (dp)
776 vnode_put(dp);
777 ndp->ni_vp = NULLVP;
778
779 if (kdebug_enable)
780 kdebug_lookup(dp, cnp);
781 return (error);
782
1c79356b 783bad:
91447636
A
784 if ((cnp->cn_flags & FSNODELOCKHELD)) {
785 cnp->cn_flags &= ~FSNODELOCKHELD;
786 unlock_fsnode(ndp->ni_dvp, NULL);
787 }
788 if (dp)
789 vnode_put(dp);
790 ndp->ni_vp = NULLVP;
791
1c79356b
A
792 if (kdebug_enable)
793 kdebug_lookup(dp, cnp);
794 return (error);
795}
796
797/*
798 * relookup - lookup a path name component
799 * Used by lookup to re-aquire things.
800 */
801int
802relookup(dvp, vpp, cnp)
803 struct vnode *dvp, **vpp;
804 struct componentname *cnp;
805{
1c79356b 806 struct vnode *dp = 0; /* the directory we are searching */
1c79356b
A
807 int wantparent; /* 1 => wantparent or lockparent flag */
808 int rdonly; /* lookup read-only flag bit */
809 int error = 0;
810#ifdef NAMEI_DIAGNOSTIC
55e303ae 811 int i, newhash; /* DEBUG: check name hash */
1c79356b
A
812 char *cp; /* DEBUG: check name ptr/len */
813#endif
91447636 814 vfs_context_t ctx = cnp->cn_context;;
1c79356b
A
815
816 /*
817 * Setup: break out flag bits into variables.
818 */
819 wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
1c79356b
A
820 rdonly = cnp->cn_flags & RDONLY;
821 cnp->cn_flags &= ~ISSYMLINK;
1c79356b 822
91447636
A
823 if (cnp->cn_flags & NOCACHE)
824 cnp->cn_flags &= ~MAKEENTRY;
825 else
826 cnp->cn_flags |= MAKEENTRY;
827
828 dp = dvp;
1c79356b
A
829
830 /*
831 * Check for degenerate name (e.g. / or "")
832 * which is a way of talking about a directory,
833 * e.g. like "/." or ".".
834 */
835 if (cnp->cn_nameptr[0] == '\0') {
836 if (cnp->cn_nameiop != LOOKUP || wantparent) {
837 error = EISDIR;
838 goto bad;
839 }
840 if (dp->v_type != VDIR) {
841 error = ENOTDIR;
842 goto bad;
843 }
91447636
A
844 if ( (vnode_get(dp)) ) {
845 error = ENOENT;
846 goto bad;
847 }
1c79356b 848 *vpp = dp;
91447636 849
1c79356b
A
850 if (cnp->cn_flags & SAVESTART)
851 panic("lookup: SAVESTART");
852 return (0);
853 }
1c79356b
A
854 /*
855 * We now have a segment name to search for, and a directory to search.
856 */
91447636
A
857 if ( (error = VNOP_LOOKUP(dp, vpp, cnp, ctx)) ) {
858 if (error != EJUSTRETURN)
859 goto bad;
1c79356b
A
860#if DIAGNOSTIC
861 if (*vpp != NULL)
862 panic("leaf should be empty");
863#endif
1c79356b
A
864 /*
865 * If creating and at end of pathname, then can consider
866 * allowing file to be created.
867 */
868 if (rdonly) {
869 error = EROFS;
870 goto bad;
871 }
1c79356b
A
872 /*
873 * We return with ni_vp NULL to indicate that the entry
874 * doesn't currently exist, leaving a pointer to the
875 * (possibly locked) directory inode in ndp->ni_dvp.
876 */
877 return (0);
878 }
879 dp = *vpp;
880
881#if DIAGNOSTIC
882 /*
883 * Check for symbolic link
884 */
885 if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW))
886 panic ("relookup: symlink found.\n");
887#endif
888
889 /*
890 * Disallow directory write attempts on read-only file systems.
891 */
892 if (rdonly &&
893 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
894 error = EROFS;
895 goto bad2;
896 }
897 /* ASSERT(dvp == ndp->ni_startdir) */
1c79356b 898
1c79356b
A
899 return (0);
900
901bad2:
91447636
A
902 vnode_put(dp);
903bad:
1c79356b 904 *vpp = NULL;
91447636 905
1c79356b
A
906 return (error);
907}
908
91447636
A
909/*
910 * Free pathname buffer
911 */
912void
913nameidone(struct nameidata *ndp)
914{
915 if ((ndp->ni_cnd.cn_flags & FSNODELOCKHELD)) {
916 ndp->ni_cnd.cn_flags &= ~FSNODELOCKHELD;
917 unlock_fsnode(ndp->ni_dvp, NULL);
918 }
919 if (ndp->ni_cnd.cn_flags & HASBUF) {
920 char *tmp = ndp->ni_cnd.cn_pnbuf;
921
922 ndp->ni_cnd.cn_pnbuf = NULL;
923 ndp->ni_cnd.cn_flags &= ~HASBUF;
924 FREE_ZONE(tmp, ndp->ni_cnd.cn_pnlen, M_NAMEI);
925 }
926}
927
1c79356b 928
0b4e3aa0 929#define NUMPARMS 23
1c79356b 930
55e303ae 931static void
1c79356b 932kdebug_lookup(dp, cnp)
55e303ae 933 struct vnode *dp;
1c79356b
A
934 struct componentname *cnp;
935{
91447636 936 register unsigned int i, n;
1c79356b 937 register int dbg_namelen;
0b4e3aa0 938 register int save_dbg_namelen;
1c79356b
A
939 register char *dbg_nameptr;
940 long dbg_parms[NUMPARMS];
941 char dbg_buf[4];
942 static char *dbg_filler = ">>>>";
943
944 /* Collect the pathname for tracing */
945 dbg_namelen = (cnp->cn_nameptr - cnp->cn_pnbuf) + cnp->cn_namelen;
946 dbg_nameptr = cnp->cn_nameptr + cnp->cn_namelen;
947
948 if (dbg_namelen > sizeof(dbg_parms))
949 dbg_namelen = sizeof(dbg_parms);
950 dbg_nameptr -= dbg_namelen;
0b4e3aa0 951 save_dbg_namelen = dbg_namelen;
1c79356b
A
952
953 i = 0;
954
955 while (dbg_namelen > 0) {
956 if (dbg_namelen >= 4) {
957 dbg_parms[i++] = *(long *)dbg_nameptr;
958 dbg_nameptr += sizeof(long);
959 dbg_namelen -= sizeof(long);
960 } else {
961 for (n = 0; n < dbg_namelen; n++)
962 dbg_buf[n] = *dbg_nameptr++;
963 while (n <= 3) {
964 if (*dbg_nameptr)
965 dbg_buf[n++] = '>';
966 else
967 dbg_buf[n++] = 0;
968 }
969 dbg_parms[i++] = *(long *)&dbg_buf[0];
970
971 break;
972 }
973 }
974 while (i < NUMPARMS) {
975 if (*dbg_nameptr)
976 dbg_parms[i++] = *(long *)dbg_filler;
977 else
978 dbg_parms[i++] = 0;
979 }
0b4e3aa0 980
9bccf70c
A
981 /*
982 In the event that we collect multiple, consecutive pathname
983 entries, we must mark the start of the path's string.
984 */
985 KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_START,
55e303ae 986 (unsigned int)dp, dbg_parms[0], dbg_parms[1], dbg_parms[2], 0);
0b4e3aa0
A
987
988 for (dbg_namelen = save_dbg_namelen-12, i=3;
989 dbg_namelen > 0;
9bccf70c 990 dbg_namelen -=(4 * sizeof(long)), i+= 4)
0b4e3aa0
A
991 {
992 KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_NONE,
9bccf70c 993 dbg_parms[i], dbg_parms[i+1], dbg_parms[i+2], dbg_parms[i+3], 0);
0b4e3aa0 994 }
1c79356b 995}