diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 09eb51a3f8fc6..99b1187b43e11 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -355,6 +355,7 @@ set(TARGET_LIBC_ENTRYPOINTS # sys/uio.h entrypoints libc.src.sys.uio.writev + libc.src.sys.uio.readv ) if(LLVM_LIBC_INCLUDE_SCUDO) diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 366e4d34294d1..df85f87140b88 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -355,6 +355,7 @@ set(TARGET_LIBC_ENTRYPOINTS # sys/uio.h entrypoints libc.src.sys.uio.writev + libc.src.sys.uio.readv ) if(LLVM_LIBC_INCLUDE_SCUDO) diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h index a4957225c9d34..79bbbe401eb02 100644 --- a/libc/include/llvm-libc-macros/limits-macros.h +++ b/libc/include/llvm-libc-macros/limits-macros.h @@ -239,4 +239,8 @@ #define _POSIX_ARG_MAX 4096 #endif +#ifndef IOV_MAX +#define IOV_MAX 1024 +#endif // IOV_MAX + #endif // LLVM_LIBC_MACROS_LIMITS_MACROS_H diff --git a/libc/include/sys/uio.yaml b/libc/include/sys/uio.yaml index 87c5bdff48245..6d3f336b2b520 100644 --- a/libc/include/sys/uio.yaml +++ b/libc/include/sys/uio.yaml @@ -15,3 +15,11 @@ functions: - type: int - type: const struct iovec * - type: int + - name: readv + standards: + - POSIX + return_type: ssize_t + arguments: + - type: int + - type: const struct iovec * + - type: int diff --git a/libc/src/sys/uio/CMakeLists.txt b/libc/src/sys/uio/CMakeLists.txt index 6298f86cd937d..c6a6429790410 100644 --- a/libc/src/sys/uio/CMakeLists.txt +++ b/libc/src/sys/uio/CMakeLists.txt @@ -8,3 +8,10 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.writev ) + +add_entrypoint_object( + readv + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.readv +) diff --git a/libc/src/sys/uio/linux/CMakeLists.txt b/libc/src/sys/uio/linux/CMakeLists.txt index 85a7a3ae4d5c2..db4fe68e4ca9c 100644 --- a/libc/src/sys/uio/linux/CMakeLists.txt +++ b/libc/src/sys/uio/linux/CMakeLists.txt @@ -5,10 +5,25 @@ add_entrypoint_object( HDRS ../writev.h DEPENDS + libc.hdr.types.ssize_t + libc.hdr.types.struct_iovec libc.include.sys_syscall libc.src.__support.OSUtil.osutil libc.src.__support.common libc.src.errno.errno +) + +add_entrypoint_object( + readv + SRCS + readv.cpp + HDRS + ../readv.h + DEPENDS libc.hdr.types.ssize_t libc.hdr.types.struct_iovec + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.__support.common + libc.src.errno.errno ) diff --git a/libc/src/sys/uio/linux/readv.cpp b/libc/src/sys/uio/linux/readv.cpp new file mode 100644 index 0000000000000..f1393a9749be9 --- /dev/null +++ b/libc/src/sys/uio/linux/readv.cpp @@ -0,0 +1,29 @@ +//===-- Implementation file for readv -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include "src/sys/uio/readv.h" +#include "hdr/types/ssize_t.h" +#include "hdr/types/struct_iovec.h" +#include "src/__support/OSUtil/syscall.h" +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" +#include + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(ssize_t, readv, (int fd, const iovec *iov, int iovcnt)) { + long ret = LIBC_NAMESPACE::syscall_impl(SYS_readv, fd, iov, iovcnt); + // On failure, return -1 and set errno. + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + // On success, return number of bytes read. + return static_cast(ret); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/uio/linux/writev.cpp b/libc/src/sys/uio/linux/writev.cpp index a3bb8986d522e..8992bed95c982 100644 --- a/libc/src/sys/uio/linux/writev.cpp +++ b/libc/src/sys/uio/linux/writev.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// #include "src/sys/uio/writev.h" +#include "hdr/types/ssize_t.h" +#include "hdr/types/struct_iovec.h" #include "src/__support/OSUtil/syscall.h" #include "src/__support/common.h" #include "src/errno/libc_errno.h" diff --git a/libc/src/sys/uio/readv.h b/libc/src/sys/uio/readv.h new file mode 100644 index 0000000000000..135b1e6fd1b5a --- /dev/null +++ b/libc/src/sys/uio/readv.h @@ -0,0 +1,22 @@ +//===-- Implementation header for readv -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SYS_UIO_READV_H +#define LLVM_LIBC_SRC_SYS_UIO_READV_H + +#include "hdr/types/ssize_t.h" +#include "hdr/types/struct_iovec.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +ssize_t readv(int fd, const iovec *iov, int iovcnt); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_SYS_UIO_READV_H diff --git a/libc/test/src/sys/uio/CMakeLists.txt b/libc/test/src/sys/uio/CMakeLists.txt index 45f8d14c16179..7ba02be5d1cc4 100644 --- a/libc/test/src/sys/uio/CMakeLists.txt +++ b/libc/test/src/sys/uio/CMakeLists.txt @@ -1,15 +1,36 @@ add_custom_target(libc_sys_uio_unittests) + add_libc_unittest( writev_test SUITE - libc_sys_uio_unittests + libc_sys_uio_unittests SRCS writev_test.cpp DEPENDS - libc.src.errno.errno + libc.hdr.types.struct_iovec libc.src.__support.common + libc.src.errno.errno + libc.src.fcntl.open libc.src.sys.uio.writev libc.src.unistd.close + libc.src.unistd.unlink + libc.test.UnitTest.ErrnoSetterMatcher +) + +add_libc_unittest( + readv_test + SUITE + libc_sys_uio_unittests + SRCS + readv_test.cpp + DEPENDS + libc.hdr.types.struct_iovec + libc.src.__support.common + libc.src.errno.errno libc.src.fcntl.open + libc.src.sys.uio.readv + libc.src.unistd.close + libc.src.unistd.unlink + libc.src.unistd.write libc.test.UnitTest.ErrnoSetterMatcher ) diff --git a/libc/test/src/sys/uio/readv_test.cpp b/libc/test/src/sys/uio/readv_test.cpp new file mode 100644 index 0000000000000..7852b8a4b136d --- /dev/null +++ b/libc/test/src/sys/uio/readv_test.cpp @@ -0,0 +1,43 @@ +//===-- Unittests for readv -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "hdr/types/struct_iovec.h" +#include "src/fcntl/open.h" +#include "src/sys/uio/readv.h" +#include "src/unistd/close.h" +#include "src/unistd/unlink.h" +#include "src/unistd/write.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +TEST(LlvmLibcSysUioReadvTest, SmokeTest) { + const char *filename = "./LlvmLibcSysUioReadvTest"; + int fd = LIBC_NAMESPACE::open(filename, O_WRONLY | O_CREAT, 0644); + ASSERT_THAT(fd, returns(GT(0)).with_errno(EQ(0))); + const char data[] = "Hello, World!\n"; + ASSERT_THAT(LIBC_NAMESPACE::write(fd, data, sizeof(data)), + returns(EQ(sizeof(data))).with_errno(EQ(0))); + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); + + fd = LIBC_NAMESPACE::open(filename, O_RDONLY); + ASSERT_THAT(fd, returns(GT(0)).with_errno(EQ(0))); + char buf0[2]; + char buf1[3]; + struct iovec iov[2]; + iov[0].iov_base = buf0; + iov[0].iov_len = 1; + iov[1].iov_base = buf1; + iov[1].iov_len = 2; + ASSERT_THAT(LIBC_NAMESPACE::readv(fd, iov, 2), + returns(EQ(3)).with_errno(EQ(0))); + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::unlink(filename), + returns(EQ(0)).with_errno(EQ(0))); +} diff --git a/libc/test/src/sys/uio/writev_test.cpp b/libc/test/src/sys/uio/writev_test.cpp index a9a314813182d..2c1c445cc7868 100644 --- a/libc/test/src/sys/uio/writev_test.cpp +++ b/libc/test/src/sys/uio/writev_test.cpp @@ -6,16 +6,19 @@ // //===----------------------------------------------------------------------===// +#include "hdr/types/struct_iovec.h" #include "src/fcntl/open.h" #include "src/sys/uio/writev.h" #include "src/unistd/close.h" +#include "src/unistd/unlink.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; TEST(LlvmLibcSysUioWritevTest, SmokeTest) { - int fd = LIBC_NAMESPACE::open("/dev/null", O_WRONLY); + const char *filename = "./LlvmLibcSysUioWritevTest"; + int fd = LIBC_NAMESPACE::open(filename, O_WRONLY | O_CREAT, 0644); ASSERT_THAT(fd, returns(GT(0)).with_errno(EQ(0))); const char *data = "Hello, World!\n"; struct iovec iov[2]; @@ -26,4 +29,6 @@ TEST(LlvmLibcSysUioWritevTest, SmokeTest) { ASSERT_THAT(LIBC_NAMESPACE::writev(fd, iov, 2), returns(EQ(15)).with_errno(EQ(0))); ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::unlink(filename), + returns(EQ(0)).with_errno(EQ(0))); }