Subject: bug#34860: Probing broken symlinks always involves errors

From: Mark H Weaver <[email-masked]>
Date: Wed, 10 Apr 2019 15:22:49 -0400

Hi Tim,

Tim Gesthuizen <[email-masked]> writes:

> I wrote a little application that tries to probe whether a symlink
> exists. The `stat` function has an undocumented optional parameter that
> lets stat return #f when the file does not exist. With this argument one
> can probe for any files excluding broken symlinks.
> lstat does not offer this argument. Therefore I needed to use
> guard-expressions around lstat to probe for broken symlinks.
>
> So probing broken symlinks relies on errors in the control flow and is
> not straight forward.

I would suggest using 'false-if-exception', which is documented in the
manual:

  (false-if-exception (lstat file-name))

That seems fairly straightforward and readable, no?

I'm not sure that errors in the control flow is necessarily something
that we need to avoid in cases like this.  It's true that there's some
minor expense involved in handling the exception, but I suspect it's
lost in the noise compared with the expense of the 'lstat' system call
itself.

Do you see a practical problem with this approach?

> Maybe we should add the optional argument that `stat` has and document
> the arguments for both commands.

I'm not strongly opposed to the idea, but it raises the question of what
to do with the corresponding C API function 'scm_lstat'.  We certainly
can't change the number of arguments to 'scm_lstat' in the 2.2.x series,
because that would break ABI compatibility.  We could change it in the
next release series, but that would require source-level changes in any
code that uses 'scm_lstat'.

Alternatively, we could keep 'scm_lstat' unchanged, and add a new
internal C function with the optional argument, bound to Scheme 'lstat'.

Anyway, I'm inclined to simply suggest using 'false-if-exception'.

What do you think?

Regardless, thanks for bringing my attention to the fact that 'scm_stat'
is incorrectly documented in the manual.  It asserts that there's only
one argument to that function, but in fact there are now two.  That's
definitely a bug.

     Regards,
       Mark