diff options
| author | Treehugger Robot <treehugger-gerrit@google.com> | 2021-10-18 22:15:38 +0000 |
|---|---|---|
| committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-10-18 22:15:38 +0000 |
| commit | a3c6e7030c128fbcb060ddbd6e89cf5ad2b95d05 (patch) | |
| tree | 619545ee8e093cad2d79464ff9b43a407d5fcdd4 /libc | |
| parent | ad60768bdfc4680edc07422693381ac152d74e37 (diff) | |
| parent | cf59e19e22fc7c4795fd955eeecd1f457d79eba0 (diff) | |
Merge "Add preadv2/pwritev2 wrappers."
Diffstat (limited to 'libc')
| -rw-r--r-- | libc/Android.bp | 1 | ||||
| -rw-r--r-- | libc/SYSCALLS.TXT | 11 | ||||
| -rw-r--r-- | libc/bionic/legacy_32_bit_support.cpp | 19 | ||||
| -rw-r--r-- | libc/bionic/preadv_pwritev.cpp | 91 | ||||
| -rw-r--r-- | libc/include/sys/uio.h | 119 | ||||
| -rw-r--r-- | libc/libc.map.txt | 8 |
6 files changed, 219 insertions, 30 deletions
diff --git a/libc/Android.bp b/libc/Android.bp index 147237104..2a8df9a47 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -1121,6 +1121,7 @@ cc_library_static { "bionic/posix_fallocate.cpp", "bionic/posix_madvise.cpp", "bionic/posix_timers.cpp", + "bionic/preadv_pwritev.cpp", "bionic/ptrace.cpp", "bionic/pty.cpp", "bionic/raise.cpp", diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index 289eddb6c..22b82f13d 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -97,13 +97,14 @@ ssize_t pwrite64(int, void*, size_t, off64_t) lp32 ssize_t pwrite64|pwrite(int, void*, size_t, off_t) lp64 # On LP32, preadv/pwritev don't use off64_t --- they use pairs of 32-bit -# arguments to avoid problems on architectures like ARM where 64-bit arguments +# arguments to avoid problems on architectures like arm32 where 64-bit arguments # must be in a register pair starting with an even-numbered register. # See linux/fs/read_write.c and https://lwn.net/Articles/311630/. -ssize_t __preadv64:preadv(int, const struct iovec*, int, long, long) lp32 -ssize_t preadv|preadv64(int, const struct iovec*, int, off_t) lp64 -ssize_t __pwritev64:pwritev(int, const struct iovec*, int, long, long) lp32 -ssize_t pwritev|pwritev64(int, const struct iovec*, int, off_t) lp64 +# Note that there's an unused always-0 second long even on LP64! +ssize_t __preadv64:preadv(int, const struct iovec*, int, long, long) all +ssize_t __pwritev64:pwritev(int, const struct iovec*, int, long, long) all +ssize_t __preadv64v2:preadv2(int, const struct iovec*, int, long, long, int) all +ssize_t __pwritev64v2:pwritev2(int, const struct iovec*, int, long, long, int) all int __close:close(int) all pid_t __getpid:getpid() all diff --git a/libc/bionic/legacy_32_bit_support.cpp b/libc/bionic/legacy_32_bit_support.cpp index f08e58266..41108e6af 100644 --- a/libc/bionic/legacy_32_bit_support.cpp +++ b/libc/bionic/legacy_32_bit_support.cpp @@ -45,8 +45,6 @@ // System calls we need. extern "C" int __llseek(int, unsigned long, unsigned long, off64_t*, int); -extern "C" int __preadv64(int, const struct iovec*, int, long, long); -extern "C" int __pwritev64(int, const struct iovec*, int, long, long); // For lseek64 we need to use the llseek system call which splits the off64_t in two and // returns the off64_t result via a pointer because 32-bit kernels can't return 64-bit results. @@ -70,23 +68,6 @@ ssize_t pwrite(int fd, const void* buf, size_t byte_count, off_t offset) { return pwrite64(fd, buf, byte_count, static_cast<off64_t>(offset)); } -// On LP32, there is no off_t preadv/pwritev, and even the 64-bit preadv/pwritev -// don't use off64_t (see SYSCALLS.TXT for more). Here, this means that we need -// to implement all four functions because the two system calls don't match any -// of the userspace functions. Unlike llseek, the pair is split lo-hi, not hi-lo. -ssize_t preadv(int fd, const struct iovec* ios, int count, off_t offset) { - return preadv64(fd, ios, count, offset); -} -ssize_t preadv64(int fd, const struct iovec* ios, int count, off64_t offset) { - return __preadv64(fd, ios, count, offset, offset >> 32); -} -ssize_t pwritev(int fd, const struct iovec* ios, int count, off_t offset) { - return pwritev64(fd, ios, count, offset); -} -ssize_t pwritev64(int fd, const struct iovec* ios, int count, off64_t offset) { - return __pwritev64(fd, ios, count, offset, offset >> 32); -} - // There is no fallocate for 32-bit off_t, so we need to widen and call fallocate64. int fallocate(int fd, int mode, off_t offset, off_t length) { return fallocate64(fd, mode, static_cast<off64_t>(offset), static_cast<off64_t>(length)); diff --git a/libc/bionic/preadv_pwritev.cpp b/libc/bionic/preadv_pwritev.cpp new file mode 100644 index 000000000..e44d3a6f7 --- /dev/null +++ b/libc/bionic/preadv_pwritev.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/uio.h> + +// System calls we need. +extern "C" int __preadv64(int, const struct iovec*, int, long, long); +extern "C" int __preadv64v2(int, const struct iovec*, int, long, long, int); +extern "C" int __pwritev64(int, const struct iovec*, int, long, long); +extern "C" int __pwritev64v2(int, const struct iovec*, int, long, long, int); + +// There is no 32-bit off_t preadv/pwritev (even on LP32). +// To avoid 32-bit ABI issues about which register pairs you're allowed +// to pass 64-bit values in, the kernel just takes two `long` arguments -- +// which are int32_t for LP32, remember -- and stitches them together. +// It even does this for LP64, taking a second unused always-zero `long`. +// (The first long was int64_t, which is the same as off64_t.) +// The pair is split lo-hi (not hi-lo, as llseek is). + +ssize_t preadv(int fd, const struct iovec* ios, int count, off_t offset) { + return preadv64(fd, ios, count, offset); +} + +ssize_t preadv64(int fd, const struct iovec* ios, int count, off64_t offset) { +#if defined(__LP64__) + return __preadv64(fd, ios, count, offset, 0); +#else + return __preadv64(fd, ios, count, offset, offset >> 32); +#endif +} + +ssize_t pwritev(int fd, const struct iovec* ios, int count, off_t offset) { + return pwritev64(fd, ios, count, offset); +} + +ssize_t pwritev64(int fd, const struct iovec* ios, int count, off64_t offset) { +#if defined(__LP64__) + return __pwritev64(fd, ios, count, offset, 0); +#else + return __pwritev64(fd, ios, count, offset, offset >> 32); +#endif +} + +ssize_t preadv2(int fd, const struct iovec* ios, int count, off_t offset, int flags) { + return preadv64v2(fd, ios, count, offset, flags); +} + +ssize_t preadv64v2(int fd, const struct iovec* ios, int count, off64_t offset, int flags) { +#if defined(__LP64__) + return __preadv64v2(fd, ios, count, offset, 0, flags); +#else + return __preadv64v2(fd, ios, count, offset, offset >> 32, flags); +#endif +} + +ssize_t pwritev2(int fd, const struct iovec* ios, int count, off_t offset, int flags) { + return pwritev64v2(fd, ios, count, offset, flags); +} + +ssize_t pwritev64v2(int fd, const struct iovec* ios, int count, off64_t offset, int flags) { +#if defined(__LP64__) + return __pwritev64v2(fd, ios, count, offset, 0, flags); +#else + return __pwritev64v2(fd, ios, count, offset, offset >> 32, flags); +#endif +} diff --git a/libc/include/sys/uio.h b/libc/include/sys/uio.h index 37961e30f..583cfc62a 100644 --- a/libc/include/sys/uio.h +++ b/libc/include/sys/uio.h @@ -26,8 +26,12 @@ * SUCH DAMAGE. */ -#ifndef _SYS_UIO_H_ -#define _SYS_UIO_H_ +#pragma once + +/** + * @file sys/uio.h + * @brief Multi-buffer ("vector") I/O operations using `struct iovec`. + */ #include <sys/cdefs.h> #include <sys/types.h> @@ -35,21 +39,124 @@ __BEGIN_DECLS +/** + * [readv(2)](http://man7.org/linux/man-pages/man2/readv.2.html) reads + * from an fd into the `__count` buffers described by `__iov`. + * + * Returns the number of bytes read on success, + * and returns -1 and sets `errno` on failure. + */ ssize_t readv(int __fd, const struct iovec* __iov, int __count); + +/** + * [writev(2)](http://man7.org/linux/man-pages/man2/writev.2.html) writes + * to an fd from the `__count` buffers described by `__iov`. + * + * Returns the number of bytes written on success, + * and returns -1 and sets `errno` on failure. + */ ssize_t writev(int __fd, const struct iovec* __iov, int __count); #if defined(__USE_GNU) + +/** + * [preadv(2)](http://man7.org/linux/man-pages/man2/preadv.2.html) reads + * from an fd into the `__count` buffers described by `__iov`, starting at + * offset `__offset` into the file. + * + * Returns the number of bytes read on success, + * and returns -1 and sets `errno` on failure. + * + * Available since API level 24. + */ ssize_t preadv(int __fd, const struct iovec* __iov, int __count, off_t __offset) __RENAME_IF_FILE_OFFSET64(preadv64) __INTRODUCED_IN(24); + +/** + * [pwritev(2)](http://man7.org/linux/man-pages/man2/pwritev.2.html) writes + * to an fd from the `__count` buffers described by `__iov`, starting at offset + * `__offset` into the file. + * + * Returns the number of bytes written on success, + * and returns -1 and sets `errno` on failure. + * + * Available since API level 24. + */ ssize_t pwritev(int __fd, const struct iovec* __iov, int __count, off_t __offset) __RENAME_IF_FILE_OFFSET64(pwritev64) __INTRODUCED_IN(24); + +/** + * Like preadv() but with a 64-bit offset even in a 32-bit process. + * + * Available since API level 24. + */ ssize_t preadv64(int __fd, const struct iovec* __iov, int __count, off64_t __offset) __INTRODUCED_IN(24); + +/** + * Like pwritev() but with a 64-bit offset even in a 32-bit process. + * + * Available since API level 24. + */ ssize_t pwritev64(int __fd, const struct iovec* __iov, int __count, off64_t __offset) __INTRODUCED_IN(24); -#endif -#if defined(__USE_GNU) +/** + * [preadv2(2)](http://man7.org/linux/man-pages/man2/preadv2.2.html) reads + * from an fd into the `__count` buffers described by `__iov`, starting at + * offset `__offset` into the file, with the given flags. + * + * Returns the number of bytes read on success, + * and returns -1 and sets `errno` on failure. + * + * Available since API level 33. + */ +ssize_t preadv2(int __fd, const struct iovec* __iov, int __count, off_t __offset, int __flags) __RENAME_IF_FILE_OFFSET64(preadv64v2) __INTRODUCED_IN(33); + +/** + * [pwritev2(2)](http://man7.org/linux/man-pages/man2/pwritev2.2.html) writes + * to an fd from the `__count` buffers described by `__iov`, starting at offset + * `__offset` into the file, with the given flags. + * + * Returns the number of bytes written on success, + * and returns -1 and sets `errno` on failure. + * + * Available since API level 33. + */ +ssize_t pwritev2(int __fd, const struct iovec* __iov, int __count, off_t __offset, int __flags) __RENAME_IF_FILE_OFFSET64(pwritev64v2) __INTRODUCED_IN(33); + +/** + * Like preadv2() but with a 64-bit offset even in a 32-bit process. + * + * Available since API level 33. + */ +ssize_t preadv64v2(int __fd, const struct iovec* __iov, int __count, off64_t __offset, int __flags) __INTRODUCED_IN(33); + +/** + * Like pwritev2() but with a 64-bit offset even in a 32-bit process. + * + * Available since API level 33. + */ +ssize_t pwritev64v2(int __fd, const struct iovec* __iov, int __count, off64_t __offset, int __flags) __INTRODUCED_IN(33); + +/** + * [process_vm_readv(2)](http://man7.org/linux/man-pages/man2/process_vm_readv.2.html) + * reads from the address space of another process. + * + * Returns the number of bytes read on success, + * and returns -1 and sets `errno` on failure. + * + * Available since API level 23. + */ ssize_t process_vm_readv(pid_t __pid, const struct iovec* __local_iov, unsigned long __local_iov_count, const struct iovec* __remote_iov, unsigned long __remote_iov_count, unsigned long __flags) __INTRODUCED_IN(23); + +/** + * [process_vm_writev(2)](http://man7.org/linux/man-pages/man2/process_vm_writev.2.html) + * writes to the address space of another process. + * + * Returns the number of bytes read on success, + * and returns -1 and sets `errno` on failure. + * + * Available since API level 23. + */ ssize_t process_vm_writev(pid_t __pid, const struct iovec* __local_iov, unsigned long __local_iov_count, const struct iovec* __remote_iov, unsigned long __remote_iov_count, unsigned long __flags) __INTRODUCED_IN(23); + #endif __END_DECLS - -#endif diff --git a/libc/libc.map.txt b/libc/libc.map.txt index 8ede3803f..12b811461 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -1565,6 +1565,14 @@ LIBC_S { # introduced=S process_madvise; } LIBC_R; +LIBC_T { # introduced=Tiramisu + global: + preadv2; + preadv64v2; + pwritev2; + pwritev64v2; +} LIBC_S; + LIBC_PRIVATE { global: __accept4; # arm x86 |
