On Jan 10, 2014, at 15:51, Alan Ruttenberg alanruttenberg@gmail.com wrote:
There are, I would offer, several arguments suggesting that the current behavior should not be the default.
- Exceptions: Generally, listing the contents of a directory is not
considered an exception unless the directory structure is corrupted. In some cases (e.g. unix "rm") you can't even do anything to the target of the link. So ABCL signals an exception when most would not expect it. Consider the case where the link points to a file on a device that may or not be mounted. If the device is taken offline, nothing in the directory changes, and yet the behavior does. It seems that this situation is more properly handled by an exception when opening the file.
The doc for truename says, about conditions: "An error of type file-error is signaled if an appropriate file cannot be located within the file system for the given file spec or if the file system cannot perform the requested operation.". Whether or not the symbolic link is a file or not. Certainly for some cases it is, for example when handled by archiving or certain version control systems, or in the cases I list in (4). In the case of "rm", the answer is yes, it is a file, implicit from the documentation: "The rm utility attempts to remove the non-directory type files specified on the command line. [...] The rm utility removes symbolic links, not the files referenced by the links. In ABCL, (directory "/") -> (#P"/"). This means that a) ABCL is inconsistent in that it sometimes returns truenames for things that can not be "opened" or b) ABCL admits that there can be truenames for entities other than files, which makes it's treatment of symbolic links inconsistent.
- Pragmatism: With the current default, the only possible
programmatic repair in the common case that you don't care about these entries - for example if you are looking for a file whose name matches a pattern not expressible using the directory wild card expressivity - is to use an implementation-specific keyword. CCL's implementation also has this property, which I also consider to be a fail. In practical terms this means that the unsuspecting programmer must wrap all calls to directory with a catch and have the handler respond in an implementation-specific way. It is much more common to protect accesses to a file than accesses to a directory.
- Truth in advertising: The exception happens independent of the
value of the :resolve-symlinks keyword. If the function is told not to resolve symlinks, one would expect it doesn't resolve symlinks. Yet it does, since that's the only way that it could figure out that the "file does not exist".
- File system operations other than opening: There are legitimate
operations on unresolvable links. For example, such files can be removed, renamed, and there are retrievable dates and other metadata retrievable about them. One would not expect directory to balk in the case that you are retrieving file names for one of these purposes.
My conclusion:
- If resolve-symlinks is false, the behavior should be either that of
SBCL's (return the name) or CCL's (don't return the name) depending on which answer the implementation takes towards the question "is a symbolic link a file?".
- If resolve-symlinks is true then signal an error.
- The default should be :resolve-symlinks nil, because cognate
directory operations in every operation's default case that I'm aware of is to not consider this case an exception.
With a (hopefully) carefully done refactoring of the underlying Pathname.listDirectory() routine, the semantics of CL:DIRECTORY are now:
(PATHSPEC &KEY (RESOLVE-SYMLINKS NIL)) Determines which, if any, files that are present in the file system have names matching PATHSPEC, and returns a fresh list of pathnames corresponding to the potential truenames of those files.
In the default behavior with :RESOLVE-SYMLINKS set to nil, a CL:TRUENAME call an individual pathname in the list may signal an error, i.e. the pathnames have been constructed as truenames, without calling the entire resolution routine of CL:TRUENAME.
If RESOLVE-SYMLINKS is T, and any of the pathnames have truenames which do not exist, this routine will signal a file error to its caller.
This should satisfy the basic issues here: there may be some corner cases to chase down. Patches are welcome.
This should also (mostly) fix the ASDF BUNDLE-OP problem (which was a problem with DIRECTORY called with :WILD-INFERIORS in a symlinked directory, as ‘/tmp' is under OS X).
[r14619]: http://abcl.org/trac/changeset/14619