#include <sys/filio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <atf-c.h>
#define CORRECT_O_ACCMODE (O_ACCMODE | O_EXEC)
static void
basic_tests(const char *path, int omode, const char *omodetext)
{
int fd, flags1, flags2, flags3;
fd = open(path, omode);
ATF_REQUIRE_MSG(fd != -1, "open(\"%s\", %s) failed: %s", path,
omodetext, strerror(errno));
flags1 = fcntl(fd, F_GETFL);
ATF_REQUIRE_MSG(flags1 != -1, "fcntl(F_GETFL) (1) failed: %s",
strerror(errno));
ATF_REQUIRE_INTEQ(omode, flags1 & CORRECT_O_ACCMODE);
ATF_REQUIRE((flags1 & O_NONBLOCK) == 0);
ATF_REQUIRE_MSG(fcntl(fd, F_SETFL, flags1) != -1,
"fcntl(F_SETFL) same flags failed: %s", strerror(errno));
flags2 = fcntl(fd, F_GETFL);
ATF_REQUIRE_MSG(flags2 != -1, "fcntl(F_GETFL) (2) failed: %s",
strerror(errno));
ATF_REQUIRE_INTEQ(flags1, flags2);
ATF_REQUIRE_MSG(fcntl(fd, F_SETFL, flags2 | O_NONBLOCK) != -1,
"fcntl(F_SETFL) O_NONBLOCK failed: %s", strerror(errno));
flags3 = fcntl(fd, F_GETFL);
ATF_REQUIRE_MSG(flags3 != -1, "fcntl(F_GETFL) (3) failed: %s",
strerror(errno));
ATF_REQUIRE_INTEQ(flags2 | O_NONBLOCK, flags3);
(void)close(fd);
}
ATF_TC_WITHOUT_HEAD(read_only_null);
ATF_TC_BODY(read_only_null, tc)
{
basic_tests("/dev/null", O_RDONLY, "O_RDONLY");
}
ATF_TC_WITHOUT_HEAD(write_only_null);
ATF_TC_BODY(write_only_null, tc)
{
basic_tests("/dev/null", O_WRONLY, "O_WRONLY");
}
ATF_TC_WITHOUT_HEAD(read_write_null);
ATF_TC_BODY(read_write_null, tc)
{
basic_tests("/dev/null", O_RDWR, "O_RDWR");
}
ATF_TC_WITHOUT_HEAD(exec_only_sh);
ATF_TC_BODY(exec_only_sh, tc)
{
basic_tests("/bin/sh", O_EXEC, "O_EXEC");
}
ATF_TC_WITHOUT_HEAD(fioasync_dev_null);
ATF_TC_BODY(fioasync_dev_null, tc)
{
int fd, flags1, flags2, val;
fd = open("/dev/null", O_RDONLY);
ATF_REQUIRE_MSG(fd != -1, "open(\"/dev/null\") failed: %s",
strerror(errno));
flags1 = fcntl(fd, F_GETFL);
ATF_REQUIRE_MSG(flags1 != -1, "fcntl(F_GETFL) (1) failed: %s",
strerror(errno));
ATF_REQUIRE((flags1 & O_ASYNC) == 0);
val = 1;
ATF_REQUIRE_ERRNO(EINVAL, ioctl(fd, FIOASYNC, &val) == -1);
flags2 = fcntl(fd, F_GETFL);
ATF_REQUIRE_MSG(flags2 != -1, "fcntl(F_GETFL) (2) failed: %s",
strerror(errno));
ATF_REQUIRE_INTEQ(flags1, flags2);
(void)close(fd);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, read_only_null);
ATF_TP_ADD_TC(tp, write_only_null);
ATF_TP_ADD_TC(tp, read_write_null);
ATF_TP_ADD_TC(tp, exec_only_sh);
ATF_TP_ADD_TC(tp, fioasync_dev_null);
return (atf_no_error());
}