On Wed, 17 Feb 2010, Poul-Henning Kamp wrote:

In message <20100218044931.s95...@delplex.bde.org>, Bruce Evans writes:
On Wed, 17 Feb 2010, Poul-Henning Kamp wrote:

Log:
 Mention EISDIR as a possible errno.

It's not a possible error.

critter phk> cat > a.c
#include <stdio.h>
#include <err.h>

int
main(int argc, char **argv)
{
       if (unlink("/"))
               err(1, "Told you so");
       return (0);
}
critter phk> cc a.c
critter phk> ./a.out
a.out: Told you so: Is a directory
critter phk>

Better fix the kernel bug than break the documentation then.

The bug is very old -- it happens in ~5.2, where the code is a bit easier
to understand:

% int
% kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
% {
%       struct mount *mp;
%       struct vnode *vp;
%       int error;
%       struct nameidata nd;
% % restart:
%       bwillwrite();
%       NDINIT(&nd, DELETE, NOFOLLOW | LOCKPARENT | LOCKLEAF, pathseg, path,
%           td);
%       if ((error = namei(&nd)) != 0)
%               return (error);

namei() returns EISDIR for "/" (due to DELETE and and the special handling
of the degenerate case which includes "/" and not much else, else the bug
would affect more cases).  Then we return the wrong errno before we test
VDIR.

%       vp = nd.ni_vp;
%       if (vp->v_type == VDIR)
%               error = EPERM;
%       else {

Untested fix for ~5.2.  Also fixes some style bugs.

% Index: vfs_syscalls.c
% ===================================================================
% RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v
% retrieving revision 1.354
% diff -u -2 -r1.354 vfs_syscalls.c
% --- vfs_syscalls.c    24 Jun 2004 17:22:29 -0000      1.354
% +++ vfs_syscalls.c    17 Feb 2010 20:01:09 -0000
% @@ -1614,10 +1605,11 @@
%  restart:
%       bwillwrite();
% -     NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, pathseg, path, td);
% +     NDINIT(&nd, DELETE, NOFOLLOW | LOCKPARENT | LOCKLEAF, pathseg, path,
% +         td);

Style fixes:
- spell out NOFOLLOW (NOFOLLOW is 0, so omitting it is just confusing).
  This bug is in about 3 other vfs syscalls.
- there are spaces around binary operators in KNF.  These spaces are
  especially important for the "|" operator since this operator looks
  more like an alphanumeric character than most operator symbols, but
  they are most often omitted for this operator :-(.

%       if ((error = namei(&nd)) != 0)
% -             return (error);
% +             return (error == EISDIR ? EPERM : error);

Fix the EISDIR bug.

%       vp = nd.ni_vp;
%       if (vp->v_type == VDIR)
% -             error = EPERM;          /* POSIX */
% +             error = EPERM;

Remove banal/misleading comment.  The new fixup needs a comment more than
this, but I don't want to add one.

%       else {
%               /*

ISTR trying to avoid the special handling for the degenerate case in
namei() and lookup() (2 almost identical copies of it).  The correct
fix may be there.  From lookup() in ~5.2:

%       /*
%        * Check for degenerate name (e.g. / or "")
%        * which is a way of talking about a directory,
%        * e.g. like "/." or ".".
%        */
%       if (cnp->cn_nameptr[0] == '\0') {
%               if (dp->v_type != VDIR) {
%                       error = ENOTDIR;
%                       goto bad;
%               }
%               if (cnp->cn_nameiop != LOOKUP) {
%                       error = EISDIR;
%                       goto bad;
%               }

Cases with trailing slashes are handled by removing the slash, but
this doesn't work for "/" since we don't want to end up with the fully
degenerate name of "".  Cases starting with this fully degnerate name
haven't been permitted since ~1988 when POSIX disallowed it, but the
comment in the code hasn't caught up with this.  The comment gives
these cases as examples only, but I think that is another bug and that
this is a complete list of degenerate names so the comment should say
"i.e.,".  After catching up with 1988 and removing "" from the list,
only "/" remains.  This is not really degenerate and can hopefully be
handled more directly and simply.  The != VDIR case in the above might
already be unreachable.

Bruce
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to