Cleanups for 4.4BSD-Lite
[unix-history] / usr / src / sys / kern / vfs_lookup.c
index 6cfb6f2..5330a8a 100644 (file)
@@ -1,25 +1,25 @@
 /*
 /*
- * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)vfs_lookup.c        7.38 (Berkeley) %G%
+ *     @(#)vfs_lookup.c        8.1 (Berkeley) %G%
  */
 
  */
 
-#include "param.h"
-#include "syslimits.h"
-#include "time.h"
-#include "namei.h"
-#include "vnode.h"
-#include "mount.h"
-#include "errno.h"
-#include "malloc.h"
-#include "filedesc.h"
-#include "proc.h"
+#include <sys/param.h>
+#include <sys/syslimits.h>
+#include <sys/time.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
 
 #ifdef KTRACE
 
 #ifdef KTRACE
-#include "ktrace.h"
+#include <sys/ktrace.h>
 #endif
 
 /*
 #endif
 
 /*
@@ -194,7 +194,6 @@ namei(ndp)
  * the target is returned locked, otherwise it is returned unlocked.
  * When creating or renaming and LOCKPARENT is specified, the target may not
  * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
  * the target is returned locked, otherwise it is returned unlocked.
  * When creating or renaming and LOCKPARENT is specified, the target may not
  * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
- * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent vnode unlocked.
  * 
  * Overall outline of lookup:
  *
  * 
  * Overall outline of lookup:
  *
@@ -251,11 +250,12 @@ dirloop:
         * the name set the SAVENAME flag. When done, they assume
         * responsibility for freeing the pathname buffer.
         */
         * the name set the SAVENAME flag. When done, they assume
         * responsibility for freeing the pathname buffer.
         */
+       cnp->cn_consume = 0;
        cnp->cn_hash = 0;
        for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
                cnp->cn_hash += (unsigned char)*cp;
        cnp->cn_namelen = cp - cnp->cn_nameptr;
        cnp->cn_hash = 0;
        for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
                cnp->cn_hash += (unsigned char)*cp;
        cnp->cn_namelen = cp - cnp->cn_nameptr;
-       if (cnp->cn_namelen >= NAME_MAX) {
+       if (cnp->cn_namelen > NAME_MAX) {
                error = ENAMETOOLONG;
                goto bad;
        }
                error = ENAMETOOLONG;
                goto bad;
        }
@@ -271,12 +271,14 @@ dirloop:
        if (*cp == '\0' && docache == 0)
                cnp->cn_flags &= ~MAKEENTRY;
        if (cnp->cn_namelen == 2 &&
        if (*cp == '\0' && docache == 0)
                cnp->cn_flags &= ~MAKEENTRY;
        if (cnp->cn_namelen == 2 &&
-                       cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
+           cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
                cnp->cn_flags |= ISDOTDOT;
                cnp->cn_flags |= ISDOTDOT;
-       else cnp->cn_flags &= ~ISDOTDOT;
+       else
+               cnp->cn_flags &= ~ISDOTDOT;
        if (*ndp->ni_next == 0)
                cnp->cn_flags |= ISLASTCN;
        if (*ndp->ni_next == 0)
                cnp->cn_flags |= ISLASTCN;
-       else cnp->cn_flags &= ~ISLASTCN;
+       else
+               cnp->cn_flags &= ~ISLASTCN;
 
 
        /*
 
 
        /*
@@ -285,7 +287,7 @@ dirloop:
         * e.g. like "/." or ".".
         */
        if (cnp->cn_nameptr[0] == '\0') {
         * e.g. like "/." or ".".
         */
        if (cnp->cn_nameptr[0] == '\0') {
-               if (cnp->cn_nameiop != LOOKUP || wantparent) {
+               if (cnp->cn_nameiop != LOOKUP) {
                        error = EISDIR;
                        goto bad;
                }
                        error = EISDIR;
                        goto bad;
                }
@@ -293,9 +295,13 @@ dirloop:
                        error = ENOTDIR;
                        goto bad;
                }
                        error = ENOTDIR;
                        goto bad;
                }
-               if (!(cnp->cn_flags & LOCKLEAF))
-                       VOP_UNLOCK(dp);
+               if (wantparent) {
+                       ndp->ni_dvp = dp;
+                       vref(dp);
+               }
                ndp->ni_vp = dp;
                ndp->ni_vp = dp;
+               if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
+                       VOP_UNLOCK(dp);
                if (cnp->cn_flags & SAVESTART)
                        panic("lookup: SAVESTART");
                return (0);
                if (cnp->cn_flags & SAVESTART)
                        panic("lookup: SAVESTART");
                return (0);
@@ -304,6 +310,7 @@ dirloop:
        /*
         * Handle "..": two special cases.
         * 1. If at root directory (e.g. after chroot)
        /*
         * Handle "..": two special cases.
         * 1. If at root directory (e.g. after chroot)
+        *    or at absolute root directory
         *    then ignore it so can't get out.
         * 2. If this vnode is the root of a mounted
         *    filesystem, then replace it with the
         *    then ignore it so can't get out.
         * 2. If this vnode is the root of a mounted
         *    filesystem, then replace it with the
@@ -312,7 +319,7 @@ dirloop:
         */
        if (cnp->cn_flags & ISDOTDOT) {
                for (;;) {
         */
        if (cnp->cn_flags & ISDOTDOT) {
                for (;;) {
-                       if (dp == ndp->ni_rootdir) {
+                       if (dp == ndp->ni_rootdir || dp == rootdir) {
                                ndp->ni_dvp = dp;
                                ndp->ni_vp = dp;
                                VREF(dp);
                                ndp->ni_dvp = dp;
                                ndp->ni_vp = dp;
                                VREF(dp);
@@ -332,6 +339,7 @@ dirloop:
        /*
         * We now have a segment name to search for, and a directory to search.
         */
        /*
         * We now have a segment name to search for, and a directory to search.
         */
+unionlookup:
        ndp->ni_dvp = dp;
        if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) {
 #ifdef DIAGNOSTIC
        ndp->ni_dvp = dp;
        if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) {
 #ifdef DIAGNOSTIC
@@ -341,6 +349,17 @@ dirloop:
 #ifdef NAMEI_DIAGNOSTIC
                printf("not found\n");
 #endif
 #ifdef NAMEI_DIAGNOSTIC
                printf("not found\n");
 #endif
+               if ((error == ENOENT) &&
+                   (dp->v_flag & VROOT) &&
+                   (dp->v_mount->mnt_flag & MNT_UNION)) {
+                       tdp = dp;
+                       dp = dp->v_mount->mnt_vnodecovered;
+                       vput(tdp);
+                       VREF(dp);
+                       VOP_LOCK(dp);
+                       goto unionlookup;
+               }
+
                if (error != EJUSTRETURN)
                        goto bad;
                /*
                if (error != EJUSTRETURN)
                        goto bad;
                /*
@@ -367,6 +386,17 @@ dirloop:
        printf("found\n");
 #endif
 
        printf("found\n");
 #endif
 
+       /*
+        * Take into account any additional components consumed by
+        * the underlying filesystem.
+        */
+       if (cnp->cn_consume > 0) {
+               cnp->cn_nameptr += cnp->cn_consume;
+               ndp->ni_next += cnp->cn_consume;
+               ndp->ni_pathlen -= cnp->cn_consume;
+               cnp->cn_consume = 0;
+       }
+
        dp = ndp->ni_vp;
        /*
         * Check for symbolic link
        dp = ndp->ni_vp;
        /*
         * Check for symbolic link