On 12/09/2026 06:22, Collin Funk wrote:
On GNU/Hurd, the GNU coreutils test test/cp/sparse-to-pipe.sh fails. The
test tries to copy a sparse file to a FIFO. Using 'rpctrace' allowed me
to track down the issue. See the output below:
$ mkfifo fifo
$ touch file
$ timeout -v 10 rpctrace cp file fifo
[...]
16<--37(pid8513)->auth_getids () = 0 1000 {1000 1000} {1000 24 25 27 29
30 44 46 100 102} {1000 1000}
task20(pid8513)->vm_allocate (0 4 1) = 0 4312129536
task20(pid8513)->vm_allocate (0 8 1) = 0 4312133632
task20(pid8513)->vm_allocate (0 40 1) = 0 4314992640
task20(pid8513)->vm_allocate (0 8 1) = 0 4314996736
19<--35(pid8513)->dir_lookup ("fifo/" 2097153 0)
timeout: sending signal TERM to command 'rpctrace'
From the trailing backslash, I can tell that it is trying to open "fifo"
as a target directory. It seems that Hurd doesn't support O_PATH or
O_SEARCH, so O_RDONLY is used. Here is a test program to confirm:
$ cat main.c
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int
main (void)
{
int fd = open ("fifo", O_RDONLY | O_DIRECTORY);
return 0;
}
Here is the output on GNU/Linux:
$ gcc main.c
$ mkfifo fifo 2>/dev/null;
$ timeout -v 10 ./a.out; echo $?
0
Here is the output on GNU/Hurd:
$ gcc main.c
$ mkfifo fifo 2>/dev/null;
$ timeout -v 10 ./a.out; echo $?
timeout: sending signal TERM to command './a.out'
124
The POSIX documentation of these flags isn't the most clear, and perhaps
a ticket should be opened to clarify this behavior [1]. However, I
suspect they intended for O_DIRECTORY overrule O_RDONLY when operationg
on FIFOs. I.e., fail immediately since it isn't a directory instead of
waiting for a writer:
$ strace --quiet=all -P fifo ./a.out; echo $?
openat(AT_FDCWD, "fifo", O_RDONLY|O_DIRECTORY) = -1 ENOTDIR (Not a
directory)
0
We have only seen GNU/Hurd wait for a writer which also backs up that
suspicion. I guess we could add O_NONBLOCK like this:
diff --git a/gl/lib/targetdir.c b/gl/lib/targetdir.c
index 24cff48c3..565c7cd9a 100644
--- a/gl/lib/targetdir.c
+++ b/gl/lib/targetdir.c
@@ -63,7 +63,9 @@ target_directory_operand (char const *file, struct stat *st)
if (must_be_working_directory (file))
return AT_FDCWD;
- int fd = open (file, O_PATHSEARCH | O_DIRECTORY);
+ int fd = open (file, (O_PATHSEARCH
+ | (O_PATHSEARCH == O_RDONLY ? O_NONBLOCK : 0)
+ | O_DIRECTORY));
/* On platforms lacking O_PATH, using O_SEARCH | O_DIRECTORY to
open an overly-protected non-directory can fail with either
However, I don't really like the idea of adding flags where it isn't
necessary. It seems harmless here, but there is always a chance some
platform has some quirky behavior when O_NONBLOCK is set.
Pádraig, what do you think about applying the attached patch? It just
adds --no-target-directory, since this isn't the goal of that test
anyway.
Collin
[1] https://pubs.opengroup.org/onlinepubs/9799919799/functions/open.html
Nice investigation.
That's fine and good to push,
but please change the "test:" to "tests:" in the summary.
thanks!
Padraig