Subject: Re: Standards compliance..? (trailing slashes)
To: Dan LaBell <dan4l-nospam@verizon.net>
From: Greg A. Woods <woods@weird.com>
List: netbsd-users
Date: 06/30/2005 14:04:28
[ On Thursday, May 26, 2005 at 00:45:13 (-0400), Dan LaBell wrote: ]
> Subject: Re: Standards compliance..? (trailing slashes)
>
> On May 25, 2005, at 4:46 PM, Greg A. Woods wrote:
> >
> > After all, _all_ of the traditional implementations of Unix have
> > _always_ universally treated trailing slashes as NULs (and collapsed
> > multiple embedded slashes to one slash, of course).
> 
> So, that things like "/usr/local/bin" , "/usr/local//bin" , or 
> "/usr/local/bin/"
> "/usr/local//bin//" all map to the same directory?

Well, no, they all map to the same _file_, if it exists, which on many
systems is normally a directory file (or maybe a symlink).


>  Meaning that one 
> does not have make a dozen or so little changes everywhere in shell 
> scripts, and makefiles to get things to work, and now not so?

If I understand what you meant, then yes, that's exactly the point, at
least as I understand it from the original code and Unix papers, and
from John Lyons' interpretation of the V6 code.


> What about "/usr/local/bin/." vs "/usr/local/bin",

Well that depends on whether or not /usr/local/bin is a directory or
not.  :-)

And if not whether it's a symlink pointing to a directory, or not, e.g.:

	13:38 [127] $ ls -l /sys
	lrwxr-xr-x  1 root  wheel  11 Oct 14  2004 /sys -> usr/src/sys
	13:38 [128] $ ls -l /sys/
	lrwxr-xr-x  1 root  wheel  11 Oct 14  2004 /sys/ -> usr/src/sys
	13:38 [128] $ ls -l /sys////
	lrwxr-xr-x  1 root  wheel  11 Oct 14  2004 /sys//// -> usr/src/sys
	13:38 [129] $ ls -l /sys/.
	total 160
	drwxr-xr-x   2 woods  wheel   512 Jun  3 13:56 CVS
	-rw-r--r--   1 woods  wheel   429 Aug  6  2003 Makefile
	. . . 

> what does the new 
> code do in this case?

Well with a trailing "/." it _should_ still work the same way as my
patched code.

> As in cp newfile /usr/local/bin/.  will give an 
> error, rather than cp newfile /usr/local/bin, which will happily make a 
> new file called bin in /usr/local, if /usr/local/bin doesn't exist.

Same on my systems which follow the traditional V7 behaviour and treat
trailing slashes as NUL bytes:

	13:40 [131] $ ls -l foo
	ls: foo: No such file or directory
	ksh: exit code: 1
	13:40 [131] $ ls -l bar
	ls: bar: No such file or directory
	ksh: exit code: 1
	13:40 [132] $ touch foo
	13:40 [133] $ cp foo bar/.
	cp: bar/.: No such file or directory
	ksh: exit code: 1

"." is just a file in a directory -- though it happens to be a hard link
to the file that is also the directory it is in.

	13:40 [134] $ cp foo bar
	13:42 [135] $ ls -l bar
	-rw-r--r--  1 woods  local  0 Jun 30 13:42 bar

I.e. one does indeed specify the desire to access /usr/local/bin as a
directory by placing a trailing "/.", or any other trailing filename, on
the pathname, not just a trailing slash, and that should work the same
on _all_ systems from V7 onwards.

As long as you remember that directories are just files you should be OK.

(I cannot even begin to fathom why people want to save one extra
character and try to get by with just a trailing slash to specify that a
file must be a directory -- it makes no sense whatsoever to me, though I
must admit most of my use of Unix systems has been those varieties
straight from Bell Labs and related places or their direct derivatives
(starting ith V7 itself), with only a short stint using 3.9 and 4.1 in
university, then more recently work with SunOS-4, until now finally in
the past few years NetBSD.)


> If multiple embedded slashes aren't supported, I may want your patch, 
> please share it.

I think they were and are supported in NetBSD, but here is the
(complete, I think, IIRC) patch to treat trailing slashes in the
traditional V7 way:

Index: vfs_lookup.c
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/sys/kern/vfs_lookup.c,v
retrieving revision 1.39.10.1
diff -u -r1.39.10.1 vfs_lookup.c
--- vfs_lookup.c	21 Jun 2002 05:47:58 -0000	1.39.10.1
+++ vfs_lookup.c	11 Sep 2003 20:45:58 -0000
@@ -395,9 +395,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 {
@@ -406,7 +407,8 @@
 		slashes = cp - ndp->ni_next;
 		ndp->ni_pathlen -= slashes;
 		ndp->ni_next = cp;
-		cnp->cn_flags |= REQUIREDIR;
+		if (*cp != '\0')
+			cnp->cn_flags |= REQUIREDIR;
 	} else {
 		slashes = 0;
 		cnp->cn_flags &= ~REQUIREDIR;
@@ -421,6 +423,7 @@
 		else
 			cnp->cn_flags &= ~MAKEENTRY;
 		cnp->cn_flags |= ISLASTCN;
+		cnp->cn_flags &= ~REQUIREDIR;
 	} else {
 		cnp->cn_flags |= MAKEENTRY;
 		cnp->cn_flags &= ~ISLASTCN;
@@ -519,8 +522,8 @@
 		if (error != EJUSTRETURN)
 			goto bad;
 		/*
-		 * If this was not the last component, or there were trailing
-		 * slashes, 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) {
 			error = ENOENT;

-- 
						Greg A. Woods

H:+1 416 218-0098  W:+1 416 489-5852 x122  VE3TCP  RoboHack <woods@robohack.ca>
Planix, Inc. <woods@planix.com>          Secrets of the Weird <woods@weird.com>