summaryrefslogtreecommitdiffstats
path: root/share/man/man9/VOP_LOOKUP.9
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>1997-03-03 18:01:01 +0000
committerdfr <dfr@FreeBSD.org>1997-03-03 18:01:01 +0000
commit7e67e1e73230219ea55118f095cc1800faf2c534 (patch)
treee33dd16a7d9cf5ad26d4f75d4b2d3db1b3d2fdd9 /share/man/man9/VOP_LOOKUP.9
parent6c38eceeb9c3076678e4763e02440823894d2323 (diff)
downloadFreeBSD-src-7e67e1e73230219ea55118f095cc1800faf2c534.zip
FreeBSD-src-7e67e1e73230219ea55118f095cc1800faf2c534.tar.gz
This is the current draft of my filesystem manpages. Some files are
incomplete and some are just placeholders but I wanted to try to get something at least into 2.2 on the grounds that what I have is a lot better than nothing. I also wanted to commit something which documents the interfaces in 2.2 before I start updating the documentation for 3.0. This is a definite 2.2 candidate and is also relavent to 2.1 if people still care about that branch.
Diffstat (limited to 'share/man/man9/VOP_LOOKUP.9')
-rw-r--r--share/man/man9/VOP_LOOKUP.9447
1 files changed, 447 insertions, 0 deletions
diff --git a/share/man/man9/VOP_LOOKUP.9 b/share/man/man9/VOP_LOOKUP.9
new file mode 100644
index 0000000..c878e39
--- /dev/null
+++ b/share/man/man9/VOP_LOOKUP.9
@@ -0,0 +1,447 @@
+.\" -*- nroff -*-
+.\"
+.\" Copyright (c) 1996 Doug Rabson
+.\"
+.\" All rights reserved.
+.\"
+.\" This program is free software.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $Id$
+.\"
+.Dd July 24, 1996
+.Os FreeBSD
+.Dt VOP_LOOKUP 9
+.Sh NAME
+.Nm VOP_LOOKUP
+.Nd lookup a component of a pathname
+.Sh SYNOPSIS
+.Fd #include <sys/vnode.h>
+.Fd #include <sys/namei.h>
+.Ft int
+.Fn VOP_LOOKUP "struct vnode *dvp" "struct vnode **vpp" "struct componentname *cnp"
+.Sh DESCRIPTION
+This VFS entry point looks up a single pathname component in a given directory.
+.Pp
+Its arguments are:
+.Bl -tag -width vpp
+.It Ar dvp
+the locked vnode of the directory to search
+.It Ar vpp
+the address of a variable where the resulting locked vnode should be stored
+.It Ar cnp
+the pathname component to be searched for
+.El
+.Pp
+.Fa Cnp
+is a pointer to a componentname structure defined as follows:
+.Bd -literal
+struct componentname {
+ /*
+ * Arguments to lookup.
+ */
+ u_long cn_nameiop; /* namei operation */
+ u_long cn_flags; /* flags to namei */
+ struct proc *cn_proc; /* process requesting lookup */
+ struct ucred *cn_cred; /* credentials */
+ /*
+ * Shared between lookup and commit routines.
+ */
+ char *cn_pnbuf; /* pathname buffer */
+ char *cn_nameptr; /* pointer to looked up name */
+ long cn_namelen; /* length of looked up component */
+ u_long cn_hash; /* hash value of looked up name */
+ long cn_consume; /* chars to consume in lookup() */
+};
+.Ed
+.Pp
+Convert a component of a pathname into a pointer to a locked vnode.
+This is a very central and rather complicated routine.
+If the file system is not maintained in a strict tree hierarchy,
+this can result in a deadlock situation.
+.Pp
+The
+.Fa cnp->cn_nameiop
+argument is
+.Dv LOOKUP ,
+.Dv CREATE ,
+.Dv RENAME ,
+or
+.Dv DELETE
+depending on the intended use of the object.
+When
+.Dv CREATE ,
+.Dv RENAME ,
+or
+.Dv DELETE
+is specified, information usable in
+creating, renaming, or deleting a directory entry may be calculated.
+.Pp
+Overall outline of VOP_LOOKUP:
+.Bd -filled -offset indent
+Check accessibility of directory.
+Look for name in cache, if found, then return name.
+Search for name in directory, goto to found or notfound as appropriate.
+.Ed
+.Pp
+notfound:
+.Bd -filled -offset indent
+If creating or renaming and at end of pathname,
+return
+.Dv EJUSTRETURN ,
+leaving info on available slots else return
+.Dv ENOENT .
+.Ed
+.Pp
+found:
+.Bd -filled -offset indent
+If at end of path and deleting, return information to allow delete.
+If at end of path and renaming, lock target
+inode and return info to allow rename.
+If not at end, add name to cache; if at end and neither creating
+nor deleting, add name to cache.
+.Ed
+.Sh LOCKS
+The directory,
+.Fa dvp
+should be locked on entry.
+If an error (note: the return value
+.Dv EJUSTRETURN
+is not considered an error)
+is detected, it will be returned locked.
+Otherwise, it will be unlocked unless both
+.Dv LOCKPARENT
+and
+.Dv ISLASTCN
+are specified in
+.Fa cnp->cn_flags .
+If an entry is found in the directory, it will be returned locked.
+.Sh RETURN VALUES
+Zero is returned with
+.Fa *vpp
+set to the locked vnode of the file if the component is found.
+If the component being searched for is ".", then the vnode just has
+an extra reference added to it with
+.Xr vref 9 .
+The caller must take care to release the locks appropriately in this
+case.
+.Pp
+If the component is not found and the operation is
+.Dv CREATE
+or
+.Dv RENAME ,
+the flag
+.Dv ISLASTCN
+is specified and the operation would succeed, the special return value
+.Dv EJUSTRETURN
+is returned.
+Otherwise, an appropriate error code is returned.
+.Sh PSEUDOCODE
+.Bd -literal
+int
+vop_lookup(struct vnode *dvp,
+ struct vnode **vpp,
+ struct componentname *cnp)
+{
+ int error;
+ int nameiop = cnp->cn_nameiop;
+ int flags = cnp->cn_flags;
+ int lockparent = flags & LOCKPARENT;
+ int islastcn = flags & ISLASTCN;
+ struct vnode *vp = NULL;
+
+ /*
+ * Check accessiblity of directory.
+ */
+ if (dvp->v_type != VDIR)
+ return ENOTDIR;
+
+ error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
+ if (error)
+ return (error);
+
+ if (islastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
+ (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+ return (EROFS);
+
+ /*
+ * Check name cachec for directory/name pair. This returns ENOENT
+ * if the name is known not to exist, -1 if the name was found, or
+ * zero if not.
+ */
+ error = cache_lookup(dvp, vpp, cnp);
+ if (error) {
+ int vpid;
+
+ if (error = ENOENT)
+ return error;
+
+ vp = *vpp;
+ if (dvp == vp) { /* lookup on "." */
+ VREF(vp);
+ error = 0;
+ } else if (flags & ISDOTDOT) {
+ /*
+ * We need to unlock the directory before getting
+ * the locked vnode for ".." to avoid deadlocks.
+ */
+ VOP_UNLOCK(dvp);
+ error = vget(vp, 1);
+ if (!error) {
+ if (lockparent && islastcn)
+ error = VOP_LOCK(dvp);
+ }
+ } else {
+ error = vget(vp, 1);
+ if (error || !(lockparent && islastcn)) {
+ VOP_UNLOCK(dvp);
+ }
+ }
+
+ /*
+ * Check that the capability number did not change
+ * while we were waiting for the lock.
+ */
+ if (!error) {
+ if (vpid == vp->v_id) {
+ /*
+ * dvp is locked if lockparent && islastcn.
+ * vp is locked.
+ */
+ return (0);
+ }
+ vput(vp);
+
+ if (dvp != vp && lockparent && islastcn)
+ VOP_UNLOCK(pdp);
+ }
+
+ /*
+ * Re-lock dvp for the directory search below.
+ */
+ error = VOP_LOCK(dvp);
+ if (error) {
+ return (error);
+ }
+
+ *vpp = NULL;
+ }
+
+ /*
+ * Search dvp for the component cnp->cn_nameptr.
+ */
+ ...;
+
+ if (!found) {
+ if ((nameiop == CREATE || nameiop == RENAME)
+ && islastcn
+ && directory dvp has not been removed) {
+ /*
+ * Check for write access on directory.
+ */
+
+ /*
+ * Possibly record the position of a slot in the directory
+ * large enough for the new component name. This can be
+ * recorded in the vnode private data for dvp.
+ * Set the SAVENAME flag to hold onto the pathname for use
+ * later in VOP_CREATE or VOP_RENAME.
+ */
+ cnp->cn_flags |= SAVENAME;
+ if (!lockparent)
+ /*
+ * Note that the extra data recorded above is only
+ * useful if lockparent is specified.
+ */
+ VOP_UNLOCK(dvp);
+
+ return EJUSTRETURN;
+ }
+
+ /*
+ * Consider inserting name into cache.
+ */
+ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
+ cache_enter(dvp, NULL, cnp);
+
+ return ENOENT;
+ } else {
+ /*
+ * If deleting, and at end of pathname, return parameters
+ * which can be used to remove file. If the wantparent flag
+ * isn't set, we return only the directory, otherwise we go on
+ * and lock the inode, being careful with ".".
+ */
+ if (nameiop == DELETE && islastcn) {
+ /*
+ * Check for write access on directory.
+ */
+ error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_proc);
+ if (error)
+ return (error);
+
+ if (found entry is same as dvp) {
+ VREF(dvp);
+ *vpp = dvp;
+ return 0;
+ }
+
+ error = VFS_VGET(dvp->v_mount, ..., &vp);
+ if (error)
+ return error;
+
+ if (directory is sticky
+ && cred->cr_uid != 0
+ && cred->cr_uid != owner of dvp
+ && owner of vp != cred->cr_uid) {
+ vput(vp);
+ return EPERM;
+ }
+ *vpp = vp;
+ if (!lockparent)
+ VOP_UNLOCK(dvp);
+
+ return 0;
+ }
+
+ /*
+ * If rewriting (RENAME), return the inode and the
+ * information required to rewrite the present directory
+ * Must get inode of directory entry to verify it's a
+ * regular file, or empty directory.
+ */
+ if (nameiop == RENAME && wantparent && islastcn) {
+ error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_proc);
+ if (error)
+ return (error);
+
+ /*
+ * Check for "."
+ */
+ if (found entry is same as dvp)
+ return EISDIR;
+
+ error = VFS_VGET(dvp->v_mount, ..., &vp);
+ if (error)
+ return error;
+ *vpp = vp;
+ /*
+ * Save the name for use in VOP_RENAME later.
+ */
+ cnp->cn_flags |= SAVENAME;
+ if (!lockparent)
+ VOP_UNLOCK(dvp);
+
+ return 0;
+ }
+
+ /*
+ * Step through the translation in the name. We do not `vput' the
+ * directory because we may need it again if a symbolic link
+ * is relative to the current directory. Instead we save it
+ * unlocked as "pdp". We must get the target inode before unlocking
+ * the directory to insure that the inode will not be removed
+ * before we get it. We prevent deadlock by always fetching
+ * inodes from the root, moving down the directory tree. Thus
+ * when following backward pointers ".." we must unlock the
+ * parent directory before getting the requested directory.
+ * There is a potential race condition here if both the current
+ * and parent directories are removed before the VFS_VGET for the
+ * inode associated with ".." returns. We hope that this occurs
+ * infrequently since we cannot avoid this race condition without
+ * implementing a sophisticated deadlock detection algorithm.
+ * Note also that this simple deadlock detection scheme will not
+ * work if the file system has any hard links other than ".."
+ * that point backwards in the directory structure.
+ */
+ if (flags & ISDOTDOT) {
+ VOP_UNLOCK(dvp); /* race to get the inode */
+ error = VFS_VGET(dvp->v_mount, ..., &vp);
+ if (error) {
+ VOP_LOCK(dvp);
+ return (error);
+ }
+ if (lockparent && islastcn) {
+ error = VOP_LOCK(dvp);
+ if (error) {
+ vput(vp);
+ return error;
+ }
+ }
+ *vpp = vp;
+ } else if (found entry is same as dvp) {
+ VREF(dvp); /* we want ourself, ie "." */
+ *vpp = dvp;
+ } else {
+ error = VFS_VGET(dvp->v_mount, ..., &vp);
+ if (error)
+ return (error);
+ if (!lockparent || !islastcn)
+ VOP_UNLOCK(dvp);
+ *vpp = vp;
+ }
+
+ /*
+ * Insert name into cache if appropriate.
+ */
+ if (cnp->cn_flags & MAKEENTRY)
+ cache_enter(dvp, *vpp, cnp);
+ return (0);
+ }
+}
+.Ed
+.Sh ERRORS
+.Bl -tag -width EJUSTRETURN
+.It Bq Er ENOTDIR
+The vnode
+.Fa dvp
+does not represent a directory.
+.It Bq Er ENOENT
+The component
+.Fa dvp
+was not found in this directory.
+.It Bq Er EACCESS
+access for the specified operation is denied.
+.It Bq Er EJUSTRETURN
+a
+.Dv CREATE
+or
+.Dv RENAME
+operation would be successful
+.El
+.Sh SEE ALSO
+.Xr VOP_ACCESS 9 ,
+.Xr VOP_CREATE 9 ,
+.Xr VOP_MKNOD 9 ,
+.Xr VOP_MKDIR 9 ,
+.Xr VOP_SYMLINK 9 ,
+.Xr VOP_RENAME 9 ,
+.Xr VOP_ABORTOP 9
+.Sh HISTORY
+The function
+.Nm
+appeared in 4.3BSD.
+.Sh SEE ALSO
+.Xr vnode 9
+.Sh AUTHORS
+This man page was written by Doug Rabson, with some text from
+comments in ufs_lookup.c.
OpenPOWER on IntegriCloud