LibCore: Add a system wrapper to pipe a file

This uses splice on Linux and mmap+write elsewhere to transfer a file to
a pipe. Note we cannot use sendfile because (at least on macOS) the
receiving fd must be a socket.
This commit is contained in:
Timothy Flynn 2025-10-08 08:01:14 -04:00 committed by Andreas Kling
parent 62e52640d0
commit e433dee543
Notes: github-actions[bot] 2025-10-14 11:42:14 +00:00
3 changed files with 35 additions and 0 deletions

View file

@ -870,4 +870,27 @@ ErrorOr<void> set_close_on_exec(int fd, bool enabled)
return {}; return {};
} }
ErrorOr<size_t> transfer_file_through_pipe(int source_fd, int target_fd, size_t source_offset, size_t source_length)
{
#if defined(AK_OS_LINUX)
auto sent = ::splice(source_fd, reinterpret_cast<off_t*>(&source_offset), target_fd, nullptr, source_length, SPLICE_F_MOVE | SPLICE_F_NONBLOCK);
if (sent < 0)
return Error::from_syscall("send_file_to_pipe"sv, errno);
return sent;
#else
static auto page_size = PAGE_SIZE;
// mmap requires the offset to be page-aligned, so we must handle that here.
auto aligned_source_offset = (source_offset / page_size) * page_size;
auto offset_adjustment = source_offset - aligned_source_offset;
auto mapped_source_length = source_length + offset_adjustment;
// FIXME: We could use MappedFile here if we update it to support offsets and not auto-close the source fd.
auto* mapped = TRY(mmap(nullptr, mapped_source_length, PROT_READ, MAP_SHARED, source_fd, aligned_source_offset));
ScopeGuard guard { [&]() { (void)munmap(mapped, mapped_source_length); } };
return TRY(write(target_fd, { static_cast<u8*>(mapped) + offset_adjustment, source_length }));
#endif
}
} }

View file

@ -190,4 +190,6 @@ bool is_socket(int fd);
ErrorOr<void> sleep_ms(u32 milliseconds); ErrorOr<void> sleep_ms(u32 milliseconds);
ErrorOr<void> set_close_on_exec(int fd, bool enabled); ErrorOr<void> set_close_on_exec(int fd, bool enabled);
ErrorOr<size_t> transfer_file_through_pipe(int source_fd, int target_fd, size_t source_offset, size_t source_length);
} }

View file

@ -403,4 +403,14 @@ ErrorOr<void> kill(pid_t pid, int signal)
return {}; return {};
} }
ErrorOr<size_t> transfer_file_through_pipe(int source_fd, int target_fd, size_t source_offset, size_t source_length)
{
(void)source_fd;
(void)target_fd;
(void)source_offset;
(void)source_length;
return Error::from_string_literal("FIXME: Implement System::transfer_file_through_pipe on Windows (for HTTP disk cache)");
}
} }