Initial implementation of flock(1)
Very useful to prevent overlapping cron jobs amongst other things.
This commit is contained in:
parent
23fdd768f0
commit
2652dcfd6c
1
Makefile
1
Makefile
@ -97,6 +97,7 @@ BIN =\
|
|||||||
expr\
|
expr\
|
||||||
false\
|
false\
|
||||||
find\
|
find\
|
||||||
|
flock\
|
||||||
fold\
|
fold\
|
||||||
getconf\
|
getconf\
|
||||||
grep\
|
grep\
|
||||||
|
29
flock.1
Normal file
29
flock.1
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
.Dd October 7, 2015
|
||||||
|
.Dt FLOCK 1
|
||||||
|
.Os sbase
|
||||||
|
.Sh NAME
|
||||||
|
.Nm flock
|
||||||
|
.Nd tool to manage locks on files
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl nsux
|
||||||
|
.Ar file
|
||||||
|
.Ar cmd Op arg ...
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
is used to manage advisory locks on open files. It is commonly used to prevent
|
||||||
|
long running cron jobs from running in parallel. If
|
||||||
|
.Ar file
|
||||||
|
does not exist, it will be created.
|
||||||
|
.Sh OPTIONS
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl n
|
||||||
|
Set non-blocking mode on the lock. Fail immediately if the lock
|
||||||
|
cannot be acquired.
|
||||||
|
.It Fl s
|
||||||
|
Acquire a shared lock.
|
||||||
|
.It Fl u
|
||||||
|
Release the lock.
|
||||||
|
.It Fl x
|
||||||
|
Acquire an exclusive lock. This is the default.
|
||||||
|
.El
|
75
flock.c
Normal file
75
flock.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/* See LICENSE file for copyright and license details. */
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
eprintf("usage: %s [-nsux] file cmd [arg ...]\n", argv0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fd, status, savederrno, flags = LOCK_EX, nonblk = 0;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
ARGBEGIN {
|
||||||
|
case 'n':
|
||||||
|
nonblk = LOCK_NB;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
flags = LOCK_SH;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
flags = LOCK_UN;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
/* for compat */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
} ARGEND;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if ((fd = open(*argv, O_RDONLY | O_CREAT)) < 0)
|
||||||
|
eprintf("open %s:", *argv);
|
||||||
|
|
||||||
|
if (flock(fd, flags | nonblk)) {
|
||||||
|
if (nonblk && errno == EWOULDBLOCK)
|
||||||
|
return 1;
|
||||||
|
eprintf("flock:");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((pid = fork())) {
|
||||||
|
case -1:
|
||||||
|
eprintf("fork:");
|
||||||
|
case 0:
|
||||||
|
argv++;
|
||||||
|
execvp(*argv, argv);
|
||||||
|
savederrno = errno;
|
||||||
|
weprintf("execvp %s:", *argv);
|
||||||
|
_exit(126 + (savederrno == ENOENT));
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
|
||||||
|
if (WIFSIGNALED(status))
|
||||||
|
return 128 + WTERMSIG(status);
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
|
||||||
|
if (close(fd) < 0)
|
||||||
|
eprintf("close:");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user