Add flopen(3) which opens and locks a file.
authorPeter Avalos <pavalos@theshell.com>
Sat, 27 Dec 2008 18:49:10 +0000 (13:49 -0500)
committerPeter Avalos <pavalos@theshell.com>
Sun, 28 Dec 2008 04:17:08 +0000 (23:17 -0500)
Obtained-from: FreeBSD

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

index 21e1f0b..e7c8695 100644 (file)
@@ -7,7 +7,7 @@ SHLIB_MAJOR= 4
 CFLAGS+=-I${.CURDIR} -I${.CURDIR}/../../sys
 CFLAGS+=-DINET6
 CFLAGS+=-D_CTYPE_H_DISABLE_MACROS_ 
-SRCS=  login.c login_tty.c logout.c logwtmp.c pty.c \
+SRCS=  flopen.c login.c login_tty.c logout.c logwtmp.c pty.c \
        login_cap.c login_class.c login_auth.c login_times.c login_ok.c \
        login_crypt.c _secure_path.c uucplock.c property.c auth.c \
        realhostname.c fparseln.c stub.c pidfile.c trimdomain.c \
@@ -15,7 +15,7 @@ SRCS= login.c login_tty.c logout.c logwtmp.c pty.c \
 INCS=  libutil.h login_cap.h
 WARNS?=        2
 
-MAN+=  login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
+MAN+=  flopen.3 login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
        login_cap.3 login_class.3 login_times.3 login_ok.3 \
        _secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
        realhostname_sa.3 trimdomain.3 fparseln.3 pidfile.3 \
diff --git a/lib/libutil/flopen.3 b/lib/libutil/flopen.3
new file mode 100644 (file)
index 0000000..4f84cbd
--- /dev/null
@@ -0,0 +1,107 @@
+.\"-
+.\" 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: src/lib/libutil/flopen.3,v 1.7 2008/10/20 18:02:16 des Exp $
+.\"
+.Dd May 10, 2007
+.Dt FLOPEN 3
+.Os
+.Sh NAME
+.Nm flopen
+.Nd "Reliably open and lock a file"
+.Sh LIBRARY
+.Lb libutil
+.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 an
+.Fn fcntl
+.Dv F_SETLK
+or
+.Dv F_SETLKW
+operation with lock type
+.Dv F_WRLCK ,
+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 fcntl 2
+and
+.Xr open 2 .
+.Sh SEE ALSO
+.Xr errno 2 ,
+.Xr fcntl 2 ,
+.Xr open 2
+.Sh HISTORY
+The
+.Fn flopen
+function first appeared in
+.Fx 6.3 .
+.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/lib/libutil/flopen.c b/lib/libutil/flopen.c
new file mode 100644 (file)
index 0000000..0564489
--- /dev/null
@@ -0,0 +1,107 @@
+/*-
+ * 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.
+ *
+ * $FreeBSD: src/lib/libutil/flopen.c,v 1.11 2008/10/20 18:11:30 des Exp $
+ */
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libutil.h>
+
+int
+flopen(const char *path, int flags, ...)
+{
+       int fd, operation, serrno, trunc;
+       struct flock lock;
+       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);
+       }
+
+       memset(&lock, 0, sizeof lock);
+       lock.l_type = ((flags & O_ACCMODE) == O_RDONLY) ? F_RDLCK : F_WRLCK;
+       lock.l_whence = SEEK_SET;
+       operation = (flags & O_NONBLOCK) ? F_SETLK : F_SETLKW;
+
+       trunc = (flags & O_TRUNC);
+       flags &= ~O_TRUNC;
+
+       for (;;) {
+               if ((fd = open(path, flags, mode)) == -1)
+                       /* non-existent or no access */
+                       return (-1);
+               if (fcntl(fd, operation, &lock) == -1) {
+                       /* unsupported or interrupted */
+                       serrno = errno;
+                       close(fd);
+                       errno = serrno;
+                       return (-1);
+               }
+               if (stat(path, &sb) == -1) {
+                       /* disappeared from under our feet */
+                       close(fd);
+                       continue;
+               }
+               if (fstat(fd, &fsb) == -1) {
+                       /* can't happen [tm] */
+                       serrno = errno;
+                       close(fd);
+                       errno = serrno;
+                       return (-1);
+               }
+               if (sb.st_dev != fsb.st_dev ||
+                   sb.st_ino != fsb.st_ino) {
+                       /* changed under our feet */
+                       close(fd);
+                       continue;
+               }
+               if (trunc && ftruncate(fd, 0) != 0) {
+                       /* can't happen [tm] */
+                       serrno = errno;
+                       close(fd);
+                       errno = serrno;
+                       return (-1);
+               }
+               return (fd);
+       }
+}
index ea0c5e2..12eeed9 100644 (file)
@@ -55,6 +55,7 @@ struct in_addr;
 struct sockaddr;
 
 __BEGIN_DECLS
+int    flopen(const char *, int, ...);
 void   login(struct utmp *);
 int    login_tty(int);
 int    logout(const char *);