From 3a8234d2440a464f5401b3444d454ac913d6b3d6 Mon Sep 17 00:00:00 2001 From: Neal H Walfield Date: Wed, 30 Oct 2019 00:03:13 +0100 Subject: libfshelp-tests: Tests for file record locking 2019-03-04 Svante Signell * test-*.c: Update code, remove test results. * README.new_tests: New file, summarize new test results. 2019-02-12 Svante Signell * test-*.c: Update code, add some test results. * Makefile: Remove extra flags. 2019-02-01 Svante Signell * Update copyright years. 2016-05-23 Svante Signell * Makefile: Add sub-directory libfshelp-tests. 2018-12-07 Svante Signell * Update copyright years. * locks.c(cmd_lock): Call fshelp_rlock_tweak() with new last argument rendezvous = MACH_PORT_NULL. 2017-01-05 Svante Signell * Update copyright years and headers. 2016-12-28 Svante Signell * Makefile: test-flock.c, test-lockf.c and test-fcntl.c * test-lockf.c: New file * Rename set-flock.c, set-fcntl.c to test-flock.c test-fcntl.c * TODO: Update README 2016-05-23 Svante Signell * Makefile: Link with pthread, add build of set-flock.c and set-fcntl.c * define temporary CPP_FLAGS until glibc is updated * set-flock.c, set-fcntl.c: New files. * Fix typos in README 2001-04-11 Neal H Walfield * ChangeLog: New file, mentioning itself in this sentence. * Makefile: New file. * README: Likewise. * fork.c: Likewise. * locks: Likewise. * locks-tests: Likewise. * locks.c: Likewise. * race.c: Likewise. --- libfshelp-tests/test-fcntl.c | 273 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 libfshelp-tests/test-fcntl.c (limited to 'libfshelp-tests/test-fcntl.c') diff --git a/libfshelp-tests/test-fcntl.c b/libfshelp-tests/test-fcntl.c new file mode 100644 index 00000000..7495e7ab --- /dev/null +++ b/libfshelp-tests/test-fcntl.c @@ -0,0 +1,273 @@ +/* test-fcntl.c: Test advisory open file record locks, see fcntl(2) + Options: + + Copyright (C) 2016-2019 Free Software Foundation, Inc. + + Written by Svante Signell + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see . */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* Parse args */ +int parse_args (int argc, char **argv, char **file_name, + int *flags, char **flagsc, + int *cmd, char **cmdc, + struct flock *lock, + char **l_typec, char **l_whencec, + int *sleep_time) +{ + int i, tmp; + char *str, *endptr; + + if (argc < 2) + error (1, 0, "Usage: %s file [flags] [cmd] [len] [sleep_time]\n\ + file : file name/device name\n\ + flags : r (O_RDONLY) | w (O_WRONLY) | rw (O_RDWR) : [rw]\n\ + cmd : g (F_GETLK), s (F_SETLK), sw (F_SETLKW) : [s]\n\ + lock.l_type : rl (F_RDLCK), wl (F_WRLCK), ul [F_UNLCK] : [ul]\n\ + lock.l_whence : ss (SEEK_SET), sc (SEEK_CUR), se (SEEK_END) : [ss]\n\ + lock.l_start : b : [b 0]\n\ + lock.l_len : l : [l 0]\n\ + sleep_time : st : [st 10]\n", + argv[0]); + + *file_name = argv[1]; + for (i = 2; i < argc; i++) + { + str = argv[i]; + if (strncmp (str, "r", 2) == 0) + { + *flags = O_RDONLY; + *flagsc = "O_RDONLY"; + continue; + } + if (strncmp (str, "w", 2) == 0) + { + *flags = O_WRONLY; + *flagsc = "O_WRONLY"; + continue; + } + if (strncmp (str, "rw", 2) == 0) + { + *flags = O_RDWR; + *flagsc = "O_RDWR"; + continue; + } + if (strncmp (str, "s", 2) == 0) + { + *cmd = F_SETLK; + *cmdc = "F_SETLK"; + continue; + } + if (strncmp (str, "sw", 2) == 0) + { + *cmd = F_SETLKW; + *cmdc = "F_SETLKW"; + continue; + } + if (strncmp (str, "g", 2) == 0) + { + *cmd = F_GETLK; + *cmdc = "F_GETLK"; + continue; + } + if (strncmp (str, "rl", 2) == 0) + { + lock->l_type = F_RDLCK; + *l_typec = "F_RDLCK"; + continue; + } + if (strncmp (str, "wl", 2) == 0) + { + lock->l_type = F_WRLCK; + *l_typec = "F_WRLCK"; + continue; + } + if (strncmp (str, "ul", 2) == 0) + { + lock->l_type = F_UNLCK; + *l_typec = "F_UNLCK"; + continue; + } + if (strncmp (str, "ss", 2) == 0) + { + lock->l_whence = SEEK_SET; + *l_whencec = "SEEK_SET"; + continue; + } + if (strncmp (str, "sc", 2) == 0) + { + lock->l_whence = SEEK_CUR; + *l_whencec = "SEEK_CUR"; + continue; + } + if (strncmp (str, "se", 2) == 0) + { + lock->l_whence = SEEK_END; + *l_whencec = "SEEK_END"; + continue; + } + if (strncmp (str, "b", 2) == 0) + { + str = argv[++i]; + if (str) + { + errno = 0; + tmp = strtol (str, &endptr, 10); + if (tmp == 0 && errno != 0) + error (1, errno, "%s", str); + if (endptr == str) + error (1, EINVAL, "%s", str); + lock->l_start = tmp; + } + else + error (1, EINVAL, "%s", str); + continue; + } + if (strncmp (str, "l", 2) == 0) + { + str = argv[++i]; + if (str) + { + errno = 0; + tmp = strtol (str, &endptr, 10); + if (tmp == 0 && errno != 0) + error (1, errno, "%s", str); + if (endptr == str) + error (1, EINVAL, "%s", str); + lock->l_len = tmp; + } + else + error (1, EINVAL, "%s", str); + continue; + } + if (strncmp (str, "st", 2) == 0) + { + str = argv[++i]; + if (str) + { + errno = 0; + tmp = strtol (str, &endptr, 10); + if (tmp == 0 && errno != 0) + error (1, errno, "%s", str); + if (endptr == str) + error (1, EINVAL, "%s", str); + *sleep_time = tmp; + } + else + error (1, EINVAL, "%s", str); + continue; + } + error (1, EINVAL, "%s", str); + } + + return 0; +} + +int main (int argc, char **argv) +{ +#ifdef __GNU__ + error_t err; +#else + int err; +#endif + int fd, ret = -1; + char *file_name = NULL; + int flags = O_RDWR; + char *flagsc = "O_RDWR"; + char *old_l_typec; + int old_l_type, old_l_pid; + int cmd = F_SETLK; + char *cmdc = "F_SETLK"; + struct flock lock = { + F_UNLCK, + SEEK_SET, + 0, + 0, + 123456}; + char *l_typec = "F_UNLCK"; + char *l_whencec = "SEEK_SET"; + int sleep_time = 10; + + ret = parse_args (argc, argv, &file_name, + &flags, &flagsc, + &cmd, &cmdc, + &lock, + &l_typec, &l_whencec, + &sleep_time); + +#ifdef __GNU__ + printf ("test-fcntl: GNU/Hurd\n"); +#else + printf ("test-fcntl: GNU/Linux\n"); +#endif + printf ("test-fcntl: [PID]=%d\n", getpid()); + printf ("file = '%s', flags = %s\n", file_name, flagsc); + fd = open (file_name, flags); + if (fd < 0) + error (1, errno, "open"); + printf ("Opening '%s', fd = %d, ", file_name, fd); + printf ("cmd = %s\n ", cmdc); + printf("lock = {l_type, l_whence, l_start, l_len, l_pid} =\n"); +#ifdef __GNU__ + printf (" {%s, %s, %lld, %lld, %d}\n", +#else + printf (" {%s, %s, %ld, %ld, %d}\n", +#endif + l_typec, l_whencec, lock.l_start, lock.l_len, lock.l_pid); + + old_l_type = lock.l_type; + old_l_typec = l_typec; + old_l_pid = lock.l_pid; + + printf ("Requesting lock\n"); + err = fcntl (fd, cmd, &lock); + if (err) + error (1, errno, "fcntl"); + + if (old_l_type != lock.l_type) + if (lock.l_type == F_UNLCK) + { + l_typec = "F_UNLCK"; + printf("[PID=%ld] Lock can be placed\n", (long) getpid()); + printf ("old_l_type = %s, l_type = %s\n", old_l_typec, l_typec); + return ret; + } + if (old_l_pid != lock.l_pid) + { + printf("[PID=%ld] Denied by %s lock on %lld:%lld " + "(held by PID %ld)\n", (long) getpid(), + (lock.l_type == F_RDLCK) ? "READ" : "WRITE", + (long long) lock.l_start, + (long long) lock.l_len, (long) lock.l_pid); + return ret; + } + printf ("Got lock: sleep_time = %d seconds\n", sleep_time); + sleep (sleep_time); + printf ("Closing '%s'\n", file_name); + close (fd); + + return ret; +} -- cgit v1.2.3