Index: t_fopen.c =================================================================== RCS file: /cvsroot/src/tests/lib/libc/stdio/t_fopen.c,v retrieving revision 1.5 diff -u -r1.5 t_fopen.c --- t_fopen.c 6 Nov 2017 23:06:55 -0000 1.5 +++ t_fopen.c 5 Feb 2019 16:49:55 -0000 @@ -31,12 +31,16 @@ #include __RCSID("$NetBSD: t_fopen.c,v 1.5 2017/11/06 23:06:55 kre Exp $"); +#include +#include +#include #include #include #include #include #include #include +#include #include #include @@ -287,6 +291,114 @@ (void)unlink(path); } +static void +check_kernel_modular(void) +{ + int err; + + err = modctl(MODCTL_EXISTS, 0); + if (err == 0) return; + if (errno == ENOSYS) + atf_tc_skip("Kernel does not have 'options MODULAR'."); + if (errno == EPERM) + atf_tc_skip("Module loading administratively forbidden"); + ATF_REQUIRE_EQ_MSG(errno, 0, "unexpected error %d from " + "modctl(MODCTL_EXISTS, 0)", errno); +} + +static bool +is_module_present(const char *name) +{ + bool found; + size_t len; + int count; + struct iovec iov; + modstat_t *ms; + + for (len = 8192; ;) { + iov.iov_base = malloc(len); + iov.iov_len = len; + + errno = 0; + + if (modctl(MODCTL_STAT, &iov) != 0) { + fprintf(stderr, "modctl(MODCTL_STAT) failed: %s\n", + strerror(errno)); + atf_tc_fail("Failed to query module status"); + } + if (len >= iov.iov_len) + break; + free(iov.iov_base); + len = iov.iov_len; + } + + found = false; + count = *(int *)iov.iov_base; + ms = (modstat_t *)((char *)iov.iov_base + sizeof(int)); + while (count > 0) { + if (strcmp(ms->ms_name, name) == 0) { + found = true; + break; + } + ms++; + count--; + } + + free(iov.iov_base); + + return found; +} + +#define COMPAT10_MODNAME "compat_10" + +ATF_TC(fopen_nullptr); +ATF_TC_HEAD(fopen_nullptr, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test fopen(3) with NULL path (without " + COMPAT10_MODNAME ")"); +} + +ATF_TC_BODY(fopen_nullptr, tc) +{ + bool compat10; + + check_kernel_modular(); + compat10 = is_module_present(COMPAT10_MODNAME); + + if (compat10) + atf_tc_skip("Kernel does have the " COMPAT10_MODNAME + "module loaded into the kernel"); + + /* NULL shall trigger error */ + ATF_REQUIRE_ERRNO(EFAULT, fopen(NULL, "r") == NULL); +} + +ATF_TC(fopen_nullptr_compat10); +ATF_TC_HEAD(fopen_nullptr_compat10, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test fopen(3) with NULL path (with " + COMPAT10_MODNAME ")"); +} + +ATF_TC_BODY(fopen_nullptr_compat10, tc) +{ + FILE *fp; + bool compat10; + + check_kernel_modular(); + compat10 = is_module_present(COMPAT10_MODNAME); + + if (!compat10) + atf_tc_skip("Kernel does not have the " COMPAT10_MODNAME + "module loaded into the kernel"); + + /* NULL is translated to "." and shall success */ + fp = fopen(NULL, "r"); + + ATF_REQUIRE(fp != NULL); + ATF_REQUIRE(fclose(fp) == 0); +} + ATF_TC(fopen_perm); ATF_TC_HEAD(fopen_perm, tc) { @@ -482,6 +594,8 @@ ATF_TP_ADD_TC(tp, fopen_append); ATF_TP_ADD_TC(tp, fopen_err); ATF_TP_ADD_TC(tp, fopen_mode); + ATF_TP_ADD_TC(tp, fopen_nullptr); + ATF_TP_ADD_TC(tp, fopen_nullptr_compat10); ATF_TP_ADD_TC(tp, fopen_perm); ATF_TP_ADD_TC(tp, fopen_regular); ATF_TP_ADD_TC(tp, fopen_symlink);