196670552SDag-Erling Smørgrav /*- 296670552SDag-Erling Smørgrav * Copyright (c) 2007 Dag-Erling Co�dan Sm�rgrav 396670552SDag-Erling Smørgrav * All rights reserved. 496670552SDag-Erling Smørgrav * 596670552SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 696670552SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 796670552SDag-Erling Smørgrav * are met: 896670552SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 996670552SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer 1096670552SDag-Erling Smørgrav * in this position and unchanged. 1196670552SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 1296670552SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 1396670552SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 1496670552SDag-Erling Smørgrav * 1596670552SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1696670552SDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1796670552SDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1896670552SDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1996670552SDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2096670552SDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2196670552SDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2296670552SDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2396670552SDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2496670552SDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2596670552SDag-Erling Smørgrav * SUCH DAMAGE. 2696670552SDag-Erling Smørgrav * 2796670552SDag-Erling Smørgrav * $Id$ 2896670552SDag-Erling Smørgrav */ 2996670552SDag-Erling Smørgrav 3096670552SDag-Erling Smørgrav #include <sys/cdefs.h> 3196670552SDag-Erling Smørgrav __FBSDID("$FreeBSD$"); 3296670552SDag-Erling Smørgrav 3396670552SDag-Erling Smørgrav #include <sys/stat.h> 3496670552SDag-Erling Smørgrav 3596670552SDag-Erling Smørgrav #include <errno.h> 3696670552SDag-Erling Smørgrav #include <fcntl.h> 3796670552SDag-Erling Smørgrav #include <stdarg.h> 3896670552SDag-Erling Smørgrav 3996670552SDag-Erling Smørgrav int 4096670552SDag-Erling Smørgrav flopen(const char *path, int flags, ...) 4196670552SDag-Erling Smørgrav { 423dea5934SDag-Erling Smørgrav int fd, operation, serrno; 4396670552SDag-Erling Smørgrav struct stat sb, fsb; 4496670552SDag-Erling Smørgrav mode_t mode; 4596670552SDag-Erling Smørgrav 4696670552SDag-Erling Smørgrav #ifdef O_EXLOCK 4796670552SDag-Erling Smørgrav flags &= ~O_EXLOCK; 4896670552SDag-Erling Smørgrav #endif 4996670552SDag-Erling Smørgrav 503dea5934SDag-Erling Smørgrav mode = 0; 5196670552SDag-Erling Smørgrav if (flags & O_CREAT) { 5296670552SDag-Erling Smørgrav va_list ap; 5396670552SDag-Erling Smørgrav 5496670552SDag-Erling Smørgrav va_start(ap, flags); 5596670552SDag-Erling Smørgrav mode = va_arg(ap, int); /* mode_t promoted to int */ 5696670552SDag-Erling Smørgrav va_end(ap); 5796670552SDag-Erling Smørgrav } 5896670552SDag-Erling Smørgrav 593dea5934SDag-Erling Smørgrav operation = LOCK_EX; 603dea5934SDag-Erling Smørgrav if (flags & O_NONBLOCK) 613dea5934SDag-Erling Smørgrav operation |= LOCK_NB; 623dea5934SDag-Erling Smørgrav 6396670552SDag-Erling Smørgrav for (;;) { 6496670552SDag-Erling Smørgrav if ((fd = open(path, flags, mode)) == -1) 6596670552SDag-Erling Smørgrav /* non-existent or no access */ 6696670552SDag-Erling Smørgrav return (-1); 673dea5934SDag-Erling Smørgrav if (flock(fd, operation) == -1) { 6896670552SDag-Erling Smørgrav /* unsupported or interrupted */ 6996670552SDag-Erling Smørgrav serrno = errno; 7096670552SDag-Erling Smørgrav close(fd); 7196670552SDag-Erling Smørgrav errno = serrno; 7296670552SDag-Erling Smørgrav return (-1); 7396670552SDag-Erling Smørgrav } 7496670552SDag-Erling Smørgrav if (stat(path, &sb) == -1) { 7596670552SDag-Erling Smørgrav /* disappeared from under our feet */ 7696670552SDag-Erling Smørgrav close(fd); 7796670552SDag-Erling Smørgrav continue; 7896670552SDag-Erling Smørgrav } 7996670552SDag-Erling Smørgrav if (fstat(fd, &fsb) == -1) { 8096670552SDag-Erling Smørgrav /* can't happen [tm] */ 8196670552SDag-Erling Smørgrav serrno = errno; 8296670552SDag-Erling Smørgrav close(fd); 8396670552SDag-Erling Smørgrav errno = serrno; 8496670552SDag-Erling Smørgrav return (-1); 8596670552SDag-Erling Smørgrav } 8696670552SDag-Erling Smørgrav if (sb.st_dev != fsb.st_dev || 8796670552SDag-Erling Smørgrav sb.st_ino != fsb.st_ino) { 8896670552SDag-Erling Smørgrav /* changed under our feet */ 8996670552SDag-Erling Smørgrav close(fd); 9096670552SDag-Erling Smørgrav continue; 9196670552SDag-Erling Smørgrav } 9296670552SDag-Erling Smørgrav return (fd); 9396670552SDag-Erling Smørgrav } 9496670552SDag-Erling Smørgrav } 95