NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/45425: how to restore traditional unix behaviour for slashes on the end of pathnames
>Number: 45425
>Category: kern
>Synopsis: how to restore traditional unix behaviour for slashes on the
>end of pathnames
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Oct 04 19:55:00 +0000 2011
>Originator: Greg A. Woods
>Release: NetBSD-current 2011/10/04
>Organization:
Planix, Inc.; Kelowna, BC; Canada
>Environment:
System: NetBSD
Architecture: all
Machine: all
>Description:
Traditional Unix, from at least V5 onwards and right through to
the end (V10) and perhaps beyond (plan 9?), always treated
slashes (in groups of one or more) in pathnames purely as
separators between components, and thus trailing slashes were
always effectively ignored (treated as NULs).
At some point BSD changed this interpretation of trailing
slashes. Apparently they forgot that appending "/." was the
correct and obvious way to specify that the final component of a
pathname must be a directory.
There has been discussion in tech-userlevel over the past decade
about this issue because the BSD behaviour has had "unexpected"
fallout causing real bugs and other odd problems. I.e. the BSD
behaviour has proven to be problemetic and at the same time has
not really added anything new or novel which has value
significant enough to justify the problems, and which could not
already be obtained with existing well known techniques
(i.e. the appending of "/." instead of just "/"). The saving of
one character which imparts even more concrete meaning is not
worth all the problems it caused.
Long ago I think I promised to post a patch which restores the
original behaviour after I had tested it, and I think 8 years of
testing in releases since NetBSD-1.6, and with a wide-spread
user-base beyond just myself, is sufficient. :-)
The only change of behaviour this "fix" causes which might
trouble some people, but which I find to be a feature for my own
use since it gives me extra information without me having to do
anything extra of different, is that "ls" of a symlink to a
directory, even when a trailing slash is appeneded to the link
name, still shows just the link, not the contents of the target
directory. Adding the trailing "/." will of course show the
contents of the target directory. The only time this shows up
is of course when one uses filename completion in an interactive
shell and the shell shows just a trailing slash -- the proper
fix would be for the shell to show a trailing "/." when the
previous component is a symlink and the user would then erase
the "." and continue with completing another pathname component
if they didn't want to see just inside the directory itself.
I plan to fix "ksh" and "sh" so that they offer "foo/." instead
of "foo/" IFF the name "foo" is a symlink (and automatically
remove the trailing "." if the user hits <tab> again
immediately). This would give the user the hint during
interactive pathname completion that a name is a symlink without
changing the final behaviour if the target directory is the
object of interest.
>How-To-Repeat:
>Fix:
Because of how the BSD behaviour has snuck into the most recent
modern unix standards (in final revisions before publication,
and in direct opposition to previous standards, and with faulty
rationale to boot), some people will still no doubt prefer if
this change is wrapped in a conditional protected by a
conditional of some sort, perhaps a sysctl, or at least an
#ifdef
I leave the choice of conditional mechanism to the person who
might choose to tackle this issue. Showing the basic change
without a conditional also shows more clearly just how simple
and elegant the change is without any unnecessary clutter.
Index: sys/kern/vfs_lookup.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/sys/kern/vfs_lookup.c,v
retrieving revision 1.192
diff -u -r1.192 vfs_lookup.c
--- sys/kern/vfs_lookup.c 27 Sep 2011 02:10:55 -0000 1.192
+++ sys/kern/vfs_lookup.c 4 Oct 2011 18:12:05 -0000
@@ -825,9 +825,10 @@
ndp->ni_pathlen -= cnp->cn_namelen;
ndp->ni_next = cp;
/*
- * If this component is followed by a slash, then move the pointer to
- * the next component forward, and remember that this component must be
- * a directory.
+ * If this component is followed by one or more slashes then move the
+ * pointer to the next component forward. If there is another
+ * component following the slash(es) then remember that this component
+ * must be a directory.
*/
if (*cp == '/') {
do {
@@ -837,6 +838,8 @@
ndp->ni_pathlen -= state->slashes;
ndp->ni_next = cp;
cnp->cn_flags |= REQUIREDIR;
+ if (*cp != '\0')
+ cnp->cn_flags |= REQUIREDIR;
} else {
state->slashes = 0;
cnp->cn_flags &= ~REQUIREDIR;
@@ -851,6 +854,7 @@
else
cnp->cn_flags &= ~MAKEENTRY;
cnp->cn_flags |= ISLASTCN;
+ cnp->cn_flags &= ~REQUIREDIR;
} else {
cnp->cn_flags |= MAKEENTRY;
cnp->cn_flags &= ~ISLASTCN;
@@ -984,9 +988,8 @@
goto done;
/*
- * If this was not the last component, or there were trailing
- * slashes, and we are not going to create a directory,
- * then the name must exist.
+ * If this was not the last component, then the name must
+ * exist (and of course it must be a directory).
*/
if ((cnp->cn_flags & (REQUIREDIR | CREATEDIR)) == REQUIREDIR) {
error = ENOENT;
Home |
Main Index |
Thread Index |
Old Index