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 * $P4: //depot/projects/trustedbsd/openbsm/compat/flopen.h#1 $ 29243730Srwatson */ 30243730Srwatson 31243730Srwatson#include <sys/file.h> 32243730Srwatson#include <sys/stat.h> 33243730Srwatson 34243730Srwatson#include <errno.h> 35243730Srwatson#include <stdarg.h> 36243730Srwatson#include <unistd.h> 37243730Srwatson 38243730Srwatsonstatic int 39243730Srwatsonflopen(const char *path, int flags, ...) 40243730Srwatson{ 41243730Srwatson int fd, operation, serrno, trunc; 42243730Srwatson struct stat sb, fsb; 43243730Srwatson mode_t mode; 44243730Srwatson 45243730Srwatson#ifdef O_EXLOCK 46243730Srwatson flags &= ~O_EXLOCK; 47243730Srwatson#endif 48243730Srwatson 49243730Srwatson mode = 0; 50243730Srwatson if (flags & O_CREAT) { 51243730Srwatson va_list ap; 52243730Srwatson 53243730Srwatson va_start(ap, flags); 54243730Srwatson mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */ 55243730Srwatson va_end(ap); 56243730Srwatson } 57243730Srwatson 58243730Srwatson operation = LOCK_EX; 59243730Srwatson if (flags & O_NONBLOCK) 60243730Srwatson operation |= LOCK_NB; 61243730Srwatson 62243730Srwatson trunc = (flags & O_TRUNC); 63243730Srwatson flags &= ~O_TRUNC; 64243730Srwatson 65243730Srwatson for (;;) { 66243730Srwatson if ((fd = open(path, flags, mode)) == -1) 67243730Srwatson /* non-existent or no access */ 68243730Srwatson return (-1); 69243730Srwatson if (flock(fd, operation) == -1) { 70243730Srwatson /* unsupported or interrupted */ 71243730Srwatson serrno = errno; 72243730Srwatson (void)close(fd); 73243730Srwatson errno = serrno; 74243730Srwatson return (-1); 75243730Srwatson } 76243730Srwatson if (stat(path, &sb) == -1) { 77243730Srwatson /* disappeared from under our feet */ 78243730Srwatson (void)close(fd); 79243730Srwatson continue; 80243730Srwatson } 81243730Srwatson if (fstat(fd, &fsb) == -1) { 82243730Srwatson /* can't happen [tm] */ 83243730Srwatson serrno = errno; 84243730Srwatson (void)close(fd); 85243730Srwatson errno = serrno; 86243730Srwatson return (-1); 87243730Srwatson } 88243730Srwatson if (sb.st_dev != fsb.st_dev || 89243730Srwatson sb.st_ino != fsb.st_ino) { 90243730Srwatson /* changed under our feet */ 91243730Srwatson (void)close(fd); 92243730Srwatson continue; 93243730Srwatson } 94243730Srwatson if (trunc && ftruncate(fd, 0) != 0) { 95243730Srwatson /* can't happen [tm] */ 96243730Srwatson serrno = errno; 97243730Srwatson (void)close(fd); 98243730Srwatson errno = serrno; 99243730Srwatson return (-1); 100243730Srwatson } 101243730Srwatson return (fd); 102243730Srwatson } 103243730Srwatson} 104