diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 3119c59b93af..efb5e1c7bd69 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -359,6 +359,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 b5b8389da97f..81dceb74a177 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -359,6 +359,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 a4957225c9d3..79bbbe401eb0 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 87c5bdff4824..6d3f336b2b52 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 6298f86cd937..c6a642979041 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 85a7a3ae4d5c..db4fe68e4ca9 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 000000000000..f1393a9749be --- /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 a3bb8986d522..8992bed95c98 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 000000000000..135b1e6fd1b5 --- /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 45f8d14c1617..7ba02be5d1cc 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.fcntl.open + 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 000000000000..7852b8a4b136 --- /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 a9a314813182..2c1c445cc786 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))); }