summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillem Jover <guillem@hadrons.org>2010-01-09 23:49:32 +0100
committerGuillem Jover <guillem@hadrons.org>2010-01-10 13:36:38 +0100
commit98a2479f0ba02a0c54ff360aa5745ff5a6939b2e (patch)
tree3b0476711febb247822421d586d02f57af66176c
parent57cc5326cf75826c5d3b415673e2574384d12850 (diff)
Add flopen function
Taken from FreeBSD.
-rw-r--r--Makefile2
-rw-r--r--Versions2
-rw-r--r--include/libutil.h2
-rw-r--r--src/flopen.3102
-rw-r--r--src/flopen.c105
5 files changed, 213 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 2d51ba1..be8314b 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ LIB_SRCS := \
bsd_getopt.c \
err.c \
fgetln.c \
+ flopen.c \
heapsort.c \
humanize_number.c \
dehumanize_number.c \
@@ -76,6 +77,7 @@ LIB_MANS := \
strlcpy.3 \
strlcat.3 \
fgetln.3 \
+ flopen.3 \
readpassphrase.3 \
humanize_number.3 \
fmtcheck.3 \
diff --git a/Versions b/Versions
index 24548ca..7b092da 100644
--- a/Versions
+++ b/Versions
@@ -51,5 +51,7 @@ LIBBSD_0.2 {
dehumanize_number;
readpassphrase;
+
+ flopen;
} LIBBSD_0.1;
diff --git a/include/libutil.h b/include/libutil.h
index 5f72f8c..298bbc3 100644
--- a/include/libutil.h
+++ b/include/libutil.h
@@ -46,6 +46,8 @@
__BEGIN_DECLS
int humanize_number(char *buf, size_t len, int64_t bytes,
const char *suffix, int scale, int flags);
+
+int flopen(const char *_path, int _flags, ...);
__END_DECLS
/* humanize_number(3) */
diff --git a/src/flopen.3 b/src/flopen.3
new file mode 100644
index 0000000..4c53d46
--- /dev/null
+++ b/src/flopen.3
@@ -0,0 +1,102 @@
+.\"-
+.\" Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 6, 2009
+.Dt FLOPEN 3
+.Os
+.Sh NAME
+.Nm flopen
+.Nd "Reliably open and lock a file"
+.Sh LIBRARY
+.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
+.Lb libbsd
+.Sh SYNOPSIS
+.In sys/fcntl.h
+.In libutil.h
+.Ft int
+.Fn flopen "const char *path" "int flags"
+.Ft int
+.Fn flopen "const char *path" "int flags" "mode_t mode"
+.Sh DESCRIPTION
+The
+.Fn flopen
+function opens or creates a file and acquires an exclusive lock on it.
+It is essentially equivalent with calling
+.Fn open
+with the same parameters followed by
+.Fn flock
+with an
+.Va operation
+argument of
+.Dv LOCK_EX ,
+except that
+.Fn flopen
+will attempt to detect and handle races that may occur between opening
+/ creating the file and locking it.
+Thus, it is well suited for opening lock files, PID files, spool
+files, mailboxes and other kinds of files which are used for
+synchronization between processes.
+.Pp
+If
+.Va flags
+includes
+.Dv O_NONBLOCK
+and the file is already locked,
+.Fn flopen
+will fail and set
+.Va errno
+to
+.Dv EWOULDBLOCK .
+.Pp
+As with
+.Fn open ,
+the additional
+.Va mode
+argument is required if
+.Va flags
+includes
+.Dv O_CREAT .
+.Sh RETURN VALUES
+If successful,
+.Fn flopen
+returns a valid file descriptor.
+Otherwise, it returns -1, and sets
+.Va errno
+as described in
+.Xr flock 2
+and
+.Xr open 2 .
+.Sh SEE ALSO
+.Xr errno 2 ,
+.Xr flock 2 ,
+.Xr open 2
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+function and this manual page were written by
+.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org .
diff --git a/src/flopen.c b/src/flopen.c
new file mode 100644
index 0000000..754c9c0
--- /dev/null
+++ b/src/flopen.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include <libutil.h>
+
+int
+flopen(const char *path, int flags, ...)
+{
+ int fd, operation, serrno, trunc;
+ struct stat sb, fsb;
+ mode_t mode;
+
+#ifdef O_EXLOCK
+ flags &= ~O_EXLOCK;
+#endif
+
+ mode = 0;
+ if (flags & O_CREAT) {
+ va_list ap;
+
+ va_start(ap, flags);
+ mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */
+ va_end(ap);
+ }
+
+ operation = LOCK_EX;
+ if (flags & O_NONBLOCK)
+ operation |= LOCK_NB;
+
+ trunc = (flags & O_TRUNC);
+ flags &= ~O_TRUNC;
+
+ for (;;) {
+ if ((fd = open(path, flags, mode)) == -1)
+ /* non-existent or no access */
+ return (-1);
+ if (flock(fd, operation) == -1) {
+ /* unsupported or interrupted */
+ serrno = errno;
+ (void)close(fd);
+ errno = serrno;
+ return (-1);
+ }
+ if (stat(path, &sb) == -1) {
+ /* disappeared from under our feet */
+ (void)close(fd);
+ continue;
+ }
+ if (fstat(fd, &fsb) == -1) {
+ /* can't happen [tm] */
+ serrno = errno;
+ (void)close(fd);
+ errno = serrno;
+ return (-1);
+ }
+ if (sb.st_dev != fsb.st_dev ||
+ sb.st_ino != fsb.st_ino) {
+ /* changed under our feet */
+ (void)close(fd);
+ continue;
+ }
+ if (trunc && ftruncate(fd, 0) != 0) {
+ /* can't happen [tm] */
+ serrno = errno;
+ (void)close(fd);
+ errno = serrno;
+ return (-1);
+ }
+ return (fd);
+ }
+}