967 lines
25 KiB
Groff
967 lines
25 KiB
Groff
.\" $NetBSD: namei.9,v 1.51 2019/05/05 20:10:57 christos Exp $
|
|
.\"
|
|
.\" Copyright (c) 2001, 2005, 2006, 2017 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Gregory McGarry.
|
|
.\"
|
|
.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
.\" ``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 FOUNDATION OR CONTRIBUTORS
|
|
.\" 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.
|
|
.\"
|
|
.Dd May 5, 2019
|
|
.Dt NAMEI 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm namei ,
|
|
.Nm NDINIT ,
|
|
.Nm NDAT ,
|
|
.Nm namei_simple_kernel ,
|
|
.Nm namei_simple_user ,
|
|
.Nm relookup ,
|
|
.Nm lookup_for_nfsd ,
|
|
.Nm lookup_for_nfsd_index
|
|
.Nd pathname lookup
|
|
.Sh SYNOPSIS
|
|
.In sys/namei.h
|
|
.In sys/uio.h
|
|
.In sys/vnode.h
|
|
.Fn NDINIT "struct nameidata *ndp" "u_long op" "u_long flags" \
|
|
"struct pathbuf *pathbuf"
|
|
.Fn NDAT "struct nameidata *ndp" "struct vnode *dvp"
|
|
.Ft int
|
|
.Fn namei "struct nameidata *ndp"
|
|
.Ft int
|
|
.Fn namei_simple_kernel "const char *path" "namei_simple_flags_t sflags" \
|
|
"struct vnode **ret"
|
|
.Ft int
|
|
.Fn namei_simple_user "const char *path" "namei_simple_flags_t sflags" \
|
|
"struct vnode **ret"
|
|
.Ft int
|
|
.Fn relookup "struct vnode *dvp" "struct vnode **vpp" \
|
|
"struct componentname *cnp" "int dummy"
|
|
.Ft int
|
|
.Fn lookup_for_nfsd "struct nameidata *ndp" "struct vnode *startdir" \
|
|
"int neverfollow"
|
|
.Ft int
|
|
.Fn lookup_for_nfsd_index "struct nameidata *ndp" "struct vnode *startdir"
|
|
.Sh DESCRIPTION
|
|
The
|
|
.Nm
|
|
interface is used to convert pathnames to file system vnodes.
|
|
The
|
|
name of the interface is actually a contraction of the words
|
|
.Em name
|
|
and
|
|
.Em inode
|
|
for name-to-inode conversion, in the days before the
|
|
.Xr vfs 9
|
|
interface was implemented.
|
|
.Pp
|
|
All access to the
|
|
.Nm
|
|
interface must be in process context.
|
|
Pathname lookups cannot be done in interrupt context.
|
|
.Pp
|
|
In the general form of
|
|
.Nm ,
|
|
a caller must:
|
|
.Bl -enum -compact
|
|
.It
|
|
Allocate storage for a
|
|
.Ft struct nameidata
|
|
object
|
|
.Fa nd .
|
|
.It
|
|
Initialize
|
|
.Fa nd
|
|
with
|
|
.Fn NDINIT
|
|
and optionally
|
|
.Fn NDAT
|
|
to specify the arguments to a lookup.
|
|
.It
|
|
Call
|
|
.Fn namei
|
|
and handle failure if it returns a nonzero error code.
|
|
.It
|
|
Read the resulting vnode out of
|
|
.Fa nd Ns Li .ni_vp .
|
|
If requested with
|
|
.Dv LOCKPARENT ,
|
|
read the directory vnode out of
|
|
.Fa nd Ns Li .ni_dvp .
|
|
.It
|
|
For directory operations, use the
|
|
.Ft struct componentname
|
|
object stored at
|
|
.Fa nd Ns Li .ni_cnd .
|
|
.El
|
|
.Pp
|
|
The other fields of
|
|
.Ft struct nameidata
|
|
should not be examined or altered directly.
|
|
.Pp
|
|
Note that the
|
|
.Xr nfs 4
|
|
code misuses
|
|
.Ft struct nameidata
|
|
and currently has an incestuous relationship with the
|
|
.Nm
|
|
code.
|
|
This is gradually being cleaned up.
|
|
.Pp
|
|
The
|
|
.Ft struct componentname
|
|
type has the following layout:
|
|
.Bd -literal
|
|
struct componentname {
|
|
/*
|
|
* Arguments to VOP_LOOKUP and directory VOP routines.
|
|
*/
|
|
uint32_t cn_nameiop; /* namei operation */
|
|
uint32_t cn_flags; /* flags to namei */
|
|
kauth_cred_t cn_cred; /* credentials */
|
|
const char *cn_nameptr; /* pointer to looked up name */
|
|
size_t cn_namelen; /* length of looked up comp */
|
|
/*
|
|
* Side result from VOP_LOOKUP.
|
|
*/
|
|
size_t cn_consume; /* chars to consume in lookup */
|
|
};
|
|
.Ed
|
|
.Pp
|
|
This structure contains the information about a single directory
|
|
component name, along with certain other information required by vnode
|
|
operations.
|
|
See
|
|
.Xr vnodeops 9
|
|
for more information about these vnode operations.
|
|
.Pp
|
|
The members:
|
|
.Bl -tag -offset indent -width cn_consumexx -compact
|
|
.It cn_nameiop
|
|
The type of operation in progress; indicates the basic operating mode
|
|
of namei.
|
|
May be one of
|
|
.Dv LOOKUP ,
|
|
.Dv CREATE ,
|
|
.Dv DELETE ,
|
|
or
|
|
.Dv RENAME .
|
|
These modes are described below.
|
|
.It cn_flags
|
|
Additional flags affecting the operation of namei.
|
|
These are described below as well.
|
|
.It cn_cred
|
|
The credentials to use for the lookup or other operation the
|
|
.Em componentname
|
|
is passed to.
|
|
This may match the credentials of the current process or it may not,
|
|
depending on where the original operation request came from and how it
|
|
has been routed.
|
|
.It cn_nameptr
|
|
The name of this directory component, followed by the rest of the path
|
|
being looked up.
|
|
.It cn_namelen
|
|
The length of the name of this directory component.
|
|
The name is not in general null terminated, although the complete
|
|
string (the full remaining path) always is.
|
|
.It cn_consume
|
|
This field starts at zero; it may be set to a larger value by
|
|
implementations of
|
|
.Xr VOP_LOOKUP 9
|
|
to indicate how many more characters beyond
|
|
.Em cn_namelen
|
|
are being consumed.
|
|
New uses of this feature are discouraged and should be discussed.
|
|
.El
|
|
.Ss Operating modes
|
|
Each lookup happens in one of the following modes, specified by
|
|
callers of
|
|
.Nm
|
|
with
|
|
.Fn NDINIT
|
|
and specified internally by
|
|
.Nm
|
|
to
|
|
.Xr VOP_LOOKUP 9 :
|
|
.Bl -bullet -compact
|
|
.It
|
|
Callers of
|
|
.Nm
|
|
specify the mode for the last component of a lookup.
|
|
.It
|
|
Internally,
|
|
.Nm
|
|
recursively calls
|
|
.Xr VOP_LOOKUP 9
|
|
in
|
|
.Dv LOOKUP
|
|
mode for each directory component, and then finally calls
|
|
.Xr VOP_LOOKUP 9
|
|
in the caller-specified mode for the last component.
|
|
.El
|
|
Each mode can fail in different ways \(em for example,
|
|
.Dv LOOKUP
|
|
mode fails with
|
|
.Er ENOENT
|
|
if no entry exists, but
|
|
.Dv CREATE
|
|
mode succeeds with a
|
|
.Dv NULL
|
|
vnode.
|
|
.Bl -tag -width LOOKUP
|
|
.It Dv LOOKUP
|
|
Yield the vnode for an existing entry.
|
|
Callers specify
|
|
.Dv LOOKUP
|
|
for operations on existing vnodes:
|
|
.Xr stat 2 ,
|
|
.Xr open 2
|
|
without
|
|
.Dv O_CREATE ,
|
|
etc.
|
|
.Pp
|
|
File systems:
|
|
.Bl -dash -compact
|
|
.It
|
|
MUST refuse if user lacks lookup permission for directory.
|
|
.It
|
|
SHOULD use
|
|
.Xr namecache 9
|
|
to cache lookup results.
|
|
.El
|
|
.Pp
|
|
.Bl -tag -compact -width ENAMETOOLONG
|
|
.It Bq Er ENOENT
|
|
No entry exists.
|
|
.El
|
|
.It Dv CREATE
|
|
Yield the vnode for an existing entry; or, if there is none, yield
|
|
.Dv NULL
|
|
and hint that it will soon be created.
|
|
Callers specify
|
|
.Dv CREATE
|
|
for operations that may create directory entries:
|
|
.Xr mkdir 2 ,
|
|
.Xr open 2
|
|
with
|
|
.Dv O_CREATE ,
|
|
etc.
|
|
.Pp
|
|
File systems:
|
|
.Bl -dash -compact
|
|
.It
|
|
MUST refuse if user lacks lookup permission for directory.
|
|
.It
|
|
MUST refuse if no entry exists and user lacks write permission for
|
|
directory.
|
|
.It
|
|
MUST refuse if no entry exists and file system is read-only.
|
|
.It
|
|
SHOULD NOT use
|
|
.Xr namecache 9
|
|
to cache negative lookup results.
|
|
.It
|
|
SHOULD save lookup hints internally in the directory for a subsequent
|
|
operation to create a directory entry.
|
|
.El
|
|
.Pp
|
|
.Bl -tag -compact -width ENAMETOOLONG
|
|
.It Bq Er EPERM
|
|
The user lacks lookup permission for the directory.
|
|
.It Bq Er EPERM
|
|
No entry exists and the user lacks write permission for the directory.
|
|
.It Bq Er EROFS
|
|
No entry exists and the file system is read-only.
|
|
.El
|
|
.It Dv DELETE
|
|
Yield the vnode of an existing entry, and hint that it will soon be
|
|
deleted.
|
|
Callers specify
|
|
.Dv DELETE
|
|
for operations that delete directory entries:
|
|
.Xr unlink 2 ,
|
|
.Xr rmdir 2 ,
|
|
etc.
|
|
.Pp
|
|
File systems:
|
|
.Bl -dash -compact
|
|
.It
|
|
MUST refuse if user lacks lookup permission for directory.
|
|
.It
|
|
MUST refuse if entry exists and user lacks write permission for
|
|
directory.
|
|
.It
|
|
MUST refuse if entry exists and file system is read-only.
|
|
.It
|
|
SHOULD NOT use
|
|
.Xr namecache 9
|
|
to cache lookup results.
|
|
.It
|
|
SHOULD save lookup hints internally in the directory for a subsequent
|
|
operation to delete a directory entry.
|
|
.El
|
|
.Pp
|
|
.Bl -tag -compact -width ENAMETOOLONG
|
|
.It Bq Er ENOENT
|
|
No entry exists.
|
|
.It Bq Er EPERM
|
|
The user lacks lookup permission for the directory.
|
|
.It Bq Er EPERM
|
|
An entry exists and the user lacks write permission for the directory.
|
|
.It Bq Er EROFS
|
|
An entry exists and the file system is read-only.
|
|
.El
|
|
.It Dv RENAME
|
|
Yield the vnode of an existing entry, and hint that it will soon be
|
|
overwritten; or, if there is none, yield
|
|
.Dv NULL ,
|
|
and hint that it will soon be created.
|
|
.Pp
|
|
Callers specify
|
|
.Dv RENAME
|
|
for an entry that is about to be created or overwritten, namely for the
|
|
target of
|
|
.Xr rename 2 .
|
|
.Pp
|
|
File systems:
|
|
.Bl -dash -compact
|
|
.It
|
|
MUST refuse if user lacks lookup permission for directory.
|
|
.It
|
|
MUST refuse if user lacks write permission for directory.
|
|
.It
|
|
MUST refuse if file system is read-only.
|
|
.It
|
|
SHOULD NOT use
|
|
.Xr namecache 9
|
|
to cache lookup results.
|
|
.It
|
|
SHOULD save lookup hints internally in the directory for a subsequent
|
|
operation to create or overwrite a directory entry.
|
|
.El
|
|
.Pp
|
|
.Bl -tag -compact -width ENAMETOOLONG
|
|
.It Bq Er EPERM
|
|
The user lacks lookup permission for the directory.
|
|
.It Bq Er EPERM
|
|
The user lacks write permission for the directory.
|
|
.It Bq Er EROFS
|
|
The file system is read-only.
|
|
.El
|
|
.El
|
|
.Pp
|
|
If a caller decides not to perform an operation it hinted at by a
|
|
destructive operating mode
|
|
.Pq Dv CREATE , Dv DELETE , No or Dv RENAME ,
|
|
it SHOULD call
|
|
.Xr VOP_ABORTOP 9
|
|
to release the hints.
|
|
If a file system fails to perform such an operation, it SHOULD call
|
|
.Xr VOP_ABORTOP 9
|
|
to release the hints.
|
|
However, the current code is inconsistent about this, and every
|
|
implementation of
|
|
.Xr VOP_ABORTOP 9
|
|
does nothing.
|
|
.Ss Flags
|
|
The following flags may be specified by
|
|
.Em callers
|
|
of
|
|
.Nm ,
|
|
and MUST NOT be used by file systems:
|
|
.Bl -tag -width NOCROSSMOUNT
|
|
.It Dv FOLLOW
|
|
Follow symbolic links in the last path component.
|
|
Used by operations that do not address symbolic links directly, such as
|
|
.Xr stat 2 .
|
|
(Does not affect symbolic links found in the middle of a path.)
|
|
.It Dv NOFOLLOW
|
|
Do not follow symbolic links in the last path component.
|
|
Used by operations that address symbolic links directly, such as
|
|
.Xr lstat 2 .
|
|
.Pp
|
|
Note: The value of
|
|
.Dv NOFOLLOW
|
|
is 0.
|
|
We define the constant to let callers say either
|
|
.Dv FOLLOW
|
|
or
|
|
.Dv NOFOLLOW
|
|
explicitly.
|
|
.It Dv LOCKLEAF
|
|
On successful lookup, lock the vnode, if any, in
|
|
.Fa ndp Ns Li ->ni_vp .
|
|
Without this flag, it would be unlocked.
|
|
.It Dv LOCKPARENT
|
|
On successful lookup, lock and return the directory vnode in
|
|
.Fa ndp Ns Li ->ni_dvp .
|
|
Without this flag, it is not returned at all.
|
|
.It Dv TRYEMULROOT
|
|
If set, the path is looked up in the emulation root of the current
|
|
process first.
|
|
If that fails, the system root is used.
|
|
.It Dv EMULROOTSET
|
|
Indicates that the caller has set
|
|
.Fa ndp Ns Li ->ni_erootdir
|
|
prior to calling
|
|
.Nm .
|
|
This is only useful or permitted when the emulation in the current
|
|
process is partway through being set up.
|
|
.It Dv NOCHROOT
|
|
Bypass normal
|
|
.Xr chroot 8
|
|
handling for absolute paths.
|
|
.It Dv NOCROSSMOUNT
|
|
Do not cross mount points.
|
|
.It Dv RDONLY
|
|
Enforce read-only behavior.
|
|
.It Dv CREATEDIR
|
|
Accept slashes after a component name that does not exist.
|
|
This only makes sense in
|
|
.Dv CREATE
|
|
mode and when creating a directory.
|
|
.It Dv NOCACHE
|
|
Do not cache the lookup result for the last component name.
|
|
This is used only with the
|
|
.Dv RENAME
|
|
mode for the target; the cache entry would be invalidated immediately.
|
|
.El
|
|
.Pp
|
|
The following flag may be set by a caller of
|
|
.Nm
|
|
and tested by a file system in
|
|
.Xr VOP_LOOKUP 9
|
|
or other subsequent directory operations:
|
|
.Bl -tag -width NOCROSSMOUNT
|
|
.It Dv DOWHITEOUT
|
|
Allow whiteouts to be seen as objects instead of functioning as
|
|
.Dq nothing there .
|
|
.El
|
|
.Pp
|
|
The following flags are set by namei for calling
|
|
.Xr VOP_LOOKUP 9 :
|
|
.Bl -tag -width NOCROSSMOUNT
|
|
.It Dv ISDOTDOT
|
|
The current pathname component is
|
|
.Dq Li .. .
|
|
May be tested by subsequent directory operations too.
|
|
.It Dv ISLASTCN
|
|
The current pathname component is the last component found in the
|
|
pathname.
|
|
Guaranteed to remain set in subsequent directory operations.
|
|
.It Dv REQUIREDIR
|
|
The current object to be looked up must be a directory.
|
|
May not be used by subsequent directory operations.
|
|
.It Dv MAKEENTRY
|
|
The lookup result for the current pathname component should be added to
|
|
the
|
|
.Xr namecache 9 .
|
|
May be used to make additional caching decisions, e.g. to store an
|
|
mtime for determining whether our cache for a remote vnode is stale.
|
|
May not be used by subsequent directory operatoins.
|
|
.El
|
|
.Pp
|
|
A file system may set the following flag on return from
|
|
.Xr VOP_LOOKUP 9
|
|
for use by
|
|
.Nm ,
|
|
.Xr namecache 9 ,
|
|
and subsequent directory operations:
|
|
.Bl -tag -width NOCROSSMOUNT
|
|
.It Dv ISWHITEOUT
|
|
The object at the current pathname component is a whiteout.
|
|
.El
|
|
.Pp
|
|
The following additional historic flags have been removed from
|
|
.Nx
|
|
and should be handled as follows if porting code from elsewhere:
|
|
.Bl -tag -width NOCROSSMOUNT
|
|
.It Dv INRENAME
|
|
Part of a misbegotten and incorrect locking scheme.
|
|
Any file-system-level code using this is presumptively incorrect.
|
|
File systems should use the
|
|
.Xr genfs_rename 9
|
|
interface to handle locking in
|
|
.Fn VOP_RENAME .
|
|
.It Dv INRELOOKUP
|
|
Used at one point for signaling to
|
|
.Xr puffs 3
|
|
to work around a protocol deficiency that was later rectified.
|
|
.It Dv ISSYMLINK
|
|
Useless internal state.
|
|
.It Dv SAVESTART
|
|
Unclean setting affect vnode reference counting.
|
|
Now effectively never in effect.
|
|
Any code referring to this is suspect.
|
|
.It Dv SAVENAME
|
|
Unclean setting relating to responsibility for freeing pathname buffers
|
|
in the days before the
|
|
.Em pathbuf
|
|
structure.
|
|
Now effectively always in effect; the caller of
|
|
.Nm
|
|
owns the
|
|
.Em pathbuf
|
|
structure and is always responsible for destroying it.
|
|
.It Dv HASBUF
|
|
Related to SAVENAME.
|
|
Any uses can be replaced with
|
|
.Dq true .
|
|
.El
|
|
.Sh FUNCTIONS
|
|
.Bl -tag -width abcd
|
|
.It Fn NDINIT "ndp" "op" "flags" "pathbuf"
|
|
Initialise a nameidata structure pointed to by
|
|
.Fa ndp
|
|
for use by the
|
|
.Nm
|
|
interface.
|
|
The operating mode and flags (as documented above) are specified by
|
|
.Fa op
|
|
and
|
|
.Fa flags
|
|
respectively.
|
|
The pathname is passed as a pathbuf structure, which should be
|
|
initialized using one of the
|
|
.Xr pathbuf 9
|
|
operations.
|
|
Destroying the pathbuf is the responsibility of the caller; this must
|
|
not be done until the caller is finished with all of the
|
|
.Nm
|
|
results and all of the nameidata contents except for the result vnode.
|
|
.Pp
|
|
This routine stores the credentials of the calling thread
|
|
.Va ( curlwp )
|
|
in
|
|
.Fa ndp .
|
|
.Fn NDINIT
|
|
sets the credentials using
|
|
.Xr kauth_cred_get 9 .
|
|
In the rare case that another set of credentials is required for the
|
|
namei operation,
|
|
.Em ndp->ni_cnd.cn_cred
|
|
must be set manually after
|
|
.Fn NDINIT .
|
|
.It Fn NDAT "ndp" "dvp"
|
|
This macro is used after
|
|
.Fn NDINIT
|
|
to set the starting directory.
|
|
This supersedes the current process's current working directory as the
|
|
initial point of departure for looking up relative paths.
|
|
This mechanism is used by
|
|
.Xr openat 2
|
|
and related calls.
|
|
.It Fn namei "ndp"
|
|
Convert a pathname into a pointer to a vnode.
|
|
The nameidata structure pointed to by
|
|
.Fa ndp
|
|
should be initialized with the
|
|
.Fn NDINIT
|
|
macro, and perhaps also the
|
|
.Fn NDAT
|
|
macro.
|
|
Direct initialization of members of struct nameidata is
|
|
.Em not
|
|
supported and may (will) break silently in the future.
|
|
.Pp
|
|
The vnode for the pathname is returned in
|
|
.Em ndp->ni_vp .
|
|
The parent directory is returned locked in
|
|
.Em ndp->ni_dvp
|
|
iff
|
|
.Dv LOCKPARENT
|
|
is specified.
|
|
.Pp
|
|
Any or all of the flags documented above as set by the caller can be
|
|
enabled by passing them (OR'd together) as the
|
|
.Fa flags
|
|
argument of
|
|
.Fn NDINIT .
|
|
As discussed above every such call should explicitly contain either
|
|
.Dv FOLLOW
|
|
or
|
|
.Dv NOFOLLOW
|
|
to control the behavior regarding final symbolic links.
|
|
.It Fn namei_simple_kernel "path" "sflags" "ret"
|
|
Look up the path
|
|
.Fa path
|
|
and translate it to a vnode, returned in
|
|
.Fa ret .
|
|
The
|
|
.Fa path
|
|
argument must be a kernel
|
|
.Pq Dv UIO_SYSSPACE
|
|
pointer.
|
|
The
|
|
.Fa sflags
|
|
argument chooses the precise behavior.
|
|
It may be set to one of the following symbols:
|
|
.Bl -tag -offset indent -width NSM_NOFOLLOW_TRYEMULROOT -compact
|
|
.It Dv NSM_NOFOLLOW_NOEMULROOT
|
|
.It Dv NSM_NOFOLLOW_TRYEMULROOT
|
|
.It Dv NSM_FOLLOW_NOEMULROOT
|
|
.It Dv NSM_FOLLOW_TRYEMULROOT
|
|
.El
|
|
These select (or not) the
|
|
.Dv FOLLOW/NOFOLLOW
|
|
and
|
|
.Dv TRYEMULROOT
|
|
flags.
|
|
Other flags are not available through this interface, which is
|
|
nonetheless sufficient for more than half the
|
|
.Fn namei
|
|
usage in the kernel.
|
|
Note that the encoding of
|
|
.Fa sflags
|
|
has deliberately been arranged to be type-incompatible with anything
|
|
else.
|
|
This prevents various possible accidents while the
|
|
.Fn namei
|
|
interface is being rototilled.
|
|
.It Fn namei_simple_user "path" "sflags" "ret"
|
|
This function is the same as
|
|
.Fn namei_simple_kernel
|
|
except that the
|
|
.Fa path
|
|
argument shall be a user pointer
|
|
.Pq Dv UIO_USERSPACE
|
|
rather than a kernel pointer.
|
|
.It Fn relookup "dvp" "vpp" "cnp" "dummy"
|
|
Reacquire a path name component is a directory.
|
|
This is a quicker way to lookup a pathname component when the parent
|
|
directory is known.
|
|
The locked parent directory vnode is specified by
|
|
.Fa dvp
|
|
and the pathname component by
|
|
.Fa cnp .
|
|
The vnode of the pathname is returned in the address specified by
|
|
.Fa vpp .
|
|
The
|
|
.Fa dummy
|
|
argument is unused.
|
|
Note that one may only use
|
|
.Fn relookup
|
|
to repeat a lookup of a final path component previously done by
|
|
.Nm ,
|
|
and one must use the same
|
|
.Em componentname
|
|
structure that call produced.
|
|
Otherwise the behavior is undefined and likely adverse.
|
|
.It Fn lookup_for_nfsd "ndp" "startdir" "neverfollow"
|
|
This is a private entry point into
|
|
.Nm
|
|
used by the NFS server code.
|
|
It looks up a path starting from
|
|
.Fa startdir .
|
|
If
|
|
.Fa neverfollow
|
|
is set,
|
|
.Em any
|
|
symbolic link (not just at the end of the path) will cause an error.
|
|
Otherwise, it follows symlinks normally.
|
|
It should not be used by new code.
|
|
.It Fn lookup_for_nfsd_index "ndp" "startdir"
|
|
This is a (second) private entry point into
|
|
.Nm
|
|
used by the NFS server code.
|
|
It looks up a single path component starting from
|
|
.Fa startdir .
|
|
It should not be used by new code.
|
|
.El
|
|
.Sh INTERNALS
|
|
The
|
|
.Em nameidata
|
|
structure has the following layout:
|
|
.Bd -literal
|
|
struct nameidata {
|
|
/*
|
|
* Arguments to namei.
|
|
*/
|
|
struct vnode *ni_atdir; /* startup dir, cwd if null */
|
|
struct pathbuf *ni_pathbuf; /* pathname container */
|
|
char *ni_pnbuf; /* extra pathname buffer ref (XXX) */
|
|
/*
|
|
* Internal starting state. (But see notes.)
|
|
*/
|
|
struct vnode *ni_rootdir; /* logical root directory */
|
|
struct vnode *ni_erootdir; /* emulation root directory */
|
|
/*
|
|
* Results from namei.
|
|
*/
|
|
struct vnode *ni_vp; /* vnode of result */
|
|
struct vnode *ni_dvp; /* vnode of intermediate directory */
|
|
/*
|
|
* Internal current state.
|
|
*/
|
|
size_t ni_pathlen; /* remaining chars in path */
|
|
const char *ni_next; /* next location in pathname */
|
|
unsigned int ni_loopcnt; /* count of symlinks encountered */
|
|
/*
|
|
* Lookup parameters: this structure describes the subset of
|
|
* information from the nameidata structure that is passed
|
|
* through the VOP interface.
|
|
*/
|
|
struct componentname ni_cnd;
|
|
};
|
|
.Ed
|
|
.Pp
|
|
These fields are:
|
|
.Bl -tag -offset indent -width ni_erootdirx -compact
|
|
.It ni_atdir
|
|
The directory to use for the starting point of relative paths.
|
|
If null, the current process's current directory is used.
|
|
This is initialized to
|
|
.Dv NULL
|
|
by
|
|
.Fn NDINIT
|
|
and set by
|
|
.Fn NDAT .
|
|
.It ni_pathbuf
|
|
The abstract path buffer in use, passed as an argument to
|
|
.Fn NDINIT .
|
|
The name pointers that appear elsewhere, such as in the
|
|
.Em componentname
|
|
structure, point into this buffer.
|
|
It is owned by the caller and must not be destroyed until all
|
|
.Nm
|
|
operations are complete.
|
|
See
|
|
.Xr pathbuf 9 .
|
|
.It ni_pnbuf
|
|
This is the name pointer used during
|
|
.Nm .
|
|
It points into
|
|
.Fa ni_pathbuf .
|
|
It is not initialized until entry into
|
|
.Nm .
|
|
.It ni_rootdir
|
|
The root directory to use as the starting point for absolute paths.
|
|
This is retrieved from the current process's current root directory
|
|
when
|
|
.Nm
|
|
starts up.
|
|
It is not initialized by
|
|
.Fn NDINIT .
|
|
.It ni_erootdir
|
|
The root directory to use as the emulation root, for processes running
|
|
in emulation.
|
|
This is retrieved from the current process's emulation root directory
|
|
when
|
|
.Nm
|
|
starts up and not initialized by
|
|
.Fn NDINIT .
|
|
As described elsewhere, it may be set by the caller if the
|
|
.Dv EMULROOTSET
|
|
flag is used, but this should only be done when the current process's
|
|
emulation root directory is not yet initialized.
|
|
(And ideally in the future things would be tidied so that this is not
|
|
necessary.)
|
|
.It ni_vp
|
|
.It ni_dvp
|
|
Returned vnodes, as described above.
|
|
These only contain valid values if
|
|
.Nm
|
|
returns successfully.
|
|
.It ni_pathlen
|
|
The length of the full current remaining path string in
|
|
.Fa ni_pnbuf .
|
|
This is not initialized by
|
|
.Fn NDINIT
|
|
and is used only internally.
|
|
.It ni_next
|
|
The remaining part of the path, after the current component found in
|
|
the
|
|
.Em componentname
|
|
structure.
|
|
This is not initialized by
|
|
.Fn NDINIT
|
|
and is used only internally.
|
|
.It ni_loopcnt
|
|
The number of symbolic links encountered (and traversed) so far.
|
|
If this exceeds a limit,
|
|
.Nm
|
|
fails with
|
|
.Er ELOOP .
|
|
This is not initialized by
|
|
.Fn NDINIT
|
|
and is used only internally.
|
|
.It ni_cnd
|
|
The
|
|
.Em componentname
|
|
structure holding the current directory component, and also the
|
|
mode, flags, and credentials.
|
|
The mode, flags, and credentials are initialized by
|
|
.Fn NDINIT ;
|
|
the rest is not initialized until
|
|
.Nm
|
|
runs.
|
|
.El
|
|
.Pp
|
|
There is also a
|
|
.Em namei_state
|
|
structure that is hidden within
|
|
.Pa vfs_lookup.c .
|
|
This contains the following additional state:
|
|
.Bl -tag -offset indent -width attempt_retry -compact
|
|
.It docache
|
|
A flag indicating whether to cache the last pathname component.
|
|
.It rdonly
|
|
The read-only state, initialized from the
|
|
.Dv RDONLY
|
|
flag.
|
|
.It slashes
|
|
The number of trailing slashes found after the current pathname
|
|
component.
|
|
.It attempt_retry
|
|
Set on some error cases (and not others) to indicate that a failure in
|
|
the emulation root should be followed by a retry in the real system
|
|
root.
|
|
.El
|
|
.Pp
|
|
The state in
|
|
.Em namei_state
|
|
is genuinely private to
|
|
.Nm .
|
|
Note that much of the state in
|
|
.Em nameidata
|
|
should also be private, but is currently not because it is misused in
|
|
some fashion by outside code, usually
|
|
.Xr nfs 4 .
|
|
.Pp
|
|
The control flow within the
|
|
.Nm
|
|
portions of
|
|
.Pa vfs_lookup.c
|
|
is as follows.
|
|
.Bl -tag -width namei_tryemulrootXX
|
|
.It Fn namei
|
|
does a complete path lookup by calling
|
|
.Fn namei_init ,
|
|
.Fn namei_tryemulroot ,
|
|
and
|
|
.Fn namei_cleanup .
|
|
.It Fn namei_init
|
|
sets up the basic internal state and makes some (precondition-type)
|
|
assertions.
|
|
.It Fn namei_cleanup
|
|
makes some postcondition-type assertions; it currently does nothing
|
|
besides this.
|
|
.It Fn namei_tryemulroot
|
|
handles
|
|
.Dv TRYEMULROOT
|
|
by calling
|
|
.Fn namei_oneroot
|
|
once or twice as needed, and attends to making sure the original
|
|
pathname is preserved for the second try.
|
|
.It Fn namei_oneroot
|
|
does a complete path search from a single root directory.
|
|
It begins with
|
|
.Fn namei_start ,
|
|
then calls
|
|
.Fn lookup_once
|
|
(and if necessary,
|
|
.Fn namei_follow )
|
|
repeatedly until done.
|
|
It also handles returning the result vnode(s) in the requested state.
|
|
.It Fn namei_start
|
|
sets up the initial state and locking; it calls
|
|
.Fn namei_getstartdir .
|
|
.It Fn namei_getstartdir
|
|
initializes the root directory state (both
|
|
.Fa ni_rootdir
|
|
and
|
|
.Fa ni_erootdir )
|
|
and picks the starting directory, consuming the leading slashes of an
|
|
absolute path and handling the magic
|
|
.Dq /../
|
|
string for bypassing the emulation root.
|
|
A different version
|
|
.Fn namei_getstartdir_for_nfsd
|
|
is used for lookups coming from
|
|
.Xr nfsd 8
|
|
as those are required to have different semantics.
|
|
.It Fn lookup_once
|
|
calls
|
|
.Fn VOP_LOOKUP
|
|
for one path component, also handling any needed crossing of mount
|
|
points (either up or down) and coping with locking requirements.
|
|
.It Fn lookup_parsepath
|
|
is called prior to each
|
|
.Fn lookup_once
|
|
call to examine the pathname and find where the next component
|
|
starts.
|
|
.It Fn namei_follow
|
|
reads the contents of a symbolic link and updates both the path buffer
|
|
and the search directory accordingly.
|
|
.El
|
|
.Pp
|
|
As a final note be advised that the magic return value associated with
|
|
.Dv CREATE
|
|
mode is different for
|
|
.Nm
|
|
than it is for
|
|
.Fn VOP_LOOKUP .
|
|
The latter
|
|
.Dq fails
|
|
with
|
|
.Er EJUSTRETURN .
|
|
.Nm
|
|
translates this into succeeding and returning a null vnode.
|
|
.Sh CODE REFERENCES
|
|
The name lookup subsystem is implemented within the file
|
|
.Pa sys/kern/vfs_lookup.c .
|
|
.Sh SEE ALSO
|
|
.Xr intro 9 ,
|
|
.Xr namecache 9 ,
|
|
.Xr vfs 9 ,
|
|
.Xr vnode 9 ,
|
|
.Xr vnodeops 9
|
|
.Sh BUGS
|
|
There should be no such thing as operating modes.
|
|
Only
|
|
.Dv LOOKUP
|
|
is actually needed.
|
|
The behavior where removing an object looks it up within
|
|
.Nm
|
|
and then calls into the file system (which must look it up again
|
|
internally or cache state from
|
|
.Fn VOP_LOOKUP )
|
|
is particularly contorted.
|
|
.Pp
|
|
Most of the flags are equally bogus.
|
|
.Pp
|
|
Most of the contents of the
|
|
.Em nameidata
|
|
structure should be private and hidden within
|
|
.Nm ;
|
|
currently it cannot be because of abuse elsewhere.
|
|
.Pp
|
|
The
|
|
.Dv EMULROOTSET
|
|
flag is messy.
|
|
.Pp
|
|
There is no good way to support file systems that want to use
|
|
a more elaborate pathname schema than the customary slash-delimited
|
|
components.
|