Re: override? argument in create-directory etc.
Lassi Kortela 22 Apr 2020 21:28 UTC
> ensure-directory-exists is different, because it can return successfully
> when mkdir() call fails
> with EEXIST and the existing object is a directory. In the current spec
> of srfi-170, create-directory
> removes the existing one.
I guess you're right. unlink() followed by mkdir() has a potential race
condition that a mere mkdir() avoids. Needlessly remaking the directory
could also change the permission bits of the mode (and other nonstandard
stuff like ACLs and MacOS attributes).
> And a trivial implementation like following is not correct:
>
> (define (create-directory path perm override?) ; omit optional
> argument handling
> (when override?
> (delete-filesystem-object-if-exists path))
> (mkdir path perm))
>
> Since it can still fail with EEXISTS if another process may create an
> object between delete-filesystem-object-if-exists
> and mkdir. (I just recently fixed a bug of the same nature that
> occurred in parallel build process.)
True. It would seem like a hack to silence an error from `mkdir` in that
implementation.
> If we want ensure-* functionality, which seems to be more useful in
> practice, I'd suggest the optional argument
> to be a flag of "if the desired type of filesystem object
> already exists, then just change the mode and return".
I don't know of any other language with this kind of override flag in
the API. Does the flag come from scsh, and is there a particular
rationale for having it?
Usually when we want to overwrite a file, we just give the truncate flag
to open(). That will fail if the existing file system object is not a
regular file, which is the right thing IMHO.
When we want to "overwrite" a directory, we use ensure-directory-exists
which is quite popular in other languages.
BTW my proposed `ensure-directory-exists` was wrong - it should create
parent directories too if they don't exist. A version that creates only
the deepest-level directory is not that useful and is a bit confusing.