Skip to content

Commit 8cd4ecf

Browse files
[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
1 parent 0e0ff85 commit 8cd4ecf

File tree

3 files changed

+61
-48
lines changed

3 files changed

+61
-48
lines changed

libc/src/__support/File/linux/file.cpp

+5-26
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "src/__support/File/file.h"
1212

1313
#include "src/__support/CPP/new.h"
14+
#include "src/__support/File/linux/lseekImpl.h"
1415
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
1516
#include "src/errno/libc_errno.h" // For error macros
1617

@@ -40,32 +41,10 @@ FileIOResult linux_file_read(File *f, void *buf, size_t size) {
4041

4142
ErrorOr<long> linux_file_seek(File *f, long offset, int whence) {
4243
auto *lf = reinterpret_cast<LinuxFile *>(f);
43-
long result;
44-
#ifdef SYS_lseek
45-
int ret =
46-
__llvm_libc::syscall_impl<int>(SYS_lseek, lf->get_fd(), offset, whence);
47-
result = ret;
48-
#elif defined(SYS_llseek)
49-
int ret = __llvm_libc::syscall_impl<int>(SYS_llseek, lf->get_fd(),
50-
(long)(((uint64_t)(offset)) >> 32),
51-
(long)offset, &result, whence);
52-
result = ret;
53-
#elif defined(SYS_llseek)
54-
int ret = __llvm_libc::syscall_impl<int>(SYS_llseek, lf->get_fd(),
55-
(long)(((uint64_t)(offset)) >> 32),
56-
(long)offset, &result, whence);
57-
result = ret;
58-
#elif defined(SYS__llseek)
59-
int ret = __llvm_libc::syscall_impl<int>(
60-
SYS__llseek, lf->get_fd(), offset >> 32, offset, &result, whence);
61-
#else
62-
#error "lseek, llseek and _llseek syscalls not available."
63-
#endif
64-
65-
if (ret < 0)
66-
return Error(-ret);
67-
68-
return result;
44+
auto result = internal::lseekimpl(lf->get_fd(), offset, whence);
45+
if (!result.has_value())
46+
return result.error();
47+
return result.value();
6948
}
7049

7150
int linux_file_close(File *f) {
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//===-- Linux implementation of lseek -------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SUPPORT_FILE_LINUX_LSEEKIMPL_H
10+
#define LLVM_LIBC_SRC_SUPPORT_FILE_LINUX_LSEEKIMPL_H
11+
12+
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
13+
#include "src/__support/common.h"
14+
#include "src/__support/error_or.h"
15+
#include "src/errno/libc_errno.h"
16+
17+
#include <stdint.h> // For uint64_t.
18+
#include <sys/syscall.h> // For syscall numbers.
19+
#include <unistd.h> // For off_t.
20+
21+
namespace __llvm_libc {
22+
namespace internal {
23+
24+
LIBC_INLINE ErrorOr<off_t> lseekimpl(int fd, off_t offset, int whence) {
25+
off_t result;
26+
#ifdef SYS_lseek
27+
int ret = __llvm_libc::syscall_impl<int>(SYS_lseek, fd, offset, whence);
28+
result = ret;
29+
#elif defined(SYS_llseek) || defined(SYS__llseek)
30+
static_assert(sizeof(size_t) == 4, "size_t must be 32 bits.");
31+
#ifdef SYS_llseek
32+
constexpr long LLSEEK_SYSCALL_NO = SYS_llseek;
33+
#elif defined(SYS__llseek)
34+
constexpr long LLSEEK_SYSCALL_NO = SYS__llseek;
35+
#endif
36+
off_t offset_64 = offset;
37+
int ret = __llvm_libc::syscall_impl<int>(
38+
LLSEEK_SYSCALL_NO, fd, offset_64 >> 32, offset_64, &result, whence);
39+
#else
40+
#error "lseek, llseek and _llseek syscalls not available."
41+
#endif
42+
if (ret < 0)
43+
return Error(-ret);
44+
return result;
45+
}
46+
47+
} // namespace internal
48+
} // namespace __llvm_libc
49+
50+
#endif // LLVM_LIBC_SRC_SUPPORT_FILE_LINUX_LSEEKIMPL_H

libc/src/unistd/linux/lseek.cpp

+6-22
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,22 @@
99
#include "src/unistd/lseek.h"
1010
#include "src/errno/libc_errno.h"
1111

12+
#include "src/__support/File/linux/lseekImpl.h"
1213
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
1314
#include "src/__support/common.h"
1415

15-
#include <stdint.h>
1616
#include <sys/syscall.h> // For syscall numbers.
17-
#include <unistd.h>
17+
#include <unistd.h> // For off_t.
1818

1919
namespace __llvm_libc {
2020

2121
LLVM_LIBC_FUNCTION(off_t, lseek, (int fd, off_t offset, int whence)) {
22-
off_t result;
23-
#ifdef SYS_lseek
24-
int ret = __llvm_libc::syscall_impl<int>(SYS_lseek, fd, offset, whence);
25-
result = ret;
26-
#elif defined(SYS_llseek) || defined(SYS__llseek)
27-
#ifdef SYS_llseek
28-
constexpr long LLSEEK_SYSCALL_NO = SYS_llseek;
29-
#elif defined(SYS__llseek)
30-
constexpr long LLSEEK_SYSCALL_NO = SYS__llseek;
31-
#endif
32-
uint64_t offset_64 = static_cast<uint64_t>(offset);
33-
int ret = __llvm_libc::syscall_impl<int>(
34-
LLSEEK_SYSCALL_NO, fd, offset_64 >> 32, offset_64, &result, whence);
35-
#else
36-
#error "lseek, llseek and _llseek syscalls not available."
37-
#endif
38-
39-
if (ret < 0) {
40-
libc_errno = -ret;
22+
auto result = internal::lseekimpl(fd, offset, whence);
23+
if (!result.has_value()) {
24+
libc_errno = result.error();
4125
return -1;
4226
}
43-
return result;
27+
return result.value();
4428
}
4529

4630
} // namespace __llvm_libc

0 commit comments

Comments
 (0)