]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
test: (mkfds::make-regular-file) add a parameter for file locking
authorMasatake YAMATO <yamato@redhat.com>
Tue, 4 Jul 2023 16:58:24 +0000 (01:58 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Wed, 5 Jul 2023 07:01:09 +0000 (16:01 +0900)
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
tests/helpers/test_mkfds.c

index a71eaea68f57835fb992b2b0edfcd33ffa8cccf2..d17e6f7cf96ced105ebdb0bfbedb37ea04c36db5 100644 (file)
@@ -22,6 +22,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <sys/file.h>
 #include <getopt.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
@@ -390,6 +391,190 @@ static void unlink_and_close_fdesc(int fd, void *data)
        close(fd);
 }
 
+typedef void (*lockFn)(int fd, const char *fname);
+
+static void lock_fn_none(int fd _U_, const char *fname _U_)
+{
+       /* Do nothing */
+}
+
+static void lock_fn_flock_sh(int fd, const char *fname)
+{
+       if (flock(fd, LOCK_SH) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock");
+       }
+}
+
+static void lock_fn_flock_ex(int fd, const char *fname)
+{
+       if (flock(fd, LOCK_EX) < 0)  {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock");
+       }
+}
+
+static void lock_fn_posix_r_(int fd, const char *fname)
+{
+       struct flock r = {
+               .l_type = F_RDLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 0,
+               .l_len = 1,
+       };
+       if (fcntl(fd, F_SETLK, &r) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock");
+       }
+}
+
+static void lock_fn_posix__w(int fd, const char *fname)
+{
+       struct flock w = {
+               .l_type = F_WRLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 0,
+               .l_len = 1,
+       };
+       if (fcntl(fd, F_SETLK, &w) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock");
+       }
+}
+
+static void lock_fn_posix_rw(int fd, const char *fname)
+{
+       struct flock r = {
+               .l_type = F_RDLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 0,
+               .l_len = 1,
+       };
+       struct flock w = {
+               .l_type = F_WRLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 2,
+               .l_len = 1,
+       };
+       if (fcntl(fd, F_SETLK, &r) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock(read)");
+       }
+       if (fcntl(fd, F_SETLK, &w) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock(write)");
+       }
+}
+
+static void lock_fn_ofd_r_(int fd, const char *fname)
+{
+       struct flock r = {
+               .l_type = F_RDLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 0,
+               .l_len = 1,
+               .l_pid = 0,
+       };
+       if (fcntl(fd, F_OFD_SETLK, &r) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock");
+       }
+}
+
+static void lock_fn_ofd__w(int fd, const char *fname)
+{
+       struct flock w = {
+               .l_type = F_WRLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 0,
+               .l_len = 1,
+               .l_pid = 0,
+       };
+       if (fcntl(fd, F_OFD_SETLK, &w) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock");
+       }
+}
+
+static void lock_fn_ofd_rw(int fd, const char *fname)
+{
+       struct flock r = {
+               .l_type = F_RDLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 0,
+               .l_len = 1,
+               .l_pid = 0,
+       };
+       struct flock w = {
+               .l_type = F_WRLCK,
+               .l_whence = SEEK_SET,
+               .l_start = 2,
+               .l_len = 1,
+               .l_pid = 0,
+       };
+       if (fcntl(fd, F_OFD_SETLK, &r) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock(read)");
+       }
+       if (fcntl(fd, F_OFD_SETLK, &w) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to lock(write)");
+       }
+}
+
+static void lock_fn_lease_w(int fd, const char *fname)
+{
+       if (fcntl(fd, F_SETLEASE, F_WRLCK) < 0) {
+               int e = errno;
+               close(fd);
+               if (fname)
+                       unlink(fname);
+               errno = e;
+               err(EXIT_FAILURE, "failed to take out a write lease");
+       }
+}
+
+
 static void *make_w_regular_file(const struct factory *factory, struct fdesc fdescs[],
                                 int argc, char ** argv)
 {
@@ -407,9 +592,53 @@ static void *make_w_regular_file(const struct factory *factory, struct fdesc fde
        struct arg readable = decode_arg("readable", factory->params, argc, argv);
        bool bReadable = ARG_BOOLEAN(readable);
 
+       struct arg lock = decode_arg("lock", factory->params, argc, argv);
+       const char *sLock = ARG_STRING(lock);
+       lockFn lock_fn;
+
        if (iWrite_bytes < 0)
-               err(EXIT_FAILURE, "write-bytes must be a positive number or zero.");
+               errx(EXIT_FAILURE, "write-bytes must be a positive number or zero.");
+
+       if (strcmp(sLock, "none") == 0)
+               lock_fn = lock_fn_none;
+       else if (strcmp(sLock, "flock-sh") == 0)
+               lock_fn = lock_fn_flock_sh;
+       else if (strcmp(sLock, "flock-ex") == 0)
+               lock_fn = lock_fn_flock_ex;
+       else if (strcmp(sLock, "posix-r-") == 0) {
+               bReadable = true;
+               if (iWrite_bytes < 1)
+                       iWrite_bytes = 1;
+               lock_fn = lock_fn_posix_r_;
+       } else if (strcmp(sLock, "posix--w") == 0) {
+               if (iWrite_bytes < 1)
+                       iWrite_bytes = 1;
+               lock_fn = lock_fn_posix__w;
+       } else if (strcmp(sLock, "posix-rw") == 0) {
+               bReadable = true;
+               if (iWrite_bytes < 3)
+                       iWrite_bytes = 3;
+               lock_fn = lock_fn_posix_rw;
+       } else if (strcmp(sLock, "ofd-r-") == 0) {
+               bReadable = true;
+               if (iWrite_bytes < 1)
+                       iWrite_bytes = 1;
+               lock_fn = lock_fn_ofd_r_;
+       } else if (strcmp(sLock, "ofd--w") == 0) {
+               if (iWrite_bytes < 1)
+                       iWrite_bytes = 1;
+               lock_fn = lock_fn_ofd__w;
+       } else if (strcmp(sLock, "ofd-rw") == 0) {
+               bReadable = true;
+               if (iWrite_bytes < 3)
+                       iWrite_bytes = 3;
+               lock_fn = lock_fn_ofd_rw;
+       } else if (strcmp(sLock, "lease-w") == 0)
+               lock_fn = lock_fn_lease_w;
+       else
+               errx(EXIT_FAILURE, "unexpected value for lock parameter: %s", sLock);
 
+       free_arg(&lock);
        free_arg(&readable);
        free_arg(&write_bytes);
        free_arg(&delete);
@@ -454,6 +683,8 @@ static void *make_w_regular_file(const struct factory *factory, struct fdesc fde
                }
        }
 
+       lock_fn(fd, fname);
+
        fdescs[0] = (struct fdesc){
                .fd    = fdescs[0].fd,
                .close = bDelete? close_fdesc: unlink_and_close_fdesc,
@@ -2661,6 +2892,12 @@ static const struct factory factories[] = {
                                .desc = "open the new file readable way",
                                .defv.string = false,
                        },
+                       {
+                               .name = "lock",
+                               .type = PTYPE_STRING,
+                               .desc = "the way for file locking: [none]|flock-sh|flock-ex|posix-r-|posix--w|posix-rw|ofd-r-|ofd--w|ofd-rw|lease-w",
+                               .defv.string = "none",
+                       },
                        PARAM_END
                },
        },