1243730Srwatson/*- 2243730Srwatson * Copyright (c) 2007 Dag-Erling Co��dan Sm��rgrav 3243730Srwatson * All rights reserved. 4243730Srwatson * 5243730Srwatson * Redistribution and use in source and binary forms, with or without 6243730Srwatson * modification, are permitted provided that the following conditions 7243730Srwatson * are met: 8243730Srwatson * 1. Redistributions of source code must retain the above copyright 9243730Srwatson * notice, this list of conditions and the following disclaimer 10243730Srwatson * in this position and unchanged. 11243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright 12243730Srwatson * notice, this list of conditions and the following disclaimer in the 13243730Srwatson * documentation and/or other materials provided with the distribution. 14243730Srwatson * 15243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18243730Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20243730Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25243730Srwatson * SUCH DAMAGE. 26243730Srwatson * 27243730Srwatson * Derived from FreeBSD head/lib/libutil/flopen.c r193591 28243730Srwatson */ 29243730Srwatson 30243730Srwatson#include <sys/file.h> 31243730Srwatson#include <sys/stat.h> 32243730Srwatson 33243730Srwatson#include <errno.h> 34243730Srwatson#include <stdarg.h> 35243730Srwatson#include <unistd.h> 36243730Srwatson 37243730Srwatsonstatic int 38243730Srwatsonflopen(const char *path, int flags, ...) 39243730Srwatson{ 40243730Srwatson int fd, operation, serrno, trunc; 41243730Srwatson struct stat sb, fsb; 42243730Srwatson mode_t mode; 43243730Srwatson 44243730Srwatson#ifdef O_EXLOCK 45243730Srwatson flags &= ~O_EXLOCK; 46243730Srwatson#endif 47243730Srwatson 48243730Srwatson mode = 0; 49243730Srwatson if (flags & O_CREAT) { 50243730Srwatson va_list ap; 51243730Srwatson 52243730Srwatson va_start(ap, flags); 53243730Srwatson mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */ 54243730Srwatson va_end(ap); 55243730Srwatson } 56243730Srwatson 57243730Srwatson operation = LOCK_EX; 58243730Srwatson if (flags & O_NONBLOCK) 59243730Srwatson operation |= LOCK_NB; 60243730Srwatson 61243730Srwatson trunc = (flags & O_TRUNC); 62243730Srwatson flags &= ~O_TRUNC; 63243730Srwatson 64243730Srwatson for (;;) { 65243730Srwatson if ((fd = open(path, flags, mode)) == -1) 66243730Srwatson /* non-existent or no access */ 67243730Srwatson return (-1); 68243730Srwatson if (flock(fd, operation) == -1) { 69243730Srwatson /* unsupported or interrupted */ 70243730Srwatson serrno = errno; 71243730Srwatson (void)close(fd); 72243730Srwatson errno = serrno; 73243730Srwatson return (-1); 74243730Srwatson } 75243730Srwatson if (stat(path, &sb) == -1) { 76243730Srwatson /* disappeared from under our feet */ 77243730Srwatson (void)close(fd); 78243730Srwatson continue; 79243730Srwatson } 80243730Srwatson if (fstat(fd, &fsb) == -1) { 81243730Srwatson /* can't happen [tm] */ 82243730Srwatson serrno = errno; 83243730Srwatson (void)close(fd); 84243730Srwatson errno = serrno; 85243730Srwatson return (-1); 86243730Srwatson } 87243730Srwatson if (sb.st_dev != fsb.st_dev || 88243730Srwatson sb.st_ino != fsb.st_ino) { 89243730Srwatson /* changed under our feet */ 90243730Srwatson (void)close(fd); 91243730Srwatson continue; 92243730Srwatson } 93243730Srwatson if (trunc && ftruncate(fd, 0) != 0) { 94243730Srwatson /* can't happen [tm] */ 95243730Srwatson serrno = errno; 96243730Srwatson (void)close(fd); 97243730Srwatson errno = serrno; 98243730Srwatson return (-1); 99243730Srwatson } 100243730Srwatson return (fd); 101243730Srwatson } 102243730Srwatson} 103