Initial implementation of flock(1)
Very useful to prevent overlapping cron jobs amongst other things.
This commit is contained in:
parent
23fdd768f0
commit
2652dcfd6c
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