[TableGen] Remove unnecessary check before calling SmallVector::erase. NFC
[llvm-project.git] / libc / src / __support / OSUtil / linux / fcntl.cpp
blob4742b2a00220bb442ee29425e440880ea8b30971
1 //===-- Implementation of internal fcntl ----------------------------------===//
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 //===----------------------------------------------------------------------===//
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"
21 #include <stdarg.h>
22 #include <sys/syscall.h> // For syscall numbers.
24 namespace LIBC_NAMESPACE_DECL {
25 namespace internal {
27 int fcntl(int fd, int cmd, void *arg) {
28 #if SYS_fcntl
29 constexpr auto FCNTL_SYSCALL_ID = SYS_fcntl;
30 #elif defined(SYS_fcntl64)
31 constexpr auto FCNTL_SYSCALL_ID = SYS_fcntl64;
32 #else
33 #error "fcntl and fcntl64 syscalls not available."
34 #endif
36 int new_cmd = cmd;
37 switch (new_cmd) {
38 case F_OFD_SETLKW: {
39 struct flock *flk = reinterpret_cast<struct flock *>(arg);
40 // convert the struct to a flock64
41 struct flock64 flk64;
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;
47 // create a syscall
48 return LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd, new_cmd,
49 &flk64);
51 case F_OFD_GETLK:
52 case F_OFD_SETLK: {
53 struct flock *flk = reinterpret_cast<struct flock *>(arg);
54 // convert the struct to a flock64
55 struct flock64 flk64;
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;
61 // create a syscall
62 int retVal = LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd,
63 new_cmd, &flk64);
64 // On failure, return
65 if (retVal == -1)
66 return -1;
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;
72 return -1;
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;
80 return retVal;
82 case F_GETOWN: {
83 struct f_owner_ex fex;
84 int ret = LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd,
85 F_GETOWN_EX, &fex);
86 if (ret >= 0)
87 return fex.type == F_OWNER_PGRP ? -fex.pid : fex.pid;
88 libc_errno = -ret;
89 return -1;
91 #ifdef SYS_fcntl64
92 case F_GETLK: {
93 if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64)
94 new_cmd = F_GETLK64;
95 break;
97 case F_SETLK: {
98 if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64)
99 new_cmd = F_SETLK64;
100 break;
102 case F_SETLKW: {
103 if constexpr (FCNTL_SYSCALL_ID == SYS_fcntl64)
104 new_cmd = F_SETLKW64;
105 break;
107 #endif
109 int retVal = LIBC_NAMESPACE::syscall_impl<int>(FCNTL_SYSCALL_ID, fd, new_cmd,
110 reinterpret_cast<void *>(arg));
111 if (retVal >= 0) {
112 return retVal;
114 libc_errno = -retVal;
115 return -1;
118 } // namespace internal
119 } // namespace LIBC_NAMESPACE_DECL