diff options
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/gen/Symbol.map | 3 | ||||
-rw-r--r-- | lib/libc/gen/elf_utils.c | 26 | ||||
-rw-r--r-- | lib/libc/gen/err.c | 51 | ||||
-rw-r--r-- | lib/libc/gen/fdopendir.c | 7 | ||||
-rw-r--r-- | lib/libc/gen/fts.3 | 2 | ||||
-rw-r--r-- | lib/libc/gen/gen-private.h | 4 | ||||
-rw-r--r-- | lib/libc/gen/libc_interposing_table.c | 1 | ||||
-rw-r--r-- | lib/libc/gen/opendir.c | 7 | ||||
-rw-r--r-- | lib/libc/gen/opendir2.c | 15 | ||||
-rw-r--r-- | lib/libc/gen/readdir.c | 11 | ||||
-rw-r--r-- | lib/libc/gen/scandir.c | 6 | ||||
-rw-r--r-- | lib/libc/gen/telldir.c | 4 | ||||
-rw-r--r-- | lib/libc/gen/telldir.h | 6 | ||||
-rw-r--r-- | lib/libc/gen/uexterr_format.c | 14 | ||||
-rw-r--r-- | lib/libc/gen/wordexp.c | 10 | ||||
-rw-r--r-- | lib/libc/include/libc_private.h | 4 | ||||
-rw-r--r-- | lib/libc/stdio/mktemp.3 | 7 | ||||
-rw-r--r-- | lib/libc/stdio/mktemp.c | 2 | ||||
-rw-r--r-- | lib/libc/tests/gen/Makefile | 1 | ||||
-rw-r--r-- | lib/libc/tests/gen/opendir_test.c | 145 | ||||
-rw-r--r-- | lib/libc/tests/gen/scandir_test.c | 12 | ||||
-rw-r--r-- | lib/libc/tests/gen/wordexp_test.c | 26 |
22 files changed, 265 insertions, 99 deletions
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 50dbf3425964..26f638568efc 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -458,8 +458,6 @@ FBSD_1.8 { aio_read2; aio_write2; execvpe; - fscandir; - fscandir_b; fdscandir; fdscandir_b; fts_open_b; @@ -598,7 +596,6 @@ FBSDprivate_1.0 { __libc_tcdrain; - __pthread_distribute_static_tls; __pthread_map_stacks_exec; __fillcontextx; __fillcontextx2; diff --git a/lib/libc/gen/elf_utils.c b/lib/libc/gen/elf_utils.c index 330aa8f17f7e..3714a0dc42b5 100644 --- a/lib/libc/gen/elf_utils.c +++ b/lib/libc/gen/elf_utils.c @@ -41,7 +41,6 @@ #include "libc_private.h" void __pthread_map_stacks_exec(void); -void __pthread_distribute_static_tls(size_t, void *, size_t, size_t); int __elf_phdr_match_addr(struct dl_phdr_info *phdr_info, void *addr) @@ -105,28 +104,3 @@ __pthread_map_stacks_exec(void) ((void (*)(void))__libc_interposing[INTERPOS_map_stacks_exec])(); } - -void -__libc_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - char *tlsbase; - -#ifdef TLS_VARIANT_I - tlsbase = (char *)_tcb_get() + offset; -#else - tlsbase = (char *)_tcb_get() - offset; -#endif - memcpy(tlsbase, src, len); - memset(tlsbase + len, 0, total_len - len); -} - -#pragma weak __pthread_distribute_static_tls -void -__pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - - ((void (*)(size_t, void *, size_t, size_t))__libc_interposing[ - INTERPOS_distribute_static_tls])(offset, src, len, total_len); -} diff --git a/lib/libc/gen/err.c b/lib/libc/gen/err.c index 24ea242560b8..16cbe27693e7 100644 --- a/lib/libc/gen/err.c +++ b/lib/libc/gen/err.c @@ -30,9 +30,12 @@ */ #include "namespace.h" +#include <sys/exterrvar.h> #include <err.h> #include <errno.h> +#include <exterr.h> #include <stdarg.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,6 +46,11 @@ static FILE *err_file; /* file to use for error output */ static void (*err_exit)(int); +static void verrci(bool doexterr, int eval, int code, const char *fmt, + va_list ap) __printf0like(4, 0) __dead2; +static void vwarnci(bool doexterr, int code, const char *fmt, va_list ap) + __printf0like(3, 0); + /* * This is declared to take a `void *' so that the caller is not required * to include <stdio.h> first. However, it is really a `FILE *', and the @@ -70,14 +78,14 @@ _err(int eval, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - verrc(eval, errno, fmt, ap); + verrci(true, eval, errno, fmt, ap); va_end(ap); } void verr(int eval, const char *fmt, va_list ap) { - verrc(eval, errno, fmt, ap); + verrci(true, eval, errno, fmt, ap); } void @@ -85,13 +93,24 @@ errc(int eval, int code, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - verrc(eval, code, fmt, ap); + verrci(false, eval, code, fmt, ap); va_end(ap); } void verrc(int eval, int code, const char *fmt, va_list ap) { + verrci(false, eval, code, fmt, ap); +} + +static void +vexterr(bool doexterr, int code, const char *fmt, va_list ap) +{ + char exterr[UEXTERROR_MAXLEN]; /* libc knows the buffer size */ + int extstatus; + + if (doexterr) + extstatus = uexterr_gettext(exterr, sizeof(exterr)); if (err_file == NULL) err_set_file(NULL); fprintf(err_file, "%s: ", _getprogname()); @@ -99,7 +118,16 @@ verrc(int eval, int code, const char *fmt, va_list ap) vfprintf(err_file, fmt, ap); fprintf(err_file, ": "); } - fprintf(err_file, "%s\n", strerror(code)); + fprintf(err_file, "%s", strerror(code)); + if (doexterr && extstatus == 0 && exterr[0] != '\0') + fprintf(err_file, " (extended error %s)", exterr); + fprintf(err_file, "\n"); +} + +static void +verrci(bool doexterr, int eval, int code, const char *fmt, va_list ap) +{ + vexterr(doexterr, code, fmt, ap); if (err_exit) err_exit(eval); exit(eval); @@ -157,17 +185,16 @@ warnc(int code, const char *fmt, ...) void vwarnc(int code, const char *fmt, va_list ap) { + vwarnci(false, code, fmt, ap); +} + +static void +vwarnci(bool doexterr, int code, const char *fmt, va_list ap) +{ int saved_errno; saved_errno = errno; - if (err_file == NULL) - err_set_file(NULL); - fprintf(err_file, "%s: ", _getprogname()); - if (fmt != NULL) { - vfprintf(err_file, fmt, ap); - fprintf(err_file, ": "); - } - fprintf(err_file, "%s\n", strerror(code)); + vexterr(doexterr, code, fmt, ap); errno = saved_errno; } diff --git a/lib/libc/gen/fdopendir.c b/lib/libc/gen/fdopendir.c index 67c0766b6d83..df6709fbcb85 100644 --- a/lib/libc/gen/fdopendir.c +++ b/lib/libc/gen/fdopendir.c @@ -30,14 +30,13 @@ */ #include "namespace.h" -#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> +#include <stdbool.h> #include "un-namespace.h" #include "gen-private.h" diff --git a/lib/libc/gen/fts.3 b/lib/libc/gen/fts.3 index 5860d1be1a1e..ee558b892c8c 100644 --- a/lib/libc/gen/fts.3 +++ b/lib/libc/gen/fts.3 @@ -394,7 +394,7 @@ must be specified. The options are selected by .Em or Ns 'ing the following values: -.Bl -tag -width "FTS_PHYSICAL" +.Bl -tag -width "FTS_COMFOLLOWDIR" .It Dv FTS_COMFOLLOW This option causes any symbolic link specified as a root path to be followed immediately whether or not diff --git a/lib/libc/gen/gen-private.h b/lib/libc/gen/gen-private.h index 3792a61ff942..b6749b3435cd 100644 --- a/lib/libc/gen/gen-private.h +++ b/lib/libc/gen/gen-private.h @@ -43,8 +43,8 @@ struct pthread_mutex; */ struct _dirdesc { int dd_fd; /* file descriptor associated with directory */ - long dd_loc; /* offset in current buffer */ - long dd_size; /* amount of data returned by getdirentries */ + size_t dd_loc; /* offset in current buffer */ + size_t dd_size; /* amount of data returned by getdirentries */ char *dd_buf; /* data buffer */ int dd_len; /* size of data buffer */ off_t dd_seek; /* magic cookie returned by getdirentries */ diff --git a/lib/libc/gen/libc_interposing_table.c b/lib/libc/gen/libc_interposing_table.c index 8eae6c7f5d95..025a67ac3eac 100644 --- a/lib/libc/gen/libc_interposing_table.c +++ b/lib/libc/gen/libc_interposing_table.c @@ -42,7 +42,6 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = { SLOT(spinlock, __libc_spinlock_stub), SLOT(spinunlock, __libc_spinunlock_stub), SLOT(map_stacks_exec, __libc_map_stacks_exec), - SLOT(distribute_static_tls, __libc_distribute_static_tls), SLOT(uexterr_gettext, __libc_uexterr_gettext), }; #undef SLOT diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index 956c92c321e8..08d9eb10eaa2 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -30,14 +30,7 @@ */ #include "namespace.h" -#include <sys/param.h> - #include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> #include "un-namespace.h" #include "gen-private.h" diff --git a/lib/libc/gen/opendir2.c b/lib/libc/gen/opendir2.c index b9ac23e6d9fd..c5c2e662efd8 100644 --- a/lib/libc/gen/opendir2.c +++ b/lib/libc/gen/opendir2.c @@ -30,11 +30,12 @@ */ #include "namespace.h" -#include <sys/param.h> +#include <sys/types.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -52,8 +53,7 @@ __opendir2(const char *name, int flags) if ((flags & (__DTF_READALL | __DTF_SKIPREAD)) != 0) return (NULL); - if ((fd = _open(name, - O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1) + if ((fd = _open(name, O_DIRECTORY | O_RDONLY | O_CLOEXEC)) == -1) return (NULL); dir = __opendir_common(fd, flags, false); @@ -264,6 +264,7 @@ DIR * __opendir_common(int fd, int flags, bool use_current_pos) { DIR *dirp; + ssize_t ret; int incr; int saved_errno; bool unionstack; @@ -313,13 +314,11 @@ __opendir_common(int fd, int flags, bool use_current_pos) * to prime dd_seek. This also checks if the * fd passed to fdopendir() is a directory. */ - dirp->dd_size = _getdirentries(dirp->dd_fd, + ret = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); - if (dirp->dd_size < 0) { - if (errno == EINVAL) - errno = ENOTDIR; + if (ret < 0) goto fail; - } + dirp->dd_size = (size_t)ret; dirp->dd_flags |= __DTF_SKIPREAD; } else { dirp->dd_size = 0; diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c index 2a2fa999b7ce..b70102954df1 100644 --- a/lib/libc/gen/readdir.c +++ b/lib/libc/gen/readdir.c @@ -48,8 +48,9 @@ struct dirent * _readdir_unlocked(DIR *dirp, int flags) { struct dirent *dp; - long initial_seek; - long initial_loc = 0; + off_t initial_seek; + size_t initial_loc = 0; + ssize_t ret; for (;;) { if (dirp->dd_loc >= dirp->dd_size) { @@ -61,11 +62,13 @@ _readdir_unlocked(DIR *dirp, int flags) } if (dirp->dd_loc == 0 && !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) { + dirp->dd_size = 0; initial_seek = dirp->dd_seek; - dirp->dd_size = _getdirentries(dirp->dd_fd, + ret = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); - if (dirp->dd_size <= 0) + if (ret <= 0) return (NULL); + dirp->dd_size = (size_t)ret; _fixtelldir(dirp, initial_seek, initial_loc); } dirp->dd_flags &= ~__DTF_SKIPREAD; diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c index 8e62fe980868..fb589f4b36b6 100644 --- a/lib/libc/gen/scandir.c +++ b/lib/libc/gen/scandir.c @@ -252,9 +252,3 @@ scandir_thunk_cmp(const void *p1, const void *p2, void *thunk) return (dc((const struct dirent **)p1, (const struct dirent **)p2)); } #endif - -#ifdef I_AM_SCANDIR_B -__weak_reference(fdscandir_b, fscandir_b); -#else -__weak_reference(fdscandir, fscandir); -#endif diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c index b751fafd975f..1731cc4d7a2c 100644 --- a/lib/libc/gen/telldir.c +++ b/lib/libc/gen/telldir.c @@ -118,7 +118,7 @@ _seekdir(DIR *dirp, long loc) struct dirent *dp; union ddloc_packed ddloc; off_t loc_seek; - long loc_loc; + size_t loc_loc; ddloc.l = loc; @@ -171,7 +171,7 @@ _seekdir(DIR *dirp, long loc) * fetching a new block to fix any such telldir locations. */ void -_fixtelldir(DIR *dirp, long oldseek, long oldloc) +_fixtelldir(DIR *dirp, off_t oldseek, size_t oldloc) { struct ddloc_mem *lp; diff --git a/lib/libc/gen/telldir.h b/lib/libc/gen/telldir.h index 6d113491e819..02fd52af9060 100644 --- a/lib/libc/gen/telldir.h +++ b/lib/libc/gen/telldir.h @@ -46,9 +46,9 @@ */ struct ddloc_mem { LIST_ENTRY(ddloc_mem) loc_lqe; /* entry in list */ - long loc_index; /* key associated with structure */ + size_t loc_index; /* key associated with structure */ off_t loc_seek; /* magic cookie returned by getdirentries */ - long loc_loc; /* offset of entry in buffer */ + size_t loc_loc; /* offset of entry in buffer */ }; #ifdef __LP64__ @@ -102,7 +102,7 @@ bool _filldir(DIR *, bool); struct dirent *_readdir_unlocked(DIR *, int); void _reclaim_telldir(DIR *); void _seekdir(DIR *, long); -void _fixtelldir(DIR *dirp, long oldseek, long oldloc); +void _fixtelldir(DIR *dirp, off_t oldseek, size_t oldloc); DIR *__opendir_common(int, int, bool); #define RDU_SKIP 0x0001 diff --git a/lib/libc/gen/uexterr_format.c b/lib/libc/gen/uexterr_format.c index 32b57ffb6e1a..e8ddfbd578e3 100644 --- a/lib/libc/gen/uexterr_format.c +++ b/lib/libc/gen/uexterr_format.c @@ -20,12 +20,16 @@ __uexterr_format(const struct uexterror *ue, char *buf, size_t bufsz) if (bufsz > UEXTERROR_MAXLEN) bufsz = UEXTERROR_MAXLEN; if (ue->error == 0) { - strlcpy(buf, "No error", bufsz); + strlcpy(buf, "", bufsz); return (0); } - snprintf(buf, bufsz, - "errno %d category %u (src line %u) p1 %#jx p2 %#jx %s", - ue->error, ue->cat, ue->src_line, - (uintmax_t)ue->p1, (uintmax_t)ue->p2, ue->msg); + if (ue->msg[0] == '\0') { + snprintf(buf, bufsz, + "errno %d category %u (src line %u) p1 %#jx p2 %#jx", + ue->error, ue->cat, ue->src_line, + (uintmax_t)ue->p1, (uintmax_t)ue->p2); + } else { + strlcpy(buf, ue->msg, bufsz); + } return (0); } diff --git a/lib/libc/gen/wordexp.c b/lib/libc/gen/wordexp.c index f1437e30bbe2..f8080c20d121 100644 --- a/lib/libc/gen/wordexp.c +++ b/lib/libc/gen/wordexp.c @@ -265,7 +265,15 @@ cleanup: errno = serrno; return (error); } - if (wpid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) + /* + * Check process exit status, but ignore ECHILD as the child may have + * been automatically reaped if the process had set SIG_IGN or + * SA_NOCLDWAIT for SIGCHLD, and our reason for waitpid was just to + * reap our own child on behalf of the calling process. + */ + if (wpid < 0 && errno != ECHILD) + return (WRDE_NOSPACE); /* abort for unknown reason */ + if (wpid >= 0 && (!WIFEXITED(status) || WEXITSTATUS(status) != 0)) return (WRDE_NOSPACE); /* abort for unknown reason */ /* diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index 1bc22f3931a5..db4cbc32be35 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -249,7 +249,7 @@ enum { INTERPOS_map_stacks_exec, INTERPOS_fdatasync, INTERPOS_clock_nanosleep, - INTERPOS_distribute_static_tls, + INTERPOS__reserved0, /* was distribute_static_tls */ INTERPOS_pdfork, INTERPOS_uexterr_gettext, INTERPOS_MAX @@ -361,8 +361,6 @@ struct dl_phdr_info; int __elf_phdr_match_addr(struct dl_phdr_info *, void *); void __init_elf_aux_vector(void); void __libc_map_stacks_exec(void); -void __libc_distribute_static_tls(__size_t, void *, __size_t, __size_t); -__uintptr_t __libc_static_tls_base(__size_t); void _pthread_cancel_enter(int); void _pthread_cancel_leave(int); diff --git a/lib/libc/stdio/mktemp.3 b/lib/libc/stdio/mktemp.3 index 2b8b2d6c9e44..8d38dd2cd57e 100644 --- a/lib/libc/stdio/mktemp.3 +++ b/lib/libc/stdio/mktemp.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 29, 2019 +.Dd July 07, 2025 .Dt MKTEMP 3 .Os .Sh NAME @@ -101,9 +101,10 @@ The permitted flags are .Dv O_DIRECT , .Dv O_SHLOCK , .Dv O_EXLOCK , -.Dv O_SYNC +.Dv O_SYNC , +.Dv O_CLOEXEC and -.Dv O_CLOEXEC . +.Dv O_CLOFORK . .Pp The .Fn mkstemps diff --git a/lib/libc/stdio/mktemp.c b/lib/libc/stdio/mktemp.c index 8aff226acf14..a2f80ee7b0dd 100644 --- a/lib/libc/stdio/mktemp.c +++ b/lib/libc/stdio/mktemp.c @@ -121,7 +121,7 @@ _gettemp(int dfd, char *path, int *doopen, int domkdir, int slen, int oflags) if ((doopen != NULL && domkdir) || slen < 0 || (oflags & ~(O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC | - O_CLOEXEC)) != 0) { + O_CLOEXEC | O_CLOFORK)) != 0) { errno = EINVAL; return (0); } diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile index a967ad5ddf91..8c2151105209 100644 --- a/lib/libc/tests/gen/Makefile +++ b/lib/libc/tests/gen/Makefile @@ -20,6 +20,7 @@ ATF_TESTS_C+= glob2_test ATF_TESTS_C+= glob_blocks_test .endif ATF_TESTS_C+= makecontext_test +ATF_TESTS_C+= opendir_test ATF_TESTS_C+= popen_test ATF_TESTS_C+= posix_spawn_test ATF_TESTS_C+= realpath2_test diff --git a/lib/libc/tests/gen/opendir_test.c b/lib/libc/tests/gen/opendir_test.c new file mode 100644 index 000000000000..b7481255654f --- /dev/null +++ b/lib/libc/tests/gen/opendir_test.c @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> + +#include <atf-c.h> + +/* + * Create a directory with a single subdirectory. + */ +static void +opendir_prepare(const struct atf_tc *tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, mkdir("dir/subdir", 0755)); +} + +/* + * Assuming dirp represents the directory created by opendir_prepare(), + * verify that readdir() returns what we expected to see there. + */ +static void +opendir_check(const struct atf_tc *tc, DIR *dirp) +{ + struct dirent *ent; + + ATF_REQUIRE((ent = readdir(dirp)) != NULL); + ATF_CHECK_EQ(1, ent->d_namlen); + ATF_CHECK_STREQ(".", ent->d_name); + ATF_CHECK_EQ(DT_DIR, ent->d_type); + ATF_REQUIRE((ent = readdir(dirp)) != NULL); + ATF_CHECK_EQ(2, ent->d_namlen); + ATF_CHECK_STREQ("..", ent->d_name); + ATF_CHECK_EQ(DT_DIR, ent->d_type); + ATF_REQUIRE((ent = readdir(dirp)) != NULL); + ATF_CHECK_EQ(sizeof("subdir") - 1, ent->d_namlen); + ATF_CHECK_STREQ("subdir", ent->d_name); + ATF_CHECK_EQ(DT_DIR, ent->d_type); + ATF_CHECK(readdir(dirp) == NULL); + ATF_CHECK(readdir(dirp) == NULL); +} + +ATF_TC(opendir_ok); +ATF_TC_HEAD(opendir_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", "Open a directory."); +} +ATF_TC_BODY(opendir_ok, tc) +{ + DIR *dirp; + + opendir_prepare(tc); + ATF_REQUIRE((dirp = opendir("dir")) != NULL); + opendir_check(tc, dirp); + ATF_CHECK_EQ(0, closedir(dirp)); +} + +ATF_TC(opendir_fifo); +ATF_TC_HEAD(opendir_fifo, tc) +{ + atf_tc_set_md_var(tc, "descr", "Do not hang if given a named pipe."); +} +ATF_TC_BODY(opendir_fifo, tc) +{ + DIR *dirp; + int fd; + + ATF_REQUIRE((fd = mkfifo("fifo", 0644)) >= 0); + ATF_REQUIRE_EQ(0, close(fd)); + ATF_REQUIRE((dirp = opendir("fifo")) == NULL); + ATF_CHECK_EQ(ENOTDIR, errno); +} + +ATF_TC(fdopendir_ok); +ATF_TC_HEAD(fdopendir_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Open a directory from a directory descriptor."); +} +ATF_TC_BODY(fdopendir_ok, tc) +{ + DIR *dirp; + int dd; + + opendir_prepare(tc); + ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ATF_REQUIRE((dirp = fdopendir(dd)) != NULL); + opendir_check(tc, dirp); + ATF_CHECK_EQ(dd, fdclosedir(dirp)); + ATF_CHECK_EQ(0, close(dd)); +} + +ATF_TC(fdopendir_ebadf); +ATF_TC_HEAD(fdopendir_ebadf, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Open a directory from an invalid descriptor."); +} +ATF_TC_BODY(fdopendir_ebadf, tc) +{ + DIR *dirp; + int dd; + + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ATF_CHECK_EQ(0, close(dd)); + ATF_REQUIRE((dirp = fdopendir(dd)) == NULL); + ATF_CHECK_EQ(EBADF, errno); +} + +ATF_TC(fdopendir_enotdir); +ATF_TC_HEAD(fdopendir_enotdir, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Open a directory from a non-directory descriptor."); +} +ATF_TC_BODY(fdopendir_enotdir, tc) +{ + DIR *dirp; + int fd; + + ATF_REQUIRE((fd = open("file", O_CREAT | O_RDWR, 0644)) >= 0); + ATF_REQUIRE((dirp = fdopendir(fd)) == NULL); + ATF_CHECK_EQ(ENOTDIR, errno); + ATF_CHECK_EQ(0, close(fd)); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, opendir_ok); + ATF_TP_ADD_TC(tp, fdopendir_ok); + ATF_TP_ADD_TC(tp, fdopendir_ebadf); + ATF_TP_ADD_TC(tp, fdopendir_enotdir); + ATF_TP_ADD_TC(tp, opendir_fifo); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/scandir_test.c b/lib/libc/tests/gen/scandir_test.c index f7b52b5e3616..afd25bf7c0b2 100644 --- a/lib/libc/tests/gen/scandir_test.c +++ b/lib/libc/tests/gen/scandir_test.c @@ -157,7 +157,7 @@ ATF_TC_BODY(scandir_error, tc) { char path[16]; struct dirent **namelist = NULL; - int fd, i, ret; + int fd, i; ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); for (i = 0; i < 1024; i++) { @@ -170,9 +170,8 @@ ATF_TC_BODY(scandir_error, tc) scandir_error_count = 0; scandir_error_fd = fd; scandir_error_select_return = 0; - ret = fdscandir(fd, &namelist, scandir_error_select, NULL); - ATF_CHECK_EQ(-1, ret); - ATF_CHECK_ERRNO(EBADF, ret < 0); + ATF_CHECK_ERRNO(EBADF, + fdscandir(fd, &namelist, scandir_error_select, NULL) < 0); ATF_CHECK_EQ(NULL, namelist); /* second pass, select everything */ @@ -180,9 +179,8 @@ ATF_TC_BODY(scandir_error, tc) scandir_error_count = 0; scandir_error_fd = fd; scandir_error_select_return = 1; - ret = fdscandir(fd, &namelist, scandir_error_select, NULL); - ATF_CHECK_EQ(-1, ret); - ATF_CHECK_ERRNO(EBADF, ret < 0); + ATF_CHECK_ERRNO(EBADF, + fdscandir(fd, &namelist, scandir_error_select, NULL) < 0); ATF_CHECK_EQ(NULL, namelist); } diff --git a/lib/libc/tests/gen/wordexp_test.c b/lib/libc/tests/gen/wordexp_test.c index 909097fbf51e..a8b9d5509633 100644 --- a/lib/libc/tests/gen/wordexp_test.c +++ b/lib/libc/tests/gen/wordexp_test.c @@ -292,6 +292,31 @@ ATF_TC_BODY(with_SIGCHILD_handler_test, tc) ATF_REQUIRE(r == 0); } +ATF_TC_WITHOUT_HEAD(with_SIGCHILD_ignore_test); +ATF_TC_BODY(with_SIGCHILD_ignore_test, tc) +{ + struct sigaction sa; + wordexp_t we; + int r; + + /* With SIGCHLD set to ignore so that the kernel auto-reaps zombies. */ + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + r = sigaction(SIGCHLD, &sa, NULL); + ATF_REQUIRE(r == 0); + r = wordexp("hello world", &we, 0); + ATF_REQUIRE(r == 0); + ATF_REQUIRE(we.we_wordc == 2); + ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0); + ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0); + ATF_REQUIRE(we.we_wordv[2] == NULL); + wordfree(&we); + sa.sa_handler = SIG_DFL; + r = sigaction(SIGCHLD, &sa, NULL); + ATF_REQUIRE(r == 0); +} + ATF_TC_WITHOUT_HEAD(with_unused_non_default_IFS_test); ATF_TC_BODY(with_unused_non_default_IFS_test, tc) { @@ -350,6 +375,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, WRDE_BADCHAR_test); ATF_TP_ADD_TC(tp, WRDE_SYNTAX_test); ATF_TP_ADD_TC(tp, with_SIGCHILD_handler_test); + ATF_TP_ADD_TC(tp, with_SIGCHILD_ignore_test); ATF_TP_ADD_TC(tp, with_unused_non_default_IFS_test); ATF_TP_ADD_TC(tp, with_used_non_default_IFS_test); |