summaryrefslogtreecommitdiff
path: root/sysutils
diff options
context:
space:
mode:
authormspo <mspo@pkgsrc.org>2013-05-22 15:09:22 +0000
committermspo <mspo@pkgsrc.org>2013-05-22 15:09:22 +0000
commitb0c2037f9a73e747b464fdfa3fcb670da03506e0 (patch)
tree796bf7be3ad12a75242bdf5caa601e686a08c47b /sysutils
parent909641953707be9397894c1f6d6e8d7e3652b678 (diff)
downloadpkgsrc-b0c2037f9a73e747b464fdfa3fcb670da03506e0.tar.gz
add the lockf package: freebsd's lockf for compatibility and building
Diffstat (limited to 'sysutils')
-rw-r--r--sysutils/Makefile3
-rw-r--r--sysutils/lockf/DESCR3
-rw-r--r--sysutils/lockf/Makefile33
-rw-r--r--sysutils/lockf/PLIST3
-rw-r--r--sysutils/lockf/distinfo1
-rw-r--r--sysutils/lockf/files/lockf.1156
-rw-r--r--sysutils/lockf/files/lockf.c236
7 files changed, 434 insertions, 1 deletions
diff --git a/sysutils/Makefile b/sysutils/Makefile
index 53450c05d66..cfc83aebe3c 100644
--- a/sysutils/Makefile
+++ b/sysutils/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.574 2013/05/15 07:01:40 jnemeth Exp $
+# $NetBSD: Makefile,v 1.575 2013/05/22 15:10:11 mspo Exp $
#
COMMENT= System utilities
@@ -263,6 +263,7 @@ SUBDIR+= liboobs
SUBDIR+= libpciaccess
SUBDIR+= libvirt
SUBDIR+= lilo
+SUBDIR+= lockf
SUBDIR+= logfinder
SUBDIR+= logrider
SUBDIR+= logrot
diff --git a/sysutils/lockf/DESCR b/sysutils/lockf/DESCR
new file mode 100644
index 00000000000..322f10df66c
--- /dev/null
+++ b/sysutils/lockf/DESCR
@@ -0,0 +1,3 @@
+Imported from FreeBSD:
+The lockf utility acquires an exclusive lock on a file, creating it if
+necessary, and removing the file on exit unless explicitly told not to.
diff --git a/sysutils/lockf/Makefile b/sysutils/lockf/Makefile
new file mode 100644
index 00000000000..eaac7055b08
--- /dev/null
+++ b/sysutils/lockf/Makefile
@@ -0,0 +1,33 @@
+# $NetBSD: Makefile,v 1.1 2013/05/22 15:09:22 mspo Exp $
+#
+
+DISTNAME= lockf-1
+CATEGORIES= sysutils
+MASTER_SITES= # none
+DISTFILES= # none
+
+MAINTAINER= pkgsrc-users@NetBSD.org
+HOMEPAGE= http://www.freebsd.org
+COMMENT= FreeBSD's lockf
+LICENSE= original-bsd
+
+WRKSRC= ${WRKDIR}
+USE_LANGUAGES= c
+
+do-extract:
+ cd ${FILESDIR} && cp *.c *.1 ${WRKSRC}/
+
+.include "../../mk/bsd.prefs.mk"
+
+INSTALLATION_DIRS= bin ${PKGMANDIR}/man1
+
+do-build:
+ @(cd ${WRKSRC}; \
+ ${ECHO} "${CC} -o lockf lockf.c"; \
+ ${CC} -o lockf lockf.c )
+
+do-install:
+ ${INSTALL_PROGRAM} ${WRKSRC}/lockf ${DESTDIR}${PREFIX}/bin/lockf
+ ${INSTALL_MAN} ${WRKSRC}/lockf.1 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man1
+
+.include "../../mk/bsd.pkg.mk"
diff --git a/sysutils/lockf/PLIST b/sysutils/lockf/PLIST
new file mode 100644
index 00000000000..adcfde095ec
--- /dev/null
+++ b/sysutils/lockf/PLIST
@@ -0,0 +1,3 @@
+@comment $NetBSD: PLIST,v 1.1 2013/05/22 15:09:22 mspo Exp $
+bin/lockf
+man/man1/lockf.1
diff --git a/sysutils/lockf/distinfo b/sysutils/lockf/distinfo
new file mode 100644
index 00000000000..273c544a1bf
--- /dev/null
+++ b/sysutils/lockf/distinfo
@@ -0,0 +1 @@
+$NetBSD: distinfo,v 1.1 2013/05/22 15:09:22 mspo Exp $
diff --git a/sysutils/lockf/files/lockf.1 b/sysutils/lockf/files/lockf.1
new file mode 100644
index 00000000000..255a8283a1f
--- /dev/null
+++ b/sysutils/lockf/files/lockf.1
@@ -0,0 +1,156 @@
+.\"
+.\" Copyright (C) 1998 John D. Polstra. 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 JOHN D. POLSTRA 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 JOHN D. POLSTRA 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 July 7, 1998
+.Dt LOCKF 1
+.Os
+.Sh NAME
+.Nm lockf
+.Nd execute a command while holding a file lock
+.Sh SYNOPSIS
+.Nm
+.Op Fl ks
+.Op Fl t Ar seconds
+.Ar file
+.Ar command
+.Op Ar arguments
+.Sh DESCRIPTION
+The
+.Nm
+utility acquires an exclusive lock on a
+.Ar file ,
+creating it if necessary,
+.Bf Em
+and removing the file on exit unless explicitly told not to.
+.Ef
+While holding the lock, it executes a
+.Ar command
+with optional
+.Ar arguments .
+After the
+.Ar command
+completes,
+.Nm
+releases the lock, and removes the
+.Ar file
+unless the
+.Fl k
+option is specified.
+.Bx Ns -style
+locking is used, as described in
+.Xr flock 2 ;
+the mere existence of the
+.Ar file
+is not considered to constitute a lock.
+.Pp
+If the
+.Nm
+utility is being used to facilitate concurrency between a number
+of processes, it is recommended that the
+.Fl k
+option be used.
+This will guarantee lock ordering, as well as implement
+a performance enhanced algorithm which minimizes CPU load associated
+with concurrent unlink, drop and re-acquire activity.
+It should be noted
+that if the
+.Fl k
+option is not used, then no guarantees around lock ordering can be made.
+.Pp
+The following options are supported:
+.Bl -tag -width ".Fl t Ar seconds"
+.It Fl k
+Causes the lock file to be kept (not removed) after the command
+completes.
+.It Fl s
+Causes
+.Nm
+to operate silently.
+Failure to acquire the lock is indicated only in the exit status.
+.It Fl t Ar seconds
+Specifies a timeout for waiting for the lock.
+By default,
+.Nm
+waits indefinitely to acquire the lock.
+If a timeout is specified with this option,
+.Nm
+will wait at most the given number of
+.Ar seconds
+before giving up.
+A timeout of 0 may be given, in which case
+.Nm
+will fail unless it can acquire the lock immediately.
+When a lock times out,
+.Ar command
+is
+.Em not
+executed.
+.El
+.Pp
+In no event will
+.Nm
+break a lock that is held by another process.
+.Sh EXIT STATUS
+If
+.Nm
+successfully acquires the lock, it returns the exit status produced by
+.Ar command .
+Otherwise, it returns one of the exit codes defined in
+.Xr sysexits 3 ,
+as follows:
+.Bl -tag -width ".Dv EX_CANTCREAT"
+.It Dv EX_TEMPFAIL
+The specified lock file was already locked by another process.
+.It Dv EX_CANTCREAT
+The
+.Nm
+utility
+was unable to create the lock file, e.g., because of insufficient access
+privileges.
+.It Dv EX_USAGE
+There was an error on the
+.Nm
+command line.
+.It Dv EX_OSERR
+A system call (e.g.,
+.Xr fork 2 )
+failed unexpectedly.
+.It Dv EX_SOFTWARE
+The
+.Ar command
+did not exit normally,
+but may have been signaled or stopped.
+.El
+.Sh SEE ALSO
+.Xr flock 2 ,
+.Xr sysexits 3
+.Sh HISTORY
+A
+.Nm
+utility first appeared in
+.Fx 2.2 .
+.Sh AUTHORS
+.An John Polstra Aq jdp@polstra.com
diff --git a/sysutils/lockf/files/lockf.c b/sysutils/lockf/files/lockf.c
new file mode 100644
index 00000000000..7b14014e3e5
--- /dev/null
+++ b/sysutils/lockf/files/lockf.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 1997 John D. Polstra. 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 JOHN D. POLSTRA 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 JOHN D. POLSTRA 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>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+static int acquire_lock(const char *name, int flags);
+static void cleanup(void);
+static void killed(int sig);
+static void timeout(int sig);
+static void usage(void);
+static void wait_for_lock(const char *name);
+
+static const char *lockname;
+static int lockfd = -1;
+static int keep;
+static volatile sig_atomic_t timed_out;
+
+/*
+ * Execute an arbitrary command while holding a file lock.
+ */
+int
+main(int argc, char **argv)
+{
+ int ch, silent, status, waitsec;
+ pid_t child;
+
+ silent = keep = 0;
+ waitsec = -1; /* Infinite. */
+ while ((ch = getopt(argc, argv, "skt:")) != -1) {
+ switch (ch) {
+ case 'k':
+ keep = 1;
+ break;
+ case 's':
+ silent = 1;
+ break;
+ case 't':
+ {
+ char *endptr;
+ waitsec = strtol(optarg, &endptr, 0);
+ if (*optarg == '\0' || *endptr != '\0' || waitsec < 0)
+ errx(EX_USAGE,
+ "invalid timeout \"%s\"", optarg);
+ }
+ break;
+ default:
+ usage();
+ }
+ }
+ if (argc - optind < 2)
+ usage();
+ lockname = argv[optind++];
+ argc -= optind;
+ argv += optind;
+ if (waitsec > 0) { /* Set up a timeout. */
+ struct sigaction act;
+
+ act.sa_handler = timeout;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0; /* Note that we do not set SA_RESTART. */
+ sigaction(SIGALRM, &act, NULL);
+ alarm(waitsec);
+ }
+ /*
+ * If the "-k" option is not given, then we must not block when
+ * acquiring the lock. If we did, then the lock holder would
+ * unlink the file upon releasing the lock, and we would acquire
+ * a lock on a file with no directory entry. Then another
+ * process could come along and acquire the same lock. To avoid
+ * this problem, we separate out the actions of waiting for the
+ * lock to be available and of actually acquiring the lock.
+ *
+ * That approach produces behavior that is technically correct;
+ * however, it causes some performance & ordering problems for
+ * locks that have a lot of contention. First, it is unfair in
+ * the sense that a released lock isn't necessarily granted to
+ * the process that has been waiting the longest. A waiter may
+ * be starved out indefinitely. Second, it creates a thundering
+ * herd situation each time the lock is released.
+ *
+ * When the "-k" option is used, the unlink race no longer
+ * exists. In that case we can block while acquiring the lock,
+ * avoiding the separate step of waiting for the lock. This
+ * yields fairness and improved performance.
+ */
+ lockfd = acquire_lock(lockname, O_NONBLOCK);
+ while (lockfd == -1 && !timed_out && waitsec != 0) {
+ if (keep)
+ lockfd = acquire_lock(lockname, 0);
+ else {
+ wait_for_lock(lockname);
+ lockfd = acquire_lock(lockname, O_NONBLOCK);
+ }
+ }
+ if (waitsec > 0)
+ alarm(0);
+ if (lockfd == -1) { /* We failed to acquire the lock. */
+ if (silent)
+ exit(EX_TEMPFAIL);
+ errx(EX_TEMPFAIL, "%s: already locked", lockname);
+ }
+ /* At this point, we own the lock. */
+ if (atexit(cleanup) == -1)
+ err(EX_OSERR, "atexit failed");
+ if ((child = fork()) == -1)
+ err(EX_OSERR, "cannot fork");
+ if (child == 0) { /* The child process. */
+ close(lockfd);
+ execvp(argv[0], argv);
+ warn("%s", argv[0]);
+ _exit(1);
+ }
+ /* This is the parent process. */
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGTERM, killed);
+ if (waitpid(child, &status, 0) == -1)
+ err(EX_OSERR, "waitpid failed");
+ return (WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE);
+}
+
+/*
+ * Try to acquire a lock on the given file, creating the file if
+ * necessary. The flags argument is O_NONBLOCK or 0, depending on
+ * whether we should wait for the lock. Returns an open file descriptor
+ * on success, or -1 on failure.
+ */
+static int
+acquire_lock(const char *name, int flags)
+{
+ int fd;
+
+ if ((fd = open(name, O_RDONLY|O_CREAT|O_EXLOCK|flags, 0666)) == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ return (-1);
+ err(EX_CANTCREAT, "cannot open %s", name);
+ }
+ return (fd);
+}
+
+/*
+ * Remove the lock file.
+ */
+static void
+cleanup(void)
+{
+
+ if (keep)
+ flock(lockfd, LOCK_UN);
+ else
+ unlink(lockname);
+}
+
+/*
+ * Signal handler for SIGTERM. Cleans up the lock file, then re-raises
+ * the signal.
+ */
+static void
+killed(int sig)
+{
+
+ cleanup();
+ signal(sig, SIG_DFL);
+ if (kill(getpid(), sig) == -1)
+ err(EX_OSERR, "kill failed");
+}
+
+/*
+ * Signal handler for SIGALRM.
+ */
+static void
+timeout(int sig __unused)
+{
+
+ timed_out = 1;
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+ "usage: lockf [-ks] [-t seconds] file command [arguments]\n");
+ exit(EX_USAGE);
+}
+
+/*
+ * Wait until it might be possible to acquire a lock on the given file.
+ * If the file does not exist, return immediately without creating it.
+ */
+static void
+wait_for_lock(const char *name)
+{
+ int fd;
+
+ if ((fd = open(name, O_RDONLY|O_EXLOCK, 0666)) == -1) {
+ if (errno == ENOENT || errno == EINTR)
+ return;
+ err(EX_CANTCREAT, "cannot open %s", name);
+ }
+ close(fd);
+}