Index: lib/libc/stdio/t_fopen.c =================================================================== RCS file: /cvsroot/src/tests/lib/libc/stdio/t_fopen.c,v retrieving revision 1.6 diff -u -r1.6 t_fopen.c --- lib/libc/stdio/t_fopen.c 5 Feb 2019 17:30:19 -0000 1.6 +++ lib/libc/stdio/t_fopen.c 6 Feb 2019 01:06:41 -0000 @@ -44,6 +44,8 @@ #include #include +#include "../../../modules/h_get_modstat_info.h" + static const char *path = "fopen"; ATF_TC_WITH_CLEANUP(fdopen_close); @@ -291,64 +293,6 @@ (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) - return; /* Module loading can be 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); @@ -360,14 +304,22 @@ ATF_TC_BODY(fopen_nullptr, tc) { - bool compat10; - - check_kernel_modular(); - compat10 = is_module_present(COMPAT10_MODNAME); + int compat10; - if (compat10) + compat10 = get_modstat_info(COMPAT10_MODNAME, NULL); + switch (compat10) { + case 0: atf_tc_skip("Kernel does have the " COMPAT10_MODNAME " module loaded into the kernel"); + case ENOSYS: + atf_tc_skip("Kernel does not have 'options MODULAR'."); + case ENOENT: + /* Expected module absent */ + break; + default: + atf_tc_fail("Failed to query module " COMPAT10_MODNAME " '%s'", + strerror(compat10)); + } /* NULL shall trigger error */ ATF_REQUIRE_ERRNO(EFAULT, fopen(NULL, "r") == NULL); @@ -383,14 +335,22 @@ ATF_TC_BODY(fopen_nullptr_compat10, tc) { FILE *fp; - bool compat10; - - check_kernel_modular(); - compat10 = is_module_present(COMPAT10_MODNAME); + int compat10; - if (!compat10) + compat10 = get_modstat_info(COMPAT10_MODNAME, NULL); + switch (compat10) { + case 0: + /* Expected module present */ + break; + case ENOSYS: + atf_tc_skip("Kernel does not have 'options MODULAR'."); + case ENOENT: atf_tc_skip("Kernel does not have the " COMPAT10_MODNAME " module loaded into the kernel"); + default: + atf_tc_fail("Failed to query module " COMPAT10_MODNAME " '%s'", + strerror(compat10)); + } /* NULL is translated to "." and shall success */ fp = fopen(NULL, "r"); Index: modules/h_get_modstat_info.h =================================================================== RCS file: modules/h_get_modstat_info.h diff -N modules/h_get_modstat_info.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/h_get_modstat_info.h 6 Feb 2019 01:06:41 -0000 @@ -0,0 +1,105 @@ +/* $NetBSD$ */ +/* + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GET_MODSTAT_INFO_H_ +#define _GET_MODSTAT_INFO_H_ + +#include +#include + +#include +#include +#include +#include +#include + +static int +get_modstat_info(const char *name, modstat_t *msdest) +{ + bool found; + size_t len; + int count; + struct iovec iov; + modstat_t *ms; + int saved_errno; + int rv; + + saved_errno = errno; + + if (modctl(MODCTL_EXISTS, 0) != 0 && errno != EPERM) { + rv = errno; + goto fini; + } + + for (len = 8192; ;) { + iov.iov_base = malloc(len); + if (iov.iov_base == NULL) { + rv = errno; + goto fini; + } + iov.iov_len = len; + + if (modctl(MODCTL_STAT, &iov) != 0) { + rv = errno; + free(iov.iov_base); + goto fini; + } + 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 (strncmp(ms->ms_name, name, MAXMODNAME) == 0) { + if (msdest != NULL) + *msdest = *ms; + found = true; + break; + } + ms++; + count--; + } + + free(iov.iov_base); + + if (found) + rv = 0; + else + rv = ENOENT; + +fini: + errno = saved_errno; + + return rv; +} + +#endif /* _GET_MODSTAT_INFO_H_ */ Index: modules/t_modctl.c =================================================================== RCS file: /cvsroot/src/tests/modules/t_modctl.c,v retrieving revision 1.13 diff -u -r1.13 t_modctl.c --- modules/t_modctl.c 27 Jan 2019 02:08:50 -0000 1.13 +++ modules/t_modctl.c 6 Feb 2019 01:06:41 -0000 @@ -44,10 +44,11 @@ #include +#include "h_get_modstat_info.h" + enum presence_check { both_checks, stat_check, sysctl_check }; static void check_permission(void); -static bool get_modstat_info(const char *, modstat_t *); static bool get_sysctl(const char *, void *buf, const size_t); static bool k_helper_is_present_stat(void); static bool k_helper_is_present_sysctl(void); @@ -79,53 +80,6 @@ "modctl(MODCTL_EXISTS, 0)", errno); } -static bool -get_modstat_info(const char *name, modstat_t *msdest) -{ - bool found; - size_t len; - int count; - struct iovec iov; - modstat_t *ms; - - check_permission(); - for (len = 8192; ;) { - iov.iov_base = malloc(len); - iov.iov_len = len; - - errno = 0; - - if (modctl(MODCTL_STAT, &iov) != 0) { - int err = errno; - fprintf(stderr, "modctl(MODCTL_STAT) failed: %s\n", - strerror(err)); - 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 ) { - if (strcmp(ms->ms_name, name) == 0) { - if (msdest != NULL) - *msdest = *ms; - found = true; - break; - } - ms++; - count--; - } - - free(iov.iov_base); - - return found; -} - /* * Queries a sysctl property. */ @@ -152,7 +106,7 @@ k_helper_is_present_stat(void) { - return get_modstat_info("k_helper", NULL); + return get_modstat_info("k_helper", NULL) == 0; } /* @@ -440,7 +394,7 @@ ATF_CHECK(k_helper_is_present(both_checks)); { modstat_t ms; - ATF_CHECK(get_modstat_info("k_helper", &ms)); + ATF_CHECK(get_modstat_info("k_helper", &ms) == 0); ATF_CHECK(ms.ms_class == MODULE_CLASS_MISC); ATF_CHECK(ms.ms_source == MODULE_SOURCE_FILESYS);