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);

Reply via email to