git: 9fb8e8eede5b - main - libc: add scandirat(3)

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Wed, 24 Aug 2022 19:44:07 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=9fb8e8eede5b48eda7dc39f61d815595c14e5752

commit 9fb8e8eede5b48eda7dc39f61d815595c14e5752
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-08-23 03:30:06 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-08-24 19:26:00 +0000

    libc: add scandirat(3)
    
    Reviewed by:    emaste, imp, kevans, markj, Aymeric Wibo <obiwac@gmail.com>
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D36301
---
 include/dirent.h        |  5 +++++
 lib/libc/gen/Symbol.map |  1 +
 lib/libc/gen/scandir.c  | 21 +++++++++++++++++++++
 3 files changed, 27 insertions(+)

diff --git a/include/dirent.h b/include/dirent.h
index 702153e28fc0..047206258471 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -131,6 +131,11 @@ int	 scandir_b(const char *, struct dirent ***,
 	    int (^)(const struct dirent **, const struct dirent **));
 #endif
 #endif
+#if __BSD_VISIBLE
+int	 scandirat(int, const char *, struct dirent ***,
+	    int (*)(const struct dirent *), int (*)(const struct dirent **,
+	    const struct dirent **));
+#endif
 #if __XSI_VISIBLE
 void	 seekdir(DIR *, long);
 long	 telldir(DIR *);
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 012c9ff11f04..74676ffe2270 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -439,6 +439,7 @@ FBSD_1.7 {
 	 posix_spawn_file_actions_addchdir_np;
 	 posix_spawn_file_actions_addclosefrom_np;
 	 posix_spawn_file_actions_addfchdir_np;
+	 scandirat;
 	 sched_getaffinity;
 	 sched_setaffinity;
 	 sched_getcpu;
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
index 4cfc823e4f94..3a891b0ad3f2 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -42,8 +42,10 @@ __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <dirent.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include "un-namespace.h"
 
 #ifdef	I_AM_SCANDIR_B
@@ -159,6 +161,25 @@ scandir(const char *dirname, struct dirent ***namelist,
 }
 
 #ifndef I_AM_SCANDIR_B
+int
+scandirat(int dirfd, const char *dirname, struct dirent ***namelist,
+    int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **,
+    const struct dirent **))
+{
+	DIR *dirp;
+	int fd;
+
+	fd = _openat(dirfd, dirname, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+	if (fd == -1)
+		return (-1);
+	dirp = fdopendir(fd);
+	if (dirp == NULL) {
+		_close(fd);
+		return (-1);
+	}
+	return (scandir_dirp(dirp, namelist, select, dcomp));
+}
+
 /*
  * Alphabetic order comparison routine for those who want it.
  * POSIX 2008 requires that alphasort() uses strcoll().