xref: /freebsd/lib/libutil/tests/flopen_test.c (revision a2f733abcff64628b7771a47089628b7327a88bd)
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