diff options
author | kib <kib@FreeBSD.org> | 2008-03-31 12:01:21 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2008-03-31 12:01:21 +0000 |
commit | eff8c6d35eb85c880ee73166dbff3ba639b6569c (patch) | |
tree | f8cc8d866703361e98f57783e3292705ce2d5dbc /sys/kern/vfs_lookup.c | |
parent | fb67926ebba3585578dba016e05aabe5090ea064 (diff) | |
download | FreeBSD-src-eff8c6d35eb85c880ee73166dbff3ba639b6569c.zip FreeBSD-src-eff8c6d35eb85c880ee73166dbff3ba639b6569c.tar.gz |
Add the support for the AT_FDCWD and fd-relative name lookups to the
namei(9).
Based on the submission by rdivacky,
sponsored by Google Summer of Code 2007
Reviewed by: rwatson, rdivacky
Tested by: pho
Diffstat (limited to 'sys/kern/vfs_lookup.c')
-rw-r--r-- | sys/kern/vfs_lookup.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index c04916b..dc34249 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/fcntl.h> #include <sys/lock.h> #include <sys/mutex.h> #include <sys/namei.h> @@ -192,10 +193,29 @@ namei(struct nameidata *ndp) ndp->ni_rootdir = fdp->fd_rdir; ndp->ni_topdir = fdp->fd_jdir; - dp = fdp->fd_cdir; + if (cnp->cn_pnbuf[0] != '/' && ndp->ni_dirfd != AT_FDCWD) { + error = fgetvp(td, ndp->ni_dirfd, &dp); + FILEDESC_SUNLOCK(fdp); + if (error == 0 && dp->v_type != VDIR) { + vfslocked = VFS_LOCK_GIANT(dp->v_mount); + vrele(dp); + VFS_UNLOCK_GIANT(vfslocked); + error = ENOTDIR; + } + if (error) { + uma_zfree(namei_zone, cnp->cn_pnbuf); +#ifdef DIAGNOSTIC + cnp->cn_pnbuf = NULL; + cnp->cn_nameptr = NULL; +#endif + return (error); + } + } else { + dp = fdp->fd_cdir; + VREF(dp); + FILEDESC_SUNLOCK(fdp); + } vfslocked = VFS_LOCK_GIANT(dp->v_mount); - VREF(dp); - FILEDESC_SUNLOCK(fdp); for (;;) { /* * Check if root directory should replace current directory. |