1163953Srrs/*- 2169382Srrs * Copyright (c) 2007 Dag-Erling Sm��rgrav 3163953Srrs * All rights reserved. 4163953Srrs * 5163953Srrs * Redistribution and use in source and binary forms, with or without 6163953Srrs * modification, are permitted provided that the following conditions 7163953Srrs * are met: 8163953Srrs * 1. Redistributions of source code must retain the above copyright 9163953Srrs * notice, this list of conditions and the following disclaimer 10163953Srrs * in this position and unchanged. 11163953Srrs * 2. Redistributions in binary form must reproduce the above copyright 12163953Srrs * notice, this list of conditions and the following disclaimer in the 13163953Srrs * documentation and/or other materials provided with the distribution. 14163953Srrs * 15163953Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16163953Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17163953Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19163953Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20163953Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21163953Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22163953Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23163953Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24163953Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25163953Srrs * SUCH DAMAGE. 26163953Srrs * 27163953Srrs * Derived from FreeBSD head/lib/libutil/flopen.c r193591 28163953Srrs */ 29163953Srrs 30163953Srrs#include <sys/file.h> 31163953Srrs#include <sys/stat.h> 32163953Srrs 33163953Srrs#include <errno.h> 34163953Srrs#include <stdarg.h> 35163953Srrs#include <unistd.h> 36163953Srrs 37163953Srrsstatic int 38167598Srrsflopen(const char *path, int flags, ...) 39163953Srrs{ 40163953Srrs int fd, operation, serrno, trunc; 41163953Srrs struct stat sb, fsb; 42163953Srrs mode_t mode; 43163953Srrs 44163953Srrs#ifdef O_EXLOCK 45163953Srrs flags &= ~O_EXLOCK; 46163953Srrs#endif 47170091Srrs 48163953Srrs mode = 0; 49163953Srrs if (flags & O_CREAT) { 50163953Srrs va_list ap; 51163953Srrs 52163953Srrs va_start(ap, flags); 53163953Srrs mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */ 54163953Srrs va_end(ap); 55163953Srrs } 56165220Srrs 57165220Srrs operation = LOCK_EX; 58165220Srrs if (flags & O_NONBLOCK) 59165220Srrs operation |= LOCK_NB; 60165220Srrs 61163953Srrs trunc = (flags & O_TRUNC); 62163953Srrs flags &= ~O_TRUNC; 63165220Srrs 64163953Srrs for (;;) { 65163953Srrs if ((fd = open(path, flags, mode)) == -1) 66163953Srrs /* non-existent or no access */ 67165220Srrs return (-1); 68165220Srrs if (flock(fd, operation) == -1) { 69165220Srrs /* unsupported or interrupted */ 70165220Srrs serrno = errno; 71165220Srrs (void)close(fd); 72165220Srrs errno = serrno; 73163953Srrs return (-1); 74163953Srrs } 75163953Srrs if (stat(path, &sb) == -1) { 76163953Srrs /* disappeared from under our feet */ 77163953Srrs (void)close(fd); 78163953Srrs continue; 79163953Srrs } 80163953Srrs if (fstat(fd, &fsb) == -1) { 81169352Srrs /* can't happen [tm] */ 82169352Srrs serrno = errno; 83163953Srrs (void)close(fd); 84163953Srrs errno = serrno; 85163953Srrs return (-1); 86163953Srrs } 87163953Srrs if (sb.st_dev != fsb.st_dev || 88169420Srrs sb.st_ino != fsb.st_ino) { 89169420Srrs /* changed under our feet */ 90163953Srrs (void)close(fd); 91163953Srrs continue; 92163953Srrs } 93163953Srrs if (trunc && ftruncate(fd, 0) != 0) { 94169420Srrs /* can't happen [tm] */ 95169420Srrs serrno = errno; 96169420Srrs (void)close(fd); 97163953Srrs errno = serrno; 98163953Srrs return (-1); 99163953Srrs } 100163953Srrs return (fd); 101169352Srrs } 102169352Srrs} 103168299Srrs