Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 5 Mar 2010 07:57:59 +0200
From:      Jaakko Heinonen <jh@FreeBSD.org>
To:        freebsd-hackers@FreeBSD.org
Cc:        freebsd-hackers@FreeBSD.org, Poul-Henning Kamp <phk@phk.freebsd.dk>, Bruce Evans <brde@optusnet.com.au>, Alexander Best <alexbestms@wwu.de>
Subject:   Re: namei() returns EISDIR for "/" (Re: svn commit: r203990 - head/lib/libc/sys)
Message-ID:  <20100305055758.GA1062@a91-153-117-195.elisa-laajakaista.fi>
In-Reply-To: <20100228174936.GA1252@a91-153-117-195.elisa-laajakaista.fi>
References:  <6413.1266433105@critter.freebsd.dk> <20100218064545.J2074@besplex.bde.org> <20100218095538.GA2318@a91-153-117-195.elisa-laajakaista.fi> <20100225195138.GA3323@a91-153-117-195.elisa-laajakaista.fi> <20100226091923.X2605@delplex.bde.org> <20100228174936.GA1252@a91-153-117-195.elisa-laajakaista.fi>

next in thread | previous in thread | raw e-mail | index | archive | help

--J2SCkAp4GZ/dPZZf
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On 2010-02-28, Jaakko Heinonen wrote:
> > > 	http://people.freebsd.org/~jh/patches/lookup-root.diff

I have updated the patch taking some of bde's comments into account. The
new version also includes updates for namei(9) manual page.

The patch is attached to this mail and also found at:

	http://people.freebsd.org/~jh/patches/lookup-root.2.diff

-- 
Jaakko

--J2SCkAp4GZ/dPZZf
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="lookup-root.2.diff"

Index: sys/kern/vfs_lookup.c
===================================================================
--- sys/kern/vfs_lookup.c	(revision 204620)
+++ sys/kern/vfs_lookup.c	(working copy)
@@ -565,18 +565,26 @@ dirloop:
 	}
 
 	/*
-	 * Check for degenerate name (e.g. / or "")
-	 * which is a way of talking about a directory,
-	 * e.g. like "/." or ".".
+	 * Check for "" which represents the root directory after slash
+	 * removal.
 	 */
 	if (cnp->cn_nameptr[0] == '\0') {
-		if (dp->v_type != VDIR) {
-			error = ENOTDIR;
-			goto bad;
-		}
-		if (cnp->cn_nameiop != LOOKUP) {
-			error = EISDIR;
-			goto bad;
+		KASSERT(dp->v_type == VDIR, ("dp is not a directory"));
+		/* 
+		 * We can't provide a parent node for CREATE,
+		 * DELETE and RENAME operations.
+		 */
+		switch (cnp->cn_nameiop) {
+		case CREATE:
+			error = EEXIST;
+			goto bad;
+		case DELETE:
+		case RENAME:
+			error = EBUSY;
+			goto bad;
+		default:
+			KASSERT(cnp->cn_nameiop == LOOKUP,
+			    ("nameiop must be LOOKUP"));
 		}
 		if (wantparent) {
 			ndp->ni_dvp = dp;
@@ -948,19 +956,17 @@ relookup(struct vnode *dvp, struct vnode
 #endif
 
 	/*
-	 * Check for degenerate name (e.g. / or "")
-	 * which is a way of talking about a directory,
-	 * e.g. like "/." or ".".
+	 * Check for "" which represents the root directory after slash
+	 * removal.
 	 */
 	if (cnp->cn_nameptr[0] == '\0') {
-		if (cnp->cn_nameiop != LOOKUP || wantparent) {
-			error = EISDIR;
-			goto bad;
-		}
-		if (dp->v_type != VDIR) {
-			error = ENOTDIR;
-			goto bad;
-		}
+		KASSERT(dp->v_type == VDIR, ("dp is not a directory"));
+		/*
+		 * Support only LOOKUP for "/" because lookup()
+		 * can't succeed for CREATE, DELETE and RENAME.
+		 */
+		KASSERT(cnp->cn_nameiop == LOOKUP, ("nameiop must be LOOKUP"));
+
 		if (!(cnp->cn_flags & LOCKLEAF))
 			VOP_UNLOCK(dp, 0);
 		*vpp = dp;
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c	(revision 204620)
+++ sys/kern/vfs_syscalls.c	(working copy)
@@ -1841,7 +1841,7 @@ restart:
 	NDINIT_AT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
 	    pathseg, path, fd, td);
 	if ((error = namei(&nd)) != 0)
-		return (error == EINVAL ? EPERM : error);
+		return ((error == EINVAL || error == EBUSY) ? EPERM : error);
 	vfslocked = NDHASGIANT(&nd);
 	vp = nd.ni_vp;
 	if (vp->v_type == VDIR && oldinum == 0) {
@@ -3617,9 +3617,6 @@ kern_renameat(struct thread *td, int old
 	if (fromnd.ni_vp->v_type == VDIR)
 		tond.ni_cnd.cn_flags |= WILLBEDIR;
 	if ((error = namei(&tond)) != 0) {
-		/* Translate error code for rename("dir1", "dir2/."). */
-		if (error == EISDIR && fvp->v_type == VDIR)
-			error = EINVAL;
 		NDFREE(&fromnd, NDF_ONLY_PNBUF);
 		vrele(fromnd.ni_dvp);
 		vrele(fvp);
Index: share/man/man9/namei.9
===================================================================
--- share/man/man9/namei.9	(revision 204620)
+++ share/man/man9/namei.9	(working copy)
@@ -338,8 +338,17 @@ An attempt is made to access a file in a
 permissions.
 .It Bq Er ELOOP
 Too many symbolic links were encountered in translating the pathname.
-.It Bq Er EISDIR
-An attempt is made to open a directory with write mode specified.
+.It Bq Er EINVAL
+The last component of the pathname specified for the RENAME operation is
+.Ql \&. .
+.It Bq Er EEXIST
+The root directory
+.Pq Ql /
+was specified for the CREATE operation.
+.It Bq Er EBUSY
+The root directory
+.Pq Ql /
+was specified for the DELETE operation.
 .It Bq Er EROFS
 An attempt is made to modify a file or directory on a read-only file system.
 .El
Index: lib/libc/sys/rename.2
===================================================================
--- lib/libc/sys/rename.2	(revision 204620)
+++ lib/libc/sys/rename.2	(working copy)
@@ -252,6 +252,12 @@ The
 .Fa to
 argument
 is a directory and is not empty.
+.It Bq Er EBUSY
+Either
+.Fa from
+or
+.Fa to
+is the root directory.
 .El
 .Pp
 In addition to the errors returned by the
Index: lib/libc/sys/unlink.2
===================================================================
--- lib/libc/sys/unlink.2	(revision 204620)
+++ lib/libc/sys/unlink.2	(working copy)
@@ -114,8 +114,6 @@ succeeds unless:
 .Bl -tag -width Er
 .It Bq Er ENOTDIR
 A component of the path prefix is not a directory.
-.It Bq Er EISDIR
-The named file is a directory.
 .It Bq Er ENAMETOOLONG
 A component of a pathname exceeded 255 characters,
 or an entire path name exceeded 1023 characters.

--J2SCkAp4GZ/dPZZf--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100305055758.GA1062>