1 //===-- Implementation of internal fcntl ----------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/OSUtil/fcntl.h"
11 #include "hdr/fcntl_macros.h"
12 #include "hdr/types/off_t.h"
13 #include "hdr/types/struct_f_owner_ex.h"
14 #include "hdr/types/struct_flock.h"
15 #include "hdr/types/struct_flock64.h"
16 #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
17 #include "src/__support/common.h"
18 #include "src/__support/macros/config.h"
19 #include "src/errno/libc_errno.h"
22 #include <sys/syscall.h> // For syscall numbers.
24 namespace LIBC_NAMESPACE_DECL
{
27 int fcntl(int fd
, int cmd
, void *arg
) {
29 constexpr auto FCNTL_SYSCALL_ID
= SYS_fcntl
;
30 #elif defined(SYS_fcntl64)
31 constexpr auto FCNTL_SYSCALL_ID
= SYS_fcntl64
;
33 #error "fcntl and fcntl64 syscalls not available."
39 struct flock
*flk
= reinterpret_cast<struct flock
*>(arg
);
40 // convert the struct to a flock64
42 flk64
.l_type
= flk
->l_type
;
43 flk64
.l_whence
= flk
->l_whence
;
44 flk64
.l_start
= flk
->l_start
;
45 flk64
.l_len
= flk
->l_len
;
46 flk64
.l_pid
= flk
->l_pid
;
48 return LIBC_NAMESPACE::syscall_impl
<int>(FCNTL_SYSCALL_ID
, fd
, new_cmd
,
53 struct flock
*flk
= reinterpret_cast<struct flock
*>(arg
);
54 // convert the struct to a flock64
56 flk64
.l_type
= flk
->l_type
;
57 flk64
.l_whence
= flk
->l_whence
;
58 flk64
.l_start
= flk
->l_start
;
59 flk64
.l_len
= flk
->l_len
;
60 flk64
.l_pid
= flk
->l_pid
;
62 int retVal
= LIBC_NAMESPACE::syscall_impl
<int>(FCNTL_SYSCALL_ID
, fd
,
67 // Check for overflow, i.e. the offsets are not the same when cast
68 // to off_t from off64_t.
69 if (static_cast<off_t
>(flk64
.l_len
) != flk64
.l_len
||
70 static_cast<off_t
>(flk64
.l_start
) != flk64
.l_start
) {
71 libc_errno
= EOVERFLOW
;
74 // Now copy back into flk, in case flk64 got modified
75 flk
->l_type
= flk64
.l_type
;
76 flk
->l_whence
= flk64
.l_whence
;
77 flk
->l_start
= static_cast<decltype(flk
->l_start
)>(flk64
.l_start
);
78 flk
->l_len
= static_cast<decltype(flk
->l_len
)>(flk64
.l_len
);
79 flk
->l_pid
= flk64
.l_pid
;
83 struct f_owner_ex fex
;
84 int ret
= LIBC_NAMESPACE::syscall_impl
<int>(FCNTL_SYSCALL_ID
, fd
,
87 return fex
.type
== F_OWNER_PGRP
? -fex
.pid
: fex
.pid
;
93 if constexpr (FCNTL_SYSCALL_ID
== SYS_fcntl64
)
98 if constexpr (FCNTL_SYSCALL_ID
== SYS_fcntl64
)
103 if constexpr (FCNTL_SYSCALL_ID
== SYS_fcntl64
)
104 new_cmd
= F_SETLKW64
;
109 int retVal
= LIBC_NAMESPACE::syscall_impl
<int>(FCNTL_SYSCALL_ID
, fd
, new_cmd
,
110 reinterpret_cast<void *>(arg
));
114 libc_errno
= -retVal
;
118 } // namespace internal
119 } // namespace LIBC_NAMESPACE_DECL