git: 5074d5c9845e - main - libc: Improve POSIX conformance of dirfd()

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Mon, 02 Feb 2026 15:51:53 UTC
The branch main has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=5074d5c9845e142883cdbb9ad212be66e57615d0

commit 5074d5c9845e142883cdbb9ad212be66e57615d0
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2026-02-02 15:46:57 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-02-02 15:46:57 +0000

    libc: Improve POSIX conformance of dirfd()
    
    POSIX states that dirfd() should set errno to EINVAL and return -1 if
    dirp does not refer to a valid directory stream.  Our interpretation is
    that this applies if dirp is null or the file descriptor associated
    with it is negative.
    
    MFC after:      1 week
    Sponsored by:   Klara, Inc.
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D55025
---
 lib/libc/gen/directory.3 | 14 +++++++++++++-
 lib/libc/gen/dirfd.c     |  5 +++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/lib/libc/gen/directory.3 b/lib/libc/gen/directory.3
index ccbc60b03776..270abb2d2371 100644
--- a/lib/libc/gen/directory.3
+++ b/lib/libc/gen/directory.3
@@ -256,7 +256,9 @@ The
 function returns 0 on success and -1 on failure.
 The
 .Fn fdclosedir
-function returns an open file descriptor on success and -1 on failure.
+and
+.Fn dirfd
+functions return an open file descriptor on success and -1 on failure.
 .Sh ERRORS
 The
 .Fn opendir
@@ -327,6 +329,16 @@ function may also fail and set
 .Va errno
 for any of the errors specified for the routine
 .Xr close 2 .
+.Pp
+The
+.Fn dirfd
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa dirp
+argument does not refer to a valid directory stream.
+.El
 .Sh SEE ALSO
 .Xr close 2 ,
 .Xr lseek 2 ,
diff --git a/lib/libc/gen/dirfd.c b/lib/libc/gen/dirfd.c
index ba8f52845b4e..fbbf703b5a2e 100644
--- a/lib/libc/gen/dirfd.c
+++ b/lib/libc/gen/dirfd.c
@@ -28,6 +28,7 @@
 
 #include "namespace.h"
 #include <dirent.h>
+#include <errno.h>
 #include "un-namespace.h"
 
 #include "gen-private.h"
@@ -35,5 +36,9 @@
 int
 dirfd(DIR *dirp)
 {
+	if (dirp == NULL || _dirfd(dirp) < 0) {
+		errno = EINVAL;
+		return (-1);
+	}
 	return (_dirfd(dirp));
 }