[issue1701] mkdir / returns EPERM instead of EEXIST (related to pkg_add)

Chris Turner c.turner at 199technologies.org
Sun Mar 28 19:41:15 PDT 2010


Stathis Kamperis (via DragonFly issue tracker) wrote:
> Stathis Kamperis <ekamperi at gmail.com> added the comment:
>
> Hey all.
>
> First, EPERM shouldn't be returned at all; instead EACCES should.
>
This indeed looks to be related to the exact section of code Alex 
mentioned - see attached for (trivial) 'mkdir' related fix. (1LOC + 
comment update)

In the current code comments (e.g. pre-this-patch), 'rmdir /' is 
explicitly mentioned, so assuming this is the related reference,
POSIX specifies that EPERM or EACCESS is OK.

http://www.opengroup.org/onlinepubs/000095399/functions/rmdir.html

There is another section of code further down, related to non-edge 
cases? labeled 'POSIX junk', of note.

So - anyhow - assuming that this terribly exiting and non-pedantic 
conversation about standards conformance is resolved in short order - 
should I commit this to the just-cut release branch or no?

(mea culpa on always having the 5min late patches. story-of-life. sigh)

Did 5-6 rudimentary tests in a vkernel, along the lines of:

mkdir / -> eexist
rmdir / -> eperm
mkdir /tmp/foo -> works!
mkdir /tmp/foo -> eexist
rmdir /tmp/foo -> works!
I'm not familiar enough with namecache users to suggest a call here ..

Cheers

- Chris

> Second, POSIX says that the order of error detection is undefined. 
So, we may
> choose to check first the permissions and then if directory exists, 
or the other
> way around. Both are valid.

nothing to say about this meself..

diff --git a/sys/kern/vfs_nlookup.c b/sys/kern/vfs_nlookup.c
index ab7df39..4d7141b 100644
--- a/sys/kern/vfs_nlookup.c
+++ b/sys/kern/vfs_nlookup.c
@@ -469,14 +469,15 @@ nlookup(struct nlookupdata *nd)
 	    nd->nl_nch = nch;		/* remains locked */
 
 	    /*
-	     * Fast-track termination.  There is no parent directory of
-	     * the root in the same mount from the point of view of
-	     * the caller so return EPERM if NLC_REFDVP is specified.
-	     * e.g. 'rmdir /' is not allowed.
+	     * Fast-track termination. In the case of '/', there is no 
+	     * parent directory from the point of view of the caller 
+	     * so return either EPERM if NLC_REFDVP is specified.
+	     * e.g. 'rmdir /' is not allowed, or return EEXIST
+	     * for the case of 'mkdir /'.
 	     */
 	    if (*ptr == 0) {
 		if (nd->nl_flags & NLC_REFDVP)
-			error = EPERM;
+			error = (nd->nl_flags & NLC_CREATE) ? EEXIST : EPERM;
 		else
 			error = 0;
 		break;




More information about the Bugs mailing list