16e675fbaSSiva Chandra Reddy //===-- Linux implementation of pread -------------------------------------===// 26e675fbaSSiva Chandra Reddy // 36e675fbaSSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 46e675fbaSSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 56e675fbaSSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 66e675fbaSSiva Chandra Reddy // 76e675fbaSSiva Chandra Reddy //===----------------------------------------------------------------------===// 86e675fbaSSiva Chandra Reddy 96e675fbaSSiva Chandra Reddy #include "src/unistd/pread.h" 106e675fbaSSiva Chandra Reddy 116e675fbaSSiva Chandra Reddy #include "src/__support/OSUtil/syscall.h" // For internal syscall function. 126e675fbaSSiva Chandra Reddy #include "src/__support/common.h" 13*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 14c6691f68Smichaelrj-google #include "src/__support/macros/sanitizer.h" // for MSAN_UNPOISON 15803437dbSMichael Jones #include "src/errno/libc_errno.h" 16c9783d2bSMikhail R. Gadelha #include <stdint.h> // For uint64_t. 176e675fbaSSiva Chandra Reddy #include <sys/syscall.h> // For syscall numbers. 186e675fbaSSiva Chandra Reddy 19*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 206e675fbaSSiva Chandra Reddy 216e675fbaSSiva Chandra Reddy LLVM_LIBC_FUNCTION(ssize_t, pread, 226e675fbaSSiva Chandra Reddy (int fd, void *buf, size_t count, off_t offset)) { 237776fba4SMikhail R. Gadelha ssize_t ret; 247776fba4SMikhail R. Gadelha if constexpr (sizeof(long) == sizeof(uint32_t) && 257776fba4SMikhail R. Gadelha sizeof(off_t) == sizeof(uint64_t)) { 267776fba4SMikhail R. Gadelha // This is a 32-bit system with a 64-bit offset, offset must be split. 277776fba4SMikhail R. Gadelha const uint64_t bits = cpp::bit_cast<uint64_t>(offset); 287776fba4SMikhail R. Gadelha const uint32_t lo = bits & UINT32_MAX; 297776fba4SMikhail R. Gadelha const uint32_t hi = bits >> 32; 307776fba4SMikhail R. Gadelha const long offset_low = cpp::bit_cast<long>(static_cast<long>(lo)); 317776fba4SMikhail R. Gadelha const long offset_high = cpp::bit_cast<long>(static_cast<long>(hi)); 327776fba4SMikhail R. Gadelha ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pread64, fd, buf, count, 337776fba4SMikhail R. Gadelha offset_low, offset_high); 347776fba4SMikhail R. Gadelha } else { 357776fba4SMikhail R. Gadelha ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pread64, fd, buf, count, 367776fba4SMikhail R. Gadelha offset); 377776fba4SMikhail R. Gadelha } 38c6691f68Smichaelrj-google // The cast is important since there is a check that dereferences the pointer 39c6691f68Smichaelrj-google // which fails on void*. 40c6691f68Smichaelrj-google MSAN_UNPOISON(reinterpret_cast<char *>(buf), count); 416e675fbaSSiva Chandra Reddy if (ret < 0) { 42f0a3954eSMichael Jones libc_errno = static_cast<int>(-ret); 436e675fbaSSiva Chandra Reddy return -1; 446e675fbaSSiva Chandra Reddy } 456e675fbaSSiva Chandra Reddy return ret; 466e675fbaSSiva Chandra Reddy } 476e675fbaSSiva Chandra Reddy 48*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 49