From c2e412e08641dafd0f8e0b8edd3e358082105a68 Mon Sep 17 00:00:00 2001 From: zijunzhao Date: Fri, 22 Apr 2022 18:08:09 +0000 Subject: [PATCH] Add copy_file_range(2) syscall stub to bionic. Test: treehugger Bug: https://buganizer.corp.google.com/issues/227784687 Change-Id: I543306cd2234189401bf7c9d80d405eeb6e4d41d --- libc/SYSCALLS.TXT | 1 + libc/include/unistd.h | 11 +++++++++++ libc/libc.map.txt | 1 + tests/unistd_test.cpp | 16 ++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index 1435e79f6..45b2a1b93 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -108,6 +108,7 @@ ssize_t __pwritev64v2:pwritev2(int, const struct iovec*, int, long, long, in int __close:close(int) all int close_range(unsigned int, unsigned int, int) all +ssize_t copy_file_range(int, off64_t*, int, off64_t*, size_t, unsigned int) all pid_t __getpid:getpid() all int memfd_create(const char*, unsigned) all int munmap(void*, size_t) all diff --git a/libc/include/unistd.h b/libc/include/unistd.h index f142525ba..b5694b8c3 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -313,6 +313,17 @@ int tcsetpgrp(int __fd, pid_t __pid); int getdomainname(char* __buf, size_t __buf_size) __INTRODUCED_IN(26); int setdomainname(const char* __name, size_t __n) __INTRODUCED_IN(26); +/** + * [copy_file_range(2)](https://man7.org/linux/man-pages/man2/copy_file_range.2.html) copies + * a range of data from one file descriptor to another. + * + * Returns the number of bytes copied on success, and returns -1 and sets errno + * on failure. + * + * Available since API level 34. + */ +ssize_t copy_file_range(int __fd_in, off64_t* __off_in, int __fd_out, off64_t* __off_out, size_t __length, unsigned int __flags) __INTRODUCED_IN(34); + #if __ANDROID_API__ >= 28 void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN(28); #endif diff --git a/libc/libc.map.txt b/libc/libc.map.txt index e64fe00bd..79f331a63 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -1579,6 +1579,7 @@ LIBC_T { # introduced=Tiramisu LIBC_U { # introduced=UpsideDownCake global: close_range; + copy_file_range; } LIBC_T; LIBC_PRIVATE { diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp index 293b45ae5..49fec12a4 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -1668,3 +1668,19 @@ TEST(UNISTD_TEST, close_range) { } #endif // __GLIBC__ } + +TEST(UNISTD_TEST, copy_file_range) { +#if defined(__GLIBC__) + GTEST_SKIP() << "glibc too old"; +#else // __GLIBC__ + TemporaryFile tf; + ASSERT_TRUE(android::base::WriteStringToFd("hello world", tf.fd)); + ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); + TemporaryFile tf2; + ASSERT_EQ(11, copy_file_range(tf.fd, NULL, tf2.fd, NULL, 11, 0)); + ASSERT_EQ(0, lseek(tf2.fd, SEEK_SET, 0)); + std::string content; + ASSERT_TRUE(android::base::ReadFdToString(tf2.fd, &content)); + ASSERT_EQ("hello world", content); +#endif // __GLIBC__ +} \ No newline at end of file