diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp index 761e352f74ead..4594dadf1ccdf 100644 --- a/libc/src/__support/File/linux/file.cpp +++ b/libc/src/__support/File/linux/file.cpp @@ -19,8 +19,8 @@ #include "src/__support/macros/config.h" #include "hdr/fcntl_macros.h" // For mode_t and other flags to the open syscall -#include // For S_IS*, S_IF*, and S_IR* flags. -#include // For syscall numbers +#include // For S_IS*, S_IF*, and S_IR* flags. +#include // For syscall numbers namespace LIBC_NAMESPACE_DECL { @@ -128,10 +128,11 @@ ErrorOr create_file_from_fd(int fd, const char *mode) { return Error(EINVAL); } - int fd_flags = internal::fcntl(fd, F_GETFL); - if (fd_flags == -1) { + auto result = internal::fcntl(fd, F_GETFL); + if (!result.has_value()) { return Error(EBADF); } + int fd_flags = result.value(); using OpenMode = File::OpenMode; if (((fd_flags & O_ACCMODE) == O_RDONLY && @@ -145,8 +146,9 @@ ErrorOr create_file_from_fd(int fd, const char *mode) { if ((modeflags & static_cast(OpenMode::APPEND)) && !(fd_flags & O_APPEND)) { do_seek = true; - if (internal::fcntl(fd, F_SETFL, - reinterpret_cast(fd_flags | O_APPEND)) == -1) { + if (!internal::fcntl(fd, F_SETFL, + reinterpret_cast(fd_flags | O_APPEND)) + .has_value()) { return Error(EBADF); } } diff --git a/libc/src/__support/OSUtil/fcntl.h b/libc/src/__support/OSUtil/fcntl.h index 46f7d28132396..3983d78f7f89c 100644 --- a/libc/src/__support/OSUtil/fcntl.h +++ b/libc/src/__support/OSUtil/fcntl.h @@ -8,12 +8,18 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_FCNTL_H #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_FCNTL_H +#include "hdr/types/mode_t.h" +#include "src/__support/error_or.h" #include "src/__support/macros/config.h" namespace LIBC_NAMESPACE_DECL { namespace internal { -int fcntl(int fd, int cmd, void *arg = nullptr); +ErrorOr fcntl(int fd, int cmd, void *arg = nullptr); + +ErrorOr open(const char *path, int flags, mode_t mode_flags = 0); + +ErrorOr close(int fd); } // namespace internal } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt index b9704d42cd33b..4681d8c2bb73c 100644 --- a/libc/src/__support/OSUtil/linux/CMakeLists.txt +++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt @@ -16,7 +16,6 @@ add_object_library( .${LIBC_TARGET_ARCHITECTURE}.linux_${LIBC_TARGET_ARCHITECTURE}_util libc.src.__support.common libc.src.__support.CPP.string_view - libc.src.errno.errno libc.hdr.fcntl_macros libc.hdr.types.struct_flock libc.hdr.types.struct_flock64 diff --git a/libc/src/__support/OSUtil/linux/fcntl.cpp b/libc/src/__support/OSUtil/linux/fcntl.cpp index 99e16ad58c918..bb76eee90efd2 100644 --- a/libc/src/__support/OSUtil/linux/fcntl.cpp +++ b/libc/src/__support/OSUtil/linux/fcntl.cpp @@ -8,23 +8,24 @@ #include "src/__support/OSUtil/fcntl.h" +#include "hdr/errno_macros.h" #include "hdr/fcntl_macros.h" +#include "hdr/types/mode_t.h" #include "hdr/types/off_t.h" #include "hdr/types/struct_f_owner_ex.h" #include "hdr/types/struct_flock.h" #include "hdr/types/struct_flock64.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" -#include "src/__support/libc_errno.h" +#include "src/__support/error_or.h" #include "src/__support/macros/config.h" -#include #include // For syscall numbers. namespace LIBC_NAMESPACE_DECL { namespace internal { -int fcntl(int fd, int cmd, void *arg) { +ErrorOr fcntl(int fd, int cmd, void *arg) { #if SYS_fcntl constexpr auto FCNTL_SYSCALL_ID = SYS_fcntl; #elif defined(SYS_fcntl64) @@ -33,8 +34,7 @@ int fcntl(int fd, int cmd, void *arg) { #error "fcntl and fcntl64 syscalls not available." #endif - int new_cmd = cmd; - switch (new_cmd) { + switch (cmd) { case F_OFD_SETLKW: { struct flock *flk = reinterpret_cast(arg); // convert the struct to a flock64 @@ -45,8 +45,11 @@ int fcntl(int fd, int cmd, void *arg) { flk64.l_len = flk->l_len; flk64.l_pid = flk->l_pid; // create a syscall - return LIBC_NAMESPACE::syscall_impl(FCNTL_SYSCALL_ID, fd, new_cmd, - &flk64); + int ret = + LIBC_NAMESPACE::syscall_impl(FCNTL_SYSCALL_ID, fd, cmd, &flk64); + if (ret < 0) + return Error(-ret); + return ret; } case F_OFD_GETLK: case F_OFD_SETLK: { @@ -59,60 +62,80 @@ int fcntl(int fd, int cmd, void *arg) { flk64.l_len = flk->l_len; flk64.l_pid = flk->l_pid; // create a syscall - int retVal = LIBC_NAMESPACE::syscall_impl(FCNTL_SYSCALL_ID, fd, - new_cmd, &flk64); + int ret = + LIBC_NAMESPACE::syscall_impl(FCNTL_SYSCALL_ID, fd, cmd, &flk64); // On failure, return - if (retVal == -1) - return -1; + if (ret < 0) + return Error(-1); // Check for overflow, i.e. the offsets are not the same when cast // to off_t from off64_t. if (static_cast(flk64.l_len) != flk64.l_len || - static_cast(flk64.l_start) != flk64.l_start) { - libc_errno = EOVERFLOW; - return -1; - } + static_cast(flk64.l_start) != flk64.l_start) + return Error(EOVERFLOW); + // Now copy back into flk, in case flk64 got modified flk->l_type = flk64.l_type; flk->l_whence = flk64.l_whence; flk->l_start = static_castl_start)>(flk64.l_start); flk->l_len = static_castl_len)>(flk64.l_len); flk->l_pid = flk64.l_pid; - return retVal; + return ret; } case F_GETOWN: { struct f_owner_ex fex; int ret = LIBC_NAMESPACE::syscall_impl(FCNTL_SYSCALL_ID, fd, F_GETOWN_EX, &fex); - if (ret >= 0) - return fex.type == F_OWNER_PGRP ? -fex.pid : fex.pid; - libc_errno = -ret; - return -1; + if (ret < 0) + return Error(-ret); + return fex.type == F_OWNER_PGRP ? -fex.pid : fex.pid; } #ifdef SYS_fcntl64 case F_GETLK: { if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64) - new_cmd = F_GETLK64; + cmd = F_GETLK64; break; } case F_SETLK: { if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64) - new_cmd = F_SETLK64; + cmd = F_SETLK64; break; } case F_SETLKW: { if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64) - new_cmd = F_SETLKW64; + cmd = F_SETLKW64; break; } #endif } - int retVal = LIBC_NAMESPACE::syscall_impl(FCNTL_SYSCALL_ID, fd, new_cmd, - reinterpret_cast(arg)); - if (retVal >= 0) { - return retVal; - } - libc_errno = -retVal; - return -1; + + // default, but may use rewritten cmd from above. + int ret = LIBC_NAMESPACE::syscall_impl(FCNTL_SYSCALL_ID, fd, cmd, + reinterpret_cast(arg)); + if (ret < 0) + return Error(-ret); + return ret; +} + +ErrorOr open(const char *path, int flags, mode_t mode_flags) { +#ifdef SYS_open + int fd = LIBC_NAMESPACE::syscall_impl(SYS_open, path, flags, mode_flags); +#else + int fd = LIBC_NAMESPACE::syscall_impl(SYS_openat, AT_FDCWD, path, flags, + mode_flags); +#endif + if (fd < 0) + return Error(-fd); + + return fd; +} + +ErrorOr close(int fd) { + int ret = LIBC_NAMESPACE::syscall_impl(SYS_close, fd); + + if (ret < 0) + return Error(-ret); + + return ret; } } // namespace internal diff --git a/libc/src/fcntl/linux/CMakeLists.txt b/libc/src/fcntl/linux/CMakeLists.txt index 580db16cd4132..c31eb3f438c10 100644 --- a/libc/src/fcntl/linux/CMakeLists.txt +++ b/libc/src/fcntl/linux/CMakeLists.txt @@ -19,6 +19,7 @@ add_entrypoint_object( DEPENDS libc.hdr.fcntl_macros libc.src.__support.OSUtil.osutil + libc.src.errno.errno ) add_entrypoint_object( diff --git a/libc/src/fcntl/linux/fcntl.cpp b/libc/src/fcntl/linux/fcntl.cpp index a0c8459ced342..fd9c48eb562f7 100644 --- a/libc/src/fcntl/linux/fcntl.cpp +++ b/libc/src/fcntl/linux/fcntl.cpp @@ -10,6 +10,7 @@ #include "src/__support/OSUtil/fcntl.h" #include "src/__support/common.h" +#include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" #include @@ -22,7 +23,14 @@ LLVM_LIBC_FUNCTION(int, fcntl, (int fd, int cmd, ...)) { va_start(varargs, cmd); arg = va_arg(varargs, void *); va_end(varargs); - return LIBC_NAMESPACE::internal::fcntl(fd, cmd, arg); + + auto result = LIBC_NAMESPACE::internal::fcntl(fd, cmd, arg); + + if (!result.has_value()) { + libc_errno = result.error(); + return -1; + } + return result.value(); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/fcntl/linux/open.cpp b/libc/src/fcntl/linux/open.cpp index a21a03788deaa..3a56d10554198 100644 --- a/libc/src/fcntl/linux/open.cpp +++ b/libc/src/fcntl/linux/open.cpp @@ -8,15 +8,13 @@ #include "src/fcntl/open.h" -#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "hdr/fcntl_macros.h" +#include "hdr/types/mode_t.h" +#include "src/__support/OSUtil/fcntl.h" #include "src/__support/common.h" #include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" - -#include "hdr/fcntl_macros.h" -#include "hdr/types/mode_t.h" #include -#include // For syscall numbers. namespace LIBC_NAMESPACE_DECL { @@ -31,17 +29,13 @@ LLVM_LIBC_FUNCTION(int, open, (const char *path, int flags, ...)) { va_end(varargs); } -#ifdef SYS_open - int fd = LIBC_NAMESPACE::syscall_impl(SYS_open, path, flags, mode_flags); -#else - int fd = LIBC_NAMESPACE::syscall_impl(SYS_openat, AT_FDCWD, path, flags, - mode_flags); -#endif - if (fd > 0) - return fd; + auto result = internal::open(path, flags, mode_flags); - libc_errno = -fd; - return -1; + if (!result.has_value()) { + libc_errno = result.error(); + return -1; + } + return result.value(); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/sys/auxv/linux/getauxval.cpp b/libc/src/sys/auxv/linux/getauxval.cpp index f3ae7c5c4e07a..b50c5845bcc2b 100644 --- a/libc/src/sys/auxv/linux/getauxval.cpp +++ b/libc/src/sys/auxv/linux/getauxval.cpp @@ -8,6 +8,8 @@ #include "src/sys/auxv/getauxval.h" #include "config/app.h" +#include "hdr/fcntl_macros.h" +#include "src/__support/OSUtil/fcntl.h" #include "src/__support/common.h" #include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" @@ -17,14 +19,18 @@ #include "src/__support/threads/callonce.h" #include "src/__support/threads/linux/futex_word.h" +// ----------------------------------------------------------------------------- +// TODO: This file should not include other public libc functions. Calling other +// public libc functions is an antipattern within LLVM-libc. This needs to be +// cleaned up. DO NOT COPY THIS. +// ----------------------------------------------------------------------------- + // for mallocing the global auxv #include "src/sys/mman/mmap.h" #include "src/sys/mman/munmap.h" // for reading /proc/self/auxv -#include "src/fcntl/open.h" #include "src/sys/prctl/prctl.h" -#include "src/unistd/close.h" #include "src/unistd/read.h" // getauxval will work either with or without __cxa_atexit support. @@ -60,17 +66,18 @@ class AuxvMMapGuard { constexpr static size_t AUXV_MMAP_SIZE = sizeof(AuxEntry) * MAX_AUXV_ENTRIES; AuxvMMapGuard() - : ptr(mmap(nullptr, AUXV_MMAP_SIZE, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) {} + : ptr(LIBC_NAMESPACE::mmap(nullptr, AUXV_MMAP_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) {} ~AuxvMMapGuard() { if (ptr != MAP_FAILED) - munmap(ptr, AUXV_MMAP_SIZE); + LIBC_NAMESPACE::munmap(ptr, AUXV_MMAP_SIZE); } void submit_to_global() { // atexit may fail, we do not set it to global in that case. int ret = __cxa_atexit( [](void *) { - munmap(auxv, AUXV_MMAP_SIZE); + LIBC_NAMESPACE::munmap(auxv, AUXV_MMAP_SIZE); auxv = nullptr; }, nullptr, nullptr); @@ -90,10 +97,16 @@ class AuxvMMapGuard { class AuxvFdGuard { public: - AuxvFdGuard() : fd(open("/proc/self/auxv", O_RDONLY | O_CLOEXEC)) {} + AuxvFdGuard() { + auto result = internal::open("/proc/self/auxv", O_RDONLY | O_CLOEXEC); + if (!result.has_value()) + fd = -1; + + fd = result.value(); + } ~AuxvFdGuard() { if (fd != -1) - close(fd); + internal::close(fd); } bool valid() const { return fd != -1; } int get() const { return fd; } @@ -135,7 +148,8 @@ static void initialize_auxv_once(void) { bool error_detected = false; // Read until we use up all the available space or we finish reading the file. while (available_size != 0) { - ssize_t bytes_read = read(fd_guard.get(), buf, available_size); + ssize_t bytes_read = + LIBC_NAMESPACE::read(fd_guard.get(), buf, available_size); if (bytes_read <= 0) { if (libc_errno == EINTR) continue; @@ -158,7 +172,7 @@ static AuxEntry read_entry(int fd) { size_t size = sizeof(AuxEntry); char *ptr = reinterpret_cast(&buf); while (size > 0) { - ssize_t ret = read(fd, ptr, size); + ssize_t ret = LIBC_NAMESPACE::read(fd, ptr, size); if (ret < 0) { if (libc_errno == EINTR) continue; @@ -195,7 +209,8 @@ LLVM_LIBC_FUNCTION(unsigned long, getauxval, (unsigned long id)) { return search_auxv(app.auxv_ptr, id); static FutexWordType once_flag; - callonce(reinterpret_cast(&once_flag), initialize_auxv_once); + LIBC_NAMESPACE::callonce(reinterpret_cast(&once_flag), + initialize_auxv_once); if (auxv != nullptr) return search_auxv(auxv, id); diff --git a/libc/src/sys/mman/linux/shm_common.h b/libc/src/sys/mman/linux/shm_common.h index 69911012ff7e9..29d1401821e49 100644 --- a/libc/src/sys/mman/linux/shm_common.h +++ b/libc/src/sys/mman/linux/shm_common.h @@ -13,6 +13,11 @@ #include "src/__support/macros/config.h" #include "src/string/memory_utils/inline_memcpy.h" +// TODO: clean this up. +// 1. Change from optional to ErrorOr, and return the errno instead of setting +// it here. +// 2. Replace inline memcpy with __builtin_memcpy + // TODO: Get PATH_MAX via https://github.com/llvm/llvm-project/issues/85121 #include diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp index 11de482272d00..3099062eace98 100644 --- a/libc/src/sys/mman/linux/shm_open.cpp +++ b/libc/src/sys/mman/linux/shm_open.cpp @@ -7,9 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/sys/mman/shm_open.h" +#include "hdr/fcntl_macros.h" #include "hdr/types/mode_t.h" +#include "src/__support/OSUtil/fcntl.h" #include "src/__support/macros/config.h" -#include "src/fcntl/open.h" #include "src/sys/mman/linux/shm_common.h" namespace LIBC_NAMESPACE_DECL { @@ -17,9 +18,16 @@ namespace LIBC_NAMESPACE_DECL { static constexpr int DEFAULT_OFLAGS = O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK; LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) { - using namespace shm_common; - if (cpp::optional buffer = translate_name(name)) - return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode); + if (cpp::optional buffer = + shm_common::translate_name(name)) { + auto result = internal::open(buffer->data(), oflags | DEFAULT_OFLAGS, mode); + + if (!result.has_value()) { + libc_errno = result.error(); + return -1; + } + return result.value(); + } return -1; } diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp index 6a76301512201..4c61c7cd16bad 100644 --- a/libc/src/sys/mman/linux/shm_unlink.cpp +++ b/libc/src/sys/mman/linux/shm_unlink.cpp @@ -13,10 +13,13 @@ namespace LIBC_NAMESPACE_DECL { +// TODO: stop calling the public unlink function. It should be calling an +// internal shared utility. + LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) { - using namespace shm_common; - if (cpp::optional buffer = translate_name(name)) - return unlink(buffer->data()); + if (cpp::optional buffer = + shm_common::translate_name(name)) + return LIBC_NAMESPACE::unlink(buffer->data()); return -1; } diff --git a/libc/src/unistd/linux/close.cpp b/libc/src/unistd/linux/close.cpp index b5842f2b64d20..6ef3a3c6d63f0 100644 --- a/libc/src/unistd/linux/close.cpp +++ b/libc/src/unistd/linux/close.cpp @@ -8,9 +8,8 @@ #include "src/unistd/close.h" -#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/OSUtil/fcntl.h" #include "src/__support/common.h" - #include "src/__support/libc_errno.h" #include "src/__support/macros/config.h" #include // For syscall numbers. @@ -18,12 +17,13 @@ namespace LIBC_NAMESPACE_DECL { LLVM_LIBC_FUNCTION(int, close, (int fd)) { - int ret = LIBC_NAMESPACE::syscall_impl(SYS_close, fd); - if (ret < 0) { - libc_errno = -ret; + auto result = internal::close(fd); + + if (!result.has_value()) { + libc_errno = result.error(); return -1; } - return ret; + return result.value(); } } // namespace LIBC_NAMESPACE_DECL diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 84a6b7d230442..7901de161b7ac 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -344,6 +344,21 @@ libc_support_library( hdrs = ["hdr/types/struct_epoll_event.h"], ) +libc_support_library( + name = "types_struct_f_owner_ex", + hdrs = ["hdr/types/struct_f_owner_ex.h"], +) + +libc_support_library( + name = "types_struct_flock", + hdrs = ["hdr/types/struct_flock.h"], +) + +libc_support_library( + name = "types_struct_flock64", + hdrs = ["hdr/types/struct_flock64.h"], +) + libc_support_library( name = "types_struct_timespec", hdrs = ["hdr/types/struct_timespec.h"], @@ -1380,6 +1395,28 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_osutil_fcntl", + srcs = ["src/__support/OSUtil/linux/fcntl.cpp"], + hdrs = ["src/__support/OSUtil/fcntl.h"], + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + deps = [ + ":__support_common", + ":__support_error_or", + ":__support_osutil_syscall", + ":hdr_errno_macros", + ":hdr_fcntl_macros", + ":types_mode_t", + ":types_off_t", + ":types_struct_f_owner_ex", + ":types_struct_flock", + ":types_struct_flock64", + ], +) + libc_support_library( name = "__support_osutil_exit", srcs = ["src/__support/OSUtil/linux/exit.cpp"], @@ -1601,8 +1638,8 @@ libc_support_library( libc_header_library( name = "libcxx_shared_headers", hdrs = [ - "shared/libc_common.h", "shared/fp_bits.h", + "shared/libc_common.h", "shared/str_to_float.h", "shared/str_to_integer.h", ], @@ -4475,13 +4512,28 @@ libc_function( }), deps = [ ":__support_common", - ":__support_osutil_syscall", + ":__support_osutil_fcntl", ":errno", ":hdr_fcntl_macros", ":types_mode_t", ], ) +libc_function( + name = "fcntl", + srcs = ["src/fcntl/linux/fcntl.cpp"], + hdrs = ["src/fcntl/fcntl.h"], + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), + deps = [ + ":__support_common", + ":__support_osutil_fcntl", + ":errno", + ], +) + libc_function( name = "openat", srcs = ["src/fcntl/linux/openat.cpp"], @@ -4542,7 +4594,7 @@ libc_function( hdrs = ["src/unistd/close.h"], deps = [ ":__support_common", - ":__support_osutil_syscall", + ":__support_osutil_fcntl", ":errno", ], )