#include <sys/ioctl.h>
#include <sys/limits.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <signal.h>
#include <unistd.h>
#include "common.h"
static char buf[1024];
int
test_common_badpgid(int fd)
{
int pgid;
pgid = 1000000;
errno = 0;
assert(fcntl(fd, F_SETOWN, pgid) == -1);
assert(errno == ESRCH);
errno = 0;
assert(ioctl(fd, FIOSETOWN, &pgid) == -1);
assert(errno == ESRCH);
pgid = -1000000;
errno = 0;
assert(fcntl(fd, F_SETOWN, pgid) == -1);
assert(errno == ESRCH);
errno = 0;
assert(ioctl(fd, FIOSETOWN, &pgid) == -1);
assert(errno == ESRCH);
return 0;
}
int
test_common_badsession(int fd)
{
int arg, sfd;
pid_t pid, ppid;
assert(setpgid(0, 0) == 0);
ppid = getpid();
if (test_fork(&pid, &sfd) == PARENT) {
test_barrier(sfd);
} else {
assert(setsid() != -1);
errno = 0;
assert(fcntl(fd, F_SETOWN, ppid) == -1);
assert(errno == EPERM);
errno = 0;
assert(fcntl(fd, F_SETOWN, -ppid) == -1);
assert(errno == EPERM);
arg = ppid;
errno = 0;
assert(ioctl(fd, FIOSETOWN, &arg) == -1);
assert(errno == EPERM);
arg = -ppid;
errno = 0;
assert(ioctl(fd, FIOSETOWN, &arg) == -1);
assert(errno == EPERM);
test_barrier(sfd);
}
return test_wait(pid, sfd);
}
int
test_common_cansigio(int *fds)
{
struct passwd *pw;
int flags, sfd;
pid_t pid, ppid;
assert((pw = getpwnam(SIGIO_REGRESS_USER)) != NULL);
assert(pw->pw_uid != getuid());
flags = fcntl(fds[0], F_GETFL);
assert(fcntl(fds[0], F_SETFL, flags | O_ASYNC) == 0);
ppid = getpid();
if (test_fork(&pid, &sfd) == PARENT) {
reject_signal(SIGIO);
test_barrier(sfd);
test_barrier(sfd);
reject_signal(SIGIO);
assert(read(fds[0], buf, 1) == 1);
test_barrier(sfd);
assert(setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == 0);
reject_signal(SIGIO);
test_barrier(sfd);
test_barrier(sfd);
expect_signal(SIGIO);
assert(read(fds[0], buf, 1) == 1);
} else {
assert(setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == 0);
assert(fcntl(fds[0], F_SETOWN, ppid) == 0);
test_barrier(sfd);
assert(write(fds[1], buf, 1) == 1);
test_barrier(sfd);
test_barrier(sfd);
test_barrier(sfd);
assert(write(fds[1], buf, 1) == 1);
test_barrier(sfd);
}
return test_wait(pid, sfd);
}
int
test_common_getown(int fd)
{
int pgid;
assert(fcntl(fd, F_GETOWN) == 0);
pgid = getpid();
assert(fcntl(fd, F_SETOWN, pgid) == 0);
assert(fcntl(fd, F_GETOWN) == pgid);
pgid = -getpgrp();
assert(fcntl(fd, F_SETOWN, pgid) == 0);
assert(fcntl(fd, F_GETOWN) == pgid);
assert(fcntl(fd, F_SETOWN, 0) == 0);
assert(fcntl(fd, F_GETOWN) == 0);
pgid = INT_MIN;
assert(ioctl(fd, FIOGETOWN, &pgid) == 0);
assert(pgid == 0);
pgid = getpid();
assert(ioctl(fd, FIOSETOWN, &pgid) == 0);
pgid = INT_MIN;
assert(ioctl(fd, FIOGETOWN, &pgid) == 0);
assert(pgid == getpid());
pgid = -getpgrp();
assert(ioctl(fd, FIOSETOWN, &pgid) == 0);
pgid = INT_MIN;
assert(ioctl(fd, FIOGETOWN, &pgid) == 0);
assert(pgid == -getpgrp());
pgid = 0;
assert(ioctl(fd, FIOSETOWN, &pgid) == 0);
pgid = INT_MIN;
assert(ioctl(fd, FIOGETOWN, &pgid) == 0);
assert(pgid == 0);
return 0;
}
int
test_common_read(int *fds)
{
int flags, sfd;
pid_t pid;
flags = fcntl(fds[0], F_GETFL);
assert(fcntl(fds[0], F_SETFL, flags | O_ASYNC) == 0);
assert(fcntl(fds[0], F_SETOWN, getpid()) == 0);
if (test_fork(&pid, &sfd) == PARENT) {
reject_signal(SIGIO);
test_barrier(sfd);
test_barrier(sfd);
expect_signal(SIGIO);
assert(read(fds[0], buf, 1) == 1);
} else {
test_barrier(sfd);
assert(write(fds[1], buf, 1) == 1);
test_barrier(sfd);
}
return test_wait(pid, sfd);
}
int
test_common_write(int *fds)
{
ssize_t n;
int flags, sfd;
pid_t pid;
flags = fcntl(fds[0], F_GETFL);
assert(fcntl(fds[0], F_SETFL, flags | O_ASYNC | O_NONBLOCK) == 0);
flags = fcntl(fds[1], F_GETFL);
assert(fcntl(fds[1], F_SETFL, flags | O_NONBLOCK) == 0);
assert(fcntl(fds[0], F_SETOWN, getpid()) == 0);
if (test_fork(&pid, &sfd) == PARENT) {
while ((n = write(fds[0], buf, sizeof(buf))) > 0)
continue;
assert(n == -1);
assert(errno == EWOULDBLOCK);
reject_signal(SIGIO);
test_barrier(sfd);
test_barrier(sfd);
expect_signal(SIGIO);
assert(write(fds[0], buf, 1) == 1);
} else {
test_barrier(sfd);
while ((n = read(fds[1], buf, sizeof(buf))) > 0)
continue;
assert(n == -1);
assert(errno == EWOULDBLOCK);
test_barrier(sfd);
}
return test_wait(pid, sfd);
}