Bun.write(file, Bun.stdin): splice a pipe source into any destination on Linux

Closed
RO
7d ago
+87-33

Fixes #14054.

Repro

echo "hello world" | bun -e 'await Bun.write(Bun.file("foo.txt"), Bun.stdin)'
# error: Non-regular files aren't supported yet
#  syscall: "fstat", errno: 95

Cause

The Linux file-to-file copy dispatch in CopyFile::run_async has three fast-path predicates before falling through to "Non-regular files aren't supported yet":

  • ISREG(src) && ISREG(dest) → copy_file_range
  • ISFIFO(src) && ISFIFO(dest) → splice
  • ISREG|ISCHR|ISSOCK(src) → sendfile

A FIFO source with a regular-file destination matches none of them.

Fix

splice(2) only requires one end to be a pipe, so drop the ISFIFO(dest) guard and take the splice branch for any FIFO source. do_copy_file_range already falls back to a read/write loop on EINVAL/ENOTSUP/ENOSYS if the destination can't be spliced to, so no new error handling is needed.

On macOS, also treat ENOTSUP from fcopyfile as a fallback trigger alongside the existing EBADF case, since the original report was macOS with ENOTSUP.

Verification

$ head -c 5000000 /dev/urandom > src.bin
$ cat src.bin | bun-debug -e 'console.log(await Bun.write(Bun.file("out.bin"), Bun.stdin))'
5000000
$ cmp src.bin out.bin && echo ok
ok

The new test in bun-write.test.js fails on released bun with Non-regular files aren't supported yet and passes with this change.


no test proof · iteration 5 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/js/bun/io/bun-write.test.js