mirror of
https://git.freebsd.org/src.git
synced 2026-01-11 19:57:22 +00:00
tests: Adapt oclo tests to FreeBSD
MFC after: 1 month Pull Request: https://github.com/freebsd/freebsd-src/pull/1698
This commit is contained in:
parent
20ee243707
commit
4140012f83
5 changed files with 128 additions and 55 deletions
|
|
@ -45,22 +45,55 @@
|
|||
* 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 <errno.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <libgen.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -23,20 +23,36 @@
|
|||
* properly cleared.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libutil.h>
|
||||
#include <stdbool.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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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=
|
||||
|
||||
|
|
|
|||
11
tests/oclo/Makefile
Normal file
11
tests/oclo/Makefile
Normal file
|
|
@ -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>
|
||||
Loading…
Add table
Reference in a new issue