#ifndef _SYS_NAMEI_H_
#define _SYS_NAMEI_H_
#include <sys/caprights.h>
#include <sys/filedesc.h>
#include <sys/queue.h>
#include <sys/_seqc.h>
#include <sys/_uio.h>
#include <vm/uma.h>
enum nameiop { LOOKUP, CREATE, DELETE, RENAME };
struct componentname {
u_int64_t cn_flags;
struct ucred *cn_cred;
enum nameiop cn_nameiop;
int cn_lkflags;
char *cn_pnbuf;
char *cn_nameptr;
long cn_namelen;
};
struct nameicap_tracker;
TAILQ_HEAD(nameicap_tracker_head, nameicap_tracker);
struct nameidata {
const char *ni_dirp;
enum uio_seg ni_segflg;
const cap_rights_t *ni_rightsneeded;
struct vnode *ni_startdir;
struct vnode *ni_rootdir;
struct vnode *ni_topdir;
int ni_dirfd;
int ni_lcf;
struct filecaps ni_filecaps;
struct vnode *ni_vp;
struct vnode *ni_dvp;
u_int ni_resflags;
u_short ni_debugflags;
u_short ni_loopcnt;
size_t ni_pathlen;
char *ni_next;
struct componentname ni_cnd;
struct nameicap_tracker_head ni_cap_tracker;
struct vnode *ni_rbeneath_dpp;
struct mount *ni_nctrack_mnt;
seqc_t ni_dvp_seqc;
seqc_t ni_vp_seqc;
};
#ifdef _KERNEL
enum cache_fpl_status { CACHE_FPL_STATUS_DESTROYED, CACHE_FPL_STATUS_ABORTED,
CACHE_FPL_STATUS_PARTIAL, CACHE_FPL_STATUS_HANDLED, CACHE_FPL_STATUS_UNSET };
int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status,
struct pwd **pwdp);
#define NAMEI_DBG_INITED 0x0001
#define NAMEI_DBG_CALLED 0x0002
#define NAMEI_DBG_HADSTARTDIR 0x0004
#define NC_NOMAKEENTRY 0x0001
#define NC_KEEPPOSENTRY 0x0002
#define NOCACHE NC_NOMAKEENTRY
#define LOCKLEAF 0x0004
#define LOCKPARENT 0x0008
#define WANTPARENT 0x0010
#define FAILIFEXISTS 0x0020
#define FOLLOW 0x0040
#define EMPTYPATH 0x0080
#define LOCKSHARED 0x0100
#define NOFOLLOW 0x0000
#define RBENEATH 0x100000000ULL
#define NAMEILOOKUP 0x200000000ULL
#define MODMASK 0xf000001ffULL
#define RDONLY 0x00000200
#define ISRESTARTED 0x00000400
#define IGNOREWHITEOUT 0x00000800
#define ISWHITEOUT 0x00001000
#define DOWHITEOUT 0x00002000
#define WILLBEDIR 0x00004000
#define ISOPEN 0x00008000
#define NOCROSSMOUNT 0x00010000
#define NOMACCHECK 0x00020000
#define AUDITVNODE1 0x00040000
#define AUDITVNODE2 0x00080000
#define NOCAPCHECK 0x00100000
#define OPENREAD 0x00200000
#define OPENWRITE 0x00400000
#define WANTIOCTLCAPS 0x00800000
#define OPENNAMED 0x01000000
#define NOEXECCHECK 0x02000000
#define MAKEENTRY 0x04000000
#define ISSYMLINK 0x08000000
#define ISLASTCN 0x10000000
#define ISDOTDOT 0x20000000
#define TRAILINGSLASH 0x40000000
#define CREATENAMED 0x80000000
#define PARAMASK 0xfffffe00
#define NAMEI_INTERNAL_FLAGS \
(NOEXECCHECK | MAKEENTRY | ISSYMLINK | ISLASTCN | ISDOTDOT | \
TRAILINGSLASH | ISRESTARTED)
#define NIRES_ABS 0x00000001
#define NIRES_STRICTREL 0x00000002
#define NIRES_EMPTYPATH 0x00000004
#define NIRES_BENEATH 0x00000008
#define NI_LCF_STRICTREL 0x0001
#define NI_LCF_CAP_DOTDOT 0x0002
#define NI_LCF_STRICTREL_KTR 0x0004
#define NI_LCF_CAP_DOTDOT_KTR 0x0008
#define NI_LCF_KTR_FLAGS (NI_LCF_STRICTREL_KTR | NI_LCF_CAP_DOTDOT_KTR)
#define NDINIT(ndp, op, flags, segflg, namep) \
NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, &cap_no_rights)
#define NDINIT_AT(ndp, op, flags, segflg, namep, dirfd) \
NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, &cap_no_rights)
#define NDINIT_ATRIGHTS(ndp, op, flags, segflg, namep, dirfd, rightsp) \
NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rightsp)
#define NDINIT_ATVP(ndp, op, flags, segflg, namep, vp) \
NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, vp, &cap_no_rights)
#if defined(INVARIANTS) || (defined(KLD_MODULE) && !defined(KLD_TIED))
#define NDINIT_PREFILL(arg) memset(arg, 0xff, offsetof(struct nameidata, \
ni_dvp_seqc))
#define NDINIT_DBG(arg) { (arg)->ni_debugflags = NAMEI_DBG_INITED; }
#define NDREINIT_DBG(arg) { \
if (((arg)->ni_debugflags & NAMEI_DBG_INITED) == 0) \
panic("namei data not inited"); \
if (((arg)->ni_debugflags & NAMEI_DBG_HADSTARTDIR) != 0) \
panic("NDREINIT on namei data with NAMEI_DBG_HADSTARTDIR"); \
if ((arg)->ni_nctrack_mnt != NULL) \
panic("NDREINIT on namei data with leaked ni_nctrack_mnt"); \
if (!TAILQ_EMPTY(&(arg)->ni_cap_tracker)) \
panic("NDREINIT on namei data with leaked ni_cap_tracker"); \
(arg)->ni_debugflags = NAMEI_DBG_INITED; \
}
#else
#define NDINIT_PREFILL(arg) do { } while (0)
#define NDINIT_DBG(arg) do { } while (0)
#define NDREINIT_DBG(arg) do { } while (0)
#endif
#define NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, startdir, rightsp) \
do { \
struct nameidata *_ndp = (ndp); \
const cap_rights_t *_rightsp = (rightsp); \
MPASS(_rightsp != NULL); \
NDINIT_PREFILL(_ndp); \
NDINIT_DBG(_ndp); \
_ndp->ni_cnd.cn_nameiop = op; \
_ndp->ni_cnd.cn_flags = (flags) | NAMEILOOKUP; \
_ndp->ni_segflg = segflg; \
_ndp->ni_dirp = namep; \
_ndp->ni_dirfd = dirfd; \
_ndp->ni_startdir = startdir; \
_ndp->ni_resflags = 0; \
filecaps_init(&_ndp->ni_filecaps); \
_ndp->ni_rightsneeded = _rightsp; \
_ndp->ni_rbeneath_dpp = NULL; \
_ndp->ni_nctrack_mnt = NULL; \
TAILQ_INIT(&_ndp->ni_cap_tracker); \
} while (0)
#define NDREINIT(ndp) do { \
struct nameidata *_ndp = (ndp); \
NDREINIT_DBG(_ndp); \
filecaps_free(&_ndp->ni_filecaps); \
_ndp->ni_resflags = 0; \
_ndp->ni_startdir = NULL; \
_ndp->ni_cnd.cn_flags &= ~NAMEI_INTERNAL_FLAGS; \
} while (0)
#define NDPREINIT(ndp) do { \
(ndp)->ni_dvp_seqc = SEQC_MOD; \
(ndp)->ni_vp_seqc = SEQC_MOD; \
} while (0)
#define NDFREE_IOCTLCAPS(ndp) do { \
struct nameidata *_ndp = (ndp); \
filecaps_free(&_ndp->ni_filecaps); \
} while (0)
#define NDFREE_PNBUF(ndp) do { \
struct nameidata *_ndp = (ndp); \
MPASS(_ndp->ni_cnd.cn_pnbuf != NULL); \
uma_zfree(namei_zone, _ndp->ni_cnd.cn_pnbuf); \
_ndp->ni_cnd.cn_pnbuf = NULL; \
} while (0)
int namei(struct nameidata *ndp);
int vfs_lookup(struct nameidata *ndp);
bool vfs_lookup_isroot(struct nameidata *ndp, struct vnode *dvp);
struct nameidata *vfs_lookup_nameidata(struct componentname *cnp);
int vfs_relookup(struct vnode *dvp, struct vnode **vpp,
struct componentname *cnp, bool refstart);
#define namei_setup_rootdir(ndp, cnp, pwd) do { \
if (__predict_true((cnp->cn_flags & ISRESTARTED) == 0)) \
ndp->ni_rootdir = pwd->pwd_adir; \
else \
ndp->ni_rootdir = pwd->pwd_rdir; \
} while (0)
#endif
struct nchstats {
long ncs_goodhits;
long ncs_neghits;
long ncs_badhits;
long ncs_falsehits;
long ncs_miss;
long ncs_long;
long ncs_pass2;
long ncs_2passes;
};
extern struct nchstats nchstats;
#endif