Cleanups for 4.4BSD-Lite
[unix-history] / usr / src / sys / kern / vfs_lookup.c
index 6ef2125..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.39 (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
 
 /*
@@ -46,8 +46,6 @@ int
 namei(ndp)
        register struct nameidata *ndp;
 {
 namei(ndp)
        register struct nameidata *ndp;
 {
-       USES_VOP_READLINK;
-       USES_VOP_UNLOCK;
        register struct filedesc *fdp;  /* pointer to file descriptor state */
        register char *cp;              /* pointer into pathname argument */
        register struct vnode *dp;      /* the directory we are searching */
        register struct filedesc *fdp;  /* pointer to file descriptor state */
        register char *cp;              /* pointer into pathname argument */
        register struct vnode *dp;      /* the directory we are searching */
@@ -196,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:
  *
@@ -218,9 +215,6 @@ int
 lookup(ndp)
        register struct nameidata *ndp;
 {
 lookup(ndp)
        register struct nameidata *ndp;
 {
-       USES_VOP_LOCK;
-       USES_VOP_LOOKUP;
-       USES_VOP_UNLOCK;
        register char *cp;              /* pointer into pathname argument */
        register struct vnode *dp = 0;  /* the directory we are searching */
        struct vnode *tdp;              /* saved dp */
        register char *cp;              /* pointer into pathname argument */
        register struct vnode *dp = 0;  /* the directory we are searching */
        struct vnode *tdp;              /* saved dp */
@@ -256,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;
        }
@@ -276,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;
 
 
        /*
 
 
        /*
@@ -290,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;
                }
@@ -298,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);
@@ -309,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
@@ -317,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);
@@ -337,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
@@ -346,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;
                /*
@@ -372,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