Attached is the third part of the patches for file record locking: libfshelp-tests_rlock.patch fcntl.diff
The patch fcntl.diff against glibc-2.29-1 should be applied after (or at the same time as) the patched hurd debs. Note that the following glibc patch have been commented out from the series file: hurd-i386/tg-WRLCK-upgrade.diff Additionally the two upstream commits are reversed by: revert-git-lockf-0.diff revert-git-fcntl64.diff If you are working with git these commits are more easily mage there. Thanks!
sysdeps/mach/hurd/Changelog 2019-01-12 Svante Signell <svante.sign...@gmail.com> * Update copyright years. 2018-12-21 Svante Signell <svante.sign...@gmail.com> * hurd-i386/fcntl.diff: Add the required new arguments when calling the updated RPC file_record_lock. 2018-12-04 Svante Signell <svante.sign...@gmail.com> * debian/patches/series: Comment out debian 2.28-1 patches: hurd-i386/git-fcntl64.diff hurd-i386/git-lockf-0.diff hurd-i386/tg-WRLCK-upgrade.diff * fcntl.c: Add support weak, hidden and strong references as in Debian 2.28-1 patch as in hurd-i386/git-fcntl64.diff. * fcntl64.c: New file, defined in fcntl.c as an alias. * hurd-i386/fcntl.diff: Refresh. 2014-08-21 Svante Signell <svante.sign...@gmail.com> * fcntl.c: Add support for file-record-lock RPC fixing posix file locking using the flock64 version of struct flock. * bits/fcntl.h: Since MIG cannot mix 32 bit and 64 bit integers define unique numbers for F_GETLK64, F_SETLK64 and F_SETLKW64 to prepare for a flock64 implementation of file record locking in hurd. Index: glibc-2.28-4.1/sysdeps/mach/hurd/bits/fcntl.h =================================================================== --- glibc-2.28-4.1.orig/sysdeps/mach/hurd/bits/fcntl.h +++ glibc-2.28-4.1/sysdeps/mach/hurd/bits/fcntl.h @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for GNU. - Copyright (C) 1993-2018 Free Software Foundation, Inc. + Copyright (C) 1993-2019 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -163,9 +163,18 @@ # define F_GETOWN 5 /* Get owner (receiver of SIGIO). */ # define F_SETOWN 6 /* Set owner (receiver of SIGIO). */ #endif +#ifdef __USE_FILE_OFFSET64 +# define F_GETLK F_GETLK64 +# define F_SETLK F_SETLK64 +# define F_SETLKW F_SETLKW64 +#else #define F_GETLK 7 /* Get record locking info. */ #define F_SETLK 8 /* Set record locking info (non-blocking). */ #define F_SETLKW 9 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 10 /* Get record locking info. */ +#define F_SETLK64 11 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 12 /* Set record locking info (blocking). */ #ifdef __USE_XOPEN2K8 # define F_DUPFD_CLOEXEC 1030 /* Duplicate, set FD_CLOEXEC on new one. */ Index: glibc-2.28-4.1/sysdeps/mach/hurd/fcntl.c =================================================================== --- glibc-2.28-4.1.orig/sysdeps/mach/hurd/fcntl.c +++ glibc-2.28-4.1/sysdeps/mach/hurd/fcntl.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2018 Free Software Foundation, Inc. +/* Copyright (C) 1992-2019 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -20,7 +20,6 @@ #include <hurd.h> #include <hurd/fd.h> #include <stdarg.h> -#include <sys/file.h> /* XXX for LOCK_* */ /* Perform file control operations on FD. */ int @@ -128,31 +127,27 @@ __libc_fcntl (int fd, int cmd, ...) case F_SETLK: case F_SETLKW: { - /* XXX - We need new RPCs to support POSIX.1 fcntl file locking!! - For the time being we support the whole-file case only, - with all kinds of WRONG WRONG WRONG semantics, - by using flock. This is definitely the Wrong Thing, - but it might be better than nothing (?). */ struct flock *fl = va_arg (ap, struct flock *); - va_end (ap); + mach_port_t rendezvous = MACH_PORT_NULL; + switch (cmd) { case F_GETLK: - errno = ENOSYS; - return -1; + cmd = F_GETLK64; + break; case F_SETLK: - cmd = LOCK_NB; + cmd = F_SETLK64; break; - default: - cmd = 0; + case F_SETLKW: + cmd = F_SETLKW64; break; } switch (fl->l_type) { - case F_RDLCK: cmd |= LOCK_SH; break; - case F_WRLCK: cmd |= LOCK_EX; break; - case F_UNLCK: cmd |= LOCK_UN; break; + case F_RDLCK: + case F_WRLCK: + case F_UNLCK: + break; default: errno = EINVAL; return -1; @@ -160,24 +155,73 @@ __libc_fcntl (int fd, int cmd, ...) switch (fl->l_whence) { case SEEK_SET: - if (fl->l_start == 0 && fl->l_len == 0) /* Whole file request. */ - break; - /* It seems to be common for applications to lock the first - byte of the file when they are really doing whole-file locking. - So, since it's so wrong already, might as well do that too. */ - if (fl->l_start == 0 && fl->l_len == 1) - break; - /* FALLTHROUGH */ case SEEK_CUR: case SEEK_END: - errno = ENOTSUP; + break; + default: + errno = EINVAL; return -1; + } + + struct flock64 fl64 = { + .l_type = fl->l_type, + .l_whence = fl->l_whence, + .l_start = fl->l_start, + .l_len = fl->l_len, + .l_pid = fl->l_pid + }; + + err = HURD_FD_PORT_USE (d, __file_record_lock (port, cmd, &fl64, rendezvous, MACH_MSG_TYPE_MAKE_SEND)); + + fl->l_type = fl64.l_type; + fl->l_whence = fl64.l_whence; + fl->l_start = fl64.l_start; + fl->l_len = fl64.l_len; + fl->l_pid = fl64.l_pid; + if ((sizeof fl->l_start != sizeof fl64.l_start + && fl->l_start != fl64.l_start) + || (sizeof fl->l_len != sizeof fl64.l_len + && fl->l_len != fl64.l_len)) + { + __set_errno (EOVERFLOW); + return -1; + } + + result = err ? __hurd_dfail (fd, err) : 0; + break; + } + + case F_GETLK64: + case F_SETLK64: + case F_SETLKW64: + { + struct flock64 *fl64 = va_arg (ap, struct flock64 *); + mach_port_t rendezvous = MACH_PORT_NULL; + + switch (fl64->l_type) + { + case F_RDLCK: + case F_WRLCK: + case F_UNLCK: + break; + default: + errno = EINVAL; + return -1; + } + switch (fl64->l_whence) + { + case SEEK_SET: + case SEEK_CUR: + case SEEK_END: + break; default: errno = EINVAL; return -1; } - return __flock (fd, cmd); + err = HURD_FD_PORT_USE (d, __file_record_lock (port, cmd, fl64, rendezvous, MACH_MSG_TYPE_MAKE_SEND)); + result = err ? __hurd_dfail (fd, err) : 0; + break; } case F_GETFL: /* Get per-open flags. */ @@ -215,3 +259,4 @@ strong_alias (__libc_fcntl, __libc_fcntl libc_hidden_def (__libc_fcntl64) weak_alias (__libc_fcntl64, __fcntl64) libc_hidden_weak (__fcntl64) +weak_alias (__fcntl64, fcntl64) Index: glibc-2.28-4.1/sysdeps/mach/hurd/fcntl64.c =================================================================== --- /dev/null +++ glibc-2.28-4.1/sysdeps/mach/hurd/fcntl64.c @@ -0,0 +1 @@ +/* fcntl64 is defined in fcntl.c as an alias. */
./ChangeLog 2019-03-04 Svante Signell <svante.sign...@gmail.com> * test-*.c: Update code, remove test results. * README.new_tests: New file, summarize new test results. 2019-02-12 Svante Signell <svante.sign...@gmail.com> * test-*.c: Update code, add some test results. * Makefile: Remove extra flags. w2019-02-01 Svante Signell <svante.sign...@gmail.com> * Update copyright years. 2016-05-23 Svante Signell <svante.sign...@gmail.com> * Makefile: Add sub-directory libfshelp-tests. libfshelp-tests/ChangeLog 2018-12-07 Svante Signell <svante.sign...@gmail.com> * Update copyright years. * locks.c(cmd_lock): Call fshelp_rlock_tweak() with new last argument rendezvous = MACH_PORT_NULL. 2017-01-05 Svante Signell <svante.sign...@gmail.com> * Update copyright years and headers. 2016-12-28 Svante Signell <svante.sign...@gmail.com> * 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 <svante.sign...@gmail.com> * 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 <n...@cs.uml.edu> * 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. Index: hurd-0.9.git20190331-8.2/Makefile =================================================================== --- hurd-0.9.git20190331-8.2.orig/Makefile +++ hurd-0.9.git20190331-8.2/Makefile @@ -1,6 +1,6 @@ # -# Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2004, -# 2006, 2009, 2011, 2012, 2013 Free Software Foundation, Inc. +# Copyright (C) 1993-1999, 2001, 2002, 2004, 2006, 2009, +# 2011-2013, 2015-2019 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -46,7 +46,7 @@ prog-subdirs = auth proc exec term \ storeio pflocal pfinet defpager mach-defpager \ login daemons boot console \ hostmux usermux ftpfs trans \ - console-client utils sutils \ + console-client utils sutils libfshelp-tests \ benchmarks fstests \ procfs \ startup \ Index: hurd-0.9.git20190331-8.2/libfshelp-tests/Makefile =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/Makefile @@ -0,0 +1,42 @@ +# Makefile libfshelp test cases +# +# Copyright (C) 2001, 2015-2019 Free Software Foundation, Inc. +# +# Written by Neal H Walfield <n...@cs.uml.edu> +# +# This file is part of the GNU Hurd. +# +# 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 2, 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 <http://www.gnu.org/licenses/>. + +dir := libfshelp-tests +makemode := utilities + +targets = race locks fork test-flock test-lockf test-fcntl +SRCS = race.c locks.c fork.c test-flock.c test-lockf.c test-fcntl.c + +MIGSTUBS = fsUser.o ioUser.o +OBJS = $(SRCS:.c=.o) $(MIGSTUBS) +HURDLIBS = fshelp ports +LDLIBS += -lpthread + +race: race.o fsUser.o ioUser.o +fork: fork.o fsUser.o +locks: locks.o +test-flock: test-flock.o +test-lockf: test-lockf.o +test-fcntl: test-fcntl.o ../libfshelp/libfshelp.a + +race locks: ../libfshelp/libfshelp.a ../libports/libports.a ../libshouldbeinlibc/libshouldbeinlibc.a + +include ../Makeconf Index: hurd-0.9.git20190331-8.2/libfshelp-tests/README =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/README @@ -0,0 +1,102 @@ +These programs are used to help test the algorithms in the libfshelp +library. + +Record Locking +============== + +Race +---- + +Race locks a file, reads an integer, increments it, writes the result to +the file and then unlocks the file -- 10,000 times. It is intended that +multiple instances of this program be run at the same time. Race takes +three arguments: the file to use, the start of the lock and the length. +For obvious reasons, it is important that all instances of race have +locks that overlap. For example: + + # rm -f foo && ( ./race foo 2 0 & ./race foo 2 3 & \ + > ./race foo 0 3 ) + Was blocked 5482 times + Was blocked 5485 times + Was blocked 5479 times + # cat foo + 30000 + +We see here that each process was blocked several thousand times and that +the result in the file foo is 30000. Perfect. + +Locks +----- + +Locks is an interactive shell that has one ``file'' and ten open file +descriptors. Using some simple commands, one can test to see if locks +are established, cleared, and enforced. The principal command is +`lock,' which takes four parameters. The first is the file descriptor +to lock, the second is the start of the lock, the third is the length of +the lock (0 = until EOF) and the last is the type of lock to establish +from the set {0: F_UNLCK, 1: F_RDLCK, 2: F_WRLCK}. Help on the other +commands can be gotten using the `help' command. + +A small run: + + # ./locks + > lock 0 10 0 1 + 0: Start = 10; Length = 0; Type = F_RDLCK + +Lock from byte 10 through the EOF. + + > lock 0 20 0 0 + 0: Start = 10; Length = 10; Type = F_RDLCK + +Unlock from byte 20 through the EOF. + + > lock 0 11 8 2 + 0: Start = 10; Length = 1; Type = F_RDLCK + Start = 11; Length = 8; Type = F_WRLCK + Start = 19; Length = 1; Type = F_RDLCK + +Upgrade bytes 11 through 19 to a write lock. + + > lock 0 9 10 1 + 0: Start = 9; Length = 2; Type = F_RDLCK + Start = 11; Length = 8; Type = F_WRLCK + Start = 19; Length = 1; Type = F_RDLCK + +Add a read lock to byte 9. + + > lock 1 0 10 1 + 1: Start = 0; Length = 10; Type = F_RDLCK + +Read lock the first ten bytes of the file through file descriptor 1. + + > lock 1 10 0 1 + Resource temporarily unavailable + +Attempts to read lock the rest of the file. This, however, fails as +there are outstanding write locks held through file descriptor 1. + + > lock 1 10 0 0 + 1: Start = 0; Length = 10; Type = F_RDLCK + +What happens when file descriptor tries to unlock the blocked range? + + > lock 1 10 0 2 + Resource temporarily unavailable + +Nothing. + +A bunch of tests live in locks-tests. One can run them through the test +program using: `./locks < ./locks-test 2>&1 | less'. If it core dumps or +triggers an assertion, that is a bug. Report it. + +Fork +---- + +Tests to see if the a child inherits the locks across a fork. According +to POSIX, the child should not. + + # ./fork foo + Parent has a write lock; Others have a write lock. + Child has a write lock; Others have a write lock. + +We are not POSIX compliant. Index: hurd-0.9.git20190331-8.2/libfshelp-tests/fork.c =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/fork.c @@ -0,0 +1,80 @@ +/* Test is a process inherits locks after a fork. + + Copyright (C) 2001 Free Software Foundation, Inc. + + Written by Neal H Walfield <n...@cs.uml.edu> + + 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 2, 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 <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <stdio.h> +#include <error.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/file.h> +#include "fs_U.h" +#include <hurd.h> + +char *lock2str (int type) +{ + if (type & LOCK_SH) + return "read"; + if (type & LOCK_EX) + return "write"; + if (type & LOCK_UN) + return "unlocked"; + assert (! "Invalid"); + return NULL; +} + +int main (int argc, char **argv) +{ + error_t err; + struct flock64 lock; + mach_port_t rendezvous = MACH_PORT_NULL; + int fd; + pid_t pid; + int mine, others; + + if (argc != 2) + error (1, 0, "Usage: %s file", argv[0]); + + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_type = F_WRLCK; + + fd = file_name_lookup (argv[1], O_READ | O_WRITE | O_CREAT, 0666); + if (fd == MACH_PORT_NULL) + error (1, errno, "file_name_lookup"); + + err = file_record_lock (fd, F_SETLK64, &lock, rendezvous, MACH_MSG_TYPE_MAKE_SEND); + if (err) + error (1, err, "file_record_lock"); + + pid = fork (); + if (pid == -1) + error (1, errno, "fork"); + + err = file_lock_stat (fd, &mine, &others); + if (err) + error (1, err, "file_lock_stat"); + + printf ("%s has a %s lock; Others have a %s lock.\n", + pid ? "Parent" : "Child", lock2str (mine), lock2str (others)); + + mach_port_deallocate (mach_task_self (), fd); + + return 0; +} Index: hurd-0.9.git20190331-8.2/libfshelp-tests/locks.c =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/locks.c @@ -0,0 +1,328 @@ +/* Test record locking. + + Copyright (C) 2001, 2018-2019 Free Software Foundation, Inc. + + Written by Neal H Walfield <n...@cs.uml.edu> + + 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 2, 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 <http://www.gnu.org/licenses/>. */ + +#include "../libfshelp/fshelp.h" +#include "../libfshelp/rlock.h" +#include <errno.h> +#include <error.h> +#include <stdio.h> +#include <string.h> + +#include "fs_U.h" + +#ifndef PEROPENS +#define PEROPENS 10 +#endif + +struct rlock_box box; +struct rlock_peropen peropens[PEROPENS]; +loff_t pointers[PEROPENS]; +loff_t file_size; + +struct command +{ + char *name; + int (*func)(char *cmds); + char *doc; +}; + +error_t cmd_help (char *); +error_t cmd_comment (char *); +error_t cmd_echo (char *); +error_t cmd_lock (char *); +error_t cmd_list (char *); +error_t cmd_seek (char *); +error_t cmd_exec (char *); + +struct command commands [] = + { + { "help", cmd_help, "Print this screen" }, + { "#", cmd_comment, "Comment (Must _start_ the line)." }, + { "echo", cmd_echo, "Echo the line." }, + { "lock", cmd_lock, + "po start length type\n" + "\ttype = { F_UNLCK=0, F_RDLCK,=1, F_WRLCK=2 }" }, + { "list", cmd_list, "list all locks' status" }, + { "seek", cmd_seek, "PO1 ... Print the position of the given po.\n" + "\tPO1=N ... Seek a given po." }, + { "exec", cmd_exec, "Execute a built in echoing the command."} + }; + +error_t +cmd_help (char *args) +{ + int i; + printf ("Commands:\n"); + for (i = 0; i < sizeof (commands) / sizeof (struct command); i ++) + printf ("%s\t%s\n", commands[i].name, commands[i].doc); + return 0; +} + +error_t +cmd_comment (char *args) +{ + return 0; +} + +error_t +cmd_echo (char *args) +{ + printf ("%s", args); + return 0; +} + +error_t +cmd_lock (char *args) +{ + int po, type; + loff_t start, len; + struct flock64 lock; + mach_port_t rendezvous = MACH_PORT_NULL; + error_t err; + + if (4 != sscanf (args, "%d %ld %ld %d", &po, (long*)&start, (long*)&len, &type)) + { + printf ("Syntax error.\n"); + return 0; + } + + lock.l_type = type; + lock.l_whence = SEEK_CUR; + lock.l_start = (long)start; + lock.l_len = (long)len; + + if (po < 0 || po >= PEROPENS) + { + printf ("Unknown peropen: %d.\n", po); + return 0; + } + + switch (type) + { + case 0: lock.l_type = F_UNLCK; break; + case 1: lock.l_type = F_RDLCK; break; + case 2: lock.l_type = F_WRLCK; break; + default: printf ("Unknown type.\n"); return 0; + } + + err= fshelp_rlock_tweak (&box, NULL, &peropens[po], O_RDWR, + file_size, pointers[po], F_SETLK64, + &lock, rendezvous); + if (! err) + { + char buf[10]; + sprintf (buf, "%d\n", po); + cmd_list (buf); + } + return err; +} + +error_t +cmd_list (char *args) +{ + char *end; + + void dump (int i) + { + struct rlock_list *l; + + printf ("%3d:", i); + for (l = *peropens[i].locks; l; l = l->po.next) + { + printf ("\tStart = %4ld; Length = %4ld; Type = ", (long)l->start, (long)l->len); + switch (l->type) + { + case F_RDLCK: printf ("F_RDLCK"); break; + case F_WRLCK: printf ("F_WRLCK"); break; + case F_UNLCK: printf ("F_UNLCK"); break; + default: printf ("UNKNOWN"); break; + } + printf ("\n"); + } + + if (*peropens[i].locks == NULL) + printf ("\n"); + } + + while (*args == ' ') + args ++; + + if (*args == '\n' || *args == '\0') + { + int i; + + for (i = 0; i < PEROPENS; i ++) + dump (i); + return 0; + } + + while (1) + { + long int p = strtoll (args, &end, 0); + if (end == args) + { + printf ("Syntax error.\n"); + return 0; + } + + if (p < 0 || p > PEROPENS) + printf ("%3ld:\tOut of range.", p); + else + dump (p); + + while (*end == ' ') + end ++; + + if (*end == '\n' || *end == '\0') + return 0; + args = end; + } +} + +error_t +cmd_seek (char *args) +{ + char *end; + int p; + + while (*args == ' ') + args ++; + + if (*args == '\n' || *args == '\0') + { + int i; + for (i = 0; i < PEROPENS; i ++) + printf ("%3d: %ld\n", i, (long)pointers[i]); + return 0; + } + + while (1) + { + int set = 0; + long seek_to = 0; + + p = strtol (args, &end, 0); + if (end == args) + { + printf ("Syntax error.\n"); + return 0; + } + + if (*end == '=') + { + set = 1; + args = end + 1; + seek_to = strtol (args, &end, 0); + if (end == args) + { + printf ("Syntax error.\n"); + return 0; + } + } + + if (p < 0 || p > PEROPENS) + printf ("%3d: unknown peropen\n", p); + else + { + printf ("%3d: %ld", p, (long)pointers[p]); + if (set) + printf (" => %ld\n", (long)(pointers[p] = seek_to)); + else + printf ("\n"); + } + + while (*end == ' ') + end ++; + if (*end == '\0' || *end == '\n') + return 0; + args = end; + } +} + +error_t +interpret (char *buffer) +{ + int i; + + while (*buffer == ' ') + buffer ++; + + if (*buffer == '\n') + return 0; + + for (i = 0; i < sizeof (commands) / sizeof (struct command); i ++) + if (strncmp (commands[i].name, buffer, strlen (commands[i].name)) == 0) + { + error_t err; + err = commands[i].func (buffer + strlen (commands[i].name) + 1); + if (err) + printf ("%s\n", strerror (err)); + return err; + } + + printf ("Unknown command.\n"); + return 0; +} + +error_t +cmd_exec (char *arg) +{ + printf ("%s", arg); + interpret (arg); + return 0; +} + +int main (int argc, char *argv[]) +{ + int i; + + if (argc != 1) + { + printf ("Usage: %s\n" + "\tType `help' at the prompt.\n" + "\tUsed to test the record locking functions in libfshelp\n", + argv[0]); + return 1; + } + + fshelp_rlock_init (&box); + for (i = 0; i < PEROPENS; i ++) + fshelp_rlock_po_init (&peropens[i]); + + while (! feof (stdin)) + { + char b[1024]; + + printf ("> "); + fflush (stdout); + + if (! fgets (b, sizeof (b), stdin)) + { + if (feof (stdin)) + break; + else + continue; + } + + interpret (b); + } + + printf ("\n"); + return 0; +} Index: hurd-0.9.git20190331-8.2/libfshelp-tests/locks-tests =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/locks-tests @@ -0,0 +1,585 @@ +echo Legend: +echo + => Shared region +echo x => Exclusive region +echo ' ' => Unlocked region +echo . => Clearing region +echo [] => Start/End of a region +echo After each lock command, the proposed region is shown followed +echo by the result of applying it. +echo * Established region wraps new region +echo ** Both boundaries align +echo [ +exec lock 0 1 10 1 +echo [+++++++++++++] +echo [ [+++++++++++++] +exec lock 0 1 10 1 +echo [+++++++++++++] +echo [ [+++++++++++++] +exec lock 0 1 10 2 +echo [xxxxxxxxxxxxx] +echo [ [xxxxxxxxxxxxx] +exec lock 0 1 10 1 +echo [+++++++++++++] +echo [ [xxxxxxxxxxxxx] +exec lock 0 1 10 2 +echo [xxxxxxxxxxxxx] +echo [ [xxxxxxxxxxxxx] +exec lock 0 1 10 0 +echo [.............] +echo [ +exec lock 0 10 0 1 +echo [++++++++ +echo [ [++++++++ +exec lock 0 10 0 1 +echo [++++++++ +echo [ [++++++++ +exec lock 0 10 0 2 +echo [xxxxxxxx +echo [ [xxxxxxxx +exec lock 0 10 0 2 +echo [xxxxxxxx +echo [ [xxxxxxxx +exec lock 0 10 0 1 +echo [++++++++ +echo [ [xxxxxxxx +exec lock 0 10 0 0 +echo [........ +echo [ +echo ** Left boundaries align +exec lock 0 1 10 1 +echo [+++++++++++] +echo [ [+++++++++++] +exec lock 0 1 5 1 +echo [+++++] +echo [ [+++++++++++] +exec lock 0 1 5 2 +echo [xxxxx] +echo [ [xxxxx][++++] +exec lock 0 1 3 1 +echo [++] +echo [ [xxxxx][++++] +exec lock 0 1 10 0 +echo [............ +echo [ +exec lock 0 1 10 1 +echo [+++++++++++] +echo [ [+++++++++++] +exec lock 0 1 9 2 +echo [xxxxxxxx] +echo [ [xxxxxxxx][+] +exec lock 0 1 5 0 +echo [...] +echo [ [***][+] +exec lock 0 6 3 0 +echo [.] +echo [ [*][+] +exec lock 0 9 1 0 +echo [.] +echo [ [+] +exec lock 0 10 1 0 +echo [.] +echo [ +exec lock 0 1 0 1 +echo [++++++++++++ +echo [ [++++++++++++ +exec lock 0 1 5 1 +echo [++++] +echo [ [++++++++++++ +exec lock 0 1 5 2 +echo [xxxx] +echo [ [xxxx][++++++ +exec lock 0 1 0 0 +echo [............ +echo [ +exec lock 0 5 0 2 +echo [xxxxxxxxxx +echo [ [xxxxxxxxxx +exec lock 0 5 5 1 +echo [++++] +echo [ [xxxxxxxxxx +exec lock 0 5 0 1 +echo [++++++++++ +echo [ [xxxxxxxxxx +exec lock 0 0 0 0 +echo [.............. +echo [ +echo ** Common right side +exec lock 0 5 5 1 +echo [+++++] +echo [ [+++++] +exec lock 0 9 1 1 +echo [+] +echo [ [+++++] +exec lock 0 9 1 2 +echo [x] +echo [ [++][x] +exec lock 0 5 4 2 +echo [xx] +echo [ [xxxxx] +exec lock 0 8 2 2 +echo [x] +echo [ [xxxxx] +exec lock 0 9 1 0 +echo [.] +echo [ [xxx] +exec lock 0 5 4 0 +echo [...] +echo [ +exec lock 0 5 0 1 +echo [++++++++++ +echo [ [++++++++++ +exec lock 0 10 0 1 +echo [+++++ +echo [ [++++++++++ +exec lock 0 10 0 2 +echo [xxxxx +echo [ [+++][xxxxx +exec lock 0 5 0 0 +echo [.......... +echo [ +echo ** Completely interior +exec lock 0 5 10 1 +echo [++++++++] +echo [ [++++++++] +exec lock 0 6 8 1 +echo [++++++] +echo [ [++++++++] +exec lock 0 8 3 1 +echo [+] +echo [ [++++++++] +exec lock 0 8 3 2 +echo [x] +echo [ [+][x][++] +exec lock 0 12 1 2 +echo x +echo [ [++xxx+x+] +exec lock 0 6 8 0 +echo [......] +echo [ [+] [+] +exec lock 0 0 0 0 +echo [.............. +echo [ +exec lock 0 5 0 1 +echo [+++++++++ +echo [ [+++++++++ +exec lock 0 10 0 1 +echo [++++ +echo [ [+++++++++ +exec lock 0 10 0 2 +echo [xxxx +echo [ [+++][xxxx +exec lock 0 11 0 0 +echo [.. +echo [ [+++][x] +exec lock 0 6 0 0 +echo [....... +echo [ [+] +exec lock 0 5 0 0 +echo [......... +echo [ +exec lock 0 10 0 1 +echo [+++++ +echo [ [+++++ +exec lock 0 11 0 1 +echo [+] +echo [ [+++++ +exec lock 0 11 0 1 +echo [+] +echo [ [+++++ +exec lock 0 11 1 2 +echo [x] +echo [ [+x+++ +exec lock 0 13 0 1 +echo [+] +echo [ [+x+++ +exec lock 0 10 0 0 +echo [..... +echo [ +echo * We wrap the locked region +echo ** Left boundaries align +exec lock 0 1 10 1 +echo [++++] +echo [[++++] +exec lock 0 1 15 1 +echo [++++++++] +echo [[++++++++] +exec lock 0 1 16 1 +echo [+++++++++] +echo [[+++++++++] +exec lock 0 1 20 2 +echo [xxxxxxxxxxxxx] +echo [[xxxxxxxxxxxxx] +exec lock 0 1 30 1 +echo [+++++++++++++++++++] +echo [[xxxxxxxxxxxxx][++++] +exec lock 0 22 11 2 +echo [xxx] +echo [[xxxxxxxxxxxxx][+][xx] +exec lock 0 1 40 0 +echo [.........................] +echo [ +exec lock 0 1 0 1 +echo [++++++++++ +echo [[++++++++++ +exec lock 0 1 0 1 +echo [++++++++++ +echo [[++++++++++ +exec lock 0 1 0 2 +echo [xxxxxxxxxx +echo [[xxxxxxxxxx +exec lock 0 0 0 0 +echo [........... +echo [ +exec lock 0 1 0 1 +echo [++++++++++ +echo [[++++++++++ +exec lock 0 10 0 1 +echo [+++++ +echo [[++++++++++ +exec lock 0 10 0 2 +echo [xxxxx +echo [[+++][xxxxx +exec lock 0 0 0 0 +echo [........... +echo [ +echo ** Right boundaries align +exec lock 0 5 10 1 +echo [++++++++] +echo [ [++++++++] +exec lock 0 4 11 1 +echo [+++++++++] +echo [ [+++++++++] +exec lock 0 3 12 2 +echo [xxxxxxxxxx] +echo [ [xxxxxxxxxx] +exec lock 0 0 15 2 +echo [xxxxxxxxxxxx] +echo [xxxxxxxxxxxx] +exec lock 0 0 0 0 +echo [............. +echo [ +exec lock 0 5 0 1 +echo [++++++++ +echo [ [++++++++ +exec lock 0 4 0 1 +echo [+++++++++ +echo [ [+++++++++ +exec lock 0 3 0 2 +echo [xxxxxxxxxx +echo [ [xxxxxxxxxx +exec lock 0 2 0 2 +echo [xxxxxxxxxxx +echo [ [xxxxxxxxxxx +exec lock 0 0 0 2 +echo [xxxxxxxxxxxxx +echo [xxxxxxxxxxxxx +exec lock 0 0 0 0 +echo [............. +echo [ +echo ** Consume locked region +exec lock 0 5 10 1 +echo [++++++++] +echo [ [++++++++] +exec lock 0 4 12 1 +echo [++++++++++] +echo [ [++++++++++] +exec lock 0 2 16 1 +echo [++++++++++++++] +echo [ [++++++++++++++] +exec lock 0 1 18 2 +echo [xxxxxxxxxxxxxxxx] +echo [[xxxxxxxxxxxxxxxx] +exec lock 0 0 24 2 +echo [xxxxxxxxxxxxxxxxxxxxx] +echo [xxxxxxxxxxxxxxxxxxxxx] +exec lock 0 0 30 0 +echo [.........................] +echo [ +exec lock 0 5 3 1 +echo [++] +echo [ [++] +exec lock 0 10 5 1 +echo [++++] +echo [ [++] [++++] +exec lock 0 20 5 2 +echo [xxxx] +echo [ [++] [++++] [xxxx] +exec lock 0 4 30 2 +echo [xxxxxxxxxxxxxxxxxxxxxxxxxx] +echo [ [xxxxxxxxxxxxxxxxxxxxxxxxxx] +exec lock 0 1 35 1 +echo [++++++++++++++++++++++++++++++] +echo [ [+[xxxxxxxxxxxxxxxxxxxxxxxxxx]+] +exec lock 0 0 40 1 +echo [+++++++++++++++++++++++++++++++++++] +echo [++][xxxxxxxxxxxxxxxxxxxxxxxxxx][+++] +exec lock 0 0 0 0 +echo [.................................... +echo [ +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 4 0 1 +echo [++++++] +echo [ [++++++] +exec lock 0 4 0 0 +echo [.......... +echo [ +exec lock 0 5 3 1 +echo [++] +echo [ [++] +exec lock 0 10 5 1 +echo [++++] +echo [ [++] [++++] +exec lock 0 0 0 1 +echo [++++++++++++++++++++ +echo [++++++++++++++++++++ +exec lock 0 0 0 0 +echo [.................... +echo [ +exec lock 0 5 3 1 +echo [++] +echo [ [++] +exec lock 0 10 3 1 +echo [++] +echo [ [++] [++] +exec lock 0 4 0 1 +echo [++++++++++++++ +echo [ [++++++++++++++ +exec lock 0 10 3 2 +echo [**] +echo [ [++++++][**][++ +exec lock 0 0 0 2 +echo [xxxxxxxxxxxxxxxxxx +echo [xxxxxxxxxxxxxxxxxx +exec lock 0 0 0 0 +echo [.................. +echo [ +echo * Our start is within the locked region or one byte after and our +echo end is after the end of the locked region. +echo ** The regions are the same type: Merge into a single large region +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 6 5 1 +echo [+++] +echo [ [++++] +exec lock 0 8 8 1 +echo [++++++] +echo [ [+++++++++] +exec lock 0 16 4 1 +echo [++] +echo [ [+++++++++++++] +exec lock 0 20 0 1 +echo [+++ +echo [ [++++++++++++++++++ +exec lock 0 5 16 0 +echo [..............] +echo [ [+++ +exec lock 0 20 0 0 +echo [... +echo [ +exec lock 0 6 6 2 +echo [xxxx] +echo [ [xxxx] +exec lock 0 7 7 2 +echo [xxxxx] +echo [ [xxxxxx] +exec lock 0 14 7 2 +echo [xxxxx] +echo [ [xxxxxxxxxxxxx] +exec lock 0 21 0 2 +echo [xx +echo [ [xxxxxxxxxxxxxxxxx +exec lock 0 6 0 0 +echo [................. +echo [ +echo ** Different types just after the end of the locked region +exec lock 0 1 3 1 +echo [++] +echo [[++] +exec lock 0 4 3 2 +echo [xx] +echo [[++][xx] +exec lock 0 7 3 1 +echo [++] +echo [[++][xx][++] +exec lock 0 10 0 2 +echo [xxx +echo [[++][xx][++][xxx +exec lock 0 5 0 0 +echo [......... +echo [[++]x +exec lock 0 5 0 1 +echo [+++ +echo [[++]x[+++ +exec lock 0 1 0 0 +echo [... +echo [ +echo ** New region consumes the intersection. +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 8 6 2 +echo [xxx] +echo [ [++][xxx] +exec lock 0 6 0 2 +echo [xxxxxx +echo [ [+][xxxxxx +exec lock 0 5 0 0 +echo [......... +echo [ +echo ** New region is dominated +exec lock 0 5 5 2 +echo [xxx] +echo [ [xxx] +exec lock 0 8 6 1 +echo [++++] +echo [ [xxx][++] +exec lock 0 6 0 1 +echo [++++++ +echo [ [xxx][+++ +exec lock 0 5 0 0 +echo [........ +echo [ +echo * Our start falls before the locked region. Our end falls just +echo before or with in the region (although we do not consume it) +echo ** The regions are the same type: Merge into a single large region +exec lock 0 10 5 1 +echo [+++] +echo [ [+++] +exec lock 0 5 5 1 +echo [+++] +echo [ [++++++++] +exec lock 0 4 4 1 +echo [++] +echo [ [+++++++++] +exec lock 0 0 10 1 +echo [+++++++++] +echo [+++++++++++++] +exec lock 0 0 15 0 +echo [...............] +echo [ +exec lock 0 10 0 1 +echo [++++ +echo [ [++++ +exec lock 0 5 5 1 +echo [+++] +echo [ [+++++++++ +exec lock 0 4 1 1 +echo + +echo [ [++++++++++ +exec lock 0 0 0 1 +echo [++++++++++++++ +echo [++++++++++++++ +exec lock 0 0 0 0 +echo [.... +echo [ +exec lock 0 10 5 2 +echo [xxx] +echo [ [xxx] +exec lock 0 5 5 2 +echo [xxx] +echo [ [xxxxxxxx] +exec lock 0 4 4 2 +echo [xx] +echo [ [xxxxxxxxx] +exec lock 0 0 10 2 +echo [xxxxxxxxx] +echo [xxxxxxxxxxxxx] +exec lock 0 0 15 0 +echo [...............] +echo [ +exec lock 0 10 0 2 +echo [xxxx +echo [ [xxxx +exec lock 0 5 5 2 +echo [xxx] +echo [ [xxxxxxxxx +exec lock 0 4 1 2 +echo x +echo [ [xxxxxxxxxx +exec lock 0 0 0 2 +echo [xxxxxxxxxxxxxx +echo [xxxxxxxxxxxxxx +exec lock 0 0 0 0 +echo [.... +echo [ +echo ** Different types just before the start of the locked region +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 3 2 2 +echo [x] +echo [ [x][+++] +exec lock 0 2 1 1 +echo + +echo [ +[x][+++] +exec lock 0 1 0 2 +echo [xxxx +echo [[xxxx +exec lock 0 0 1 1 +echo + +echo +[xxxx +exec lock 0 0 0 0 +echo [.... +echo [.... +exec lock 0 5 0 1 +echo [++++ +echo [ [++++ +exec lock 0 0 5 2 +echo [xxxxxxxxx +echo [xxxxxxxxx +exec lock 0 0 0 0 +echo [.... +echo [ +echo ** New region consumes the intersection. +exec lock 0 5 5 1 +echo [+++] +echo [ [+++] +exec lock 0 4 3 2 +echo [x] +echo [ [x][+] +exec lock 0 2 0 2 +echo [xxxxxx +echo [ [xxxxxx +exec lock 0 0 0 0 +echo [.... +echo [ +exec lock 0 5 0 1 +echo [++++++ +echo [ [++++++ +exec lock 0 4 5 2 +echo [xxx] +echo [ [xxx][++ +exec lock 0 4 0 0 +echo [.... +echo [ +exec lock 0 5 0 1 +echo [++++ +echo [ [++++ +exec lock 0 0 0 2 +echo [xxxxxxxxxx +echo [xxxxxxxxxx +exec lock 0 0 0 0 +echo [.... +echo [ +echo ** New region is dominated +exec lock 0 5 5 2 +echo [xxx] +echo [ [xxx] +exec lock 0 4 5 1 +echo [+++] +echo [ +[xxx] +exec lock 0 0 0 0 +echo [... +echo [ +exec lock 0 5 0 2 +echo [xxxx +echo [ [xxxx +exec lock 0 0 0 1 +echo [++++++++ +echo [+++[xxxx +exec lock 0 0 0 0 +echo [.... +echo [ Index: hurd-0.9.git20190331-8.2/libfshelp-tests/race.c =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/race.c @@ -0,0 +1,83 @@ +/* Test races in the record locking code. + + Copyright (C) 2001 Free Software Foundation, Inc. + + Written by Neal H Walfield <n...@cs.uml.edu> + + 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 2, 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 <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <error.h> +#include <fcntl.h> +#include <unistd.h> +#include "fs_U.h" +#include <hurd.h> +#include "io_U.h" + +int main (int argc, char **argv) +{ + error_t err; + struct flock64 lock; + mach_port_t rendezvous = MACH_PORT_NULL; + int fd; + int i; + uint v; + int blocked = 0; + char buf[10] = ""; + char *bufp; + + if (argc != 4) + error (1, 0, "Usage: %s file start len", argv[0]); + + lock.l_whence = SEEK_SET; + lock.l_start = atoi (argv[2]); + lock.l_len = atoi (argv[3]); + + fd = file_name_lookup (argv[1], O_READ | O_WRITE | O_CREAT, 0666); + if (fd == MACH_PORT_NULL) + error (1, errno, "file_name_lookup"); + + for (i = 0; i < 10000; i ++) + { + lock.l_type = F_WRLCK; + err = file_record_lock (fd, F_SETLK64, &lock, rendezvous, MACH_MSG_TYPE_MAKE_SEND); + if (err) + { + blocked ++; + err = file_record_lock (fd, F_SETLKW64, &lock, rendezvous, MACH_MSG_TYPE_MAKE_SEND); + } + if (err) + error (1, err, "file_record_lock"); + + v = sizeof (buf); + bufp = buf; + io_read (fd, &bufp, &v, 0, v); + + v = atoi (bufp); + sprintf (buf, "%d\n", v + 1); + + v = 10; + io_write (fd, buf, sizeof (buf), 0, &v); + if (v == 0) + error (1, errno, "write (%d)", i); + + lock.l_type = F_UNLCK; + file_record_lock (fd, F_SETLK64, &lock, rendezvous, MACH_MSG_TYPE_MAKE_SEND); + } + + mach_port_deallocate (mach_task_self (), fd); + + printf ("Was blocked %d times\n", blocked); + return 0; +} Index: hurd-0.9.git20190331-8.2/libfshelp-tests/README.new_tests =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/README.new_tests @@ -0,0 +1,146 @@ +File: README.new_tests + +C-code: +======= +test-fcntl.c +test-lockf.c +test-flock.c + +Compile: +======== +gcc -g -Wall -D_FILE_OFFSET_BITS=64 -o test-fcntl test-fcntl.c +gcc -g -Wall -D_FILE_OFFSET_BITS=64 -o test-lockf test-lockf.c +gcc -g -Wall -D_FILE_OFFSET_BITS=64 -o test-flock test-flock.c + +./test-fcntl +./test-fcntl: Usage: ./test-fcntl file [flags] [cmd] [len] [sleep_time] + file : file name/device name + flags : r (O_RDONLY) | w (O_WRONLY) | rw (O_RDWR) : [rw] + cmd : g (F_GETLK), s (F_SETLK), sw (F_SETLKW) : [s] + lock.l_type : rl (F_RDLCK), wl (F_WRLCK), ul [F_UNLCK] : [ul] + lock.l_whence : ss (SEEK_SET), sc (SEEK_CUR), se (SEEK_END) : [ss] + lock.l_start : b <number> : [b 0] + lock.l_len : l <number> : [l 0] + sleep_time : st <number> : [st 10] + +./test-lockf +./test-lockf: Usage: ./test-lockf file [flags] [cmd] [len] [sleep_time] + file : file name/device name + flags : r (O_RDONLY) | w (O_WRONLY) | rw (O_RDWR) : [w] + cmd : x (F_LOCK), xt (F_TLOCK), u (F_ULOCK), + t (F_TEST) : [x] + len : l <number> : [0] + sleep_time : st <number> : [st 10] + +./test-flock +./test-flock: Usage: ./test-flock file [flags] [operation] [sleep_time] + file : file name/device name + flags : r (O_RDONLY) | w (O_WRONLY) | rw (O_RDWR) : [w] + operation : s (LOCK_SH), x (LOCK_EX), u (LOCK_UN), + sn (LOCK_SH | LOCK_UN), xn (LOCK_EX | LOCK_UN) : [s] + sleep_time : st <number> : [st 10] + +Results: +======== +New version of file_record_lock: +libdiskfs/file-lock.c(diskfs_S_file_lock): Commented out +libnetfs/file-lock.c(netfs_S_file_lock): Commented out +libtrivfs/file-lock.c(trivfs_S_file_lock): TODO: Add+comment out +libtrivfs/make-peropen.c(trivfs_S_file_lock): FIXME: po->openmodes = O_RDWR; +if (openstat & (O_RDONLY|O_WRONLY|O_EXEC)) openstat |= O_RDONLY|O_WRONLY; + +libfshelp/rlock-tweak.c(fshelp_rlock_tweak): Removed +if (lock->l_type == F_RDLCK && !(open_mode & O_READ)) + return EACCES; +if (lock->l_type == F_WRLCK && !(open_mode & O_WRITE)) + return EACCES; +Added: +/* From POSIX-1003.1: A request for an exclusive lock shall fail if + the file descriptor was not opened with write access. */ +if ((cmd == F_SETLK64 || cmd == F_SETLKW64 ) + && lock->l_type == F_WRLCK && !(open_mode & O_WRITE)) + return EBADF; + +test-fcntl: +=========== +libdiskfs: +---------- + +touch foo +./test-fcntl foo {r,w} g {rl,wl} +./test-fcntl foo r {s,sw} wl +./test-fcntl: fcntl: Bad file descriptor +./test-fcntl foo r {s,sw} {rl,ul} + +T1: T2: +./test-fcntl foo {r,w} {s,sw} {rl,wl} +./test-fcntl foo {r,w} {s,sw} {rl,wl} + +libnetfs: +--------- +Not applicable on GNU/Linux? + +settrans -c ftp: /hurd/hostmux /hurd/ftpfs / +Check: +file ftp: +ftp:: directory +ls ftp://ftp.gnu.org/ +less ftp://ftp.gnu.org/README + +./test-fcntl ftp://ftp.gnu.org/README r g {rl,wl} +./test-fcntl ftp://ftp.gnu.org/README w g {rl,wl} +./test-fcntl: open: Permission denied + +./test-fcntl ftp://ftp.gnu.org/README r {s,sw} {rl,ul} +./test-fcntl ftp://ftp.gnu.org/README r {s,sw} wl +./test-fcntl: fcntl: Bad file descriptor + +settrans -fg ftp: +rm ftp: + +libtrivs: +--------- +BUG: ./test-fcntl /dev/null r s wl +GNU/Linux: +./test-fcntl: fcntl: Bad file descriptor + +test-lockf: +=========== +libdiskfs: +---------- +touch foo +./test-lockf foo {r,w} {x,xt,u,t} +T1, T2: +./test-lockf foo {r,w} {x,xt,u,t} + +libnetfs: +--------- + +libtrivfs: +---------- + +test-flock: +=========== +libdiskfs: +---------- +touch foo +./test-flock foo {r,w} {s,x,u,sn,xn} + +GNU/Linux: +./test-flock foo r x + +GNU/Hurd: +./test-flock foo r {x,xn} +./test-flock: flock: Bad file descriptor + +T1: ./test-flock foo w s,x +T2: ./test-flock foo w x (waits for the first lock) + +libnetfs: +--------- + +libtrivfs: +---------- +GNU/Hurd +T1: ./test-flock /dev/null w s,x +BUG: T2: ./test-flock /dev/null w x (does not wait for the first lock) Index: hurd-0.9.git20190331-8.2/libfshelp-tests/test-fcntl.c =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/test-fcntl.c @@ -0,0 +1,273 @@ +/* test-fcntl.c: Test advisory open file record locks, see fcntl(2) + Options: <see below> + + Copyright (C) 2016-2019 Free Software Foundation, Inc. + + Written by Svante Signell <svante.sign...@gmail.com> + + 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 <http://www.gnu.org/licenses/>. */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <error.h> +#include <errno.h> +#include <unistd.h> +#include <sys/file.h> + +/* 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 <number> : [b 0]\n\ + lock.l_len : l <number> : [l 0]\n\ + sleep_time : st <number> : [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; +} Index: hurd-0.9.git20190331-8.2/libfshelp-tests/test-lockf.c =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/test-lockf.c @@ -0,0 +1,184 @@ +/* test-lockf.c: Test advisory open file record locks: + lockf(3) is an interface on top of fcntl(2) locking. + Options: <see below> + + Copyright (C) 2016-2019 Free Software Foundation, Inc. + + Written by Svante Signell <svante.sign...@gmail.com> + + 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 <http://www.gnu.org/licenses/>. */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <error.h> +#include <errno.h> +#include <unistd.h> +#include <sys/file.h> + +/* Parse args */ +int parse_args (int argc, char **argv, char **file_name, + int *flags, char **flagsc, + int *cmd, char **cmdc, + off_t *len, 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) : [w]\n\ + cmd : x (F_LOCK), xt (F_TLOCK), u (F_ULOCK),\n\ + t (F_TEST) : [x]\n\ + len : l <number> : [0]\n\ + sleep_time : st <number> : [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, "x", 2) == 0) + { + *cmd = F_LOCK; + *cmdc = "F_LOCK"; + continue; + } + if (strncmp (str, "xt", 2) == 0) + { + *cmd = F_TLOCK; + *cmdc = "F_TLOCK"; + continue; + } + if (strncmp (str, "u", 2) == 0) + { + *cmd = F_ULOCK; + *cmdc = "F_LOCK"; + continue; + } + if (strncmp (str, "t", 2) == 0) + { + *cmd = F_TEST; + *cmdc = "F_TEST"; + 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); + *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_WRONLY; + char *flagsc = "O_WRONLY"; + int cmd = F_LOCK; + char *cmdc = "F_LOCK"; + off_t len = 0; + int sleep_time = 10; + + ret = parse_args (argc, argv, &file_name, + &flags, &flagsc, + &cmd, &cmdc, + &len, &sleep_time); + +#ifdef __GNU__ + printf ("test-lockf: GNU/Hurd\n"); +#else + printf ("test-lockf: GNU/Linux\n"); +#endif + + 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, len = %ld\n", cmdc, len); + printf ("Requesting lock\n"); + err = lockf (fd, cmd, len); + if (err) + error (1, errno, "lockf"); + + printf ("Got lock: sleep_time = %d seconds\n", sleep_time); + sleep (sleep_time); + + printf ("Closing '%s'\n", file_name); + close (fd); + + return ret; +} Index: hurd-0.9.git20190331-8.2/libfshelp-tests/test-flock.c =================================================================== --- /dev/null +++ hurd-0.9.git20190331-8.2/libfshelp-tests/test-flock.c @@ -0,0 +1,170 @@ +/* test-flock.c: Test advisory open file locks, see flock(2) + Options: <see below> + + Copyright (C) 2016-2019 Free Software Foundation, Inc. + + Written by Svante Signell <svante.sign...@gmail.com> + + 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 <http://www.gnu.org/licenses/>. */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <error.h> +#include <errno.h> +#include <unistd.h> +#include <sys/file.h> + +/* Parse args */ +int parse_args (int argc, char **argv, char **file_name, + int *flags, char **flagsc, + int *op, char **opc, + int *sleep_time) +{ + int i, tmp; + char *str, *endptr; + + if (argc < 2) + error (1, 0, "Usage: %s file [flags] [operation] [sleep_time]\n\ + file : file name/device name\n\ + flags : r (O_RDONLY) | w (O_WRONLY) | rw (O_RDWR) : [w]\n\ + operation : s (LOCK_SH), x (LOCK_EX), u (LOCK_UN),\n\ + sn (LOCK_SH | LOCK_UN), xn (LOCK_EX | LOCK_UN) : [s]\n\ + sleep_time : st <number> : [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) + { + *op = LOCK_SH; + *opc = "LOCK_SH"; + continue; + } + if (strncmp (str, "sn", 2) == 0) + { + *op = LOCK_SH | LOCK_NB; + *opc = "LOCK_SH | LOCK_NB"; + continue; + } + if (strncmp (str, "x", 2) == 0) + { + *op = LOCK_EX; + *opc = "LOCK_EX"; + continue; + } + if (strncmp (str, "xn", 2) == 0) + { + *op = LOCK_EX | LOCK_NB; + *opc = "LOCK_EX | LOCK_NB"; + continue; + } + if (strncmp (str, "u", 2) == 0) + { + *op = LOCK_UN; + *opc = "LOCK_UN"; + 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_RDONLY; + char *flagsc = "O_RDONLY"; + int op = LOCK_SH; + char *opc = "LOCK_SH"; + int sleep_time = 10; + + ret = parse_args (argc, argv, &file_name, + &flags, &flagsc, + &op, &opc, + &sleep_time); + +#ifdef __GNU__ + printf ("test-flock: GNU/Hurd\n"); +#else + printf ("test-flock: GNU/Linux\n"); +#endif + + 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 ("operation = %s\n", opc); + printf ("Requesting lock\n"); + err = flock (fd, op); + if (err) + error (1, errno, "flock"); + + printf ("Got lock: sleep_time = %d seconds\n", sleep_time); + sleep (sleep_time); + + printf ("Closing '%s'\n", file_name); + close (fd); + + return ret; +}
REVERT!! commit 346ef23f197a0c8ba807c344bd39101b711050ee Author: Samuel Thibault <samuel.thiba...@ens-lyon.org> Date: Thu Nov 15 00:52:36 2018 +0100 hurd: Fix F_*LK* fcntl with __USE_FILE_OFFSET64 struct flock64 uses 64bit values. This introduces other values for F_GETLK, F_SETLK, F_SETLKW to distinguish between both. * sysdeps/mach/hurd/bits/fcntl.h (F_GETLK64, F_SETLK64, F_SETLKW64): New macros [__USE_FILE_OFFSET64] (F_GETLK, F_SETLK, F_SETLKW): Define to F_GETLK64, F_SETLK64, F_SETLKW64, respectively. * sysdeps/mach/hurd/f_setlk.c: New file. * sysdeps/mach/hurd/f_setlk.h: New file. * sysdeps/mach/hurd/Makefile [$(subdir) = io] (sysdeps_routines): Add f_setlk. * sysdeps/mach/hurd/fcntl.c: Include "f_setlk.h".h". (__libc_fcntl): Move non-flock operations to... * sysdeps/mach/hurd/vfcntl.c (__libc_vfcntl): ... New file. --- a/sysdeps/mach/hurd/Makefile 2019-09-11 10:50:11.000000000 +0200 +++ b/sysdeps/mach/hurd/Makefile 2019-09-11 10:52:30.000000000 +0200 @@ -195,10 +195,6 @@ sysdep_routines += cthreads endif -ifeq (io, $(subdir)) -sysdep_routines += f_setlk -endif - ifeq ($(subdir),sunrpc) sysdep_headers += nfs/nfs.h endif --- a/sysdeps/mach/hurd/bits/fcntl.h 2019-09-11 14:48:46.000000000 +0200 +++ b/sysdeps/mach/hurd/bits/fcntl.h 2019-09-11 14:50:24.000000000 +0200 @@ -1,5 +1,5 @@ /* O_*, F_*, FD_* bit values for GNU. - Copyright (C) 1993-2019 Free Software Foundation, Inc. + Copyright (C) 1993-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -163,18 +163,9 @@ # define F_GETOWN 5 /* Get owner (receiver of SIGIO). */ # define F_SETOWN 6 /* Set owner (receiver of SIGIO). */ #endif -#ifdef __USE_FILE_OFFSET64 -# define F_GETLK F_GETLK64 -# define F_SETLK F_SETLK64 -# define F_SETLKW F_SETLKW64 -#else -# define F_GETLK 7 /* Get record locking info. */ -# define F_SETLK 8 /* Set record locking info (non-blocking). */ -# define F_SETLKW 9 /* Set record locking info (blocking). */ -#endif -#define F_GETLK64 10 /* Get record locking info. */ -#define F_SETLK64 11 /* Set record locking info (non-blocking). */ -#define F_SETLKW64 12 /* Set record locking info (blocking). */ +#define F_GETLK 7 /* Get record locking info. */ +#define F_SETLK 8 /* Set record locking info (non-blocking). */ +#define F_SETLKW 9 /* Set record locking info (blocking). */ #ifdef __USE_XOPEN2K8 # define F_DUPFD_CLOEXEC 1030 /* Duplicate, set FD_CLOEXEC on new one. */ --- a/sysdeps/mach/hurd/f_setlk.c 2019-09-11 14:34:15.000000000 +0200 +++ /dev/null 2017-01-20 12:59:50.000000000 +0100 @@ -1,69 +0,0 @@ -/* f_setlk -- locking part of fcntl - Copyright (C) 2014-2015 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <sys/types.h> -#include <sys/file.h> -#include <fcntl.h> -#include <errno.h> - -/* XXX - We need new RPCs to support POSIX.1 fcntl file locking!! - For the time being we support the whole-file case only, - with all kinds of WRONG WRONG WRONG semantics, - by using flock. This is definitely the Wrong Thing, - but it might be better than nothing (?). */ -int -__f_setlk (int fd, int type, int whence, __off64_t start, __off64_t len, int wait) -{ - int cmd = 0; - - switch (type) - { - case F_RDLCK: cmd = LOCK_SH; break; - case F_WRLCK: cmd = LOCK_EX; break; - case F_UNLCK: cmd = LOCK_UN; break; - default: - errno = EINVAL; - return -1; - } - - if (cmd != LOCK_UN && wait == 0) - cmd |= LOCK_NB; - - switch (whence) - { - case SEEK_SET: - if (start == 0 && len == 0) /* Whole file request. */ - break; - /* It seems to be common for applications to lock the first - byte of the file when they are really doing whole-file locking. - So, since it's so wrong already, might as well do that too. */ - if (start == 0 && len == 1) - break; - /* FALLTHROUGH */ - case SEEK_CUR: - case SEEK_END: - errno = ENOTSUP; - return -1; - default: - errno = EINVAL; - return -1; - } - - return __flock (fd, cmd); -} --- a/sysdeps/mach/hurd/f_setlk.h 2019-01-31 17:45:36.000000000 +0100 +++ /dev/null 2017-01-20 12:59:50.000000000 +0100 @@ -1,23 +0,0 @@ -/* Copyright (C) 2014-2019 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _F_SETLK_H -#define _F_SETLK_H 1 - -extern int __f_setlk (int fd, int type, int whence, __off64_t start, __off64_t len, int wait); - -#endif /* f_setlk.h */ --- a/sysdeps/mach/hurd/fcntl.c.orig 2019-01-31 17:45:36.000000000 +0100 +++ b/sysdeps/mach/hurd/fcntl.c 2019-09-11 11:12:34.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 1992-2019 Free Software Foundation, Inc. +/* Copyright (C) 1992-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -21,7 +21,6 @@ #include <hurd/fd.h> #include <stdarg.h> #include <sys/file.h> /* XXX for LOCK_* */ -#include "f_setlk.h" /* Perform file control operations on FD. */ int @@ -129,48 +128,56 @@ case F_SETLK: case F_SETLKW: { + /* XXX + We need new RPCs to support POSIX.1 fcntl file locking!! + For the time being we support the whole-file case only, + with all kinds of WRONG WRONG WRONG semantics, + by using flock. This is definitely the Wrong Thing, + but it might be better than nothing (?). */ struct flock *fl = va_arg (ap, struct flock *); - int wait = 0; va_end (ap); switch (cmd) { case F_GETLK: errno = ENOSYS; return -1; - case F_SETLKW: - wait = 1; - /* FALLTHROUGH */ case F_SETLK: - return __f_setlk (fd, fl->l_type, fl->l_whence, - fl->l_start, fl->l_len, wait); + cmd = LOCK_NB; + break; + default: + cmd = 0; + break; + } + switch (fl->l_type) + { + case F_RDLCK: cmd |= LOCK_SH; break; + case F_WRLCK: cmd |= LOCK_EX; break; + case F_UNLCK: cmd |= LOCK_UN; break; default: errno = EINVAL; return -1; } - } - - case F_GETLK64: - case F_SETLK64: - case F_SETLKW64: - { - struct flock64 *fl = va_arg (ap, struct flock64 *); - int wait = 0; - va_end (ap); - switch (cmd) + switch (fl->l_whence) { - case F_GETLK64: - errno = ENOSYS; - return -1; - case F_SETLKW64: - wait = 1; + case SEEK_SET: + if (fl->l_start == 0 && fl->l_len == 0) /* Whole file request. */ + break; + /* It seems to be common for applications to lock the first + byte of the file when they are really doing whole-file locking. + So, since it's so wrong already, might as well do that too. */ + if (fl->l_start == 0 && fl->l_len == 1) + break; /* FALLTHROUGH */ - case F_SETLK64: - return __f_setlk (fd, fl->l_type, fl->l_whence, - fl->l_start, fl->l_len, wait); + case SEEK_CUR: + case SEEK_END: + errno = ENOTSUP; + return -1; default: errno = EINVAL; return -1; } + + return __flock (fd, cmd); } case F_GETFL: /* Get per-open flags. */ @@ -208,4 +215,3 @@ libc_hidden_def (__libc_fcntl64) weak_alias (__libc_fcntl64, __fcntl64) libc_hidden_weak (__fcntl64) -weak_alias (__fcntl64, fcntl64) --- a/sysdeps/mach/hurd/fcntl64.c 2019-01-31 17:45:36.000000000 +0100 +++ /dev/null 2017-01-20 12:59:50.000000000 +0100 @@ -1 +0,0 @@ -/* fcntl64 is defined in fcntl.c as an alias. */
--- a/sysdeps/mach/hurd/f_setlk.c 2019-09-11 14:25:03.000000000 +0200 +++ b/sysdeps/mach/hurd/f_setlk.c 2019-09-11 14:29:12.000000000 +0200 @@ -1,5 +1,5 @@ /* f_setlk -- locking part of fcntl - Copyright (C) 2014-2019 Free Software Foundation, Inc. + Copyright (C) 2014-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,7 +19,6 @@ #include <sys/types.h> #include <sys/file.h> #include <fcntl.h> -#include <unistd.h> #include <errno.h> /* XXX @@ -46,18 +45,6 @@ if (cmd != LOCK_UN && wait == 0) cmd |= LOCK_NB; - if (whence == SEEK_CUR) - { - /* In case the target position is 0, we can support it below. */ - __off64_t cur = __lseek64 (fd, 0, SEEK_CUR); - - if (cur >= 0) - { - start = cur + start; - whence = SEEK_SET; - } - } - switch (whence) { case SEEK_SET: