]>
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 * 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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
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.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
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.
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
60 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95
63 #include <sys/param.h>
64 #include <sys/syslimits.h>
66 #include <sys/namei.h>
68 #include <sys/vnode.h>
69 #include <sys/mount.h>
70 #include <sys/errno.h>
71 #include <sys/malloc.h>
72 #include <sys/filedesc.h>
74 #include <sys/kdebug.h>
75 #include <sys/unistd.h> /* For _PC_NAME_MAX */
78 #include <sys/ktrace.h>
82 * Convert a pathname into a pointer to a locked inode.
84 * The FOLLOW flag is set when symbolic links are to be followed
85 * when they occur at the end of the name translation process.
86 * Symbolic links are always followed for all other pathname
87 * components other than the last.
89 * The segflg defines whether the name is to be copied from user
90 * space or kernel space.
92 * Overall outline of namei:
95 * get starting directory
96 * while (!done && !error) {
97 * call lookup to search path.
98 * if symbolic link, massage name in buffer and continue
103 register struct nameidata
*ndp
;
105 register struct filedesc
*fdp
; /* pointer to file descriptor state */
106 register char *cp
; /* pointer into pathname argument */
107 register struct vnode
*dp
; /* the directory we are searching */
108 struct iovec aiov
; /* uio for reading symbolic links */
111 struct componentname
*cnp
= &ndp
->ni_cnd
;
112 struct proc
*p
= cnp
->cn_proc
;
114 ndp
->ni_cnd
.cn_cred
= ndp
->ni_cnd
.cn_proc
->p_ucred
;
116 if (!cnp
->cn_cred
|| !cnp
->cn_proc
)
117 panic ("namei: bad cred/proc");
118 if (cnp
->cn_nameiop
& (~OPMASK
))
119 panic ("namei: nameiop contaminated with flags");
120 if (cnp
->cn_flags
& OPMASK
)
121 panic ("namei: flags contaminated with nameiops");
123 fdp
= cnp
->cn_proc
->p_fd
;
126 * Get a buffer for the name to be translated, and copy the
127 * name into the buffer.
129 if ((cnp
->cn_flags
& HASBUF
) == 0) {
130 MALLOC_ZONE(cnp
->cn_pnbuf
, caddr_t
,
131 MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
132 cnp
->cn_pnlen
= MAXPATHLEN
;
134 if (ndp
->ni_segflg
== UIO_SYSSPACE
)
135 error
= copystr(ndp
->ni_dirp
, cnp
->cn_pnbuf
,
136 MAXPATHLEN
, &ndp
->ni_pathlen
);
138 error
= copyinstr(ndp
->ni_dirp
, cnp
->cn_pnbuf
,
139 MAXPATHLEN
, &ndp
->ni_pathlen
);
141 * Do not allow empty pathnames
143 if (!error
&& *cnp
->cn_pnbuf
== '\0')
147 _FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
153 if (KTRPOINT(cnp
->cn_proc
, KTR_NAMEI
))
154 ktrnamei(cnp
->cn_proc
->p_tracep
, cnp
->cn_pnbuf
);
158 * Get starting point for the translation.
160 if ((ndp
->ni_rootdir
= fdp
->fd_rdir
) == NULL
)
161 ndp
->ni_rootdir
= rootvnode
;
166 * Check if root directory should replace current directory.
167 * Done at start of translation and after symbolic link.
169 cnp
->cn_nameptr
= cnp
->cn_pnbuf
;
170 if (*(cnp
->cn_nameptr
) == '/') {
172 while (*(cnp
->cn_nameptr
) == '/') {
176 dp
= ndp
->ni_rootdir
;
179 ndp
->ni_startdir
= dp
;
180 if (error
= lookup(ndp
)) {
181 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
185 * Check for symbolic link
187 if ((cnp
->cn_flags
& ISSYMLINK
) == 0) {
188 if ((cnp
->cn_flags
& (SAVENAME
| SAVESTART
)) == 0) {
189 FREE_ZONE(cnp
->cn_pnbuf
,
190 cnp
->cn_pnlen
, M_NAMEI
);
192 cnp
->cn_flags
|= HASBUF
;
196 if ((cnp
->cn_flags
& LOCKPARENT
) && ndp
->ni_pathlen
== 1)
197 VOP_UNLOCK(ndp
->ni_dvp
, 0, p
);
198 if (ndp
->ni_loopcnt
++ >= MAXSYMLINKS
) {
202 if (ndp
->ni_pathlen
> 1) {
203 MALLOC_ZONE(cp
, char *, MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
208 aiov
.iov_len
= MAXPATHLEN
;
209 auio
.uio_iov
= &aiov
;
212 auio
.uio_rw
= UIO_READ
;
213 auio
.uio_segflg
= UIO_SYSSPACE
;
214 auio
.uio_procp
= (struct proc
*)0;
215 auio
.uio_resid
= MAXPATHLEN
;
216 if (error
= VOP_READLINK(ndp
->ni_vp
, &auio
, cnp
->cn_cred
)) {
217 if (ndp
->ni_pathlen
> 1)
218 _FREE_ZONE(cp
, MAXPATHLEN
, M_NAMEI
);
221 linklen
= MAXPATHLEN
- auio
.uio_resid
;
222 if (linklen
+ ndp
->ni_pathlen
>= MAXPATHLEN
) {
223 if (ndp
->ni_pathlen
> 1)
224 _FREE_ZONE(cp
, MAXPATHLEN
, M_NAMEI
);
225 error
= ENAMETOOLONG
;
228 if (ndp
->ni_pathlen
> 1) {
229 bcopy(ndp
->ni_next
, cp
+ linklen
, ndp
->ni_pathlen
);
230 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
232 cnp
->cn_pnlen
= MAXPATHLEN
;
234 cnp
->cn_pnbuf
[linklen
] = '\0';
235 ndp
->ni_pathlen
+= linklen
;
239 FREE_ZONE(cnp
->cn_pnbuf
, cnp
->cn_pnlen
, M_NAMEI
);
248 * This is a very central and rather complicated routine.
250 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
251 * The starting directory is taken from ni_startdir. The pathname is
252 * descended until done, or a symbolic link is encountered. The variable
253 * ni_more is clear if the path is completed; it is set to one if a
254 * symbolic link needing interpretation is encountered.
256 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
257 * whether the name is to be looked up, created, renamed, or deleted.
258 * When CREATE, RENAME, or DELETE is specified, information usable in
259 * creating, renaming, or deleting a directory entry may be calculated.
260 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
261 * locked. If flag has WANTPARENT or'ed into it, the parent directory is
262 * returned unlocked. Otherwise the parent directory is not returned. If
263 * the target of the pathname exists and LOCKLEAF is or'ed into the flag
264 * the target is returned locked, otherwise it is returned unlocked.
265 * When creating or renaming and LOCKPARENT is specified, the target may not
266 * be ".". When deleting and LOCKPARENT is specified, the target may be ".".
268 * Overall outline of lookup:
271 * identify next component of name at ndp->ni_ptr
272 * handle degenerate case where name is null string
273 * if .. and crossing mount points and on mounted filesys, find parent
274 * call VOP_LOOKUP routine for next component name
275 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
276 * component vnode returned in ni_vp (if it exists), locked.
277 * if result vnode is mounted on and crossing mount points,
278 * find mounted on vnode
279 * if more components of name, do next level at dirloop
280 * return the answer in ni_vp, locked if LOCKLEAF set
281 * if LOCKPARENT set, return locked parent in ni_dvp
282 * if WANTPARENT set, return unlocked parent in ni_dvp
286 register struct nameidata
*ndp
;
288 register char *cp
; /* pointer into pathname argument */
289 register struct vnode
*dp
= 0; /* the directory we are searching */
290 struct vnode
*tdp
; /* saved dp */
291 struct mount
*mp
; /* mount table entry */
292 int namemax
= 0; /* maximun number of bytes for filename returned by pathconf() */
293 int docache
; /* == 0 do not cache last component */
294 int wantparent
; /* 1 => wantparent or lockparent flag */
295 int dp_unlocked
= 0; /* 1 => dp already VOP_UNLOCK()-ed */
296 int rdonly
; /* lookup read-only flag bit */
299 struct componentname
*cnp
= &ndp
->ni_cnd
;
300 struct proc
*p
= cnp
->cn_proc
;
304 * Setup: break out flag bits into variables.
306 wantparent
= cnp
->cn_flags
& (LOCKPARENT
| WANTPARENT
);
307 docache
= (cnp
->cn_flags
& NOCACHE
) ^ NOCACHE
;
308 if (cnp
->cn_nameiop
== DELETE
||
309 (wantparent
&& cnp
->cn_nameiop
!= CREATE
&&
310 cnp
->cn_nameiop
!= LOOKUP
))
312 rdonly
= cnp
->cn_flags
& RDONLY
;
314 cnp
->cn_flags
&= ~ISSYMLINK
;
315 dp
= ndp
->ni_startdir
;
316 ndp
->ni_startdir
= NULLVP
;
317 vn_lock(dp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
321 * Search a new directory.
323 * The cn_hash value is for use by vfs_cache.
324 * Check pathconf for maximun length of name
325 * The last component of the filename is left accessible via
326 * cnp->cn_nameptr for callers that need the name. Callers needing
327 * the name set the SAVENAME flag. When done, they assume
328 * responsibility for freeing the pathname buffer.
332 for (cp
= cnp
->cn_nameptr
, i
=1; *cp
!= 0 && *cp
!= '/'; i
++, cp
++)
333 cnp
->cn_hash
+= (unsigned char)*cp
* i
;
334 cnp
->cn_namelen
= cp
- cnp
->cn_nameptr
;
335 if (VOP_PATHCONF(dp
, _PC_NAME_MAX
, &namemax
))
337 if (cnp
->cn_namelen
> namemax
) {
338 error
= ENAMETOOLONG
;
341 #ifdef NAMEI_DIAGNOSTIC
344 printf("{%s}: ", cnp
->cn_nameptr
);
347 ndp
->ni_pathlen
-= cnp
->cn_namelen
;
351 * Replace multiple slashes by a single slash and trailing slashes
352 * by a null. This must be done before VOP_LOOKUP() because some
353 * fs's don't know about trailing slashes. Remember if there were
354 * trailing slashes to handle symlinks, existing non-directories
355 * and non-existing files that won't be directories specially later.
358 while (*cp
== '/' && (cp
[1] == '/' || cp
[1] == '\0')) {
363 *ndp
->ni_next
= '\0';
368 cnp
->cn_flags
|= MAKEENTRY
;
369 if (*cp
== '\0' && docache
== 0)
370 cnp
->cn_flags
&= ~MAKEENTRY
;
371 if (cnp
->cn_namelen
== 2 &&
372 cnp
->cn_nameptr
[1] == '.' && cnp
->cn_nameptr
[0] == '.')
373 cnp
->cn_flags
|= ISDOTDOT
;
375 cnp
->cn_flags
&= ~ISDOTDOT
;
376 if (*ndp
->ni_next
== 0)
377 cnp
->cn_flags
|= ISLASTCN
;
379 cnp
->cn_flags
&= ~ISLASTCN
;
383 * Check for degenerate name (e.g. / or "")
384 * which is a way of talking about a directory,
385 * e.g. like "/." or ".".
387 if (cnp
->cn_nameptr
[0] == '\0') {
388 if (dp
->v_type
!= VDIR
) {
392 if (cnp
->cn_nameiop
!= LOOKUP
) {
401 if (!(cnp
->cn_flags
& (LOCKPARENT
| LOCKLEAF
)))
402 VOP_UNLOCK(dp
, 0, p
);
403 if (cnp
->cn_flags
& SAVESTART
)
404 panic("lookup: SAVESTART");
409 * Handle "..": two special cases.
410 * 1. If at root directory (e.g. after chroot)
411 * or at absolute root directory
412 * then ignore it so can't get out.
413 * 2. If this vnode is the root of a mounted
414 * filesystem, then replace it with the
415 * vnode which was mounted on so we take the
416 * .. in the other file system.
418 if (cnp
->cn_flags
& ISDOTDOT
) {
420 if (dp
== ndp
->ni_rootdir
|| dp
== rootvnode
) {
426 if ((dp
->v_flag
& VROOT
) == 0 ||
427 (cnp
->cn_flags
& NOCROSSMOUNT
))
429 if (dp
->v_mount
== NULL
) { /* forced umount */
435 dp
= dp
->v_mount
->mnt_vnodecovered
;
438 vn_lock(dp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
443 * We now have a segment name to search for, and a directory to search.
448 if (error
= VOP_LOOKUP(dp
, &ndp
->ni_vp
, cnp
)) {
450 if (ndp
->ni_vp
!= NULL
)
451 panic("leaf should be empty");
453 #ifdef NAMEI_DIAGNOSTIC
454 printf("not found\n");
456 if ((error
== ENOENT
) &&
457 (dp
->v_flag
& VROOT
) && (dp
->v_mount
!= NULL
) &&
458 (dp
->v_mount
->mnt_flag
& MNT_UNION
)) {
460 dp
= dp
->v_mount
->mnt_vnodecovered
;
463 vn_lock(dp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
467 if (error
!= EJUSTRETURN
)
470 * If creating and at end of pathname, then can consider
471 * allowing file to be created.
477 if (*cp
== '\0' && trailing_slash
&&
478 !(cnp
->cn_flags
& WILLBEDIR
)) {
483 * We return with ni_vp NULL to indicate that the entry
484 * doesn't currently exist, leaving a pointer to the
485 * (possibly locked) directory inode in ndp->ni_dvp.
487 if (cnp
->cn_flags
& SAVESTART
) {
488 ndp
->ni_startdir
= ndp
->ni_dvp
;
489 VREF(ndp
->ni_startdir
);
492 kdebug_lookup(ndp
->ni_dvp
, cnp
);
495 #ifdef NAMEI_DIAGNOSTIC
500 * Take into account any additional components consumed by
501 * the underlying filesystem.
503 if (cnp
->cn_consume
> 0) {
504 cnp
->cn_nameptr
+= cnp
->cn_consume
;
505 ndp
->ni_next
+= cnp
->cn_consume
;
506 ndp
->ni_pathlen
-= cnp
->cn_consume
;
512 * Check to see if the vnode has been mounted on;
513 * if so find the root of the mounted file system.
515 while (dp
->v_type
== VDIR
&& (mp
= dp
->v_mountedhere
) &&
516 (cnp
->cn_flags
& NOCROSSMOUNT
) == 0) {
517 if (vfs_busy(mp
, 0, 0, p
))
519 VOP_UNLOCK(dp
, 0, p
);
520 error
= VFS_ROOT(mp
, &tdp
);
523 dp_unlocked
= 1; /* Signal error path 'dp' has already been unlocked */
527 ndp
->ni_vp
= dp
= tdp
;
531 * Check for symbolic link
533 if ((dp
->v_type
== VLNK
) &&
534 ((cnp
->cn_flags
& FOLLOW
) || trailing_slash
||
535 *ndp
->ni_next
== '/')) {
536 cnp
->cn_flags
|= ISSYMLINK
;
541 * Check for bogus trailing slashes.
543 if (trailing_slash
&& dp
->v_type
!= VDIR
) {
550 * Not a symbolic link. If more pathname,
551 * continue at next component, else return.
553 if (*ndp
->ni_next
== '/') {
554 cnp
->cn_nameptr
= ndp
->ni_next
;
555 while (*cnp
->cn_nameptr
== '/') {
564 * Disallow directory write attempts on read-only file systems.
567 (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
)) {
571 if (cnp
->cn_flags
& SAVESTART
) {
572 ndp
->ni_startdir
= ndp
->ni_dvp
;
573 VREF(ndp
->ni_startdir
);
577 if ((cnp
->cn_flags
& LOCKLEAF
) == 0)
578 VOP_UNLOCK(dp
, 0, p
);
580 kdebug_lookup(dp
, cnp
);
584 if ((cnp
->cn_flags
& LOCKPARENT
) && *ndp
->ni_next
== '\0')
585 VOP_UNLOCK(ndp
->ni_dvp
, 0, p
);
595 kdebug_lookup(dp
, cnp
);
600 * relookup - lookup a path name component
601 * Used by lookup to re-aquire things.
604 relookup(dvp
, vpp
, cnp
)
605 struct vnode
*dvp
, **vpp
;
606 struct componentname
*cnp
;
608 struct proc
*p
= cnp
->cn_proc
;
609 struct vnode
*dp
= 0; /* the directory we are searching */
610 int docache
; /* == 0 do not cache last component */
611 int wantparent
; /* 1 => wantparent or lockparent flag */
612 int rdonly
; /* lookup read-only flag bit */
614 #ifdef NAMEI_DIAGNOSTIC
615 int newhash
; /* DEBUG: check name hash */
616 char *cp
; /* DEBUG: check name ptr/len */
620 * Setup: break out flag bits into variables.
622 wantparent
= cnp
->cn_flags
& (LOCKPARENT
|WANTPARENT
);
623 docache
= (cnp
->cn_flags
& NOCACHE
) ^ NOCACHE
;
624 if (cnp
->cn_nameiop
== DELETE
||
625 (wantparent
&& cnp
->cn_nameiop
!= CREATE
))
627 rdonly
= cnp
->cn_flags
& RDONLY
;
628 cnp
->cn_flags
&= ~ISSYMLINK
;
630 vn_lock(dp
, LK_EXCLUSIVE
| LK_RETRY
, p
);
634 * Search a new directory.
636 * The cn_hash value is for use by vfs_cache.
637 * The last component of the filename is left accessible via
638 * cnp->cn_nameptr for callers that need the name. Callers needing
639 * the name set the SAVENAME flag. When done, they assume
640 * responsibility for freeing the pathname buffer.
642 #ifdef NAMEI_DIAGNOSTIC
643 for (newhash
= 0, cp
= cnp
->cn_nameptr
; *cp
!= 0 && *cp
!= '/'; cp
++)
644 newhash
+= (unsigned char)*cp
;
645 if (newhash
!= cnp
->cn_hash
)
646 panic("relookup: bad hash");
647 if (cnp
->cn_namelen
!= cp
- cnp
->cn_nameptr
)
648 panic ("relookup: bad len");
650 panic("relookup: not last component");
651 printf("{%s}: ", cnp
->cn_nameptr
);
655 * Check for degenerate name (e.g. / or "")
656 * which is a way of talking about a directory,
657 * e.g. like "/." or ".".
659 if (cnp
->cn_nameptr
[0] == '\0') {
660 if (cnp
->cn_nameiop
!= LOOKUP
|| wantparent
) {
664 if (dp
->v_type
!= VDIR
) {
668 if (!(cnp
->cn_flags
& LOCKLEAF
))
669 VOP_UNLOCK(dp
, 0, p
);
671 if (cnp
->cn_flags
& SAVESTART
)
672 panic("lookup: SAVESTART");
676 if (cnp
->cn_flags
& ISDOTDOT
)
677 panic ("relookup: lookup on dot-dot");
680 * We now have a segment name to search for, and a directory to search.
682 if (error
= VOP_LOOKUP(dp
, vpp
, cnp
)) {
685 panic("leaf should be empty");
687 if (error
!= EJUSTRETURN
)
690 * If creating and at end of pathname, then can consider
691 * allowing file to be created.
697 /* ASSERT(dvp == ndp->ni_startdir) */
698 if (cnp
->cn_flags
& SAVESTART
)
701 * We return with ni_vp NULL to indicate that the entry
702 * doesn't currently exist, leaving a pointer to the
703 * (possibly locked) directory inode in ndp->ni_dvp.
711 * Check for symbolic link
713 if (dp
->v_type
== VLNK
&& (cnp
->cn_flags
& FOLLOW
))
714 panic ("relookup: symlink found.\n");
718 * Disallow directory write attempts on read-only file systems.
721 (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
)) {
725 /* ASSERT(dvp == ndp->ni_startdir) */
726 if (cnp
->cn_flags
& SAVESTART
)
731 if ((cnp
->cn_flags
& LOCKLEAF
) == 0)
732 VOP_UNLOCK(dp
, 0, p
);
736 if ((cnp
->cn_flags
& LOCKPARENT
) && (cnp
->cn_flags
& ISLASTCN
))
737 VOP_UNLOCK(dvp
, 0, p
);
748 kdebug_lookup(dp
, cnp
)
750 struct componentname
*cnp
;
753 register int dbg_namelen
;
754 register int save_dbg_namelen
;
755 register char *dbg_nameptr
;
756 long dbg_parms
[NUMPARMS
];
758 static char *dbg_filler
= ">>>>";
760 /* Collect the pathname for tracing */
761 dbg_namelen
= (cnp
->cn_nameptr
- cnp
->cn_pnbuf
) + cnp
->cn_namelen
;
762 dbg_nameptr
= cnp
->cn_nameptr
+ cnp
->cn_namelen
;
764 if (dbg_namelen
> sizeof(dbg_parms
))
765 dbg_namelen
= sizeof(dbg_parms
);
766 dbg_nameptr
-= dbg_namelen
;
767 save_dbg_namelen
= dbg_namelen
;
771 while (dbg_namelen
> 0) {
772 if (dbg_namelen
>= 4) {
773 dbg_parms
[i
++] = *(long *)dbg_nameptr
;
774 dbg_nameptr
+= sizeof(long);
775 dbg_namelen
-= sizeof(long);
777 for (n
= 0; n
< dbg_namelen
; n
++)
778 dbg_buf
[n
] = *dbg_nameptr
++;
785 dbg_parms
[i
++] = *(long *)&dbg_buf
[0];
790 while (i
< NUMPARMS
) {
792 dbg_parms
[i
++] = *(long *)dbg_filler
;
798 In the event that we collect multiple, consecutive pathname
799 entries, we must mark the start of the path's string.
801 KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW
,36)) | DBG_FUNC_START
,
802 dp
, dbg_parms
[0], dbg_parms
[1], dbg_parms
[2], 0);
804 for (dbg_namelen
= save_dbg_namelen
-12, i
=3;
806 dbg_namelen
-=(4 * sizeof(long)), i
+= 4)
808 KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW
,36)) | DBG_FUNC_NONE
,
809 dbg_parms
[i
], dbg_parms
[i
+1], dbg_parms
[i
+2], dbg_parms
[i
+3], 0);