Hi Bruno,
On 5/18/24 3:42 AM, Bruno Haible wrote:
> An interesting approach. But I think this added code comes too early:
> In case of oldfd == newfd && newfd < 0, it would fail with EINVAL instead
> of EBADF.
>
> How about trying the system call first, and test for newfd == oldfd only if
> that system call succeeds?
Ah, I think you are right. The ordering is important. It looks like
FreeBSD and OpenBSD behave as expected [1] [2]. Therefore I think it
is best to #ifdef it for NetBSD. No need to perform the check elsewhere.
How does this look? Passes tests on NetBSD 10.00.
$ git diff .
diff --git a/lib/dup3.c b/lib/dup3.c
index a810d3be19..8c4e983df1 100644
--- a/lib/dup3.c
+++ b/lib/dup3.c
@@ -45,6 +45,15 @@ dup3 (int oldfd, int newfd, int flags)
if (!(result < 0 && errno == ENOSYS))
{
have_dup3_really = 1;
+ /* On NetBSD dup3 is a no-op when oldfd == newfd, but we expect
+ an error with errno == EINVAL. */
+# ifdef __NetBSD__
+ if (newfd == oldfd)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+# endif
# if REPLACE_FCHDIR
if (0 <= result)
result = _gl_register_dup (oldfd, newfd);
Should I report this to the NetBSD people? I guess it isn't
standardized so they are free to do as they wish. But it seems strange
to behave differently then everyone else...
Collin
[1] https://man.freebsd.org/cgi/man.cgi?query=dup3&sektion=3
[2] https://man.openbsd.org/dup.2