1169446Sdes/*- 2184094Sdes * Copyright (c) 2007 Dag-Erling Co��dan Sm��rgrav 3169446Sdes * All rights reserved. 4169446Sdes * 5169446Sdes * Redistribution and use in source and binary forms, with or without 6169446Sdes * modification, are permitted provided that the following conditions 7169446Sdes * are met: 8169446Sdes * 1. Redistributions of source code must retain the above copyright 9169446Sdes * notice, this list of conditions and the following disclaimer 10169446Sdes * in this position and unchanged. 11169446Sdes * 2. Redistributions in binary form must reproduce the above copyright 12169446Sdes * notice, this list of conditions and the following disclaimer in the 13169446Sdes * documentation and/or other materials provided with the distribution. 14169446Sdes * 15169446Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16169446Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17169446Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18169446Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19169446Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20169446Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21169446Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22169446Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23169446Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24169446Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25169446Sdes * SUCH DAMAGE. 26169446Sdes */ 27169446Sdes 28169446Sdes#include <sys/cdefs.h> 29169446Sdes__FBSDID("$FreeBSD$"); 30169446Sdes 31193591Sdes#include <sys/file.h> 32169446Sdes#include <sys/stat.h> 33169446Sdes 34169446Sdes#include <errno.h> 35169446Sdes#include <stdarg.h> 36169450Sdes#include <unistd.h> 37169446Sdes 38169450Sdes#include <libutil.h> 39169450Sdes 40169446Sdesint 41169446Sdesflopen(const char *path, int flags, ...) 42169446Sdes{ 43169899Sdes int fd, operation, serrno, trunc; 44169446Sdes struct stat sb, fsb; 45169446Sdes mode_t mode; 46169446Sdes 47169446Sdes#ifdef O_EXLOCK 48169446Sdes flags &= ~O_EXLOCK; 49169446Sdes#endif 50169446Sdes 51169447Sdes mode = 0; 52169446Sdes if (flags & O_CREAT) { 53169446Sdes va_list ap; 54169446Sdes 55169446Sdes va_start(ap, flags); 56184094Sdes mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */ 57169446Sdes va_end(ap); 58169446Sdes } 59169446Sdes 60193591Sdes operation = LOCK_EX; 61193591Sdes if (flags & O_NONBLOCK) 62193591Sdes operation |= LOCK_NB; 63169447Sdes 64169899Sdes trunc = (flags & O_TRUNC); 65169897Sdes flags &= ~O_TRUNC; 66169894Sdes 67169446Sdes for (;;) { 68169446Sdes if ((fd = open(path, flags, mode)) == -1) 69169446Sdes /* non-existent or no access */ 70169446Sdes return (-1); 71193591Sdes if (flock(fd, operation) == -1) { 72169446Sdes /* unsupported or interrupted */ 73169446Sdes serrno = errno; 74184094Sdes (void)close(fd); 75169446Sdes errno = serrno; 76169446Sdes return (-1); 77169446Sdes } 78169446Sdes if (stat(path, &sb) == -1) { 79169446Sdes /* disappeared from under our feet */ 80184094Sdes (void)close(fd); 81169446Sdes continue; 82169446Sdes } 83169446Sdes if (fstat(fd, &fsb) == -1) { 84169446Sdes /* can't happen [tm] */ 85169446Sdes serrno = errno; 86184094Sdes (void)close(fd); 87169446Sdes errno = serrno; 88169446Sdes return (-1); 89169446Sdes } 90169446Sdes if (sb.st_dev != fsb.st_dev || 91169446Sdes sb.st_ino != fsb.st_ino) { 92169446Sdes /* changed under our feet */ 93184094Sdes (void)close(fd); 94169446Sdes continue; 95169446Sdes } 96169899Sdes if (trunc && ftruncate(fd, 0) != 0) { 97169894Sdes /* can't happen [tm] */ 98169894Sdes serrno = errno; 99184094Sdes (void)close(fd); 100169894Sdes errno = serrno; 101169894Sdes return (-1); 102169894Sdes } 103169446Sdes return (fd); 104169446Sdes } 105169446Sdes} 106