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