]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Add flopen function
authorGuillem Jover <guillem@hadrons.org>
Sat, 9 Jan 2010 22:49:32 +0000 (23:49 +0100)
committerGuillem Jover <guillem@hadrons.org>
Sun, 10 Jan 2010 12:36:38 +0000 (13:36 +0100)
Taken from FreeBSD.

Makefile
Versions
include/libutil.h
src/flopen.3 [new file with mode: 0644]
src/flopen.c [new file with mode: 0644]

index 2d51ba1c22dd793b0e152901c6924daf7413cb2f..be8314bd0c326c61c054a5e3dfed6b64286cb1a0 100644 (file)
--- 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 \
index 24548caa471545e2cd4287f3e2b8398e3e5763ba..7b092da2310d3bed234ccc36f07b5e39581d30e9 100644 (file)
--- a/Versions
+++ b/Versions
@@ -51,5 +51,7 @@ LIBBSD_0.2 {
     dehumanize_number;
 
     readpassphrase;
+
+    flopen;
 } LIBBSD_0.1;
 
index 5f72f8c184d58a5d645cc30b2e9366b1e9c8a454..298bbc3110114313dc7e69cc37c5cb6815c57c5e 100644 (file)
@@ -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 (file)
index 0000000..4c53d46
--- /dev/null
@@ -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 (file)
index 0000000..754c9c0
--- /dev/null
@@ -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);
+       }
+}