libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
+ # sys/sendfile entrypoints
+ libc.src.sys.sendfile.sendfile
+
# sys/stat.h entrypoints
libc.src.sys.stat.chmod
libc.src.sys.stat.fchmod
def SysStatAPI : PublicAPI<"sys/stat.h"> {
let Types = ["mode_t"];
}
+
+def SysSendfileAPI : PublicAPI<"sys/sendfile.h"> {
+ let Types = ["off_t", "size_t", "ssize_t"];
+}
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
+ # sys/sendfile entrypoints
+ libc.src.sys.sendfile.sendfile
+
# sys/stat.h entrypoints
libc.src.sys.stat.chmod
libc.src.sys.stat.fchmod
)
add_gen_header(
+ sys_sendfile
+ DEF_FILE sys/sendfile.h.def
+ GEN_HDR sys/sendfile.h
+ DEPENDS
+ .llvm_libc_common_h
+ .llvm-libc-types.off_t
+ .llvm-libc-types.ssize_t
+)
+
+add_gen_header(
sys_syscall
DEF_FILE sys/syscall.h.def
GEN_HDR sys/syscall.h
--- /dev/null
+//===-- Linux sys/sendfile.h ----------------------------------------------===//
+//
+// 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_SYS_SENDFILE_H
+#define LLVM_LIBC_SYS_SENDFILE_H
+
+#include <__llvm-libc-common.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_SENDFILE_H
]
>;
+ HeaderSpec SendFile = HeaderSpec<
+ "sys/sendfile.h",
+ [], // Macros
+ [OffTType, SizeTType, SSizeTType,], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "sendfile",
+ RetValSpec<SSizeTType>,
+ [ArgSpec<IntType>, ArgSpec<IntType>, ArgSpec<OffTPtr>, ArgSpec<SizeTType>]
+ >,
+ ]
+ >;
+
let Headers = [
CType,
FEnv,
Math,
PThread,
+ SendFile,
StdIO,
String,
];
ConstType ConstRestrictedCharPtr = ConstType<RestrictedCharPtr>;
NamedType ModeTType = NamedType<"mode_t">;
- NamedType OffTType = NamedType<"off_t">;
- NamedType SSizeTType = NamedType<"ssize_t">;
NamedType PThreadAttrTType = NamedType<"pthread_attr_t">;
PtrType PThreadAttrTPtr = PtrType<PThreadAttrTType>;
def IntMaxTType : NamedType<"intmax_t">;
def UIntMaxTType : NamedType<"uintmax_t">;
+def OffTType : NamedType<"off_t">;
+def OffTPtr : PtrType<OffTType>;
+def SSizeTType : NamedType<"ssize_t">;
+
// _Noreturn is really not a type, but it is convenient to treat it as a type.
def NoReturn : NamedType<"_Noreturn void">;
add_subdirectory(mman)
+add_subdirectory(sendfile)
add_subdirectory(stat)
--- /dev/null
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+ sendfile
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sendfile
+)
+
--- /dev/null
+add_entrypoint_object(
+ sendfile
+ SRCS
+ sendfile.cpp
+ HDRS
+ ../sendfile.h
+ DEPENDS
+ libc.include.sys_sendfile
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
--- /dev/null
+//===-- Linux implementation of sendfile ----------------------------------===//
+//
+// 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/sendfile/sendfile.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/sendfile.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(ssize_t, sendfile,
+ (int out_fd, int in_fd, off_t *offset, size_t count)) {
+ long ret = __llvm_libc::syscall(SYS_sendfile, in_fd, out_fd, offset, count);
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ return ret;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Implementation header for sendfile ----------------------*- C++ -*-===//
+//
+// 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_STAT_SENDFILE_H
+#define LLVM_LIBC_SRC_SYS_STAT_SENDFILE_H
+
+#include <sys/sendfile.h>
+
+namespace __llvm_libc {
+
+ssize_t sendfile(int, int, off_t *, size_t);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SYS_STAT_SENDFILE_H
add_subdirectory(mman)
+add_subdirectory(sendfile)
add_subdirectory(stat)
--- /dev/null
+add_libc_testsuite(libc_sys_sendfile_unittests)
+
+add_subdirectory(testdata)
+
+add_libc_unittest(
+ sendfile_test
+ SUITE
+ libc_sys_sendfile_unittests
+ SRCS
+ sendfile_test.cpp
+ DEPENDS
+ libc.include.errno
+ libc.include.fcntl
+ libc.include.sys_stat
+ libc.src.fcntl.open
+ libc.src.sys.sendfile.sendfile
+ libc.src.unistd.close
+ libc.src.unistd.read
+ libc.src.unistd.unlink
+ libc.src.unistd.write
+)
--- /dev/null
+//===-- Unittests for sendfile --------------------------------------------===//
+//
+// 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/__support/CPP/string_view.h"
+#include "src/fcntl/open.h"
+#include "src/sys/sendfile/sendfile.h"
+#include "src/unistd/close.h"
+#include "src/unistd/read.h"
+#include "src/unistd/unlink.h"
+#include "src/unistd/write.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include "utils/testutils/FDReader.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+namespace cpp = __llvm_libc::cpp;
+
+TEST(LlvmLibcSendfileTest, CreateAndTransfer) {
+ using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+ using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+
+ // The test strategy is to
+ // 1. Create a temporary file with known data.
+ // 2. Use sendfile to copy it to another file.
+ // 3. Make sure that the data was actually copied.
+ // 4. Clean up the temporary files.
+ constexpr const char *IN_FILE = "testdata/sendfile_in.test";
+ constexpr const char *OUT_FILE = "testdata/sendfile_out.test";
+ const char IN_DATA[] = "sendfile test";
+ constexpr ssize_t IN_SIZE = ssize_t(sizeof(IN_DATA));
+ errno = 0;
+
+ int in_fd = __llvm_libc::open(IN_FILE, O_CREAT | O_WRONLY, S_IRWXU);
+ ASSERT_GT(in_fd, 0);
+ ASSERT_EQ(errno, 0);
+ ASSERT_EQ(__llvm_libc::write(in_fd, IN_DATA, IN_SIZE), IN_SIZE);
+ ASSERT_THAT(__llvm_libc::close(in_fd), Succeeds(0));
+
+ in_fd = __llvm_libc::open(IN_FILE, O_RDONLY);
+ ASSERT_GT(in_fd, 0);
+ ASSERT_EQ(errno, 0);
+ int out_fd = __llvm_libc::open(OUT_FILE, O_CREAT | O_WRONLY, S_IRWXU);
+ ASSERT_GT(out_fd, 0);
+ ASSERT_EQ(errno, 0);
+ ssize_t size = __llvm_libc::sendfile(in_fd, out_fd, nullptr, IN_SIZE);
+ ASSERT_EQ(size, IN_SIZE);
+ ASSERT_THAT(__llvm_libc::close(in_fd), Succeeds(0));
+ ASSERT_THAT(__llvm_libc::close(out_fd), Succeeds(0));
+
+ out_fd = __llvm_libc::open(OUT_FILE, O_RDONLY);
+ ASSERT_GT(out_fd, 0);
+ ASSERT_EQ(errno, 0);
+ char buf[IN_SIZE];
+ ASSERT_EQ(IN_SIZE, __llvm_libc::read(out_fd, buf, IN_SIZE));
+ ASSERT_EQ(cpp::string_view(buf), cpp::string_view(IN_DATA));
+
+ ASSERT_THAT(__llvm_libc::unlink(IN_FILE), Succeeds(0));
+ ASSERT_THAT(__llvm_libc::unlink(OUT_FILE), Succeeds(0));
+}
--- /dev/null
+# Directory to hold temporary files created by tests.