1171707Sdes/*- 2199134Sdes * Copyright (c) 2007-2009 Dag-Erling Co��dan Sm��rgrav 3171707Sdes * All rights reserved. 4171707Sdes * 5171707Sdes * Redistribution and use in source and binary forms, with or without 6171707Sdes * modification, are permitted provided that the following conditions 7171707Sdes * are met: 8171707Sdes * 1. Redistributions of source code must retain the above copyright 9171707Sdes * notice, this list of conditions and the following disclaimer 10171707Sdes * in this position and unchanged. 11171707Sdes * 2. Redistributions in binary form must reproduce the above copyright 12171707Sdes * notice, this list of conditions and the following disclaimer in the 13171707Sdes * documentation and/or other materials provided with the distribution. 14171707Sdes * 15171707Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16171707Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17171707Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18171707Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19171707Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20171707Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21171707Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22171707Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23171707Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24171707Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25171707Sdes * SUCH DAMAGE. 26171707Sdes */ 27171707Sdes 28171707Sdes#include <sys/cdefs.h> 29171707Sdes__FBSDID("$FreeBSD$"); 30171707Sdes 31171707Sdes#include <sys/types.h> 32171707Sdes#include <sys/fcntl.h> 33171707Sdes 34171707Sdes#include <errno.h> 35199212Sdes#include <signal.h> 36171707Sdes#include <stdint.h> 37171707Sdes#include <stdio.h> 38171707Sdes#include <stdlib.h> 39171707Sdes#include <string.h> 40171707Sdes#include <unistd.h> 41171707Sdes 42171707Sdes#include <libutil.h> 43171707Sdes 44171707Sdes/* 45171707Sdes * Test that flopen() can create a file. 46171707Sdes */ 47171707Sdesconst char * 48171707Sdestest_flopen_create(void) 49171707Sdes{ 50171707Sdes const char *fn = "test_flopen_create"; 51171707Sdes const char *result = NULL; 52171707Sdes int fd; 53171707Sdes 54171707Sdes unlink(fn); 55171707Sdes fd = flopen(fn, O_RDWR|O_CREAT, 0640); 56171707Sdes if (fd < 0) { 57171707Sdes result = strerror(errno); 58171707Sdes } else { 59171707Sdes close(fd); 60171707Sdes } 61171707Sdes unlink(fn); 62171707Sdes return (result); 63171707Sdes} 64171707Sdes 65171707Sdes/* 66171707Sdes * Test that flopen() can open an existing file. 67171707Sdes */ 68171707Sdesconst char * 69171707Sdestest_flopen_open(void) 70171707Sdes{ 71171707Sdes const char *fn = "test_flopen_open"; 72171707Sdes const char *result = NULL; 73171707Sdes int fd; 74171707Sdes 75171707Sdes fd = open(fn, O_RDWR|O_CREAT, 0640); 76171707Sdes if (fd < 0) { 77171707Sdes result = strerror(errno); 78171707Sdes } else { 79171707Sdes close(fd); 80171707Sdes fd = flopen(fn, O_RDWR); 81171707Sdes if (fd < 0) { 82171707Sdes result = strerror(errno); 83171707Sdes } else { 84171707Sdes close(fd); 85171707Sdes } 86171707Sdes } 87171707Sdes unlink(fn); 88171707Sdes return (result); 89171707Sdes} 90171707Sdes 91171707Sdes/* 92171707Sdes * Test that flopen() can lock against itself 93171707Sdes */ 94171707Sdesconst char * 95171707Sdestest_flopen_lock_self(void) 96171707Sdes{ 97193592Sdes const char *fn = "test_flopen_lock_self"; 98171707Sdes const char *result = NULL; 99171707Sdes int fd1, fd2; 100171707Sdes 101171707Sdes unlink(fn); 102171707Sdes fd1 = flopen(fn, O_RDWR|O_CREAT, 0640); 103171707Sdes if (fd1 < 0) { 104171707Sdes result = strerror(errno); 105171707Sdes } else { 106171707Sdes fd2 = flopen(fn, O_RDWR|O_NONBLOCK); 107171707Sdes if (fd2 >= 0) { 108171707Sdes result = "second open succeeded"; 109171707Sdes close(fd2); 110171707Sdes } 111171707Sdes close(fd1); 112171707Sdes } 113171707Sdes unlink(fn); 114171707Sdes return (result); 115171707Sdes} 116171707Sdes 117171707Sdes/* 118171707Sdes * Test that flopen() can lock against other processes 119171707Sdes */ 120171707Sdesconst char * 121171707Sdestest_flopen_lock_other(void) 122171707Sdes{ 123193592Sdes const char *fn = "test_flopen_lock_other"; 124171707Sdes const char *result = NULL; 125171707Sdes volatile int fd1, fd2; 126171707Sdes 127171707Sdes unlink(fn); 128171707Sdes fd1 = flopen(fn, O_RDWR|O_CREAT, 0640); 129171707Sdes if (fd1 < 0) { 130171707Sdes result = strerror(errno); 131171707Sdes } else { 132171707Sdes fd2 = -42; 133171707Sdes if (vfork() == 0) { 134171707Sdes fd2 = flopen(fn, O_RDWR|O_NONBLOCK); 135171707Sdes close(fd2); 136171707Sdes _exit(0); 137171707Sdes } 138171707Sdes if (fd2 == -42) 139171707Sdes result = "vfork() doesn't work as expected"; 140171707Sdes if (fd2 >= 0) 141171707Sdes result = "second open succeeded"; 142171707Sdes close(fd1); 143171707Sdes } 144171707Sdes unlink(fn); 145171707Sdes return (result); 146171707Sdes} 147171707Sdes 148193592Sdes/* 149193592Sdes * Test that child processes inherit the lock 150193592Sdes */ 151193592Sdesconst char * 152193592Sdestest_flopen_lock_child(void) 153193592Sdes{ 154193592Sdes const char *fn = "test_flopen_lock_child"; 155193592Sdes const char *result = NULL; 156193592Sdes pid_t pid; 157193592Sdes volatile int fd1, fd2; 158193592Sdes 159193592Sdes unlink(fn); 160193592Sdes fd1 = flopen(fn, O_RDWR|O_CREAT, 0640); 161193592Sdes if (fd1 < 0) { 162193592Sdes result = strerror(errno); 163193592Sdes } else { 164199134Sdes pid = fork(); 165199134Sdes if (pid == -1) { 166199134Sdes result = strerror(errno); 167199134Sdes } else if (pid == 0) { 168193592Sdes select(0, 0, 0, 0, 0); 169193592Sdes _exit(0); 170193592Sdes } 171193592Sdes close(fd1); 172199212Sdes if ((fd2 = flopen(fn, O_RDWR|O_NONBLOCK)) != -1) { 173199212Sdes result = "second open succeeded"; 174193592Sdes close(fd2); 175193592Sdes } 176193592Sdes kill(pid, SIGINT); 177193592Sdes } 178193592Sdes unlink(fn); 179193592Sdes return (result); 180193592Sdes} 181193592Sdes 182171707Sdesstatic struct test { 183171707Sdes const char *name; 184171707Sdes const char *(*func)(void); 185171707Sdes} t[] = { 186171707Sdes { "flopen_create", test_flopen_create }, 187171707Sdes { "flopen_open", test_flopen_open }, 188171707Sdes { "flopen_lock_self", test_flopen_lock_self }, 189171707Sdes { "flopen_lock_other", test_flopen_lock_other }, 190193592Sdes { "flopen_lock_child", test_flopen_lock_child }, 191171707Sdes}; 192171707Sdes 193171707Sdesint 194171707Sdesmain(void) 195171707Sdes{ 196171707Sdes const char *result; 197171707Sdes int i, nt; 198171707Sdes 199171707Sdes nt = sizeof(t) / sizeof(*t); 200171707Sdes printf("1..%d\n", nt); 201171707Sdes for (i = 0; i < nt; ++i) { 202171707Sdes if ((result = t[i].func()) != NULL) 203171707Sdes printf("not ok %d - %s # %s\n", i + 1, 204171707Sdes t[i].name, result); 205171707Sdes else 206171707Sdes printf("ok %d - %s\n", i + 1, 207171707Sdes t[i].name); 208171707Sdes } 209171707Sdes exit(0); 210171707Sdes} 211