]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
flock: support locking with byte-range
authorMasatake YAMATO <yamato@redhat.com>
Fri, 21 Feb 2025 15:21:51 +0000 (00:21 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Mon, 24 Feb 2025 11:19:50 +0000 (20:19 +0900)
New options, --start and --length are for specifying the byte-range.
The options assume used with --fcntl option.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
bash-completion/flock
sys-utils/flock.1.adoc
sys-utils/flock.c

index 5312167e06c791cf4e649e63f3cb4b8174db6cb9..a4de186f3889676f5afb2394877c1ed6973098cd 100644 (file)
@@ -34,6 +34,8 @@ _flock_module()
                                --command
                                --no-fork
                                --fcntl
+                               --start
+                               --length
                                --help
                                --version"
                        COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
index 2ffae4380e5a706e09507e6675d84efd174b94a9..08843942f9ccf7cba888b55f75d9ed35097ac11b 100644 (file)
@@ -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.
 
index c42c9da51c57fc8db353866003d68ecf4bb8756b..4747ebaab7743e79826ede390242da2380d1b2e3 100644 (file)
@@ -82,6 +82,8 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(  " -c, --command <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 <offset>     starting offset for lock (implies --fcntl)\n"), stdout);
+       fputs(_(  "     --length <number>    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:
                        /*