Re: git: d549de769055 - main - libc: Remove readdir_r(3) [This broke building rust 1.88]

From: Olivier Certner <olce_at_freebsd.org>
Date: Fri, 12 Sep 2025 13:23:01 UTC
> readdir_r() should never have existed.

Sure, but it exists.
 
> (snip)
>   but usually the size of the buffer is well-defined.  That is not the
>   case for readdir_r().  Callers have to check in advance by calling
>   pathconf() or fpathconf() not just once at startup but _for every
>   directory they open_.

The size of the buffer is actually well-defined (on systems where {NAME_MAX} is not indeterminate, that is), but it is indeed not static.  That's cumbersome, but also has been documented from the start, in the standard and in our manual page at least.  Though I would bet that most programs calling it do not do the proper dance.  You certainly have a point here.

> * Because unionfs exists, it is possible for pathconf() to return the
>   wrong value.  If you union-mount a directory with a small _PC_NAME_MAX
>   on top of a directory with a large _PC_NAME_MAX, fpathconf() will
>   return the smaller of the two values.  If you size your buffer
>   accordingly and the lower directory has children with long names, you
>   will suffer a buffer overrun.

Yes, that's a fundamental problem for a flexible unionfs where the upper and lower layers can be changed underneath the union view.  But we have a workaround here: Simply return NAME_MAX.  We could as well just decide that we will cap _PC_NAME_MAX by that of the upper layer (which implies creating directories there, which our unionfs currently always does, but may not necessarily in the future).
 
> * People have gotten used to reflexively choosing foo_r() over foo()
>   when both exist.  In most cases that is the correct choice, but in
>   this particular case readdir() is almost always completely safe to use
>   (the only exception is if you have multiple threads calling readdir()
>   with the same DIR *, which is a bad idea and easily avoided).  It is
>   also faster than readdir_r().

I completely agree, but see these more as points to actually obsolete readdir_r(), as POSIX just did (and we did long ago).  We'll eventually remove it anyway.

> * The fact that Rust uses readdir_r() on FreeBSD is evidence that it
>   needs to die.  (...)

It's strange and a bit sad they were not up to their task on this.

>   Rust is (hopefully) going to get fixed now, but
>   the only way to avoid a repeat performance is to drop readdir_r().

Now that readdir_r() is "officially" obsolete, we can hope that this time people will actually comply by themselves or when we poke them to.  Hopefully, we'll be able to remove readdir_r() in 16.

-- 
Olivier Certner