Re: Directory listings, continued
Lassi Kortela 11 Dec 2019 10:58 UTC
>> I like directory-files because it's the dead simple API: directory
>> path in, list of entries out (dot-files optional). It is of course
>> redundant with the generator interface, and would not be the end of
>> the world to omit.
We all like it, but it's up for debate where it should go. IMHO
higher-level niceties such as glob, directory-files and various
shell-like procedures (pwd/cd/ls/cp/mv) would go better in a separate
SRFI or other library. Then the current SRFI would have the essential
stuff that's hard to implement due to being OS/FFI-dependent. Stuff
that's simple to implement using portable building blocks from this SRFI
I would classify as higher-level abstractions.
>> For example, use cases which don't require reading the entire
>> directory: maybe you need to check for a few files and can stop
>> after you find them, or only need to confirm it has at least N
>> files. close-directory only happens when the generator is exhausted,
>> or, if you get the underpinnings correct, upon it getting gc-ed.
You are absolutely right. We shouldn't force users to read the entire
directory in order to close it. This is a winning argument in my book as
well.
> Glad to hear that. There's a stronger argument for
> open-/read-/close-directory, on Linux and OpenBSD (only ones I checked),
> they're library, not system calls. Looking at the glibc code, it really
> and truly opens the directory as a file, and reads dirent structures
On the syscall level, opendir() and closedir() are always just open()
and close() AFAIK. readdir() is getdirentries(), getdents() or
equivalent - each call reads an array of directory entries which are
internally buffered by libc and returned one by one via readdir().
Implementations such as Loko Scheme may want to skip the libc buffering
and call getdents() directly, doing their own buffering in Scheme.
Our current API does not expose the file descriptor from open-directory
to the user of the SRFI.
Note that the WinAPI directory listing function, FindFirstFile(),
returns a search HANDLE whereas OpenFile() returns a HFILE.
> bit indirectly, which I've not drilling down to, bit suspicious given
> all the filesystems Linux supports). So failure to exhaust the
> generator would add to your limited count of open file descriptors ...
Also right. Some systems (at least OpenBSD) have had a tight default
value on the limit of open fd's. Their Go port had to adjust something a
while back (either on Go's end or OpenBSD's) since Go was too
freewheeling about opening and GC'ing file descriptors.
> (define (directory-fold dir kons knil . o)
> (let-optionals o ((dot-files? #f))
> (let ((do (open-directory dir dot-files?)))
> (let lp ((res knil))
> (let ((file (read-directory do)))
> (if (not (eof-object? file))
> (lp (kons file res))
> (begin (close-directory do) res)))))))
>
> Which is called with (directory-fold dir cons '() dot-files?). I have
> no informed opinion on whether it should be added to the API.
Since you gave very good arguments for exposing an open/read/close API,
a fold would just be this thin wrapper around it. IMHO we don't need to
have both APIs. (directory-fold ...) looks like it would be neat to
implement in terms of a general (resource-fold open read close ...).