15aa45fcbSEnji Cooper /*-
2*e738085bSDag-Erling Smørgrav * Copyright (c) 2007-2009 Dag-Erling Smørgrav
35aa45fcbSEnji Cooper * All rights reserved.
45aa45fcbSEnji Cooper *
55aa45fcbSEnji Cooper * Redistribution and use in source and binary forms, with or without
65aa45fcbSEnji Cooper * modification, are permitted provided that the following conditions
75aa45fcbSEnji Cooper * are met:
85aa45fcbSEnji Cooper * 1. Redistributions of source code must retain the above copyright
95aa45fcbSEnji Cooper * notice, this list of conditions and the following disclaimer
105aa45fcbSEnji Cooper * in this position and unchanged.
115aa45fcbSEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
125aa45fcbSEnji Cooper * notice, this list of conditions and the following disclaimer in the
135aa45fcbSEnji Cooper * documentation and/or other materials provided with the distribution.
145aa45fcbSEnji Cooper *
155aa45fcbSEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
165aa45fcbSEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175aa45fcbSEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
185aa45fcbSEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
195aa45fcbSEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
205aa45fcbSEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
215aa45fcbSEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
225aa45fcbSEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
235aa45fcbSEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
245aa45fcbSEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
255aa45fcbSEnji Cooper * SUCH DAMAGE.
265aa45fcbSEnji Cooper */
275aa45fcbSEnji Cooper
285aa45fcbSEnji Cooper #include <sys/types.h>
295aa45fcbSEnji Cooper #include <sys/fcntl.h>
305aa45fcbSEnji Cooper
315aa45fcbSEnji Cooper #include <errno.h>
325aa45fcbSEnji Cooper #include <signal.h>
335aa45fcbSEnji Cooper #include <stdint.h>
345aa45fcbSEnji Cooper #include <stdio.h>
355aa45fcbSEnji Cooper #include <stdlib.h>
365aa45fcbSEnji Cooper #include <string.h>
375aa45fcbSEnji Cooper #include <unistd.h>
385aa45fcbSEnji Cooper
395aa45fcbSEnji Cooper #include <libutil.h>
405aa45fcbSEnji Cooper
415aa45fcbSEnji Cooper /*
425aa45fcbSEnji Cooper * Test that flopen() can create a file.
435aa45fcbSEnji Cooper */
445aa45fcbSEnji Cooper const char *
test_flopen_create(void)455aa45fcbSEnji Cooper test_flopen_create(void)
465aa45fcbSEnji Cooper {
475aa45fcbSEnji Cooper const char *fn = "test_flopen_create";
485aa45fcbSEnji Cooper const char *result = NULL;
495aa45fcbSEnji Cooper int fd;
505aa45fcbSEnji Cooper
515aa45fcbSEnji Cooper unlink(fn);
525aa45fcbSEnji Cooper fd = flopen(fn, O_RDWR|O_CREAT, 0640);
535aa45fcbSEnji Cooper if (fd < 0) {
545aa45fcbSEnji Cooper result = strerror(errno);
555aa45fcbSEnji Cooper } else {
565aa45fcbSEnji Cooper close(fd);
575aa45fcbSEnji Cooper }
585aa45fcbSEnji Cooper unlink(fn);
595aa45fcbSEnji Cooper return (result);
605aa45fcbSEnji Cooper }
615aa45fcbSEnji Cooper
625aa45fcbSEnji Cooper /*
635aa45fcbSEnji Cooper * Test that flopen() can open an existing file.
645aa45fcbSEnji Cooper */
655aa45fcbSEnji Cooper const char *
test_flopen_open(void)665aa45fcbSEnji Cooper test_flopen_open(void)
675aa45fcbSEnji Cooper {
685aa45fcbSEnji Cooper const char *fn = "test_flopen_open";
695aa45fcbSEnji Cooper const char *result = NULL;
705aa45fcbSEnji Cooper int fd;
715aa45fcbSEnji Cooper
725aa45fcbSEnji Cooper fd = open(fn, O_RDWR|O_CREAT, 0640);
735aa45fcbSEnji Cooper if (fd < 0) {
745aa45fcbSEnji Cooper result = strerror(errno);
755aa45fcbSEnji Cooper } else {
765aa45fcbSEnji Cooper close(fd);
775aa45fcbSEnji Cooper fd = flopen(fn, O_RDWR);
785aa45fcbSEnji Cooper if (fd < 0) {
795aa45fcbSEnji Cooper result = strerror(errno);
805aa45fcbSEnji Cooper } else {
815aa45fcbSEnji Cooper close(fd);
825aa45fcbSEnji Cooper }
835aa45fcbSEnji Cooper }
845aa45fcbSEnji Cooper unlink(fn);
855aa45fcbSEnji Cooper return (result);
865aa45fcbSEnji Cooper }
875aa45fcbSEnji Cooper
885aa45fcbSEnji Cooper /*
895aa45fcbSEnji Cooper * Test that flopen() can lock against itself
905aa45fcbSEnji Cooper */
915aa45fcbSEnji Cooper const char *
test_flopen_lock_self(void)925aa45fcbSEnji Cooper test_flopen_lock_self(void)
935aa45fcbSEnji Cooper {
945aa45fcbSEnji Cooper const char *fn = "test_flopen_lock_self";
955aa45fcbSEnji Cooper const char *result = NULL;
965aa45fcbSEnji Cooper int fd1, fd2;
975aa45fcbSEnji Cooper
985aa45fcbSEnji Cooper unlink(fn);
995aa45fcbSEnji Cooper fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
1005aa45fcbSEnji Cooper if (fd1 < 0) {
1015aa45fcbSEnji Cooper result = strerror(errno);
1025aa45fcbSEnji Cooper } else {
1035aa45fcbSEnji Cooper fd2 = flopen(fn, O_RDWR|O_NONBLOCK);
1045aa45fcbSEnji Cooper if (fd2 >= 0) {
1055aa45fcbSEnji Cooper result = "second open succeeded";
1065aa45fcbSEnji Cooper close(fd2);
1075aa45fcbSEnji Cooper }
1085aa45fcbSEnji Cooper close(fd1);
1095aa45fcbSEnji Cooper }
1105aa45fcbSEnji Cooper unlink(fn);
1115aa45fcbSEnji Cooper return (result);
1125aa45fcbSEnji Cooper }
1135aa45fcbSEnji Cooper
1145aa45fcbSEnji Cooper /*
1155aa45fcbSEnji Cooper * Test that flopen() can lock against other processes
1165aa45fcbSEnji Cooper */
1175aa45fcbSEnji Cooper const char *
test_flopen_lock_other(void)1185aa45fcbSEnji Cooper test_flopen_lock_other(void)
1195aa45fcbSEnji Cooper {
1205aa45fcbSEnji Cooper const char *fn = "test_flopen_lock_other";
1215aa45fcbSEnji Cooper const char *result = NULL;
1225aa45fcbSEnji Cooper volatile int fd1, fd2;
1235aa45fcbSEnji Cooper
1245aa45fcbSEnji Cooper unlink(fn);
1255aa45fcbSEnji Cooper fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
1265aa45fcbSEnji Cooper if (fd1 < 0) {
1275aa45fcbSEnji Cooper result = strerror(errno);
1285aa45fcbSEnji Cooper } else {
1295aa45fcbSEnji Cooper fd2 = -42;
1305aa45fcbSEnji Cooper if (vfork() == 0) {
1315aa45fcbSEnji Cooper fd2 = flopen(fn, O_RDWR|O_NONBLOCK);
1325aa45fcbSEnji Cooper close(fd2);
1335aa45fcbSEnji Cooper _exit(0);
1345aa45fcbSEnji Cooper }
1355aa45fcbSEnji Cooper if (fd2 == -42)
1365aa45fcbSEnji Cooper result = "vfork() doesn't work as expected";
1375aa45fcbSEnji Cooper if (fd2 >= 0)
1385aa45fcbSEnji Cooper result = "second open succeeded";
1395aa45fcbSEnji Cooper close(fd1);
1405aa45fcbSEnji Cooper }
1415aa45fcbSEnji Cooper unlink(fn);
1425aa45fcbSEnji Cooper return (result);
1435aa45fcbSEnji Cooper }
1445aa45fcbSEnji Cooper
1455aa45fcbSEnji Cooper /*
1465aa45fcbSEnji Cooper * Test that child processes inherit the lock
1475aa45fcbSEnji Cooper */
1485aa45fcbSEnji Cooper const char *
test_flopen_lock_child(void)1495aa45fcbSEnji Cooper test_flopen_lock_child(void)
1505aa45fcbSEnji Cooper {
1515aa45fcbSEnji Cooper const char *fn = "test_flopen_lock_child";
1525aa45fcbSEnji Cooper const char *result = NULL;
1535aa45fcbSEnji Cooper pid_t pid;
1545aa45fcbSEnji Cooper volatile int fd1, fd2;
1555aa45fcbSEnji Cooper
1565aa45fcbSEnji Cooper unlink(fn);
1575aa45fcbSEnji Cooper fd1 = flopen(fn, O_RDWR|O_CREAT, 0640);
1585aa45fcbSEnji Cooper if (fd1 < 0) {
1595aa45fcbSEnji Cooper result = strerror(errno);
1605aa45fcbSEnji Cooper } else {
1615aa45fcbSEnji Cooper pid = fork();
1625aa45fcbSEnji Cooper if (pid == -1) {
1635aa45fcbSEnji Cooper result = strerror(errno);
1645aa45fcbSEnji Cooper } else if (pid == 0) {
1655aa45fcbSEnji Cooper select(0, 0, 0, 0, 0);
1665aa45fcbSEnji Cooper _exit(0);
1675aa45fcbSEnji Cooper }
1685aa45fcbSEnji Cooper close(fd1);
1695aa45fcbSEnji Cooper if ((fd2 = flopen(fn, O_RDWR|O_NONBLOCK)) != -1) {
1705aa45fcbSEnji Cooper result = "second open succeeded";
1715aa45fcbSEnji Cooper close(fd2);
1725aa45fcbSEnji Cooper }
1735aa45fcbSEnji Cooper kill(pid, SIGINT);
1745aa45fcbSEnji Cooper }
1755aa45fcbSEnji Cooper unlink(fn);
1765aa45fcbSEnji Cooper return (result);
1775aa45fcbSEnji Cooper }
1785aa45fcbSEnji Cooper
1795aa45fcbSEnji Cooper static struct test {
1805aa45fcbSEnji Cooper const char *name;
1815aa45fcbSEnji Cooper const char *(*func)(void);
1825aa45fcbSEnji Cooper } t[] = {
1835aa45fcbSEnji Cooper { "flopen_create", test_flopen_create },
1845aa45fcbSEnji Cooper { "flopen_open", test_flopen_open },
1855aa45fcbSEnji Cooper { "flopen_lock_self", test_flopen_lock_self },
1865aa45fcbSEnji Cooper { "flopen_lock_other", test_flopen_lock_other },
1875aa45fcbSEnji Cooper { "flopen_lock_child", test_flopen_lock_child },
1885aa45fcbSEnji Cooper };
1895aa45fcbSEnji Cooper
1905aa45fcbSEnji Cooper int
main(void)1915aa45fcbSEnji Cooper main(void)
1925aa45fcbSEnji Cooper {
1935aa45fcbSEnji Cooper const char *result;
1945aa45fcbSEnji Cooper int i, nt;
1955aa45fcbSEnji Cooper
1965aa45fcbSEnji Cooper nt = sizeof(t) / sizeof(*t);
1975aa45fcbSEnji Cooper printf("1..%d\n", nt);
1985aa45fcbSEnji Cooper for (i = 0; i < nt; ++i) {
1995aa45fcbSEnji Cooper if ((result = t[i].func()) != NULL)
2005aa45fcbSEnji Cooper printf("not ok %d - %s # %s\n", i + 1,
2015aa45fcbSEnji Cooper t[i].name, result);
2025aa45fcbSEnji Cooper else
2035aa45fcbSEnji Cooper printf("ok %d - %s\n", i + 1,
2045aa45fcbSEnji Cooper t[i].name);
2055aa45fcbSEnji Cooper }
2065aa45fcbSEnji Cooper exit(0);
2075aa45fcbSEnji Cooper }
208