]> git.saurik.com Git - apple/xnu.git/blob - bsd/vfs/vfs_lookup.c
xnu-344.21.73.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_lookup.c
1 /*
2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
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.
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>
67 #include <sys/syslimits.h>
68 #include <sys/time.h>
69 #include <sys/namei.h>
70 #include <sys/vm.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>
76 #include <sys/proc.h>
77 #include <sys/kdebug.h>
78 #include <sys/unistd.h> /* For _PC_NAME_MAX */
79
80 #if KTRACE
81 #include <sys/ktrace.h>
82 #endif
83
84 /*
85 * Convert a pathname into a pointer to a locked inode.
86 *
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.
91 *
92 * The segflg defines whether the name is to be copied from user
93 * space or kernel space.
94 *
95 * Overall outline of namei:
96 *
97 * copy in name
98 * get starting directory
99 * while (!done && !error) {
100 * call lookup to search path.
101 * if symbolic link, massage name in buffer and continue
102 * }
103 */
104 int
105 namei(ndp)
106 register struct nameidata *ndp;
107 {
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 */
112 struct uio auio;
113 int error, linklen;
114 struct componentname *cnp = &ndp->ni_cnd;
115 struct proc *p = cnp->cn_proc;
116
117 ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred;
118 #if DIAGNOSTIC
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");
125 #endif
126 fdp = cnp->cn_proc->p_fd;
127
128 /*
129 * Get a buffer for the name to be translated, and copy the
130 * name into the buffer.
131 */
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;
136 }
137 if (ndp->ni_segflg == UIO_SYSSPACE)
138 error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
139 MAXPATHLEN, &ndp->ni_pathlen);
140 else
141 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
142 MAXPATHLEN, &ndp->ni_pathlen);
143 /*
144 * Do not allow empty pathnames
145 */
146 if (!error && *cnp->cn_pnbuf == '\0')
147 error = ENOENT;
148
149 if (error) {
150 _FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
151 ndp->ni_vp = NULL;
152 return (error);
153 }
154 ndp->ni_loopcnt = 0;
155 #if KTRACE
156 if (KTRPOINT(cnp->cn_proc, KTR_NAMEI))
157 ktrnamei(cnp->cn_proc->p_tracep, cnp->cn_pnbuf);
158 #endif
159
160 /*
161 * Get starting point for the translation.
162 */
163 if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL)
164 ndp->ni_rootdir = rootvnode;
165 dp = fdp->fd_cdir;
166 VREF(dp);
167 for (;;) {
168 /*
169 * Check if root directory should replace current directory.
170 * Done at start of translation and after symbolic link.
171 */
172 cnp->cn_nameptr = cnp->cn_pnbuf;
173 if (*(cnp->cn_nameptr) == '/') {
174 vrele(dp);
175 while (*(cnp->cn_nameptr) == '/') {
176 cnp->cn_nameptr++;
177 ndp->ni_pathlen--;
178 }
179 dp = ndp->ni_rootdir;
180 VREF(dp);
181 }
182 ndp->ni_startdir = dp;
183 if (error = lookup(ndp)) {
184 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
185 return (error);
186 }
187 /*
188 * Check for symbolic link
189 */
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);
194 } else {
195 cnp->cn_flags |= HASBUF;
196 }
197 return (0);
198 }
199 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
200 VOP_UNLOCK(ndp->ni_dvp, 0, p);
201 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
202 error = ELOOP;
203 break;
204 }
205 if (ndp->ni_pathlen > 1) {
206 MALLOC_ZONE(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
207 } else {
208 cp = cnp->cn_pnbuf;
209 }
210 aiov.iov_base = cp;
211 aiov.iov_len = MAXPATHLEN;
212 auio.uio_iov = &aiov;
213 auio.uio_iovcnt = 1;
214 auio.uio_offset = 0;
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);
222 break;
223 }
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;
229 break;
230 }
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);
234 cnp->cn_pnbuf = cp;
235 cnp->cn_pnlen = MAXPATHLEN;
236 } else
237 cnp->cn_pnbuf[linklen] = '\0';
238 ndp->ni_pathlen += linklen;
239 vput(ndp->ni_vp);
240 dp = ndp->ni_dvp;
241 }
242 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
243 vrele(ndp->ni_dvp);
244 vput(ndp->ni_vp);
245 ndp->ni_vp = NULL;
246 return (error);
247 }
248
249 /*
250 * Search a pathname.
251 * This is a very central and rather complicated routine.
252 *
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.
258 *
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 ".".
270 *
271 * Overall outline of lookup:
272 *
273 * dirloop:
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
286 */
287 int
288 lookup(ndp)
289 register struct nameidata *ndp;
290 {
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 */
300 int trailing_slash;
301 int error = 0;
302 struct componentname *cnp = &ndp->ni_cnd;
303 struct proc *p = cnp->cn_proc;
304 int i;
305
306 /*
307 * Setup: break out flag bits into variables.
308 */
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))
314 docache = 0;
315 rdonly = cnp->cn_flags & RDONLY;
316 ndp->ni_dvp = NULL;
317 cnp->cn_flags &= ~ISSYMLINK;
318 dp = ndp->ni_startdir;
319 ndp->ni_startdir = NULLVP;
320 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
321
322 dirloop:
323 /*
324 * Search a new directory.
325 *
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.
332 */
333 cnp->cn_consume = 0;
334 cnp->cn_hash = 0;
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))
339 namemax = NAME_MAX;
340 if (cnp->cn_namelen > namemax) {
341 error = ENAMETOOLONG;
342 goto bad;
343 }
344 #ifdef NAMEI_DIAGNOSTIC
345 { char c = *cp;
346 *cp = '\0';
347 printf("{%s}: ", cnp->cn_nameptr);
348 *cp = c; }
349 #endif
350 ndp->ni_pathlen -= cnp->cn_namelen;
351 ndp->ni_next = cp;
352
353 /*
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.
359 */
360 trailing_slash = 0;
361 while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
362 cp++;
363 ndp->ni_pathlen--;
364 if (*cp == '\0') {
365 trailing_slash = 1;
366 *ndp->ni_next = '\0';
367 }
368 }
369 ndp->ni_next = cp;
370
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;
377 else
378 cnp->cn_flags &= ~ISDOTDOT;
379 if (*ndp->ni_next == 0)
380 cnp->cn_flags |= ISLASTCN;
381 else
382 cnp->cn_flags &= ~ISLASTCN;
383
384
385 /*
386 * Check for degenerate name (e.g. / or "")
387 * which is a way of talking about a directory,
388 * e.g. like "/." or ".".
389 */
390 if (cnp->cn_nameptr[0] == '\0') {
391 if (dp->v_type != VDIR) {
392 error = ENOTDIR;
393 goto bad;
394 }
395 if (cnp->cn_nameiop != LOOKUP) {
396 error = EISDIR;
397 goto bad;
398 }
399 if (wantparent) {
400 ndp->ni_dvp = dp;
401 VREF(dp);
402 }
403 ndp->ni_vp = dp;
404 if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
405 VOP_UNLOCK(dp, 0, p);
406 if (cnp->cn_flags & SAVESTART)
407 panic("lookup: SAVESTART");
408 return (0);
409 }
410
411 /*
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.
420 */
421 if (cnp->cn_flags & ISDOTDOT) {
422 for (;;) {
423 if (dp == ndp->ni_rootdir || dp == rootvnode) {
424 ndp->ni_dvp = dp;
425 ndp->ni_vp = dp;
426 VREF(dp);
427 goto nextname;
428 }
429 if ((dp->v_flag & VROOT) == 0 ||
430 (cnp->cn_flags & NOCROSSMOUNT))
431 break;
432 if (dp->v_mount == NULL) { /* forced umount */
433 error = EBADF;
434 goto bad;
435 }
436
437 tdp = dp;
438 dp = dp->v_mount->mnt_vnodecovered;
439 vput(tdp);
440 VREF(dp);
441 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
442 }
443 }
444
445 /*
446 * We now have a segment name to search for, and a directory to search.
447 */
448 unionlookup:
449 ndp->ni_dvp = dp;
450 ndp->ni_vp = NULL;
451 if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) {
452 #if DIAGNOSTIC
453 if (ndp->ni_vp != NULL)
454 panic("leaf should be empty");
455 #endif
456 #ifdef NAMEI_DIAGNOSTIC
457 printf("not found\n");
458 #endif
459 if ((error == ENOENT) &&
460 (dp->v_flag & VROOT) && (dp->v_mount != NULL) &&
461 (dp->v_mount->mnt_flag & MNT_UNION)) {
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 goto unionlookup;
468 }
469
470 if (error != EJUSTRETURN)
471 goto bad;
472 /*
473 * If creating and at end of pathname, then can consider
474 * allowing file to be created.
475 */
476 if (rdonly) {
477 error = EROFS;
478 goto bad;
479 }
480 if (*cp == '\0' && trailing_slash &&
481 !(cnp->cn_flags & WILLBEDIR)) {
482 error = ENOENT;
483 goto bad;
484 }
485 /*
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.
489 */
490 if (cnp->cn_flags & SAVESTART) {
491 ndp->ni_startdir = ndp->ni_dvp;
492 VREF(ndp->ni_startdir);
493 }
494 if (kdebug_enable)
495 kdebug_lookup(ndp->ni_dvp, cnp);
496 return (0);
497 }
498 #ifdef NAMEI_DIAGNOSTIC
499 printf("found\n");
500 #endif
501
502 /*
503 * Take into account any additional components consumed by
504 * the underlying filesystem.
505 */
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;
510 cnp->cn_consume = 0;
511 }
512
513 dp = ndp->ni_vp;
514 /*
515 * Check to see if the vnode has been mounted on;
516 * if so find the root of the mounted file system.
517 */
518 while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
519 (cnp->cn_flags & NOCROSSMOUNT) == 0) {
520 if (vfs_busy(mp, 0, 0, p))
521 continue;
522 VOP_UNLOCK(dp, 0, p);
523 error = VFS_ROOT(mp, &tdp);
524 vfs_unbusy(mp, p);
525 if (error) {
526 dp_unlocked = 1; /* Signal error path 'dp' has already been unlocked */
527 goto bad2;
528 };
529 vrele(dp);
530 ndp->ni_vp = dp = tdp;
531 }
532
533 /*
534 * Check for symbolic link
535 */
536 if ((dp->v_type == VLNK) &&
537 ((cnp->cn_flags & FOLLOW) || trailing_slash ||
538 *ndp->ni_next == '/')) {
539 cnp->cn_flags |= ISSYMLINK;
540 return (0);
541 }
542
543 /*
544 * Check for bogus trailing slashes.
545 */
546 if (trailing_slash && dp->v_type != VDIR) {
547 error = ENOTDIR;
548 goto bad2;
549 }
550
551 nextname:
552 /*
553 * Not a symbolic link. If more pathname,
554 * continue at next component, else return.
555 */
556 if (*ndp->ni_next == '/') {
557 cnp->cn_nameptr = ndp->ni_next;
558 while (*cnp->cn_nameptr == '/') {
559 cnp->cn_nameptr++;
560 ndp->ni_pathlen--;
561 }
562 vrele(ndp->ni_dvp);
563 goto dirloop;
564 }
565
566 /*
567 * Disallow directory write attempts on read-only file systems.
568 */
569 if (rdonly &&
570 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
571 error = EROFS;
572 goto bad2;
573 }
574 if (cnp->cn_flags & SAVESTART) {
575 ndp->ni_startdir = ndp->ni_dvp;
576 VREF(ndp->ni_startdir);
577 }
578 if (!wantparent)
579 vrele(ndp->ni_dvp);
580 if ((cnp->cn_flags & LOCKLEAF) == 0)
581 VOP_UNLOCK(dp, 0, p);
582 if (kdebug_enable)
583 kdebug_lookup(dp, cnp);
584 return (0);
585
586 bad2:
587 if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0')
588 VOP_UNLOCK(ndp->ni_dvp, 0, p);
589 vrele(ndp->ni_dvp);
590 bad:
591 if (dp_unlocked) {
592 vrele(dp);
593 } else {
594 vput(dp);
595 };
596 ndp->ni_vp = NULL;
597 if (kdebug_enable)
598 kdebug_lookup(dp, cnp);
599 return (error);
600 }
601
602 /*
603 * relookup - lookup a path name component
604 * Used by lookup to re-aquire things.
605 */
606 int
607 relookup(dvp, vpp, cnp)
608 struct vnode *dvp, **vpp;
609 struct componentname *cnp;
610 {
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 */
616 int error = 0;
617 #ifdef NAMEI_DIAGNOSTIC
618 int newhash; /* DEBUG: check name hash */
619 char *cp; /* DEBUG: check name ptr/len */
620 #endif
621
622 /*
623 * Setup: break out flag bits into variables.
624 */
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))
629 docache = 0;
630 rdonly = cnp->cn_flags & RDONLY;
631 cnp->cn_flags &= ~ISSYMLINK;
632 dp = dvp;
633 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
634
635 /* dirloop: */
636 /*
637 * Search a new directory.
638 *
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.
644 */
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");
652 if (*cp != 0)
653 panic("relookup: not last component");
654 printf("{%s}: ", cnp->cn_nameptr);
655 #endif
656
657 /*
658 * Check for degenerate name (e.g. / or "")
659 * which is a way of talking about a directory,
660 * e.g. like "/." or ".".
661 */
662 if (cnp->cn_nameptr[0] == '\0') {
663 if (cnp->cn_nameiop != LOOKUP || wantparent) {
664 error = EISDIR;
665 goto bad;
666 }
667 if (dp->v_type != VDIR) {
668 error = ENOTDIR;
669 goto bad;
670 }
671 if (!(cnp->cn_flags & LOCKLEAF))
672 VOP_UNLOCK(dp, 0, p);
673 *vpp = dp;
674 if (cnp->cn_flags & SAVESTART)
675 panic("lookup: SAVESTART");
676 return (0);
677 }
678
679 if (cnp->cn_flags & ISDOTDOT)
680 panic ("relookup: lookup on dot-dot");
681
682 /*
683 * We now have a segment name to search for, and a directory to search.
684 */
685 if (error = VOP_LOOKUP(dp, vpp, cnp)) {
686 #if DIAGNOSTIC
687 if (*vpp != NULL)
688 panic("leaf should be empty");
689 #endif
690 if (error != EJUSTRETURN)
691 goto bad;
692 /*
693 * If creating and at end of pathname, then can consider
694 * allowing file to be created.
695 */
696 if (rdonly) {
697 error = EROFS;
698 goto bad;
699 }
700 /* ASSERT(dvp == ndp->ni_startdir) */
701 if (cnp->cn_flags & SAVESTART)
702 VREF(dvp);
703 /*
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.
707 */
708 return (0);
709 }
710 dp = *vpp;
711
712 #if DIAGNOSTIC
713 /*
714 * Check for symbolic link
715 */
716 if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW))
717 panic ("relookup: symlink found.\n");
718 #endif
719
720 /*
721 * Disallow directory write attempts on read-only file systems.
722 */
723 if (rdonly &&
724 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
725 error = EROFS;
726 goto bad2;
727 }
728 /* ASSERT(dvp == ndp->ni_startdir) */
729 if (cnp->cn_flags & SAVESTART)
730 VREF(dvp);
731
732 if (!wantparent)
733 vrele(dvp);
734 if ((cnp->cn_flags & LOCKLEAF) == 0)
735 VOP_UNLOCK(dp, 0, p);
736 return (0);
737
738 bad2:
739 if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
740 VOP_UNLOCK(dvp, 0, p);
741 vrele(dvp);
742 bad:
743 vput(dp);
744 *vpp = NULL;
745 return (error);
746 }
747
748
749 #define NUMPARMS 23
750
751 kdebug_lookup(dp, cnp)
752 struct vnode *dp;
753 struct componentname *cnp;
754 {
755 register int i, n;
756 register int dbg_namelen;
757 register int save_dbg_namelen;
758 register char *dbg_nameptr;
759 long dbg_parms[NUMPARMS];
760 char dbg_buf[4];
761 static char *dbg_filler = ">>>>";
762
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;
766
767 if (dbg_namelen > sizeof(dbg_parms))
768 dbg_namelen = sizeof(dbg_parms);
769 dbg_nameptr -= dbg_namelen;
770 save_dbg_namelen = dbg_namelen;
771
772 i = 0;
773
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);
779 } else {
780 for (n = 0; n < dbg_namelen; n++)
781 dbg_buf[n] = *dbg_nameptr++;
782 while (n <= 3) {
783 if (*dbg_nameptr)
784 dbg_buf[n++] = '>';
785 else
786 dbg_buf[n++] = 0;
787 }
788 dbg_parms[i++] = *(long *)&dbg_buf[0];
789
790 break;
791 }
792 }
793 while (i < NUMPARMS) {
794 if (*dbg_nameptr)
795 dbg_parms[i++] = *(long *)dbg_filler;
796 else
797 dbg_parms[i++] = 0;
798 }
799
800 /*
801 In the event that we collect multiple, consecutive pathname
802 entries, we must mark the start of the path's string.
803 */
804 KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_START,
805 dp, dbg_parms[0], dbg_parms[1], dbg_parms[2], 0);
806
807 for (dbg_namelen = save_dbg_namelen-12, i=3;
808 dbg_namelen > 0;
809 dbg_namelen -=(4 * sizeof(long)), i+= 4)
810 {
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);
813 }
814 }