Module Name: src
Committed By: dholland
Date: Sun Sep 27 17:23:54 UTC 2009
Modified Files:
src/share/man/man9: namei.9
src/sys/kern: vfs_lookup.c
src/sys/nfs: nfs_srvsubs.c
src/sys/sys: namei.src
Log Message:
Move a big wodge of symlink-following code from nfsd to inside
lookup_for_nfsd(). This code is, or at least should be, the same as
the regular symlink-following code plus an extra flag nfsd needs.
The two lots of code can/will be merged in the future.
To generate a diff of this commit:
cvs rdiff -u -r1.22 -r1.23 src/share/man/man9/namei.9
cvs rdiff -u -r1.119 -r1.120 src/sys/kern/vfs_lookup.c
cvs rdiff -u -r1.4 -r1.5 src/sys/nfs/nfs_srvsubs.c
cvs rdiff -u -r1.12 -r1.13 src/sys/sys/namei.src
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/share/man/man9/namei.9
diff -u src/share/man/man9/namei.9:1.22 src/share/man/man9/namei.9:1.23
--- src/share/man/man9/namei.9:1.22 Sun Sep 27 17:19:07 2009
+++ src/share/man/man9/namei.9 Sun Sep 27 17:23:53 2009
@@ -1,4 +1,4 @@
-.\" $NetBSD: namei.9,v 1.22 2009/09/27 17:19:07 dholland Exp $
+.\" $NetBSD: namei.9,v 1.23 2009/09/27 17:23:53 dholland Exp $
.\"
.\" Copyright (c) 2001, 2005, 2006 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -46,7 +46,8 @@
.Ft int
.Fn namei "struct nameidata *ndp"
.Ft int
-.Fn lookup_for_nfsd "struct nameidata *ndp"
+.Fn lookup_for_nfsd "struct nameidata *ndp" "struct vnode *startdir" \
+"int neverfollow"
.Ft int
.Fn lookup_for_nfsd_index "struct nameidata *ndp"
.Ft int
@@ -288,11 +289,19 @@
is comparable to the historic
.Fn lookup
but this code is slated for refactoring.
-.It Fn lookup_for_nfsd "ndp"
+.It Fn lookup_for_nfsd "ndp" "startdir" "neverfollow"
This is a private entry point into
.Nm
used by the NFS server code.
-Its semantics are similar to the historic
+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.
+Its semantics are similar to a symlink-following loop around the historic
.Fn lookup
function described above.
It should not be used by new code.
@@ -304,9 +313,6 @@
.Fn lookup
function described above.
It should not be used by new code.
-(For now it differs from the preceding private entry point in that it
-has a different call site with a different context and different
-custom initialization of what ought to be private namei state.)
.It Fn relookup "dvp" "vpp" "cnp"
Reacquire a path name component is a directory.
This is a quicker way to lookup a pathname component when the parent
Index: src/sys/kern/vfs_lookup.c
diff -u src/sys/kern/vfs_lookup.c:1.119 src/sys/kern/vfs_lookup.c:1.120
--- src/sys/kern/vfs_lookup.c:1.119 Sun Sep 27 17:19:07 2009
+++ src/sys/kern/vfs_lookup.c Sun Sep 27 17:23:54 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_lookup.c,v 1.119 2009/09/27 17:19:07 dholland Exp $ */
+/* $NetBSD: vfs_lookup.c,v 1.120 2009/09/27 17:23:54 dholland Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.119 2009/09/27 17:19:07 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.120 2009/09/27 17:23:54 dholland Exp $");
#include "opt_magiclinks.h"
@@ -1158,14 +1158,144 @@
*/
int
-lookup_for_nfsd(struct nameidata *ndp)
+lookup_for_nfsd(struct nameidata *ndp, struct vnode *dp, int neverfollow)
{
struct namei_state state;
int error;
+ struct iovec aiov;
+ struct uio auio;
+ int linklen;
+ char *cp;
+
/* For now at least we don't have to frob the state */
namei_init(&state, ndp);
+
+ /*
+ * BEGIN wodge of code from nfsd
+ */
+
+ VREF(dp);
+ vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
+
+ for (;;) {
+
+ state.cnp->cn_nameptr = state.cnp->cn_pnbuf;
+ state.ndp->ni_startdir = dp;
+
+ /*
+ * END wodge of code from nfsd
+ */
+
error = do_lookup(&state);
+ if (error) {
+ /* BEGIN from nfsd */
+ if (ndp->ni_dvp) {
+ vput(ndp->ni_dvp);
+ }
+ PNBUF_PUT(state.cnp->cn_pnbuf);
+ /* END from nfsd */
+ namei_cleanup(&state);
+ return error;
+ }
+
+ /*
+ * BEGIN wodge of code from nfsd
+ */
+
+ /*
+ * Check for encountering a symbolic link
+ */
+ if ((state.cnp->cn_flags & ISSYMLINK) == 0) {
+ if ((state.cnp->cn_flags & LOCKPARENT) == 0 && state.ndp->ni_dvp) {
+ if (state.ndp->ni_dvp == state.ndp->ni_vp) {
+ vrele(state.ndp->ni_dvp);
+ } else {
+ vput(state.ndp->ni_dvp);
+ }
+ }
+ if (state.cnp->cn_flags & (SAVENAME | SAVESTART)) {
+ state.cnp->cn_flags |= HASBUF;
+ } else {
+ PNBUF_PUT(state.cnp->cn_pnbuf);
+#if defined(DIAGNOSTIC)
+ state.cnp->cn_pnbuf = NULL;
+#endif /* defined(DIAGNOSTIC) */
+ }
+ return (0);
+ } else {
+ if (neverfollow) {
+ error = EINVAL;
+ goto out;
+ }
+ if (state.ndp->ni_loopcnt++ >= MAXSYMLINKS) {
+ error = ELOOP;
+ goto out;
+ }
+ if (state.ndp->ni_vp->v_mount->mnt_flag & MNT_SYMPERM) {
+ error = VOP_ACCESS(ndp->ni_vp, VEXEC, state.cnp->cn_cred);
+ if (error != 0)
+ goto out;
+ }
+ if (state.ndp->ni_pathlen > 1)
+ cp = PNBUF_GET();
+ else
+ cp = state.cnp->cn_pnbuf;
+ aiov.iov_base = cp;
+ aiov.iov_len = MAXPATHLEN;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_offset = 0;
+ auio.uio_rw = UIO_READ;
+ auio.uio_resid = MAXPATHLEN;
+ UIO_SETUP_SYSSPACE(&auio);
+ error = VOP_READLINK(ndp->ni_vp, &auio, state.cnp->cn_cred);
+ if (error) {
+badlink:
+ if (ndp->ni_pathlen > 1)
+ PNBUF_PUT(cp);
+ goto out;
+ }
+ linklen = MAXPATHLEN - auio.uio_resid;
+ if (linklen == 0) {
+ error = ENOENT;
+ goto badlink;
+ }
+ if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
+ error = ENAMETOOLONG;
+ goto badlink;
+ }
+ if (ndp->ni_pathlen > 1) {
+ memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);
+ PNBUF_PUT(state.cnp->cn_pnbuf);
+ state.cnp->cn_pnbuf = cp;
+ } else
+ state.cnp->cn_pnbuf[linklen] = '\0';
+ state.ndp->ni_pathlen += linklen;
+ vput(state.ndp->ni_vp);
+ dp = state.ndp->ni_dvp;
+
+ /*
+ * Check if root directory should replace current directory.
+ */
+ if (state.cnp->cn_pnbuf[0] == '/') {
+ vput(dp);
+ dp = ndp->ni_rootdir;
+ VREF(dp);
+ vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
+ }
+ }
+
+ }
+ out:
+ vput(state.ndp->ni_vp);
+ vput(state.ndp->ni_dvp);
+ state.ndp->ni_vp = NULL;
+ PNBUF_PUT(state.cnp->cn_pnbuf);
+
+ /*
+ * END wodge of code from nfsd
+ */
namei_cleanup(&state);
return error;
Index: src/sys/nfs/nfs_srvsubs.c
diff -u src/sys/nfs/nfs_srvsubs.c:1.4 src/sys/nfs/nfs_srvsubs.c:1.5
--- src/sys/nfs/nfs_srvsubs.c:1.4 Sun Sep 27 17:19:07 2009
+++ src/sys/nfs/nfs_srvsubs.c Sun Sep 27 17:23:54 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_srvsubs.c,v 1.4 2009/09/27 17:19:07 dholland Exp $ */
+/* $NetBSD: nfs_srvsubs.c,v 1.5 2009/09/27 17:23:54 dholland Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.4 2009/09/27 17:19:07 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.5 2009/09/27 17:23:54 dholland Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -121,10 +121,9 @@
int i, rem;
struct mbuf *md;
char *fromcp, *tocp, *cp;
- struct iovec aiov;
- struct uio auio;
struct vnode *dp;
- int error, rdonly, linklen;
+ int error, rdonly;
+ int neverfollow;
struct componentname *cnp = &ndp->ni_cnd;
*retdirp = NULL;
@@ -254,111 +253,17 @@
cnp->cn_flags |= NOCROSSMOUNT;
}
- VREF(dp);
- vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
-
- for (;;) {
- cnp->cn_nameptr = cnp->cn_pnbuf;
- ndp->ni_startdir = dp;
+ neverfollow = !pubflag;
/*
* And call lookup() to do the real work
*/
- error = lookup_for_nfsd(ndp);
+ error = lookup_for_nfsd(ndp, dp, neverfollow);
if (error) {
- if (ndp->ni_dvp) {
- vput(ndp->ni_dvp);
- }
- PNBUF_PUT(cnp->cn_pnbuf);
return (error);
}
+ return 0;
- /*
- * Check for encountering a symbolic link
- */
- if ((cnp->cn_flags & ISSYMLINK) == 0) {
- if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp) {
- if (ndp->ni_dvp == ndp->ni_vp) {
- vrele(ndp->ni_dvp);
- } else {
- vput(ndp->ni_dvp);
- }
- }
- if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
- cnp->cn_flags |= HASBUF;
- } else {
- PNBUF_PUT(cnp->cn_pnbuf);
-#if defined(DIAGNOSTIC)
- cnp->cn_pnbuf = NULL;
-#endif /* defined(DIAGNOSTIC) */
- }
- return (0);
- } else {
- if (!pubflag) {
- error = EINVAL;
- break;
- }
- if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
- error = ELOOP;
- break;
- }
- if (ndp->ni_vp->v_mount->mnt_flag & MNT_SYMPERM) {
- error = VOP_ACCESS(ndp->ni_vp, VEXEC, cnp->cn_cred);
- if (error != 0)
- break;
- }
- if (ndp->ni_pathlen > 1)
- cp = PNBUF_GET();
- else
- cp = cnp->cn_pnbuf;
- aiov.iov_base = cp;
- aiov.iov_len = MAXPATHLEN;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_offset = 0;
- auio.uio_rw = UIO_READ;
- auio.uio_resid = MAXPATHLEN;
- UIO_SETUP_SYSSPACE(&auio);
- error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
- if (error) {
-badlink:
- if (ndp->ni_pathlen > 1)
- PNBUF_PUT(cp);
- break;
- }
- linklen = MAXPATHLEN - auio.uio_resid;
- if (linklen == 0) {
- error = ENOENT;
- goto badlink;
- }
- if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
- error = ENAMETOOLONG;
- goto badlink;
- }
- if (ndp->ni_pathlen > 1) {
- memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);
- PNBUF_PUT(cnp->cn_pnbuf);
- cnp->cn_pnbuf = cp;
- } else
- cnp->cn_pnbuf[linklen] = '\0';
- ndp->ni_pathlen += linklen;
- vput(ndp->ni_vp);
- dp = ndp->ni_dvp;
-
- /*
- * Check if root directory should replace current directory.
- */
- if (cnp->cn_pnbuf[0] == '/') {
- vput(dp);
- dp = ndp->ni_rootdir;
- VREF(dp);
- vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
- }
- }
- }
- vput(ndp->ni_dvp);
- vput(ndp->ni_vp);
- ndp->ni_vp = NULL;
out:
PNBUF_PUT(cnp->cn_pnbuf);
return (error);
Index: src/sys/sys/namei.src
diff -u src/sys/sys/namei.src:1.12 src/sys/sys/namei.src:1.13
--- src/sys/sys/namei.src:1.12 Sun Sep 27 17:19:07 2009
+++ src/sys/sys/namei.src Sun Sep 27 17:23:54 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: namei.src,v 1.12 2009/09/27 17:19:07 dholland Exp $ */
+/* $NetBSD: namei.src,v 1.13 2009/09/27 17:23:54 dholland Exp $ */
/*
* Copyright (c) 1985, 1989, 1991, 1993
@@ -228,7 +228,7 @@
int namei(struct nameidata *);
uint32_t namei_hash(const char *, const char **);
-int lookup_for_nfsd(struct nameidata *);
+int lookup_for_nfsd(struct nameidata *, struct vnode *, int neverfollow);
int lookup_for_nfsd_index(struct nameidata *);
int relookup(struct vnode *, struct vnode **, struct componentname *);
void cache_purge1(struct vnode *, const struct componentname *, int);