Subject: Re: lib/30943: realpath() behaviour changed with nonexistant relative
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Elad Efrat <elad@NetBSD.org>
List: netbsd-bugs
Date: 08/13/2005 00:14:01
The following reply was made to PR lib/30943; it has been noted by GNATS.
From: Elad Efrat <elad@NetBSD.org>
To: gnats-bugs@netbsd.org
Cc: mark@mcs.vuw.ac.nz
Subject: Re: lib/30943: realpath() behaviour changed with nonexistant relative
path
Date: Sat, 13 Aug 2005 03:04:20 +0300
Hi,
Looking at several revisions of realpath(3):
1.35: 6 months, 2 weeks ago
1.36: 6 months, 1 week ago (imported FreeBSD code)
1.38: 5 weeks, 3 days ago (bug fix)
1.39: not yet commited
We'll try realpath(3) on a path with a non-existant last element
and see how it behaves. My current working directory is
/home/elad/work/realpath/realpath
[ first let's see it works the same for an existing path ]
phyre:realpath {33} ls
realpath* realpath.c
phyre:realpath {34} mkdir foo
phyre:realpath {35} ./realpath foo
Revision 1.35:
buf=[/home/elad/work/realpath/realpath/foo]
ret=[/home/elad/work/realpath/realpath/foo]
errno=[0]
Revision 1.36:
buf=[/home/elad/work/realpath/realpath/foo]
ret=[/home/elad/work/realpath/realpath/foo]
errno=[0]
Revision 1.38:
buf=[/home/elad/work/realpath/realpath/foo]
ret=[/home/elad/work/realpath/realpath/foo]
errno=[0]
(to be) Revision 1.39:
buf=[/home/elad/work/realpath/realpath/foo]
ret=[/home/elad/work/realpath/realpath/foo]
errno=[0]
[ so far so good. ]
phyre:realpath {36} ./realpath foo/bar/
Revision 1.35:
buf=[foo/bar]
ret=[(null)]
errno=[2]
Revision 1.36:
buf=[/home/elad/work/realpath/realpath/foo/bar]
ret=[(null)]
errno=[2]
Revision 1.38:
buf=[/home/elad/work/realpath/realpath/foo/bar]
ret=[/home/elad/work/realpath/realpath/foo/bar]
errno=[2]
(to be) Revision 1.39:
buf=[/home/elad/work/realpath/realpath/foo/bar]
ret=[(null)]
errno=[2]
[ revision 1.35 acts like solaris, broken. revision 1.36 acts
like you mentioned it should. revision 1.38 *supposedly*
breaks behavior. ]
phyre:realpath {37} ./realpath foo/bar
Revision 1.35:
buf=[/home/elad/work/realpath/realpath/foo/bar]
ret=[/home/elad/work/realpath/realpath/foo/bar]
errno=[2]
Revision 1.36:
buf=[/home/elad/work/realpath/realpath/foo/bar]
ret=[/home/elad/work/realpath/realpath/foo/bar]
errno=[2]
Revision 1.38:
buf=[/home/elad/work/realpath/realpath/foo/bar]
ret=[/home/elad/work/realpath/realpath/foo/bar]
errno=[2]
(to be) Revision 1.39:
buf=[/home/elad/work/realpath/realpath/foo/bar]
ret=[(null)]
errno=[2]
[ look how removing the trailing slash makes revision 1.36 behave
``wrong''. revision 1.38 didn't introduce bad behavior - it
fixed a bug in revision 1.36.]
Conclusions:
1. Don't rely on an inconsistent API. :)
2. Don't use realpath(3) when you really want stat(2).
If you like what ``revision 1.39'' is doing, use this patch:
Index: getcwd.c
===================================================================
RCS file: /cvsroot/src/lib/libc/gen/getcwd.c,v
retrieving revision 1.38
diff -u -p -r1.38 getcwd.c
--- getcwd.c 5 Jul 2005 02:56:12 -0000 1.38
+++ getcwd.c 13 Aug 2005 00:05:26 -0000
@@ -160,12 +160,6 @@ loop:
*/
if (lstat(resolved, &sb) == -1) {
/* Allow nonexistent component if this is the last one. */
- while (*q == '/')
- q++;
- if (*q == 0 && errno == ENOENT) {
- errno = serrno;
- return (resolved);
- }
return (NULL);
}
if (S_ISLNK(sb.st_mode)) {
Thanks,
-e.
--
Elad Efrat
PGP Key ID: 0x666EB914