]>
git.saurik.com Git - apple/xnu.git/blob - bsd/vfs/vfs_lookup.c
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
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.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
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.
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
63 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95
66 #include <sys/param.h>
67 #include <sys/syslimits.h>
69 #include <sys/namei.h>
71 #include <sys/vnode.h>
72 #include <sys/mount.h>
73 #include <sys/errno.h>
74 #include <sys/malloc.h>
75 #include <sys/filedesc.h>
77 #include <sys/kdebug.h>
78 #include <sys/unistd.h> /* For _PC_NAME_MAX */
81 #include <sys/ktrace.h>
85 * Convert a pathname into a pointer to a locked inode.
87 * The FOLLOW flag is set when symbolic links are to be followed
88 * when they occur at the end of the name translation process.
89 * Symbolic links are always followed for all other pathname
90 * components other than the last.
92 * The segflg defines whether the name is to be copied from user
93 * space or kernel space.
95 * Overall outline of namei:
98 * get starting directory
99 * while (!done && !error) {
100 * call lookup to search path.
101 * if symbolic link, massage name in buffer and continue
106 register struct nameidata
*ndp
;
108 register struct filedesc
*fdp
; /* pointer to file descriptor state */
109 register char *cp
; /* pointer into pathname argument */
110 register struct vnode
*dp
; /* the directory we are searching */
111 struct iovec aiov
; /* uio for reading symbolic links */
114 struct componentname
*cnp
= &ndp
->ni_cnd
;
115 struct proc
*p
= cnp
->cn_proc
;
117 ndp
->ni_cnd
.cn_cred
= ndp
->ni_cnd
.cn_proc
->p_ucred
;
119 if (!cnp
->cn_cred
|| !cnp
->cn_proc
)
120 panic ("namei: bad cred/proc");
121 if (cnp
->cn_nameiop
& (~OPMASK
))
122 panic ("namei: nameiop contaminated with flags");
123 if (cnp
->cn_flags
& OPMASK
)
124 panic ("namei: flags contaminated with nameiops");
126 fdp
= cnp
->cn_proc
->p_fd
;
129 * Get a buffer for the name to be translated, and copy the
130 * name into the buffer.
132 if ((cnp
->cn_flags
& HASBUF
) == 0) {
133 MALLOC_ZONE(cnp
->cn_pnbuf
, caddr_t
,
134 MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
135 cnp
->cn_pnlen
= MAXPATHLEN
;
137 if (ndp
->ni_segflg
== UIO_SYSSPACE
)
138 error
= copystr(ndp
->ni_dirp
, cnp
->cn_pnbuf
,
139 MAXPATHLEN
, &ndp
->ni_pathlen
);
141 error
= copyinstr(ndp
->ni_dirp
, cnp
->cn_pnbuf
,
142 MAXPATHLEN
, &ndp
->ni_pathlen
);
144 * Do not allow empty pathnames
146 if (!error
&& *cnp
->cn_pnbuf
== '\0')
150 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
156 if (KTRPOINT(cnp
->cn_proc
, KTR_NAMEI
))
157 ktrnamei(cnp
->cn_proc
->p_tracep
, cnp
->cn_pnbuf
);
161 * Get starting point for the translation.
163 if ((ndp
->ni_rootdir
= fdp
->fd_rdir
) == NULL
)
164 ndp
->ni_rootdir
= rootvnode
;
169 * Check if root directory should replace current directory.
170 * Done at start of translation and after symbolic link.
172 cnp
->cn_nameptr
= cnp
->cn_pnbuf
;
173 if (*(cnp
->cn_nameptr
) == '/') {
175 while (*(cnp
->cn_nameptr
) == '/') {
179 dp
= ndp
->ni_rootdir
;
182 ndp
->ni_startdir
= dp
;
183 if (error
= lookup(ndp
)) {
184 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
188 * Check for symbolic link
190 if ((cnp
->cn_flags
& ISSYMLINK
) == 0) {
191 if ((cnp
->cn_flags
& (SAVENAME
| SAVESTART
)) == 0) {
192 FREE_ZONE(cnp
->cn_pnbuf
,
193 cnp
->cn_pnlen
, M_NAMEI
);
195 cnp
->cn_flags
|= HASBUF
;
199 if ((cnp
->cn_flags
& LOCKPARENT
) && ndp
->ni_pathlen
== 1)
200 VOP_UNLOCK(ndp
->ni_dvp
, 0, p
);
201 if (ndp
->ni_loopcnt
++ >= MAXSYMLINKS
) {
205 if (ndp
->ni_pathlen
> 1) {
206 MALLOC_ZONE(cp
, char *, MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
211 aiov
.iov_len
= MAXPATHLEN
;
212 auio
.uio_iov
= &aiov
;
215 auio
.uio_rw
= UIO_READ
;
216 auio
.uio_segflg
= UIO_SYSSPACE
;
217 auio
.uio_procp
= (struct proc
*)0;
218 auio
.uio_resid
= MAXPATHLEN
;
219 if (error
= VOP_READLINK(ndp
->ni_vp
, &auio
, cnp
->cn_cred
)) {
220 if (ndp
->ni_pathlen
> 1)
221 _FREE_ZONE(cp
, MAXPATHLEN
, M_NAMEI
);
224 linklen
= MAXPATHLEN
- auio
.uio_resid
;
225 if (linklen
+ ndp
->ni_pathlen
>= MAXPATHLEN
) {
226 if (ndp
->ni_pathlen
> 1)
227 _FREE_ZONE(cp
, MAXPATHLEN
, M_NAMEI
);
228 error
= ENAMETOOLONG
;
231 if (ndp
->ni_pathlen
> 1) {
232 bcopy(ndp
->ni_next
, cp
+ linklen
, ndp
->ni_pathlen
);
233 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
235 cnp
->cn_pnlen
= MAXPATHLEN
;
237 cnp
->cn_pnbuf
[linklen
] = '\0';
238 ndp
->ni_pathlen
+= linklen
;
242 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
251 * This is a very central and rather complicated routine.
253 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
254 * The starting directory is taken from ni_startdir. The pathname is
255 * descended until done, or a symbolic link is encountered. The variable
256 * ni_more is clear if the path is completed; it is set to one if a
257 * symbolic link needing interpretation is encountered.
259 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
260 * whether the name is to be looked up, created, renamed, or deleted.
261 * When CREATE, RENAME, or DELETE is specified, information usable in
262 * creating, renaming, or deleting a directory entry may be calculated.
263 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
264 * locked. If flag has WANTPARENT or'ed into it, the parent directory is
265 * returned unlocked. Otherwise the parent directory is not returned. If
266 * the target of the pathname exists and LOCKLEAF is or'ed into the flag
267 * the target is returned locked, otherwise it is returned unlocked.
268 * When creating or renaming and LOCKPARENT is specified, the target may not
269 * be ".". When deleting and LOCKPARENT is specified, the target may be ".".
271 * Overall outline of lookup:
274 * identify next component of name at ndp->ni_ptr
275 * handle degenerate case where name is null string
276 * if .. and crossing mount points and on mounted filesys, find parent
277 * call VOP_LOOKUP routine for next component name
278 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
279 * component vnode returned in ni_vp (if it exists), locked.
280 * if result vnode is mounted on and crossing mount points,
281 * find mounted on vnode
282 * if more components of name, do next level at dirloop
283 * return the answer in ni_vp, locked if LOCKLEAF set
284 * if LOCKPARENT set, return locked parent in ni_dvp
285 * if WANTPARENT set, return unlocked parent in ni_dvp
289 register struct nameidata
*ndp
;
291 register char *cp
; /* pointer into pathname argument */
292 register struct vnode
*dp
= 0; /* the directory we are searching */
293 struct vnode
*tdp
; /* saved dp */
294 struct mount
*mp
; /* mount table entry */
295 int namemax
= 0; /* maximun number of bytes for filename returned by pathconf() */
296 int docache
; /* == 0 do not cache last component */
297 int wantparent
; /* 1 => wantparent or lockparent flag */
298 int dp_unlocked
= 0; /* 1 => dp already VOP_UNLOCK()-ed */
299 int rdonly
; /* lookup read-only flag bit */
302 struct componentname
*cnp
= &ndp
->ni_cnd
;
303 struct proc
*p
= cnp
->cn_proc
;
307 * Setup: break out flag bits into variables.
309 wantparent
= cnp
->cn_flags
& (LOCKPARENT
| WANTPARENT
);
310 docache
= (cnp
->cn_flags
& NOCACHE
) ^ NOCACHE
;
311 if (cnp
->cn_nameiop
== DELETE
||
312 (wantparent
&& cnp
->cn_nameiop
!= CREATE
&&
313 cnp
->cn_nameiop
!= LOOKUP
))
315 rdonly
= cnp
->cn_flags
& RDONLY
;
317 cnp
->cn_flags
&= ~ISSYMLINK
;
318 dp
= ndp
->ni_startdir
;
319 ndp
->ni_startdir
= NULLVP
;
320 vn_lock(dp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
324 * Search a new directory.
326 * The cn_hash value is for use by vfs_cache.
327 * Check pathconf for maximun length of name
328 * The last component of the filename is left accessible via
329 * cnp->cn_nameptr for callers that need the name. Callers needing
330 * the name set the SAVENAME flag. When done, they assume
331 * responsibility for freeing the pathname buffer.
335 for (cp
= cnp
->cn_nameptr
, i
=1; *cp
!= 0 && *cp
!= '/'; i
++, cp
++)
336 cnp
->cn_hash
+= (unsigned char)*cp
* i
;
337 cnp
->cn_namelen
= cp
- cnp
->cn_nameptr
;
338 if (VOP_PATHCONF(dp
, _PC_NAME_MAX
, &namemax
))
340 if (cnp
->cn_namelen
> namemax
) {
341 error
= ENAMETOOLONG
;
344 #ifdef NAMEI_DIAGNOSTIC
347 printf("{%s}: ", cnp
->cn_nameptr
);
350 ndp
->ni_pathlen
-= cnp
->cn_namelen
;
354 * Replace multiple slashes by a single slash and trailing slashes
355 * by a null. This must be done before VOP_LOOKUP() because some
356 * fs's don't know about trailing slashes. Remember if there were
357 * trailing slashes to handle symlinks, existing non-directories
358 * and non-existing files that won't be directories specially later.
361 while (*cp
== '/' && (cp
[1] == '/' || cp
[1] == '\0')) {
366 *ndp
->ni_next
= '\0';
371 cnp
->cn_flags
|= MAKEENTRY
;
372 if (*cp
== '\0' && docache
== 0)
373 cnp
->cn_flags
&= ~MAKEENTRY
;
374 if (cnp
->cn_namelen
== 2 &&
375 cnp
->cn_nameptr
[1] == '.' && cnp
->cn_nameptr
[0] == '.')
376 cnp
->cn_flags
|= ISDOTDOT
;
378 cnp
->cn_flags
&= ~ISDOTDOT
;
379 if (*ndp
->ni_next
== 0)
380 cnp
->cn_flags
|= ISLASTCN
;
382 cnp
->cn_flags
&= ~ISLASTCN
;
386 * Check for degenerate name (e.g. / or "")
387 * which is a way of talking about a directory,
388 * e.g. like "/." or ".".
390 if (cnp
->cn_nameptr
[0] == '\0') {
391 if (dp
->v_type
!= VDIR
) {
395 if (cnp
->cn_nameiop
!= LOOKUP
) {
404 if (!(cnp
->cn_flags
& (LOCKPARENT
| LOCKLEAF
)))
405 VOP_UNLOCK(dp
, 0, p
);
406 if (cnp
->cn_flags
& SAVESTART
)
407 panic("lookup: SAVESTART");
412 * Handle "..": two special cases.
413 * 1. If at root directory (e.g. after chroot)
414 * or at absolute root directory
415 * then ignore it so can't get out.
416 * 2. If this vnode is the root of a mounted
417 * filesystem, then replace it with the
418 * vnode which was mounted on so we take the
419 * .. in the other file system.
421 if (cnp
->cn_flags
& ISDOTDOT
) {
423 if (dp
== ndp
->ni_rootdir
|| dp
== rootvnode
) {
429 if ((dp
->v_flag
& VROOT
) == 0 ||
430 (cnp
->cn_flags
& NOCROSSMOUNT
))
432 if (dp
->v_mount
== NULL
) { /* forced umount */
438 dp
= dp
->v_mount
->mnt_vnodecovered
;
441 vn_lock(dp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
446 * We now have a segment name to search for, and a directory to search.
451 if (error
= VOP_LOOKUP(dp
, &ndp
->ni_vp
, cnp
)) {
453 if (ndp
->ni_vp
!= NULL
)
454 panic("leaf should be empty");
456 #ifdef NAMEI_DIAGNOSTIC
457 printf("not found\n");
459 if ((error
== ENOENT
) &&
460 (dp
->v_flag
& VROOT
) && (dp
->v_mount
!= NULL
) &&
461 (dp
->v_mount
->mnt_flag
& MNT_UNION
)) {
463 dp
= dp
->v_mount
->mnt_vnodecovered
;
466 vn_lock(dp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
470 if (error
!= EJUSTRETURN
)
473 * If creating and at end of pathname, then can consider
474 * allowing file to be created.
480 if (*cp
== '\0' && trailing_slash
&&
481 !(cnp
->cn_flags
& WILLBEDIR
)) {
486 * We return with ni_vp NULL to indicate that the entry
487 * doesn't currently exist, leaving a pointer to the
488 * (possibly locked) directory inode in ndp->ni_dvp.
490 if (cnp
->cn_flags
& SAVESTART
) {
491 ndp
->ni_startdir
= ndp
->ni_dvp
;
492 VREF(ndp
->ni_startdir
);
495 kdebug_lookup(ndp
->ni_dvp
, cnp
);
498 #ifdef NAMEI_DIAGNOSTIC
503 * Take into account any additional components consumed by
504 * the underlying filesystem.
506 if (cnp
->cn_consume
> 0) {
507 cnp
->cn_nameptr
+= cnp
->cn_consume
;
508 ndp
->ni_next
+= cnp
->cn_consume
;
509 ndp
->ni_pathlen
-= cnp
->cn_consume
;
515 * Check to see if the vnode has been mounted on;
516 * if so find the root of the mounted file system.
518 while (dp
->v_type
== VDIR
&& (mp
= dp
->v_mountedhere
) &&
519 (cnp
->cn_flags
& NOCROSSMOUNT
) == 0) {
520 if (vfs_busy(mp
, 0, 0, p
))
522 VOP_UNLOCK(dp
, 0, p
);
523 error
= VFS_ROOT(mp
, &tdp
);
526 dp_unlocked
= 1; /* Signal error path 'dp' has already been unlocked */
530 ndp
->ni_vp
= dp
= tdp
;
534 * Check for symbolic link
536 if ((dp
->v_type
== VLNK
) &&
537 ((cnp
->cn_flags
& FOLLOW
) || trailing_slash
||
538 *ndp
->ni_next
== '/')) {
539 cnp
->cn_flags
|= ISSYMLINK
;
544 * Check for bogus trailing slashes.
546 if (trailing_slash
&& dp
->v_type
!= VDIR
) {
553 * Not a symbolic link. If more pathname,
554 * continue at next component, else return.
556 if (*ndp
->ni_next
== '/') {
557 cnp
->cn_nameptr
= ndp
->ni_next
;
558 while (*cnp
->cn_nameptr
== '/') {
567 * Disallow directory write attempts on read-only file systems.
570 (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
)) {
574 if (cnp
->cn_flags
& SAVESTART
) {
575 ndp
->ni_startdir
= ndp
->ni_dvp
;
576 VREF(ndp
->ni_startdir
);
580 if ((cnp
->cn_flags
& LOCKLEAF
) == 0)
581 VOP_UNLOCK(dp
, 0, p
);
583 kdebug_lookup(dp
, cnp
);
587 if ((cnp
->cn_flags
& LOCKPARENT
) && *ndp
->ni_next
== '\0')
588 VOP_UNLOCK(ndp
->ni_dvp
, 0, p
);
598 kdebug_lookup(dp
, cnp
);
603 * relookup - lookup a path name component
604 * Used by lookup to re-aquire things.
607 relookup(dvp
, vpp
, cnp
)
608 struct vnode
*dvp
, **vpp
;
609 struct componentname
*cnp
;
611 struct proc
*p
= cnp
->cn_proc
;
612 struct vnode
*dp
= 0; /* the directory we are searching */
613 int docache
; /* == 0 do not cache last component */
614 int wantparent
; /* 1 => wantparent or lockparent flag */
615 int rdonly
; /* lookup read-only flag bit */
617 #ifdef NAMEI_DIAGNOSTIC
618 int newhash
; /* DEBUG: check name hash */
619 char *cp
; /* DEBUG: check name ptr/len */
623 * Setup: break out flag bits into variables.
625 wantparent
= cnp
->cn_flags
& (LOCKPARENT
|WANTPARENT
);
626 docache
= (cnp
->cn_flags
& NOCACHE
) ^ NOCACHE
;
627 if (cnp
->cn_nameiop
== DELETE
||
628 (wantparent
&& cnp
->cn_nameiop
!= CREATE
))
630 rdonly
= cnp
->cn_flags
& RDONLY
;
631 cnp
->cn_flags
&= ~ISSYMLINK
;
633 vn_lock(dp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
637 * Search a new directory.
639 * The cn_hash value is for use by vfs_cache.
640 * The last component of the filename is left accessible via
641 * cnp->cn_nameptr for callers that need the name. Callers needing
642 * the name set the SAVENAME flag. When done, they assume
643 * responsibility for freeing the pathname buffer.
645 #ifdef NAMEI_DIAGNOSTIC
646 for (newhash
= 0, cp
= cnp
->cn_nameptr
; *cp
!= 0 && *cp
!= '/'; cp
++)
647 newhash
+= (unsigned char)*cp
;
648 if (newhash
!= cnp
->cn_hash
)
649 panic("relookup: bad hash");
650 if (cnp
->cn_namelen
!= cp
- cnp
->cn_nameptr
)
651 panic ("relookup: bad len");
653 panic("relookup: not last component");
654 printf("{%s}: ", cnp
->cn_nameptr
);
658 * Check for degenerate name (e.g. / or "")
659 * which is a way of talking about a directory,
660 * e.g. like "/." or ".".
662 if (cnp
->cn_nameptr
[0] == '\0') {
663 if (cnp
->cn_nameiop
!= LOOKUP
|| wantparent
) {
667 if (dp
->v_type
!= VDIR
) {
671 if (!(cnp
->cn_flags
& LOCKLEAF
))
672 VOP_UNLOCK(dp
, 0, p
);
674 if (cnp
->cn_flags
& SAVESTART
)
675 panic("lookup: SAVESTART");
679 if (cnp
->cn_flags
& ISDOTDOT
)
680 panic ("relookup: lookup on dot-dot");
683 * We now have a segment name to search for, and a directory to search.
685 if (error
= VOP_LOOKUP(dp
, vpp
, cnp
)) {
688 panic("leaf should be empty");
690 if (error
!= EJUSTRETURN
)
693 * If creating and at end of pathname, then can consider
694 * allowing file to be created.
700 /* ASSERT(dvp == ndp->ni_startdir) */
701 if (cnp
->cn_flags
& SAVESTART
)
704 * We return with ni_vp NULL to indicate that the entry
705 * doesn't currently exist, leaving a pointer to the
706 * (possibly locked) directory inode in ndp->ni_dvp.
714 * Check for symbolic link
716 if (dp
->v_type
== VLNK
&& (cnp
->cn_flags
& FOLLOW
))
717 panic ("relookup: symlink found.\n");
721 * Disallow directory write attempts on read-only file systems.
724 (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
)) {
728 /* ASSERT(dvp == ndp->ni_startdir) */
729 if (cnp
->cn_flags
& SAVESTART
)
734 if ((cnp
->cn_flags
& LOCKLEAF
) == 0)
735 VOP_UNLOCK(dp
, 0, p
);
739 if ((cnp
->cn_flags
& LOCKPARENT
) && (cnp
->cn_flags
& ISLASTCN
))
740 VOP_UNLOCK(dvp
, 0, p
);
751 kdebug_lookup(dp
, cnp
)
753 struct componentname
*cnp
;
756 register int dbg_namelen
;
757 register int save_dbg_namelen
;
758 register char *dbg_nameptr
;
759 long dbg_parms
[NUMPARMS
];
761 static char *dbg_filler
= ">>>>";
763 /* Collect the pathname for tracing */
764 dbg_namelen
= (cnp
->cn_nameptr
- cnp
->cn_pnbuf
) + cnp
->cn_namelen
;
765 dbg_nameptr
= cnp
->cn_nameptr
+ cnp
->cn_namelen
;
767 if (dbg_namelen
> sizeof(dbg_parms
))
768 dbg_namelen
= sizeof(dbg_parms
);
769 dbg_nameptr
-= dbg_namelen
;
770 save_dbg_namelen
= dbg_namelen
;
774 while (dbg_namelen
> 0) {
775 if (dbg_namelen
>= 4) {
776 dbg_parms
[i
++] = *(long *)dbg_nameptr
;
777 dbg_nameptr
+= sizeof(long);
778 dbg_namelen
-= sizeof(long);
780 for (n
= 0; n
< dbg_namelen
; n
++)
781 dbg_buf
[n
] = *dbg_nameptr
++;
788 dbg_parms
[i
++] = *(long *)&dbg_buf
[0];
793 while (i
< NUMPARMS
) {
795 dbg_parms
[i
++] = *(long *)dbg_filler
;
801 In the event that we collect multiple, consecutive pathname
802 entries, we must mark the start of the path's string.
804 KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW
,36)) | DBG_FUNC_START
,
805 dp
, dbg_parms
[0], dbg_parms
[1], dbg_parms
[2], 0);
807 for (dbg_namelen
= save_dbg_namelen
-12, i
=3;
809 dbg_namelen
-=(4 * sizeof(long)), i
+= 4)
811 KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW
,36)) | DBG_FUNC_NONE
,
812 dbg_parms
[i
], dbg_parms
[i
+1], dbg_parms
[i
+2], dbg_parms
[i
+3], 0);