xref: /llvm-project/libc/src/unistd/linux/pwrite.cpp (revision 5ff3ff33ff930e4ec49da7910612d8a41eb068cb)
16e675fbaSSiva Chandra Reddy //===-- Linux implementation of pwrite ------------------------------------===//
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/pwrite.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"
136e675fbaSSiva Chandra Reddy 
14*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
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, pwrite,
226e675fbaSSiva Chandra Reddy                    (int fd, const void *buf, size_t count, off_t offset)) {
237776fba4SMikhail R. Gadelha 
247776fba4SMikhail R. Gadelha   ssize_t ret;
257776fba4SMikhail R. Gadelha   if constexpr (sizeof(long) == sizeof(uint32_t) &&
267776fba4SMikhail R. Gadelha                 sizeof(off_t) == sizeof(uint64_t)) {
277776fba4SMikhail R. Gadelha     // This is a 32-bit system with a 64-bit offset, offset must be split.
287776fba4SMikhail R. Gadelha     const uint64_t bits = cpp::bit_cast<uint64_t>(offset);
297776fba4SMikhail R. Gadelha     const uint32_t lo = bits & UINT32_MAX;
307776fba4SMikhail R. Gadelha     const uint32_t hi = bits >> 32;
317776fba4SMikhail R. Gadelha     const long offset_low = cpp::bit_cast<long>(static_cast<long>(lo));
327776fba4SMikhail R. Gadelha     const long offset_high = cpp::bit_cast<long>(static_cast<long>(hi));
337776fba4SMikhail R. Gadelha     ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pwrite64, fd, buf, count,
347776fba4SMikhail R. Gadelha                                                 offset_low, offset_high);
357776fba4SMikhail R. Gadelha   } else {
367776fba4SMikhail R. Gadelha     ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pwrite64, fd, buf, count,
377776fba4SMikhail R. Gadelha                                                 offset);
387776fba4SMikhail R. Gadelha   }
397776fba4SMikhail R. Gadelha 
406e675fbaSSiva Chandra Reddy   if (ret < 0) {
41f0a3954eSMichael Jones     libc_errno = static_cast<int>(-ret);
426e675fbaSSiva Chandra Reddy     return -1;
436e675fbaSSiva Chandra Reddy   }
446e675fbaSSiva Chandra Reddy   return ret;
456e675fbaSSiva Chandra Reddy }
466e675fbaSSiva Chandra Reddy 
47*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
48