Add -w option to lockf(1).
By default, lockf(1) opens its lock file O_RDONLY|O_EXLOCK. On NFS, if the file already exists, this is split into opening the file read-only and then requesting an exclusive lock -- and the second step fails because NFS does not permit exclusive locking on files which are opened read-only. The new -w option changes the open flags to O_WRONLY|O_EXLOCK, allowing it to work on NFS -- at the cost of not working if the file cannot be opened for writing. (Whether the traditional BSD behaviour of allowing exclusive locks to be obtained on a file which cannot be opened for writing is a good idea is perhaps questionable since it may allow less-privileged users to perform a local denial of service; however this behaviour has been present for a long time and changing it now seems like it would cause problems.) Reviewed by: rmacklem Differential Revision: https://reviews.freebsd.org/D26005
This commit is contained in:
parent
cb6e502fff
commit
d0e6339a5a
@ -1,4 +1,4 @@
|
||||
.\"
|
||||
.\"
|
||||
.\" Copyright (C) 1998 John D. Polstra. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 18, 2020
|
||||
.Dd August 26, 2020
|
||||
.Dt LOCKF 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -32,7 +32,7 @@
|
||||
.Nd execute a command while holding a file lock
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl kns
|
||||
.Op Fl knsw
|
||||
.Op Fl t Ar seconds
|
||||
.Ar file
|
||||
.Ar command
|
||||
@ -121,6 +121,14 @@ When a lock times out,
|
||||
is
|
||||
.Em not
|
||||
executed.
|
||||
.It Fl w
|
||||
Causes
|
||||
.Nm
|
||||
to open
|
||||
.Ar file
|
||||
for writing rather than reading.
|
||||
This is necessary on filesystems (including NFSv4) where a file which
|
||||
has been opened read-only cannot be exclusively locked.
|
||||
.El
|
||||
.Pp
|
||||
In no event will
|
||||
|
@ -62,9 +62,9 @@ main(int argc, char **argv)
|
||||
pid_t child;
|
||||
|
||||
silent = keep = 0;
|
||||
flags = O_CREAT;
|
||||
flags = O_CREAT | O_RDONLY;
|
||||
waitsec = -1; /* Infinite. */
|
||||
while ((ch = getopt(argc, argv, "sknt:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "sknt:w")) != -1) {
|
||||
switch (ch) {
|
||||
case 'k':
|
||||
keep = 1;
|
||||
@ -84,6 +84,9 @@ main(int argc, char **argv)
|
||||
"invalid timeout \"%s\"", optarg);
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
flags = (flags & ~O_RDONLY) | O_WRONLY;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
@ -171,7 +174,7 @@ acquire_lock(const char *name, int flags)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if ((fd = open(name, O_RDONLY|O_EXLOCK|flags, 0666)) == -1) {
|
||||
if ((fd = open(name, O_EXLOCK|flags, 0666)) == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
return (-1);
|
||||
else if (errno == ENOENT && (flags & O_CREAT) == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user