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