From 8cd4ecfa6001eed7486fa3618bbd6bde47a0b075 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Wed, 6 Sep 2023 11:35:11 -0300 Subject: [PATCH] [libc] Unify lseek implementations In patch D157792, the calls to SYS_llseek/SYS_llseek for 32-bit systems were fixed in lseek.cpp but there was another implementation in file.cpp that was missed. To reduce the code duplication, this patch unifies both call sites to use a new lseekimpl function. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D159208 --- libc/src/__support/File/linux/file.cpp | 31 +++----------- libc/src/__support/File/linux/lseekImpl.h | 50 +++++++++++++++++++++++ libc/src/unistd/linux/lseek.cpp | 28 +++---------- 3 files changed, 61 insertions(+), 48 deletions(-) create mode 100644 libc/src/__support/File/linux/lseekImpl.h diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp index 611d45ea7ac4..2d4481bc4b56 100644 --- a/libc/src/__support/File/linux/file.cpp +++ b/libc/src/__support/File/linux/file.cpp @@ -11,6 +11,7 @@ #include "src/__support/File/file.h" #include "src/__support/CPP/new.h" +#include "src/__support/File/linux/lseekImpl.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/errno/libc_errno.h" // For error macros @@ -40,32 +41,10 @@ FileIOResult linux_file_read(File *f, void *buf, size_t size) { ErrorOr linux_file_seek(File *f, long offset, int whence) { auto *lf = reinterpret_cast(f); - long result; -#ifdef SYS_lseek - int ret = - __llvm_libc::syscall_impl(SYS_lseek, lf->get_fd(), offset, whence); - result = ret; -#elif defined(SYS_llseek) - int ret = __llvm_libc::syscall_impl(SYS_llseek, lf->get_fd(), - (long)(((uint64_t)(offset)) >> 32), - (long)offset, &result, whence); - result = ret; -#elif defined(SYS_llseek) - int ret = __llvm_libc::syscall_impl(SYS_llseek, lf->get_fd(), - (long)(((uint64_t)(offset)) >> 32), - (long)offset, &result, whence); - result = ret; -#elif defined(SYS__llseek) - int ret = __llvm_libc::syscall_impl( - SYS__llseek, lf->get_fd(), offset >> 32, offset, &result, whence); -#else -#error "lseek, llseek and _llseek syscalls not available." -#endif - - if (ret < 0) - return Error(-ret); - - return result; + auto result = internal::lseekimpl(lf->get_fd(), offset, whence); + if (!result.has_value()) + return result.error(); + return result.value(); } int linux_file_close(File *f) { diff --git a/libc/src/__support/File/linux/lseekImpl.h b/libc/src/__support/File/linux/lseekImpl.h new file mode 100644 index 000000000000..8594cd3536fc --- /dev/null +++ b/libc/src/__support/File/linux/lseekImpl.h @@ -0,0 +1,50 @@ +//===-- Linux implementation of lseek -------------------------------------===// +// +// 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_SUPPORT_FILE_LINUX_LSEEKIMPL_H +#define LLVM_LIBC_SRC_SUPPORT_FILE_LINUX_LSEEKIMPL_H + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/__support/error_or.h" +#include "src/errno/libc_errno.h" + +#include // For uint64_t. +#include // For syscall numbers. +#include // For off_t. + +namespace __llvm_libc { +namespace internal { + +LIBC_INLINE ErrorOr lseekimpl(int fd, off_t offset, int whence) { + off_t result; +#ifdef SYS_lseek + int ret = __llvm_libc::syscall_impl(SYS_lseek, fd, offset, whence); + result = ret; +#elif defined(SYS_llseek) || defined(SYS__llseek) + static_assert(sizeof(size_t) == 4, "size_t must be 32 bits."); +#ifdef SYS_llseek + constexpr long LLSEEK_SYSCALL_NO = SYS_llseek; +#elif defined(SYS__llseek) + constexpr long LLSEEK_SYSCALL_NO = SYS__llseek; +#endif + off_t offset_64 = offset; + int ret = __llvm_libc::syscall_impl( + LLSEEK_SYSCALL_NO, fd, offset_64 >> 32, offset_64, &result, whence); +#else +#error "lseek, llseek and _llseek syscalls not available." +#endif + if (ret < 0) + return Error(-ret); + return result; +} + +} // namespace internal +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SUPPORT_FILE_LINUX_LSEEKIMPL_H diff --git a/libc/src/unistd/linux/lseek.cpp b/libc/src/unistd/linux/lseek.cpp index 87900e2f8c08..3ab0084269e2 100644 --- a/libc/src/unistd/linux/lseek.cpp +++ b/libc/src/unistd/linux/lseek.cpp @@ -9,38 +9,22 @@ #include "src/unistd/lseek.h" #include "src/errno/libc_errno.h" +#include "src/__support/File/linux/lseekImpl.h" #include "src/__support/OSUtil/syscall.h" // For internal syscall function. #include "src/__support/common.h" -#include #include // For syscall numbers. -#include +#include // For off_t. namespace __llvm_libc { LLVM_LIBC_FUNCTION(off_t, lseek, (int fd, off_t offset, int whence)) { - off_t result; -#ifdef SYS_lseek - int ret = __llvm_libc::syscall_impl(SYS_lseek, fd, offset, whence); - result = ret; -#elif defined(SYS_llseek) || defined(SYS__llseek) -#ifdef SYS_llseek - constexpr long LLSEEK_SYSCALL_NO = SYS_llseek; -#elif defined(SYS__llseek) - constexpr long LLSEEK_SYSCALL_NO = SYS__llseek; -#endif - uint64_t offset_64 = static_cast(offset); - int ret = __llvm_libc::syscall_impl( - LLSEEK_SYSCALL_NO, fd, offset_64 >> 32, offset_64, &result, whence); -#else -#error "lseek, llseek and _llseek syscalls not available." -#endif - - if (ret < 0) { - libc_errno = -ret; + auto result = internal::lseekimpl(fd, offset, whence); + if (!result.has_value()) { + libc_errno = result.error(); return -1; } - return result; + return result.value(); } } // namespace __llvm_libc