diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp --- 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 @@ 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/unistd/linux/lseek.cpp b/libc/src/__support/File/linux/lseekImpl.h copy from libc/src/unistd/linux/lseek.cpp copy to libc/src/__support/File/linux/lseekImpl.h --- a/libc/src/unistd/linux/lseek.cpp +++ b/libc/src/__support/File/linux/lseekImpl.h @@ -6,41 +6,45 @@ // //===----------------------------------------------------------------------===// -#include "src/unistd/lseek.h" -#include "src/errno/libc_errno.h" +#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 +#include // For uint64_t. #include // For syscall numbers. -#include +#include // For off_t. namespace __llvm_libc { +namespace internal { -LLVM_LIBC_FUNCTION(off_t, lseek, (int fd, off_t offset, int whence)) { +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 - uint64_t offset_64 = static_cast(offset); + 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) { - libc_errno = -ret; - return -1; - } + 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 --- 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