diff --git a/bash-completion/flock b/bash-completion/flock index 5312167e06c..a4de186f388 100644 --- a/bash-completion/flock +++ b/bash-completion/flock @@ -34,6 +34,8 @@ _flock_module() --command --no-fork --fcntl + --start + --length --help --version" COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) ) diff --git a/sys-utils/flock.1.adoc b/sys-utils/flock.1.adoc index 2ffae4380e5..08843942f9c 100644 --- a/sys-utils/flock.1.adoc +++ b/sys-utils/flock.1.adoc @@ -85,6 +85,12 @@ Instead of flock(2), apply an fcntl(2) open file description lock (that is, usin This is only available on kernel versions >= 3.15. +*--start* _offset_:: +The starting offset for lock. Ths option implies *--fcntl*. + +*--length* _number_:: +The number of bytes to lock. Ths option implies *--fcntl*. + *--verbose*:: Report how long it took to acquire the lock, or why the lock could not be obtained. diff --git a/sys-utils/flock.c b/sys-utils/flock.c index c42c9da51c5..4747ebaab77 100644 --- a/sys-utils/flock.c +++ b/sys-utils/flock.c @@ -82,6 +82,8 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_( " -c, --command run a single command string through the shell\n"), stdout); fputs(_( " -F, --no-fork execute command without forking\n"), stdout); fputs(_( " --fcntl use fcntl(F_OFD_SETLK) rather than flock()\n"), stdout); + fputs(_( " --start starting offset for lock (implies --fcntl)\n"), stdout); + fputs(_( " --length number of bytes to lock (implies --fcntl)\n"), stdout); fputs(_( " --verbose increase verbosity\n"), stdout); fputs(USAGE_SEPARATOR, stdout); fprintf(stdout, USAGE_HELP_OPTIONS(26)); @@ -152,25 +154,25 @@ static int flock_to_fcntl_type(int op) } } -static int fcntl_lock(int fd, int op, int block) +static int fcntl_lock(int fd, int op, int block, off_t start, off_t len) { struct flock arg = { .l_type = flock_to_fcntl_type(op), .l_whence = SEEK_SET, - .l_start = 0, - .l_len = 0, + .l_start = start, + .l_len = len, }; int cmd = (block & LOCK_NB) ? F_OFD_SETLK : F_OFD_SETLKW; return fcntl(fd, cmd, &arg); } -static int do_lock(int api, int fd, int op, int block) +static int do_lock(int api, int fd, int op, int block, off_t start, off_t len) { switch (api) { case API_FLOCK: return flock(fd, op | block); case API_FCNTL_OFD: - return fcntl_lock(fd, op, block); + return fcntl_lock(fd, op, block, start, len); /* * Should never happen, api can never have values other than * API_*. @@ -197,6 +199,7 @@ int main(int argc, char *argv[]) int verbose = 0; int api = API_FLOCK; struct timeval time_start = { 0 }, time_done = { 0 }; + off_t start = 0, length = 0; /* * The default exit code for lock conflict or timeout * is specified in man flock.1 @@ -207,6 +210,8 @@ int main(int argc, char *argv[]) enum { OPT_VERBOSE = CHAR_MAX + 1, OPT_FCNTL, + OPT_FCNTL_START, + OPT_FCNTL_LENGTH, }; static const struct option long_options[] = { {"shared", no_argument, NULL, 's'}, @@ -221,6 +226,8 @@ int main(int argc, char *argv[]) {"no-fork", no_argument, NULL, 'F'}, {"verbose", no_argument, NULL, OPT_VERBOSE}, {"fcntl", no_argument, NULL, OPT_FCNTL}, + {"start", required_argument, NULL, OPT_FCNTL_START}, + {"length", required_argument, NULL, OPT_FCNTL_LENGTH}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} @@ -278,6 +285,16 @@ int main(int argc, char *argv[]) case OPT_FCNTL: api = API_FCNTL_OFD; break; + case OPT_FCNTL_START: + start = strtosize_or_err(optarg, + _("invalid as start offset")); + api = API_FCNTL_OFD; + break; + case OPT_FCNTL_LENGTH: + length = strtosize_or_err(optarg, + _("invalid as lenght of lock range")); + api = API_FCNTL_OFD; + break; case OPT_VERBOSE: verbose = 1; break; @@ -348,7 +365,7 @@ int main(int argc, char *argv[]) if (verbose) gettime_monotonic(&time_start); - while (do_lock(api, fd, type, block)) { + while (do_lock(api, fd, type, block, start, length)) { switch (errno) { case EWOULDBLOCK: /*