The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4140012f83690e9ed9b31d87c16e4f698332e24c

commit 4140012f83690e9ed9b31d87c16e4f698332e24c
Author:     Ricardo Branco <rbra...@suse.de>
AuthorDate: 2025-06-16 17:45:54 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2025-07-06 23:09:10 +0000

    tests: Adapt oclo tests to FreeBSD
    
    MFC after:      1 month
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1698
---
 .../opensolaris/tests/os-tests/tests/oclo/oclo.c   | 91 +++++++++++++++-------
 .../tests/os-tests/tests/oclo/oclo_errors.c        | 25 ++++--
 .../tests/os-tests/tests/oclo/ocloexec_verify.c    | 47 +++++++----
 tests/Makefile                                     |  5 ++
 tests/oclo/Makefile                                | 11 +++
 5 files changed, 126 insertions(+), 53 deletions(-)

diff --git a/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/oclo.c 
b/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/oclo.c
index b21c253fca24..8e6f7c726f24 100644
--- a/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/oclo.c
+++ b/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/oclo.c
@@ -45,21 +45,54 @@
  * with the divergence of other implementations.
  */
 
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <err.h>
-#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
 #include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/sysmacros.h>
-#include <sys/fork.h>
-#include <wait.h>
+#include <sys/wait.h>
+
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include <err.h>
 #include <errno.h>
-#include <string.h>
-#include <limits.h>
+#include <fcntl.h>
 #include <libgen.h>
-#include <sys/socket.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+void *recallocarray(void *, size_t, size_t, size_t);
+
+#define strerrorname_np(e) (sys_errlist[e])
+
+/*
+ * Get pathname to avoid reading /proc/curproc/exe
+ *
+ * Taken from procstat_getpathname_sysctl()
+ */
+static int
+getpathname(pid_t pid, char *pathname, size_t maxlen)
+{
+       int error, name[4];
+       size_t len;
+
+       name[0] = CTL_KERN;
+       name[1] = KERN_PROC;
+       name[2] = KERN_PROC_PATHNAME;
+       name[3] = pid;
+       len = maxlen;
+       error = sysctl(name, nitems(name), pathname, &len, NULL, 0);
+       if (error != 0 && errno != ESRCH)
+               warn("sysctl: kern.proc.pathname: %d", pid);
+       if (len == 0)
+               pathname[0] = '\0';
+       return (error);
+}
 
 /*
  * Verification program name.
@@ -93,8 +126,8 @@ typedef struct clo_rtdata {
 } clo_rtdata_t;
 
 static clo_rtdata_t *oclo_rtdata;
-size_t oclo_rtdata_nents = 0;
-size_t oclo_rtdata_next = 0;
+static size_t oclo_rtdata_nents = 0;
+static size_t oclo_rtdata_next = 0;
 static int oclo_nextfd = STDERR_FILENO + 1;
 
 static bool
@@ -267,11 +300,13 @@ oclo_fdup_common(const clo_create_t *c, int targ_flags, 
int cmd)
                break;
        case F_DUP2FD:
        case F_DUP2FD_CLOEXEC:
+#ifdef F_DUP2FD_CLOFORK
        case F_DUP2FD_CLOFORK:
+#endif
                dup = fcntl(fd, cmd, fd + 1);
                break;
        case F_DUP3FD:
-               dup = fcntl(fd, cmd, fd + 1, targ_flags);
+               dup = fcntl(fd, cmd | (targ_flags << F_DUP3FD_SHIFT), fd + 1);
                break;
        default:
                errx(EXIT_FAILURE, "TEST FAILURE: %s: internal error: "
@@ -310,11 +345,13 @@ oclo_fdup2fd(const clo_create_t *c)
        oclo_fdup_common(c, 0, F_DUP2FD);
 }
 
+#ifdef F_DUP2FD_CLOFORK
 static void
 oclo_fdup2fd_fork(const clo_create_t *c)
 {
        oclo_fdup_common(c, FD_CLOFORK, F_DUP2FD_CLOFORK);
 }
+#endif
 
 static void
 oclo_fdup2fd_exec(const clo_create_t *c)
@@ -604,7 +641,7 @@ oclo_rights_common(const clo_create_t *c, int targ_flags)
 
        if (msg.msg_controllen < CMSG_SPACE(sizeof (int))) {
                errx(EXIT_FAILURE, "TEST FAILED: %s: found insufficient "
-                   "message control length: expected at least 0x%x, found "
+                   "message control length: expected at least 0x%zx, found "
                    "0x%x", c->clo_desc, CMSG_SPACE(sizeof (int)),
                    msg.msg_controllen);
        }
@@ -795,6 +832,7 @@ static const clo_create_t oclo_create[] = { {
        .clo_flags = FD_CLOEXEC | FD_CLOFORK,
        .clo_func = oclo_fdup2fd
 }, {
+#ifdef F_DUP2FD_CLOFORK
        .clo_desc = "fcntl(F_DUP2FD_CLOFORK) none",
        .clo_flags = 0,
        .clo_func = oclo_fdup2fd_fork
@@ -811,6 +849,7 @@ static const clo_create_t oclo_create[] = { {
        .clo_flags = FD_CLOEXEC | FD_CLOFORK,
        .clo_func = oclo_fdup2fd_fork
 }, {
+#endif
        .clo_desc = "fcntl(F_DUP2FD_CLOEXEC) none",
        .clo_flags = 0,
        .clo_func = oclo_fdup2fd_exec
@@ -1216,20 +1255,12 @@ oclo_exec(void)
        char dir[PATH_MAX], file[PATH_MAX];
        char **argv;
 
-       ret = readlink("/proc/self/path/a.out", dir, sizeof (dir));
-       if (ret < 0) {
-               err(EXIT_FAILURE, "TEST FAILED: failed to read our a.out path "
-                   "from /proc");
-       } else if (ret == 0) {
-               errx(EXIT_FAILURE, "TEST FAILED: reading /proc/self/path/a.out "
-                   "returned 0 bytes");
-       } else if (ret == sizeof (dir)) {
-               errx(EXIT_FAILURE, "TEST FAILED: Using /proc/self/path/a.out "
-                   "requires truncation");
-       }
+       ret = getpathname(getpid(), dir, sizeof(dir));
+       if (ret < 0)
+               err(EXIT_FAILURE, "TEST FAILED: failed to read executable 
path");
 
        if (snprintf(file, sizeof (file), "%s/%s", dirname(dir), OCLO_VERIFY) >=
-           sizeof (file)) {
+           (int)sizeof (file)) {
                errx(EXIT_FAILURE, "TEST FAILED: cannot assemble exec path "
                    "name: internal buffer overflow");
        }
@@ -1270,11 +1301,11 @@ main(void)
         * Treat failure during this set up phase as a hard failure. There's no
         * reason to continue if we can't successfully create the FDs we expect.
         */
-       for (size_t i = 0; i < ARRAY_SIZE(oclo_create); i++) {
+       for (size_t i = 0; i < nitems(oclo_create); i++) {
                oclo_create[i].clo_func(&oclo_create[i]);
        }
 
-       pid_t child = forkx(FORK_NOSIGCHLD | FORK_WAITPID);
+       pid_t child = fork();
        if (child == 0) {
                if (!oclo_verify_fork()) {
                        ret = EXIT_FAILURE;
diff --git a/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/oclo_errors.c 
b/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/oclo_errors.c
index 9d9841271856..05b0c1a0839b 100644
--- a/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/oclo_errors.c
+++ b/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/oclo_errors.c
@@ -24,16 +24,21 @@
  *  o accept4()
  */
 
-#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
 #include <err.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/stdbool.h>
 #include <errno.h>
-#include <string.h>
 #include <fcntl.h>
 #include <limits.h>
-#include <sys/socket.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define strerrorname_np(e) (sys_errlist[e])
 
 static bool
 oclo_check(const char *desc, const char *act, int ret, int e)
@@ -42,7 +47,7 @@ oclo_check(const char *desc, const char *act, int ret, int e)
                warnx("TEST FAILED: %s: fd was %s!", desc, act);
                return (false);
        } else if (errno != EINVAL) {
-               int e = errno;
+               e = errno;
                warnx("TEST FAILED: %s: failed with %s, expected "
                    "EINVAL", desc, strerrorname_np(e));
                return (false);
@@ -63,7 +68,7 @@ oclo_dup3(const char *desc, int flags)
 static bool
 oclo_dup3fd(const char *desc, int flags)
 {
-       int fd = fcntl(STDERR_FILENO, F_DUP3FD, 23, flags);
+       int fd = fcntl(STDERR_FILENO, F_DUP3FD | (flags << F_DUP3FD_SHIFT), 23);
        return (oclo_check(desc, "duplicated", fd, errno));
 }
 
@@ -77,12 +82,14 @@ oclo_pipe2(const char *desc, int flags)
        return (oclo_check(desc, "piped", ret, errno));
 }
 
+#if 0
 static bool
 oclo_socket(const char *desc, int type)
 {
        int fd = socket(PF_UNIX, SOCK_STREAM | type, 0);
        return (oclo_check(desc, "created", fd, errno));
 }
+#endif
 
 static bool
 oclo_accept(const char *desc, int flags)
@@ -169,6 +176,7 @@ main(void)
                ret = EXIT_FAILURE;
        }
 
+#if 0  /* These tests are known to fail on FreeBSD */
        if (!oclo_socket("socket(): INT32_MAX", INT32_MAX)) {
                ret = EXIT_FAILURE;
        }
@@ -176,6 +184,7 @@ main(void)
        if (!oclo_socket("socket(): 3 << 25", 3 << 25)) {
                ret = EXIT_FAILURE;
        }
+#endif
 
        if (!oclo_accept("accept4(): INT32_MAX", INT32_MAX)) {
                ret = EXIT_FAILURE;
diff --git 
a/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/ocloexec_verify.c 
b/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/ocloexec_verify.c
index ea8ad0e058b1..e33c61f03d54 100644
--- a/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/ocloexec_verify.c
+++ b/cddl/contrib/opensolaris/tests/os-tests/tests/oclo/ocloexec_verify.c
@@ -23,20 +23,36 @@
  * properly cleared.
  */
 
+#include <sys/types.h>
+#include <sys/user.h>
 #include <err.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <libutil.h>
 #include <stdbool.h>
-#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+
+#define strerrorname_np(e) (sys_errlist[e])
 
 static int
-verify_fdwalk_cb(void *arg, int fd)
+getmaxfd(void)
 {
-       int *max = arg;
-       *max = fd;
-       return (0);
+       struct kinfo_file *files;
+       int i, cnt, max;
+
+       if ((files = kinfo_getfile(getpid(), &cnt)) == NULL)
+               err(1, "kinfo_getfile");
+
+       max = -1;
+       for (i = 0; i < cnt; i++)
+               if (files[i].kf_fd > max)
+                       max = files[i].kf_fd;
+
+       free(files);
+       return (max);
 }
 
 /*
@@ -103,7 +119,7 @@ verify_flags(int fd, int exp_flags)
 int
 main(int argc, char *argv[])
 {
-       int maxfd = STDIN_FILENO;
+       int maxfd;
        int ret = EXIT_SUCCESS;
 
        /*
@@ -112,24 +128,25 @@ main(int argc, char *argv[])
         * program name, which we want to skip. Note, the last fd may not exist
         * because it was marked for close, hence the use of '>' below.
         */
-       (void) fdwalk(verify_fdwalk_cb, &maxfd);
+       maxfd = getmaxfd();
        if (maxfd - 3 > argc - 1) {
                errx(EXIT_FAILURE, "TEST FAILED: found more fds %d than "
                    "arguments %d", maxfd - 3, argc - 1);
        }
 
        for (int i = 1; i < argc; i++) {
-               const char *errstr;
+               char *endptr;
                int targ_fd = i + STDERR_FILENO;
-               long long targ_flags = strtonumx(argv[i], 0,
-                   FD_CLOEXEC | FD_CLOFORK, &errstr, 0);
+               errno = 0;
+               long long val = strtoll(argv[i], &endptr, 0);
 
-               if (errstr != NULL) {
+               if (errno != 0 || *endptr != '\0' ||
+                   (val < 0 || val > (FD_CLOEXEC | FD_CLOFORK))) {
                        errx(EXIT_FAILURE, "TEST FAILED: failed to parse "
-                           "argument %d: %s is %s", i, argv[i], errstr);
+                           "argument %d: %s", i, argv[i]);
                }
 
-               if (!verify_flags(targ_fd, (int)targ_flags))
+               if (!verify_flags(targ_fd, (int)val))
                        ret = EXIT_FAILURE;
        }
 
diff --git a/tests/Makefile b/tests/Makefile
index e8dd7793f169..451d55498a26 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,3 +1,5 @@
+.include <src.opts.mk>
+
 PACKAGE= tests
 
 TESTSDIR= ${TESTSBASE}
@@ -11,6 +13,9 @@ SUBDIR+= examples
 SUBDIR+= include
 SUBDIR+= sys
 SUBDIR+= atf_python
+.if ${MK_CDDL} != "no"
+SUBDIR+= oclo
+.endif
 
 SUBDIR_PARALLEL=
 
diff --git a/tests/oclo/Makefile b/tests/oclo/Makefile
new file mode 100644
index 000000000000..350c9f857c85
--- /dev/null
+++ b/tests/oclo/Makefile
@@ -0,0 +1,11 @@
+.PATH: ${SRCTOP}/cddl/contrib/opensolaris/tests/os-tests/tests/oclo
+
+TESTSDIR=      ${TESTSBASE}/cddl/oclo
+
+PLAIN_TESTS_C= oclo oclo_errors ocloexec_verify
+
+SRCS.oclo=     oclo.c
+LIBADD.oclo+=  openbsd
+LIBADD.ocloexec_verify+= util
+
+.include <bsd.test.mk>

Reply via email to