I initially neglected to send this register an account w/ osicat-devel and mailed the following exchange to Nikodemus directly with the subject line: "osicat:list-directory vs. cl-fad:list-directory"
No doubt Nikodemus has plenty on his plate right now as it is and needn't be solely responsible for fielding this verobisty :)
I should have taken the time to register an osicat-devel account. Having done so I am now forwarding a transcript of my previous exchange.
-------------- On 12 August 2011 19:46, MON KEY wrote: I noticed today that on SBCL these return differently:
(cl-fad:list-directory ".") (osicat:list-directory ".") (cl-fad:list-directory "..") (osicat:list-directory "..")
Assuming this is a bug, then i'm pretty sure its origin is around the reliance on osicat:with-directory-iterator.
osicat:call-with-directory-iterator binds *d-p-d* to the value of the dir var before setting cwd in the protected form of its unwind-protect.
Further up in osicat:call-with-directory-iterator there is a merge with *d-p-d* via:
(osicat:absolute-pathname <PATHSPEC>)
When the PATHSPEC arg to osicat:list-directory is a dotted namestring e.g. "." or ".." the merge with *d-p-d* in osicat:call-with-directory-iterator will yield the equivalent of:
(merge-pathnames "." *default-pathname-defaults*)
such that for the duration of each #'one-iter *d-p-d* gets dynamically funky bound.
--------------
On Fri, Aug 12, 2011 at 1:07 PM, Nikodemus Siivola wrote:
The docstrings for many of the osicat functions mirror cl-fad's, so I am ssuming this is a bug, then i'm pretty sure its origin is around
Well, Osicat predates CL-FAD by a year or so, so not really.
A quick look at results from Osicat looks like just what I would expect -- what exactly is the difference you think is a bug?
Possibly you're looking for :bare-pathnames t?
---------------
On 12 August 2011 19:46, MON KEY wrote:
The docstrings for many of the osicat functions mirror cl-fad's, so I am assuming this is a bug, then i'm pretty sure its origin is around
Well, Osicat predates CL-FAD by a year or so, so not really.
Would you not agree that they are curiosly similar?
Possibly you're looking for :bare-pathnames t?
No, I didn't find :bare-pathnames t necessarily applicable w/r/t dotted-namestrings, and neither of the respcective below pairs do what I would expect:
(osicat:list-directory ".") (osicat:list-directory "." :bare-pathnames t)
(osicat:list-directory "..") (osicat:list-directory ".." :bare-pathnames t)
Note however, that these forms do retrun what i would expect:
(osicat:list-directory "./") (osicat:list-directory "." :bare-pathnames t)
(osicat:list-directory "../") (osicat:list-directory "../" :bare-pathnames t)
When a namestring is given as a dotted-namestring and a trailing #/ (solidus) is _not_ present, I would expect Osicat to resolve dotted-namestrings their cl:truename before executing the inspection PATHSPEC in the iterations.
When a namestring is given as a dotted-namestring and a trailing #/ (solidus) _is_ present I would expect Osicat to _not_ resolve the dotted-namestrings.
A quick look at results from Osicat looks like just what I would expect -- what exactly is the difference you think is a bug?
Following evaulated from SBCL "1.0.47.1":
*default-pathname-defaults* ;=> #P"/home/me/long-path/here/subdir/sub-subdir/"
(cl:pathname-type #P".") ;=> NIL
(cl:pathname-name #P".") ;=> "."
(cl:pathname-name "..") ;=> "."
(cl:pathname-name "..") ;=> "."
(cl:pathname-name "../") => NIL
(cl:pathname-name "./") => NIL
(cl:pathname-type ".") ;=> NIL
(cl:pathname-type "..") ;=> ""
(cl:pathname-type "./") ;=> NIL
(cl:pathname-type "../") ;=> NIL
(cl:pathname-directory ".") ;=> NIL
(cl:pathname-directory "..") ;=> NIL
(pathname-directory "./") ;=> (:RELATIVE ".")
(pathname-directory "../") ;=> (:RELATIVE :UP)
(cl:truename ".") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/"
(cl:truename "..") ;=> #p"/home/sp/hg-repos/cl-repo-hg/cl-mon-code/"
(cl:truename "./") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/"
(cl:truename "../") ;=> #P"/home/me/long-path/here/subdir/"
(cl:probe-file ".") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/"
(cl:probe-file "..") ;=> #P"/home/me/long-path/here/subdir/"
(directory ".") ;=> (#P"/home/me/long-path/here/subdir/sub-subdir/")
(directory "..") ;=> (#P"/home/me/long-path/here/subdir/")
(osicat:absolute-pathname ".") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/."
(osicat:absolute-pathname "..") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/.."
(osicat:file-kind ".") ;=> :DIRECTORY
(osicat:file-kind "..") ;=> :DIRECTORY
(osicat:file-kind (osicat:absolute-pathname "..")) ;=> :DIRECTORY
(osicat:file-kind (osicat:absolute-pathname ".")) ;=> :DIRECTORY
(osicat:directory-pathname-p ".") ;=> NIL
(osicat:directory-pathname-p "..") ;=> NIL
(osicat:pathname-as-directory ".") ;=> #P"./"
(osicat:pathname-as-directory "..") ;=> #P"../"
(osicat:pathname-directory-pathname ".") ;=> #P""
(osicat:pathname-directory-pathname "..") ;=> #P""
Disregarding the following assertion from the README of Quicklisp's dist of Osicat as to the extent of its Posixness:
,---- | | Osicat is a lightweight operating system interface for Common Lisp | on Unix-platforms. It is not a POSIX-style API, but rather a simple | lispy accompaniment to the standard ANSI facilities. | `---- :SOURE osicat-20110619-git/README
It may be worth considering osicats behaviour w/r/t following from POSIX.1-2008 apropos dotted namestrings:
,---- | | 4.12 Pathname Resolution | {...} | | The special filename dot shall refer to the directory specified by | its predecessor. The special filename dot-dot shall refer to the | parent directory of its predecessor directory. As a special case, in | the root directory, dot-dot may refer to the root directory itself. | | The Open Group Base Specifications Issue 7 IEEE Std 1003.1-2008 | `---- :SOURCE (URL `http://pubs.opengroup.org/onlinepubs/9699919799/')
Following may also be applicable: (URL `http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#dot')
As mentioned on #lisp, I'm not interested in advocating that Osicat be changed if it isn't broken.
The reliable portablility offered by Osicat underscores my interest in it and I am currently in the process of converting the CL-FAD and SBCL specific routines use in my code to use Osicat instead :) As such, my concern/curiousity is to learn the rationale for its implementation so as to avoid unnecessary future surprises.
AFAICT Osicat absolute-pathname treats the dotted namestring as pathname-name whereas these: (osicat:file-kind "..") (osicat:file-kind ".") consider them to be pathname-directory.
So long as Osicat allows pathspec args to take occur as a namestring (as opposed to a #P"." or #P"..") then there remains a certain ambiguity as to what type of pathname component the user intended the dotted-namestring to resolve to.
To the extent with which the following behave similiarly: (osicat:list-directory ".") shell> ls . (osicat:list-directory ".") shell> ls ..
Osicats dotted-namestring seems sane.
However, barring `scandir` `readdir` where there isn't really a POSIX equivalent to osicat:mapdir, osicat:walk-directory, osicat:with-directory-iterator I would advocate that Osicat behave as SBLC does and resolve the dotted-namestring to its cl:truename.
-- /s_P\
On 12 August 2011 22:36, MON KEY monkey@sandpframing.com wrote:
I apologize for excising most of your post, but before getting into whys and hows, I'd like to understand the _what_.
dotted-namestrings, and neither of the respcective below pairs do what I would expect:
(osicat:list-directory ".") (osicat:list-directory "." :bare-pathnames t)
(osicat:list-directory "..") (osicat:list-directory ".." :bare-pathnames t)
Note however, that these forms do retrun what i would expect:
(osicat:list-directory "./") (osicat:list-directory "." :bare-pathnames t)
(osicat:list-directory "../") (osicat:list-directory "../" :bare-pathnames t)
I'm having trouble following your argument since for me:
(equal (osicat:list-directory ".") (osicat:list-directory "./")) => T
. However, I did just discover that unexpectedly
(equal (osicat:list-directory "..") (osicat:list-directory "../")) => NIL
but the proximate cause of this appears to be an SBCL's failure to normalize (:RELATIVE "..") to (:RELATIVE :UP), which doesn't seem right at all and violates print/read consistency requirements:
CL-USER> (pathname-directory (pathname "\../")) (:RELATIVE "..") CL-USER> (pathname "\../") #P"../" CL-USER> (pathname-directory #p"../") (:RELATIVE :UP)
While "./" gets (:RELATIVE ".") which seems a bit odd, it is not AFAIK strictly speaking wrong.
If you're objecting to (:relative "..") I concur.
If you're objecting to something else, please clarify.
Cheers,
-- nikodemus
On Sat, Aug 13, 2011 at 9:15 AM, Nikodemus Siivola nikodemus@random-state.net wrote:
On 12 August 2011 22:36, MON KEY monkey@sandpframing.com wrote:
I apologize for excising most of your post, but before getting into whys and hows, I'd like to understand the _what_.
To be clear when i am refering to dotted-pathnames and/or dotted-namestrings I am referecing the following objects:
"." ; An unresolved CL:NAMESTRING with CL:PATHNAME-NAME "." ".." ; An unresolved CL:NAMESTRING with CL:PATHNAME-NAME "." and CL:PATHNAME-TYPE "" #P"." ; A CL:PATHNAME-NAME with CL:PATHNAME-NAME "." #P".." ; A CL:PATHNAME-NAME with CL:PATHNAME-NAME "." and CL:PATHNAME-TYPE ""
When i am refering to relative-dotted-pathnames and/or relative-dotted-namestrings I am referecing the following objects:
"./" ; An unresolved CL:NAMESTRING with CL:PATHNAME-DIRECTORY (:relative ".") "../" ; An unresolved CL:NAMESTRING with CL:PATHNAME-DIRECTORY (:relative :up) #P"./" ; An unresolved CL:PATHNAME with CL:PATHNAME-DIRECTORY (:relative ".") #P"../" ; An unresolved CL:PATHNAME with CL:PATHNAME-DIRECTORY (:relative :up)
I'm having trouble following your argument since for me:
(equal (osicat:list-directory ".") (osicat:list-directory "./")) => T
Yes, it does for me too.
Can you acknowledge if on your SBCL system(s) the pathnames returned of the above OSICAT:LIST-DIRECTORY forms are truncated relatively?
Can you acknowledge if on your SBCL system(s) when given a dotted-namestring as argument to OSICAT:LIST-DIRECTORY the return value is a list of pathnames with the directory component forms are truncated as relative pathnames for the pathnames contained of such lists?
And if so, can you acknowledge whether you understand that the truncation as relative pathnames is part of what I'm finding problematic?
And if so, can you acknowledge whether you understand that I am asserting that there is a problem b/c SBCL does not consider dotted-pathnames without trailing #/ (solidus) to be representative of a CL:PATHNAME-DIRECTORY? IOW can you acknowledge that SBCL does not consider dotted-namestring/dotted-pathnames to be CL:EQUAL with a dotted-namestring/dotted-pathnames with a trailing #/ (solidus):
CL-USER> (equal (pathname-directory #P".") (pathname-directory #P"./")) ;=> NIL
CL-USER> (equal (pathname-directory (truename #P".")) (pathname-directory (truename #P"./"))) ;=> T
CL-USER> (equal (pathname-directory #P"..") (pathname-directory #P"../")) ;=> NIL
CL-USER> (equal (pathname-directory (truename #P"..")) (pathname-directory (truename #P"../"))) ;=> T
Again, I would prefer that (osicat:list-directory ".") not return a value that is CL:EQUAL (osicat:absolute-pathname "./").
My rationale for this preference is predicated on the return value of the following forms, which on my current SBCL these are not CL:EQUAL:
CL-USER> (equal (osicat:absolute-pathname #P".") (osicat:absolute-pathname #P"./")) ;=> NIL
CL-USER> (equal (osicat:absolute-pathname #P"..") (osicat:absolute-pathname #P"../")) ;=> NIL
. However, I did just discover that unexpectedly
(equal (osicat:list-directory "..") (osicat:list-directory "../")) => NIL
Yes, I think this example begins to approach the problem/issue.
but the proximate cause of this appears to be an SBCL's failure to normalize (:RELATIVE "..") to (:RELATIVE :UP), which doesn't seem right at all and violates print/read consistency requirements:
Perhaps SBCL has funky interpretation of the spec. my interpretation is certainly less qualified than yours in this regard :)
However, regardless of whether SBCLs normalization is the locus of the problem the normalization of dotted pathnames is none the less made manifest with OSICAT:ABSOLUTE-PATHNAME.
I find this problematic because OSICAT:ABSOLUTE-PATHNAME is often topmost in the call-chain of Osicat's directory walking/mapping/listing procedures.
Can you acknowledge whether on your SBCL system(s) you get similar return values for the following forms:
CL-USER> (pathname-directory #P".") ;=> NIL
CL-USER> (pathname-name #P".") ;=> "."
CL-USER> (pathname-type #P".") ;=> NIL
CL-USER> (pathname-directory #P"./") ;=> (:RELATIVE ".")
CL-USER> (pathname-name #P"./") ;=> NIL
CL-USER> (pathname-type #P"./") ;=> NIL
CL-USER> (equal (pathname-name #P".") (pathname-name #P"./")) ;=> NIL
CL-USER> (pathname-directory #P"..") ;=> NIL
CL-USER> (pathname-name #P"..") ;=> "."
CL-USER> (pathname-type #P"..") ;=> ""
CL-USER> (pathname-directory #P"../") ;=> (:RELATIVE :UP)
CL-USER> (pathname-name #P"../") ;=> NIL
CL-USER> (pathname-type #P"../") ;=> NIL
CL-USER> (equal (pathname-name #P"..") (pathname-name #P"../")) ;=> NIL
CL-USER> (equal (pathname-type #P"..") (pathname-type #P"../")) ;=> NIL
If so, can you acknowledge whether you understand that I find the following return values problematic w/r/t OSICAT:ABSOLUTE-PATHNAME b/c it resolves dotted-namestring/dotted-pathnames differently than it resolves relative-dotted-pathnames/relative-dotted-namestrings?
CL-USER> (osicat:absolute-pathname #P".") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/."
CL-USER> (pathname-name (osicat:absolute-pathname #P".")) ;=> "."
CL-USER> (pathname-type (osicat:absolute-pathname #P".")) => NIL
CL-USER> (osicat:absolute-pathname #P"./") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/./"
CL-USER> (pathname-name (osicat:absolute-pathname #P"./")) ;=> NIL
CL-USER> (pathname-type (osicat:absolute-pathname #P"./")) ;=> NIL
CL-USER> (equal (osicat:absolute-pathname #P"./") (osicat:absolute-pathname #P".")) ;=> NIL
CL-USER> (osicat:absolute-pathname #P"..") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/.."
CL-USER> (pathname-name (osicat:absolute-pathname #P"..")) ;=> "."
CL-USER> (pathname-type (osicat:absolute-pathname #P"..")) ;=> ""
CL-USER> (osicat:absolute-pathname #P"../") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/../"
CL-USER> (pathname-name (osicat:absolute-pathname #P"../")) ;=> NIL
CL-USER> (pathname-type (osicat:absolute-pathname #P"../")) ;=> NIL
CL-USER> (osicat:absolute-pathname #P"../") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/../"
CL-USER> (equal (pathname-name (osicat:absolute-pathname #P"..")) (pathname-name (osicat:absolute-pathname #P"../"))) ;=> NIL
And if so, can you acknowledge whether you understand that I find this problematic b/c where OSICAT:ABSOLUTE-PATHNAME's is top-most in a call chain if/when it resolves relative-dotted-pathnames and/or relative-dotted-namestrings differently than dotted-namestring and/or dotted-pathnames on SBCL the return value to the calling function causes unecessary inconsistencies with the Osicat directory listing/mapping/walking functions and that such inconsistencies may in turn present inconsistencies with the SBCLs interpretation of the Common Lisp "API":
Such inconsistencies can be illustrated by return value of following:
(osicat:list-directory (osicat:absolute-pathname #P"."))
(osicat:list-directory (osicat:absolute-pathname #P".."))
CL-USER> (let* ((dot-ls (osicat:list-directory (osicat:absolute-pathname #P"."))) (dot-ls-map (map 'list #'osicat:file-exists-p dot-ls))) (equal dot-ls dot-ls-map)) ;=> NIL
CL-USER> (let* ((dot-dot-ls (osicat:list-directory (osicat:absolute-pathname #P"."))) (dot-dot-ls-map (map 'list #'osicat:file-exists-p dot-dot-ls))) (equal dot-dot-ls dot-dot-ls-map)) ;=> NIL
CL-USER> (equal (directory (osicat:absolute-pathname #P".")) (directory (osicat:absolute-pathname #P"./"))) => T
CL-USER> (equal (directory (osicat:absolute-pathname #P"../")) (directory (osicat:absolute-pathname #P".."))) => T
While "./" gets (:RELATIVE ".") which seems a bit odd, it is not AFAIK strictly speaking wrong.
This seems reasonable... In any event I've incorporated a rationale into my understandting of SBCL's interpretation of the CL spec :)
What return value were you expecting, maybe Clisp's (:relative) instead?
If you're objecting to (:relative "..") I concur.
Yes. Maybe. I object to the use of (pathname-directory #P"\../")
Is there some specific reason why you prepended "\" to the relative-dotted-namestrings?
Is there some Windows specific rationale for this?
IIRC Windows should be capable of resolving #P"../"
This being said, (truename #P"\../") resolves correctly relative to *default-pathname-defaults*.
CL-USER> (truename #P"\../") ;=> #P"/home/me/long-path/here/subdir/"
Whereas IMHO this return value is (from a CL perspective) wrong:
CL-USER> (osicat:absolute-pathname #P"\../") ;=> #P"/home/me/long-path/here/subdir/sub-subdir/../"
One must then truenamize the result to get what I would consider a reasonably sane CL pathanme:
CL-USER> (truename (osicat:absolute-pathname #P"\../")) ;=> #P"/home/me/long-path/here/subdir/"
I would however acknowledge that from a posix perspective the following does appear to return sanely:
CL-USER> (let ((current (osicat:current-directory))) (unwind-protect (equal (list T T) (list (equal current
#P"/home/me/long-path/here/subdir/sub-subdir/") (equal (progn (osicat-posix:chdir (osicat:absolute-pathname #P"\../")) (osicat:current-directory)) #P"/home/me/long-path/here/subdir/"))) (osicat-posix:chdir current))) ;=> T
If you're objecting to something else, please clarify.
I hope i've clarified _something_ :)
-- /s_P\
Very sorry for needing to do this again. Where previous mail said:
,---- | Again, I would prefer that (osicat:list-directory ".") not return a | value that is CL:EQUAL (osicat:absolute-pathname "./"). `----
It should have said:
Again, I would prefer that (osicat:list-directory ".") not return a value that is CL:EQUAL (osicat:list-directory "./").
-- /s_P\
On 17 August 2011 21:00, MON KEY monkey@sandpframing.com wrote:
Again, I would prefer that (osicat:list-directory ".") not return a value that is CL:EQUAL (osicat:list-directory "./").
I honestly didn't understand /what/ you were finding objectionable before. So we're making progress here...
However, I disagree with this: treating "." and "./" identically is consistent with the way other directory name designators are dealt with, and has more to do with the CL pathname logic (and braindamage) than with POSIX.
Two questions:
1. Assuming current directory contains a single file "foo.txt", what would you like (osicat:list-directory ".") and (osicat:list-directory "./") to return?
2. What's the use-case?
Re. Osicat and POSIX:
Yep, the README is out of date. *However* Osicat is not /just/ a POSIX API. It has two layers:
* The Osicat API in package OSICAT.
* The low-level APIs: currently OSICAT-POSIX and OSICAT-MACH. In the future there will probably be OSICAT-WIN32 as well.
The Osicat API is not a POSIX API. It tries to find a place to stand among the concepts shared by modern OSes and be a nice Lispy extension to things in the standard.
Cheers,
-- Nikodemus
Crowdfunding SBCL: http://www.indiegogo.com/SBCL-Threading-Improvements-1
On Thu, Aug 18, 2011 at 2:47 AM, Nikodemus Siivola nikodemus@random-state.net wrote:
On 17 August 2011 21:00, MON KEY monkey@sandpframing.com wrote:
Again, I would prefer that (osicat:list-directory ".") not return a value that is CL:EQUAL (osicat:list-directory "./").
I honestly didn't understand /what/ you were finding objectionable before. So we're making progress here...
Great! I apologize if my previous communication was opaque.
However, I disagree with this: treating "." and "./" identically is consistent with the way other directory name designators are dealt
I'm not clear on this. What is meant by:
"is consistent with the way other directory name designators are dealt with"
Is the referenced consistency w/r/t Osicat's dealings or CL's dealings?
with, and has more to do with the CL pathname logic (and braindamage) than with POSIX.
Maybe, but these also seem braindamaged:
(osicat:absolute-pathname ".") ;=> #P"/home/bubba/quux/."
(osicat:absolute-pathname "..") ;=> #P"/home/bubba/quux/.."
Whereas the equivalent of SBCL's CL pathname logic does not:
(truename (make-pathname :directory (pathname-directory ".") :defaults *default-pathname-defaults*)) ;=> #P"/home/bubba/quux/"
(truename (make-pathname :directory '(:RELATIVE :UP) :defaults *default-pathname-defaults*)) ;=> #P"/home/bubba/"
Two questions:
- Assuming current directory contains a single file "foo.txt", what
would you like (osicat:list-directory ".") and (osicat:list-directory "./") to return?
I will answer your question with the proviso that I am currently given to believe that the return value of OSICAT:LIST-DIRECTORY is predicated upon the return value of OSICAT:ABSOLUTE-PATHNAME and that it is the nuanced manner with which OSICAT:LIST-DIRECTORY interacts with OSICAT:ABSOLUTE-PATHNAME which is objectionable:
Assuming current directory is "/home/bubba/quux/" and that the following is true:
(equal (osicat:current-directory) *default-pathname-defaults*) ;=> t
For (osicat:list-directory ".") I would like to see:
(osicat:list-directory #P".") ;=> (#P"/home/bubba/quux/foo.txt")
I find this to be more in keeping with the following equivalent invocation of COMMON-LISP:DIRECTORY, e.g.:
(directory (make-pathname :name :wild :type :wild :defaults (osicat:current-directory))) ;=> (#P"/home/bubba/quux/foo.txt")
Likewise, for (osicat:list-directory #P"./") I would like to see: (osicat:list-directory #P"./") ;=> (#P"./foo.txt")
IOW, when the user expliclitly provides the trailing #/ (solidus) then return a list of relative pathnames, else return a list of pathnames fully resolved to current directory.
- What's the use-case?
To have surety that Osicat resolves the pathname designator "." consistently at all levels of its API and does so in a maner most consistent with CL handling of pathnames w/ specific regards to *default-pathname-defaults*.
In my mind, if Osicat allows "." as a designator for a pathname, and if "." _always_ resolves to the directory that is current (whether value of "current directory" is OSICAT:CURRENT-DIRECTORY or *DEFAULT-PATHNAME-DEFAULTS*), then its return value should be treated equivalently to CL's *default-pathname-defaults* e.g. from the Spec for *d-p-d*:
,---- | a pathname, used as the default whenever a function needs a default | pathname and one is not supplied. `----
The general use case is therefor to have "." and ".." be fully resolved to an absolute pathname.
And more generally that "." returned as an absolute pathname in the same manner as getcwd(3).
The Osicat API is not a POSIX API. It tries to find a place to stand among the concepts shared by modern OSes and be a nice Lispy extension to things in the standard.
Which standard, POSIX or ANSI-CL?
Thanks again for taking the time to answer my questions.
On 22 August 2011 01:44, MON KEY monkey@sandpframing.com wrote:
Maybe, but these also seem braindamaged:
(osicat:absolute-pathname ".") ;=> #P"/home/bubba/quux/."
(osicat:absolute-pathname "..") ;=> #P"/home/bubba/quux/.."
I think I agree. I'll need to think on this -- and the split in responsibility between the host lisp and CL some more, though.
- Assuming current directory contains a single file "foo.txt", what
would you like (osicat:list-directory ".") and (osicat:list-directory "./") to return?
I will answer your question with the proviso that I am currently given to believe that the return value of OSICAT:LIST-DIRECTORY is predicated upon the return value of OSICAT:ABSOLUTE-PATHNAME and that it is the nuanced manner with which OSICAT:LIST-DIRECTORY interacts with OSICAT:ABSOLUTE-PATHNAME which is objectionable:
No, please. Don't assume that. See the docstring:
Returns a fresh list of pathnames corresponding to all files within the directory named by the non-wild pathname designator PATHSPEC. If BARE-PATHNAMES is non-NIL only the files's bare pathnames are returned (with an empty directory component), otherwise the files' pathnames are merged with PATHSPEC.
Nothing about ABSOLUTE-PATHNAME there.
Assuming current directory is "/home/bubba/quux/" and that the following is true:
(equal (osicat:current-directory) *default-pathname-defaults*) ;=> t
For (osicat:list-directory ".") I would like to see:
(osicat:list-directory #P".") ;=> (#P"/home/bubba/quux/foo.txt")
This is not an unreasonable thing to want, but wrong for "." given LIST-DIRECTORY's contract.
One of the key features of LIST-DIRECTORY is that if you feed it a relative pathname, you get a list of relative pathnames back.
Changing that as a default is not acceptable.
You have to remember that we're talking about _lisp_ pathnames and namestrings here, not POSIX ones -- so meaning of "." is implementation dependent to a frightening degree.
/Practically/ at the end of the day, it mostly means same as POSIX . but before the final syscall is done implementations are allowed to parse the namestring "." in myriad different ways, as long as it unparses back to the same string.
It might be reasonable for ABSOLUTE-PATHNAME to treat "." and ".." specially. Not sure -- but I'm quite hesitant to do that and rather leave the details to implementation's MERGE-PATHNAMES logic.
(In case of SBCL, I think it should treat those a bit more specially than it does right now.)
To get what you want, you should do:
(osicat:list-directory (osicat:absolute-pathname *default-pathname-defaults*))
or -- somewhat less portable, but shorter:
(osicat:list-directory (osicat:absolute-pathname ""))
To have surety that Osicat resolves the pathname designator "." consistently at all levels of its API and does so in a maner most consistent with CL handling of pathnames w/ specific regards to *default-pathname-defaults*.
No such guarantee, sorry.
What's portable about LIST-DIRECTORY is the way it gets the contents of a directory: different implementations are annoyingly different when it comes to constructing a wild pathname for DIRECTORY that gets all files and subdirectories. With LIST-DIRECTORY you know what you get, everywhere.
What's unportable about LIST-DIRECTORY is the canonicalization done by MERGE-PATHNAMES of the host Lisp.
The Osicat API is not a POSIX API. It tries to find a place to stand among the concepts shared by modern OSes and be a nice Lispy extension to things in the standard.
Which standard, POSIX or ANSI-CL?
ANSI CL.
Cheers,
-- Nikodemus
On Fri, 2011-08-12 at 15:36 -0400, MON KEY wrote:
I initially neglected to send this register an account w/ osicat-devel and mailed the following exchange to Nikodemus directly with the subject line: "osicat:list-directory vs. cl-fad:list-directory"
No doubt Nikodemus has plenty on his plate right now as it is and needn't be solely responsible for fielding this verobisty :)
I should have taken the time to register an osicat-devel account. Having done so I am now forwarding a transcript of my previous exchange.
On 12 August 2011 19:46, MON KEY wrote: I noticed today that on SBCL these return differently:
(cl-fad:list-directory ".") (osicat:list-directory ".") (cl-fad:list-directory "..") (osicat:list-directory "..")
Assuming this is a bug, then i'm pretty sure its origin is around the reliance on osicat:with-directory-iterator.
This is the intended behavior, not a bug
[...]
When a namestring is given as a dotted-namestring and a trailing #/ (solidus) is _not_ present, I would expect Osicat to resolve dotted-namestrings their cl:truename before executing the inspection PATHSPEC in the iterations.
When a namestring is given as a dotted-namestring and a trailing #/ (solidus) _is_ present I would expect Osicat to _not_ resolve the dotted-namestrings.
[...]
Disregarding the following assertion from the README of Quicklisp's dist of Osicat as to the extent of its Posixness:
,---- | | Osicat is a lightweight operating system interface for Common Lisp | on Unix-platforms. It is not a POSIX-style API, but rather a simple | lispy accompaniment to the standard ANSI facilities. | `---- :SOURE osicat-20110619-git/README
The README will probably need to be corrected, then
It may be worth considering osicats behaviour w/r/t following from POSIX.1-2008 apropos dotted namestrings:
,---- | | 4.12 Pathname Resolution | {...} | | The special filename dot shall refer to the directory specified by | its predecessor. The special filename dot-dot shall refer to the | parent directory of its predecessor directory. As a special case, in | the root directory, dot-dot may refer to the root directory itself. | | The Open Group Base Specifications Issue 7 IEEE Std 1003.1-2008 | `---- :SOURCE (URL `http://pubs.opengroup.org/onlinepubs/9699919799/')
Following may also be applicable: (URL `http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#dot')
As mentioned on #lisp, I'm not interested in advocating that Osicat be changed if it isn't broken.
The reliable portablility offered by Osicat underscores my interest in it and I am currently in the process of converting the CL-FAD and SBCL specific routines use in my code to use Osicat instead :) As such, my concern/curiousity is to learn the rationale for its implementation so as to avoid unnecessary future surprises.
AFAICT Osicat absolute-pathname treats the dotted namestring as pathname-name whereas these: (osicat:file-kind "..") (osicat:file-kind ".") consider them to be pathname-directory.
POSIX file-systems have no notion of name and type, and syntax-wise a file and a directory are the same, so ".." is the same thing as "../"
On Sat, Aug 13, 2011 at 12:38 PM, Stelian Ionescu sionescu@cddr.org wrote:
The README will probably need to be corrected, then
So, are you suggestiong that osicat is intended as POSIX-style API?
POSIX file-systems have no notion of name and type, and syntax-wise a file and a directory are the same, so ".." is the same thing as "../"
Permit me to disagree.
By all means feel free to ignore my objections to Osicat's behaviour around a corner case in differences between CL pathnames and POSIX. However, please have the courtesy to at least consider that my citation of section 4.12 IEEE Std 1003.1-2008 was not without reason and was in fact an attempt to illustrate reasonably that POSIX 2008 _does_ have some fairly clear stipulations about the syntax for pathnames around a file and a directory not always being the same.
POSIX prescribes certain syntax as denoting a "special filename":
"." (dot) ".." (dot-dot) "/" (<slash>) "//" (<slash> <slash>) "///*" (<slash> <slash> <slash>*)
FFR following are what i believe to be relevant sections of POSIX-2008:
,---- | 3.266 Pathname | | A character string that is used to identify a file. In the context of | POSIX.1-2008, a pathname may be limited to {PATH_MAX} bytes, including | the terminating null byte. It has an optional beginning <slash>, | followed by zero or more filenames separated by <slash> characters. A | pathname may optionally contain one or more trailing <slash> | characters. Multiple successive <slash> characters are considered to | be the same as one <slash>, except for the case of exactly two leading | <slash> characters. | | Note: | Pathname Resolution is defined in detail in Pathname Resolution . | | { ... elided ... } | | 3.268 Path Prefix | | The part of a pathname up to, but not including, the last component | and any trailing <slash> characters, unless the pathname consists | entirely of <slash> characters, in which case the path prefix is '/' | for a pathname containing either a single <slash> or three or more | <slash> characters, and '//' for the pathname //. The path prefix of a | pathname containing no <slash> characters is empty, but is treated as | referring to the current working directory. | | Note: The term is used both in the sense of identifying part of a | pathname that forms the prefix and of joining a non-empty path | prefix to a filename to form a pathname. In the latter case, the | path prefix need not have a trailing <slash> (in which case the | joining is done with a <slash> character). `----
,---- | | 4.12 Pathname Resolution | {...} | | The special filename dot shall refer to the directory specified by | its predecessor. The special filename dot-dot shall refer to the | parent directory of its predecessor directory. As a special case, in | the root directory, dot-dot may refer to the root directory itself. | | The Open Group Base Specifications Issue 7 IEEE Std 1003.1-2008 | `---- :SOURCE (URL `http://pubs.opengroup.org/onlinepubs/9699919799/')
-- /s_P\
On Wed, 2011-08-17 at 14:39 -0400, MON KEY wrote:
On Sat, Aug 13, 2011 at 12:38 PM, Stelian Ionescu sionescu@cddr.org wrote:
The README will probably need to be corrected, then
So, are you suggestiong that osicat is intended as POSIX-style API?
That's how I see it
POSIX file-systems have no notion of name and type, and syntax-wise a file and a directory are the same, so ".." is the same thing as "../"
Permit me to disagree.
By all means feel free to ignore my objections to Osicat's behaviour around a corner case in differences between CL pathnames and POSIX. However, please have the courtesy to at least consider that my citation of section 4.12 IEEE Std 1003.1-2008 was not without reason and was in fact an attempt to illustrate reasonably that POSIX 2008 _does_ have some fairly clear stipulations about the syntax for pathnames around a file and a directory not always being the same.
POSIX prescribes certain syntax as denoting a "special filename":
"." (dot) ".." (dot-dot) "/" (<slash>) "//" (<slash> <slash>) "///*" (<slash> <slash> <slash>*)
POSIX says that 3 or more "/" are to be normalized to a single one
FFR following are what i believe to be relevant sections of POSIX-2008:
[...]
I read all that but I still don't understand your point