1 | /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. |
2 | * |
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
4 | * of this software and associated documentation files (the "Software"), to |
5 | * deal in the Software without restriction, including without limitation the |
6 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
7 | * sell copies of the Software, and to permit persons to whom the Software is |
8 | * furnished to do so, subject to the following conditions: |
9 | * |
10 | * The above copyright notice and this permission notice shall be included in |
11 | * all copies or substantial portions of the Software. |
12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
19 | * IN THE SOFTWARE. |
20 | */ |
21 | |
22 | #include "linux-syscalls.h" |
23 | #include <unistd.h> |
24 | #include <signal.h> |
25 | #include <sys/syscall.h> |
26 | #include <sys/types.h> |
27 | #include <errno.h> |
28 | |
29 | #if defined(__arm__) |
30 | # if defined(__thumb__) || defined(__ARM_EABI__) |
31 | # define UV_SYSCALL_BASE 0 |
32 | # else |
33 | # define UV_SYSCALL_BASE 0x900000 |
34 | # endif |
35 | #endif /* __arm__ */ |
36 | |
37 | #ifndef __NR_recvmmsg |
38 | # if defined(__x86_64__) |
39 | # define __NR_recvmmsg 299 |
40 | # elif defined(__arm__) |
41 | # define __NR_recvmmsg (UV_SYSCALL_BASE + 365) |
42 | # endif |
43 | #endif /* __NR_recvmsg */ |
44 | |
45 | #ifndef __NR_sendmmsg |
46 | # if defined(__x86_64__) |
47 | # define __NR_sendmmsg 307 |
48 | # elif defined(__arm__) |
49 | # define __NR_sendmmsg (UV_SYSCALL_BASE + 374) |
50 | # endif |
51 | #endif /* __NR_sendmmsg */ |
52 | |
53 | #ifndef __NR_utimensat |
54 | # if defined(__x86_64__) |
55 | # define __NR_utimensat 280 |
56 | # elif defined(__i386__) |
57 | # define __NR_utimensat 320 |
58 | # elif defined(__arm__) |
59 | # define __NR_utimensat (UV_SYSCALL_BASE + 348) |
60 | # endif |
61 | #endif /* __NR_utimensat */ |
62 | |
63 | #ifndef __NR_preadv |
64 | # if defined(__x86_64__) |
65 | # define __NR_preadv 295 |
66 | # elif defined(__i386__) |
67 | # define __NR_preadv 333 |
68 | # elif defined(__arm__) |
69 | # define __NR_preadv (UV_SYSCALL_BASE + 361) |
70 | # endif |
71 | #endif /* __NR_preadv */ |
72 | |
73 | #ifndef __NR_pwritev |
74 | # if defined(__x86_64__) |
75 | # define __NR_pwritev 296 |
76 | # elif defined(__i386__) |
77 | # define __NR_pwritev 334 |
78 | # elif defined(__arm__) |
79 | # define __NR_pwritev (UV_SYSCALL_BASE + 362) |
80 | # endif |
81 | #endif /* __NR_pwritev */ |
82 | |
83 | #ifndef __NR_dup3 |
84 | # if defined(__x86_64__) |
85 | # define __NR_dup3 292 |
86 | # elif defined(__i386__) |
87 | # define __NR_dup3 330 |
88 | # elif defined(__arm__) |
89 | # define __NR_dup3 (UV_SYSCALL_BASE + 358) |
90 | # endif |
91 | #endif /* __NR_pwritev */ |
92 | |
93 | #ifndef __NR_copy_file_range |
94 | # if defined(__x86_64__) |
95 | # define __NR_copy_file_range 326 |
96 | # elif defined(__i386__) |
97 | # define __NR_copy_file_range 377 |
98 | # elif defined(__s390__) |
99 | # define __NR_copy_file_range 375 |
100 | # elif defined(__arm__) |
101 | # define __NR_copy_file_range (UV_SYSCALL_BASE + 391) |
102 | # elif defined(__aarch64__) |
103 | # define __NR_copy_file_range 285 |
104 | # elif defined(__powerpc__) |
105 | # define __NR_copy_file_range 379 |
106 | # elif defined(__arc__) |
107 | # define __NR_copy_file_range 285 |
108 | # endif |
109 | #endif /* __NR_copy_file_range */ |
110 | |
111 | #ifndef __NR_statx |
112 | # if defined(__x86_64__) |
113 | # define __NR_statx 332 |
114 | # elif defined(__i386__) |
115 | # define __NR_statx 383 |
116 | # elif defined(__aarch64__) |
117 | # define __NR_statx 397 |
118 | # elif defined(__arm__) |
119 | # define __NR_statx (UV_SYSCALL_BASE + 397) |
120 | # elif defined(__ppc__) |
121 | # define __NR_statx 383 |
122 | # elif defined(__s390__) |
123 | # define __NR_statx 379 |
124 | # endif |
125 | #endif /* __NR_statx */ |
126 | |
127 | #ifndef __NR_getrandom |
128 | # if defined(__x86_64__) |
129 | # define __NR_getrandom 318 |
130 | # elif defined(__i386__) |
131 | # define __NR_getrandom 355 |
132 | # elif defined(__aarch64__) |
133 | # define __NR_getrandom 384 |
134 | # elif defined(__arm__) |
135 | # define __NR_getrandom (UV_SYSCALL_BASE + 384) |
136 | # elif defined(__ppc__) |
137 | # define __NR_getrandom 359 |
138 | # elif defined(__s390__) |
139 | # define __NR_getrandom 349 |
140 | # endif |
141 | #endif /* __NR_getrandom */ |
142 | |
143 | struct uv__mmsghdr; |
144 | |
145 | int uv__sendmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { |
146 | #if defined(__i386__) |
147 | unsigned long args[4]; |
148 | int rc; |
149 | |
150 | args[0] = (unsigned long) fd; |
151 | args[1] = (unsigned long) mmsg; |
152 | args[2] = (unsigned long) vlen; |
153 | args[3] = /* flags */ 0; |
154 | |
155 | /* socketcall() raises EINVAL when SYS_SENDMMSG is not supported. */ |
156 | rc = syscall(/* __NR_socketcall */ 102, 20 /* SYS_SENDMMSG */, args); |
157 | if (rc == -1) |
158 | if (errno == EINVAL) |
159 | errno = ENOSYS; |
160 | |
161 | return rc; |
162 | #elif defined(__NR_sendmmsg) |
163 | return syscall(__NR_sendmmsg, fd, mmsg, vlen, /* flags */ 0); |
164 | #else |
165 | return errno = ENOSYS, -1; |
166 | #endif |
167 | } |
168 | |
169 | |
170 | int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { |
171 | #if defined(__i386__) |
172 | unsigned long args[5]; |
173 | int rc; |
174 | |
175 | args[0] = (unsigned long) fd; |
176 | args[1] = (unsigned long) mmsg; |
177 | args[2] = (unsigned long) vlen; |
178 | args[3] = /* flags */ 0; |
179 | args[4] = /* timeout */ 0; |
180 | |
181 | /* socketcall() raises EINVAL when SYS_RECVMMSG is not supported. */ |
182 | rc = syscall(/* __NR_socketcall */ 102, 19 /* SYS_RECVMMSG */, args); |
183 | if (rc == -1) |
184 | if (errno == EINVAL) |
185 | errno = ENOSYS; |
186 | |
187 | return rc; |
188 | #elif defined(__NR_recvmmsg) |
189 | return syscall(__NR_recvmmsg, fd, mmsg, vlen, /* flags */ 0, /* timeout */ 0); |
190 | #else |
191 | return errno = ENOSYS, -1; |
192 | #endif |
193 | } |
194 | |
195 | |
196 | ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { |
197 | #if !defined(__NR_preadv) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 |
198 | return errno = ENOSYS, -1; |
199 | #else |
200 | return syscall(__NR_preadv, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); |
201 | #endif |
202 | } |
203 | |
204 | |
205 | ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset) { |
206 | #if !defined(__NR_pwritev) || defined(__ANDROID_API__) && __ANDROID_API__ < 24 |
207 | return errno = ENOSYS, -1; |
208 | #else |
209 | return syscall(__NR_pwritev, fd, iov, iovcnt, (long)offset, (long)(offset >> 32)); |
210 | #endif |
211 | } |
212 | |
213 | |
214 | int uv__dup3(int oldfd, int newfd, int flags) { |
215 | #if !defined(__NR_dup3) || defined(__ANDROID_API__) && __ANDROID_API__ < 21 |
216 | return errno = ENOSYS, -1; |
217 | #else |
218 | return syscall(__NR_dup3, oldfd, newfd, flags); |
219 | #endif |
220 | } |
221 | |
222 | |
223 | ssize_t |
224 | uv__fs_copy_file_range(int fd_in, |
225 | off_t* off_in, |
226 | int fd_out, |
227 | off_t* off_out, |
228 | size_t len, |
229 | unsigned int flags) |
230 | { |
231 | #ifdef __NR_copy_file_range |
232 | return syscall(__NR_copy_file_range, |
233 | fd_in, |
234 | off_in, |
235 | fd_out, |
236 | off_out, |
237 | len, |
238 | flags); |
239 | #else |
240 | return errno = ENOSYS, -1; |
241 | #endif |
242 | } |
243 | |
244 | |
245 | int uv__statx(int dirfd, |
246 | const char* path, |
247 | int flags, |
248 | unsigned int mask, |
249 | struct uv__statx* statxbuf) { |
250 | #if !defined(__NR_statx) || defined(__ANDROID_API__) && __ANDROID_API__ < 30 |
251 | return errno = ENOSYS, -1; |
252 | #else |
253 | return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); |
254 | #endif |
255 | } |
256 | |
257 | |
258 | ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) { |
259 | #if !defined(__NR_getrandom) || defined(__ANDROID_API__) && __ANDROID_API__ < 28 |
260 | return errno = ENOSYS, -1; |
261 | #else |
262 | return syscall(__NR_getrandom, buf, buflen, flags); |
263 | #endif |
264 | } |
265 | |