diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2024-04-15 15:47:59 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2024-04-15 15:47:59 +0000 |
commit | 1d90ac41252b2d73e048a1fc0b11b5ac2aa78cf3 (patch) | |
tree | 353ea9246e72e8a2c0980fe237523f5237afe978 /lib/libc | |
parent | 3b9c76ef0bfa2d6ed3e2da376697e789a14e3c71 (diff) |
Add scandirat(3); from freebsd
To be used in httpd(8) shortly to prevent toctu issues.
This makes __fdopendir internally accessible to avoid unnecessary
syscalls in scandirat(3). Suggested & diff by guenther
suggested by & OK millert
tweak & OK guenther
OK tb, jca
This rides the libc crank.
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/Symbols.list | 1 | ||||
-rw-r--r-- | lib/libc/gen/opendir.c | 5 | ||||
-rw-r--r-- | lib/libc/gen/scandir.3 | 37 | ||||
-rw-r--r-- | lib/libc/gen/scandir.c | 43 | ||||
-rw-r--r-- | lib/libc/hidden/dirent.h | 7 |
5 files changed, 81 insertions, 12 deletions
diff --git a/lib/libc/Symbols.list b/lib/libc/Symbols.list index 251760f812e..b1e7e916bbc 100644 --- a/lib/libc/Symbols.list +++ b/lib/libc/Symbols.list @@ -750,6 +750,7 @@ readdir_r readpassphrase rewinddir scandir +scandirat seekdir setclasscontext setdomainname diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index 71d30da9386..ef198924efb 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: opendir.c,v 1.30 2016/09/21 04:38:56 guenther Exp $ */ +/* $OpenBSD: opendir.c,v 1.31 2024/04/15 15:47:58 florian Exp $ */ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -39,7 +39,6 @@ #include "telldir.h" -static DIR *__fdopendir(int fd); /* * Open a directory specified by name. @@ -89,7 +88,7 @@ fdopendir(int fd) } DEF_WEAK(fdopendir); -static DIR * +DIR * __fdopendir(int fd) { DIR *dirp; diff --git a/lib/libc/gen/scandir.3 b/lib/libc/gen/scandir.3 index 50033134303..fda3a82f702 100644 --- a/lib/libc/gen/scandir.3 +++ b/lib/libc/gen/scandir.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: scandir.3,v 1.16 2021/06/17 18:18:15 jmc Exp $ +.\" $OpenBSD: scandir.3,v 1.17 2024/04/15 15:47:58 florian Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -27,11 +27,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: June 17 2021 $ +.Dd $Mdocdate: April 15 2024 $ .Dt SCANDIR 3 .Os .Sh NAME .Nm scandir , +.Nm scandirat , .Nm alphasort .Nd scan a directory .Sh SYNOPSIS @@ -45,6 +46,14 @@ .Fa "int (*compar)(const struct dirent **, const struct dirent **)" .Fc .Ft int +.Fo scandirat +.Fa "int dirfd" +.Fa "const char *dirname" +.Fa "struct dirent ***namelist" +.Fa "int (*select)(const struct dirent *)" +.Fa "int (*compar)(const struct dirent **, const struct dirent **)" +.Fc +.Ft int .Fn alphasort "const struct dirent **d1" "const struct dirent **d2" .Sh DESCRIPTION The @@ -91,6 +100,30 @@ parameter to sort the array alphabetically. The memory allocated for the array can be deallocated with .Xr free 3 , by freeing each pointer in the array and then the array itself. +.Pp +The +.Fn scandirat +function is similar to +.Fn scandir , +but takes an additional +.Fa dirfd +argument. +If +.Fa dirname +is relative, +.Fa dirfd +must be a valid file descriptor referencing a directory, in which case the +.Fa dirname +lookup is performed relative to the directory referenced by +.Fa dirfd . +If +.Fa dirfd +has the special value +.Va AT_FDCWD , +then the current process directory is used as the base for relative lookups. +See +.Xr openat 2 +for additional details. .Sh DIAGNOSTICS Returns \-1 if the directory cannot be opened for reading or if .Xr malloc 3 diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c index f767ca503fa..5d62fb7a089 100644 --- a/lib/libc/gen/scandir.c +++ b/lib/libc/gen/scandir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scandir.c,v 1.22 2024/04/14 11:21:08 florian Exp $ */ +/* $OpenBSD: scandir.c,v 1.23 2024/04/15 15:47:58 florian Exp $ */ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. @@ -39,9 +39,11 @@ #include <sys/stat.h> #include <dirent.h> #include <errno.h> +#include <fcntl.h> #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "telldir.h" #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) @@ -57,8 +59,8 @@ ((sizeof(struct dirent) - sizeof(dp)->d_name) + \ (((dp)->d_namlen + 1 + 3) &~ 3)) -int -scandir(const char *dirname, struct dirent ***namelist, +static int +scandir_dirp(DIR *dirp, struct dirent ***namelist, int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **, const struct dirent **)) { @@ -66,10 +68,7 @@ scandir(const char *dirname, struct dirent ***namelist, size_t nitems = 0; struct stat stb; long arraysz; - DIR *dirp; - if ((dirp = opendir(dirname)) == NULL) - return (-1); if (fstat(dirp->dd_fd, &stb) == -1) goto fail; @@ -140,6 +139,38 @@ fail: return (-1); } +int +scandir(const char *dirname, struct dirent ***namelist, + int (*select)(const struct dirent *), + int (*dcomp)(const struct dirent **, const struct dirent **)) +{ + DIR *dirp; + + if ((dirp = opendir(dirname)) == NULL) + return (-1); + + return (scandir_dirp(dirp, namelist, select, dcomp)); +} + +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 = HIDDEN(openat)(dirfd, dirname, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + if (fd == -1) + return (-1); + dirp = __fdopendir(fd); + if (dirp == NULL) { + HIDDEN(close)(fd); + return (-1); + } + return (scandir_dirp(dirp, namelist, select, dcomp)); +} + /* * Alphabetic order comparison routine for those who want it. */ diff --git a/lib/libc/hidden/dirent.h b/lib/libc/hidden/dirent.h index 1e8398291c8..e683252e016 100644 --- a/lib/libc/hidden/dirent.h +++ b/lib/libc/hidden/dirent.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dirent.h,v 1.1 2015/09/12 13:34:22 guenther Exp $ */ +/* $OpenBSD: dirent.h,v 1.2 2024/04/15 15:47:58 florian Exp $ */ /* * Copyright (c) 2015 Philip Guenther <guenther@openbsd.org> * @@ -20,6 +20,10 @@ #include_next <dirent.h> +__BEGIN_HIDDEN_DECLS +DIR *__fdopendir(int fd); +__END_HIDDEN_DECLS + PROTO_DEPRECATED(alphasort); PROTO_NORMAL(closedir); PROTO_NORMAL(dirfd); @@ -30,6 +34,7 @@ PROTO_NORMAL(readdir); PROTO_DEPRECATED(readdir_r); PROTO_DEPRECATED(rewinddir); PROTO_DEPRECATED(scandir); +PROTO_DEPRECATED(scandirat); PROTO_NORMAL(seekdir); PROTO_NORMAL(telldir); |