filesystem-7.8 fails on darwin when realpath() is used, and succeeds
otherwise. The failure is that
succeeds but does not change the current directory
I've tracked this down to differing behaviour in
TclpObjNormalizePath() when normalizing 'simplefs:/simpledir'
depending on NO_REALPATH being defined:
- with NO_REALPATH, the "slow way" of getting the subpath to be
normalized at the start of TclpObjNormalizePath() fails at access()
on the first path component 'simplefs:', which leads to the correct
return value of 'simplefs:/simpledir' as expected.
- without NO_REALPATH, the fast way of using realpath() to get the
subpath to be normalized calls 'realpath("simplefs:")' which returns
the absolute path "[pwd]/simplefs:", this leads to
TclpObjNormalizePath() returning the incorrect value '[pwd]/
the result of this path normalization is used to identify the
filesystem owning the path in question, this fails to find the
simplefilesystem in the second case which ends up leading to the
the crux of the issue stems from the behaviour of realpath() on
relative paths. The BSD spec says that realpath() always returns an
absolute path, and that all except the last path component given
must exist (c.f. manpage below). This is exactly what seems to
happen in this case on darwin, so it looks like the design of
TclpObjNormalizePath() didn't take BSD realpath into account?
according to the caveats in the manpage, solaris realpath() doesn't
behave in the same way, this may also be true on other platforms?
as I've proposed in the past, maybe a compat/ implementation of
realpath() is needed that behaves the same on all platforms? this
would also solve the non-thread safeness issue of realpath() on
darwin that requires NO_REALPATH to be defined in the threaded
REALPATH(3) BSD Library Functions Manual
realpath - returns the canonicalized absolute pathname
Standard C Library (libc, -lc)
realpath(const char *pathname, char
The realpath() function resolves all symbolic links, extra ``/''
ters and references to /./ and /../ in pathname, and copies the
absolute pathname into the memory referenced by
resolved_path argument must refer to a buffer capable of
storing at least
The realpath() function will resolve both absolute and relative
return the absolute pathname corresponding to pathname. All
but the last
component of pathname must exist when realpath() is called.
The realpath() function returns resolved_path on success. If an
occurs, realpath() returns NULL, and resolved_path contains the
which caused the problem.
The function realpath() may fail and set the external variable
any of the errors specified for the library functions lstat(2),
readlink(2) and getcwd(3).
This implementation of realpath() differs slightly from the
implementation. The 4.4BSD version always returns absolute
whereas the Solaris implementation will, under certain
return a relative resolved_path when given a relative pathname.
The realpath() function first appeared in 4.4BSD.
BSD February 16, 1994