linux_unsafe/
funcs.rs

1use core::ffi;
2
3use super::raw;
4use super::result::{prepare_arg as arg, prepare_standard_result as mkresult, Result};
5use super::types::*;
6
7macro_rules! syscall {
8    ($n:expr) => {
9        mkresult(raw::syscall0($n))
10    };
11    ($n:expr, $a0:expr) => {
12        mkresult(raw::syscall1($n, arg($a0)))
13    };
14    ($n:expr, $a0:expr, $a1:expr) => {
15        mkresult(raw::syscall2($n, arg($a0), arg($a1)))
16    };
17    ($n:expr, $a0:expr, $a1:expr, $a2:expr) => {
18        mkresult(raw::syscall3($n, arg($a0), arg($a1), arg($a2)))
19    };
20    ($n:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
21        mkresult(raw::syscall4($n, arg($a0), arg($a1), arg($a2), arg($a3)))
22    };
23    ($n:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
24        mkresult(raw::syscall5(
25            $n,
26            arg($a0),
27            arg($a1),
28            arg($a2),
29            arg($a3),
30            arg($a4),
31        ))
32    };
33    ($n:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
34        mkresult(raw::syscall6(
35            $n,
36            arg($a0),
37            arg($a1),
38            arg($a2),
39            arg($a3),
40            arg($a4),
41            arg($a5),
42        ))
43    };
44}
45
46/// Accept a connection on a socket.
47#[cfg(have_syscall = "accept")]
48#[inline(always)]
49pub unsafe fn accept(sockfd: int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> Result<int> {
50    syscall!(raw::ACCEPT, sockfd, addr as *const void, addrlen)
51}
52
53/// Accept a connection on a socket with additional flags.
54#[cfg(have_syscall = "accept4")]
55#[inline(always)]
56pub unsafe fn accept4(
57    sockfd: int,
58    addr: *mut sockaddr,
59    addrlen: *mut socklen_t,
60    flags: int,
61) -> Result<int> {
62    syscall!(raw::ACCEPT4, sockfd, addr as *const void, addrlen, flags)
63}
64
65/// Check user's permissions for a file.
66#[cfg(have_syscall = "access")]
67#[inline(always)]
68pub unsafe fn access(pathname: *const char, mode: int) -> Result<int> {
69    syscall!(raw::ACCESS, pathname, mode)
70}
71
72/// Switch process accounting on or off.
73#[cfg(have_syscall = "acct")]
74#[inline(always)]
75pub unsafe fn acct(filename: *const char) -> Result<int> {
76    syscall!(raw::ACCT, filename)
77}
78
79/// Set an alarm clock for delivery of a signal.
80#[cfg(have_syscall = "alarm")]
81#[inline(always)]
82pub unsafe fn alarm(seconds: uint) -> uint {
83    use crate::args::AsRawV;
84    uint::from_raw_result(raw::syscall1(raw::ALARM, arg(seconds)))
85}
86
87/// Bind a name to a socket.
88#[cfg(have_syscall = "bind")]
89#[inline(always)]
90pub unsafe fn bind(sockfd: int, addr: *const sockaddr, addrlen: socklen_t) -> Result<int> {
91    syscall!(raw::BIND, sockfd, addr as *const void, addrlen)
92}
93
94/// Set the program break.
95#[cfg(have_syscall = "brk")]
96#[inline(always)]
97pub unsafe fn brk(brk: ulong) -> long {
98    use crate::args::AsRawV;
99    long::from_raw_result(raw::syscall1(raw::BRK, arg(brk)))
100}
101
102/// Change working directory.
103#[cfg(have_syscall = "chdir")]
104#[inline(always)]
105pub unsafe fn chdir(path: *const char) -> Result<int> {
106    syscall!(raw::CHDIR, path)
107}
108
109/// Change permissions of a file.
110#[cfg(have_syscall = "chmod")]
111#[inline(always)]
112pub unsafe fn chmod(pathname: *const char, mode: mode_t) -> Result<int> {
113    syscall!(raw::CHMOD, pathname, mode)
114}
115
116/// Change ownership of a file.
117#[cfg(all(have_syscall = "chown", not(have_syscall = "chown32")))]
118#[inline(always)]
119pub unsafe fn chown(pathname: *const char, owner: uid_t, group: gid_t) -> Result<int> {
120    syscall!(raw::CHOWN, pathname, owner, group)
121}
122
123/// Change ownership of a file.
124///
125/// On this platform this is actually a wrapper around the `chown32` system call.
126#[cfg(have_syscall = "chown32")]
127#[inline(always)]
128pub unsafe fn chown(pathname: *const char, owner: uid_t, group: gid_t) -> Result<int> {
129    syscall!(raw::CHOWN32, pathname, owner, group)
130}
131
132/// Change the root directory.
133#[cfg(have_syscall = "chroot")]
134#[inline(always)]
135pub unsafe fn chroot(path: *const char) -> Result<int> {
136    syscall!(raw::CHROOT, path)
137}
138
139/// Close a file.
140#[cfg(have_syscall = "close")]
141#[inline(always)]
142pub unsafe fn close(fd: int) -> Result<int> {
143    syscall!(raw::CLOSE, fd)
144}
145
146/// Close all file descriptors in a given range.
147#[cfg(have_syscall = "close_range")]
148#[inline(always)]
149pub unsafe fn close_range(first: int, last: int, flags: uint) -> Result<int> {
150    syscall!(raw::CLOSE_RANGE, first, last, flags)
151}
152
153/// Initiate a connection on a socket.
154#[cfg(have_syscall = "connect")]
155#[inline(always)]
156pub unsafe fn connect(sockfd: int, addr: *const sockaddr, addrlen: socklen_t) -> Result<int> {
157    syscall!(raw::CONNECT, sockfd, addr as *const void, addrlen)
158}
159
160/// Create a file.
161#[cfg(have_syscall = "creat")]
162#[inline(always)]
163pub unsafe fn creat(pathname: *const char, mode: mode_t) -> Result<int> {
164    syscall!(raw::CREAT, pathname, mode)
165}
166
167/// Duplicate a file descriptor.
168#[cfg(have_syscall = "dup")]
169#[inline(always)]
170pub unsafe fn dup(oldfd: int) -> Result<int> {
171    syscall!(raw::DUP, oldfd)
172}
173
174/// Duplicate a file descriptor.
175#[cfg(have_syscall = "dup2")]
176#[inline(always)]
177pub unsafe fn dup2(oldfd: int, newfd: int) -> Result<int> {
178    syscall!(raw::DUP2, oldfd, newfd)
179}
180
181/// Duplicate a file descriptor.
182#[cfg(have_syscall = "dup3")]
183#[inline(always)]
184pub unsafe fn dup3(oldfd: int, newfd: int, flags: int) -> Result<int> {
185    syscall!(raw::DUP3, oldfd, newfd, flags)
186}
187
188/// Open an epoll file descriptor.
189#[cfg(have_syscall = "epoll_create")]
190#[inline(always)]
191pub unsafe fn epoll_create(size: int) -> Result<int> {
192    syscall!(raw::EPOLL_CREATE, size)
193}
194
195/// Open an epoll file descriptor.
196#[cfg(have_syscall = "epoll_create1")]
197#[inline(always)]
198pub unsafe fn epoll_create1(flags: int) -> Result<int> {
199    syscall!(raw::EPOLL_CREATE1, flags)
200}
201
202/// Control interface for an epoll file descriptor.
203#[cfg(have_syscall = "epoll_ctl")]
204#[inline(always)]
205pub unsafe fn epoll_ctl(epfd: int, op: int, fd: int, event: *const epoll_event) -> Result<int> {
206    syscall!(raw::EPOLL_CTL, epfd, op, fd, event)
207}
208
209/// Wait for an I/O event on an epoll file descriptor.
210#[cfg(have_syscall = "epoll_wait")]
211#[inline(always)]
212pub unsafe fn epoll_wait(
213    epfd: int,
214    events: *const epoll_event,
215    maxevents: int,
216    timeout: int,
217) -> Result<int> {
218    syscall!(raw::EPOLL_WAIT, epfd, events, maxevents, timeout)
219}
220
221/// Create a file descriptor for event notification.
222#[cfg(have_syscall = "eventfd")]
223#[inline(always)]
224pub unsafe fn eventfd(initval: uint) -> Result<int> {
225    syscall!(raw::EVENTFD, initval)
226}
227
228/// Create a file descriptor for event notification.
229#[cfg(have_syscall = "eventfd2")]
230#[inline(always)]
231pub unsafe fn eventfd2(initval: uint, flags: int) -> Result<int> {
232    syscall!(raw::EVENTFD2, initval, flags)
233}
234
235/// Immediately terminate the current thread, without giving Rust or libc
236/// any opportunity to run destructors or other cleanup code.
237#[cfg(have_syscall = "exit")]
238#[inline(always)]
239pub unsafe fn exit(status: int) -> ! {
240    raw::syscall1(raw::EXIT, arg(status));
241    unreachable!()
242}
243
244/// Immediately terminate all threads in the current process's thread group,
245/// without giving Rust or libc any opportunity to run destructors or other
246/// cleanup code.
247#[cfg(have_syscall = "exit_group")]
248#[inline(always)]
249pub unsafe fn exit_group(status: int) -> ! {
250    raw::syscall1(raw::EXIT_GROUP, arg(status));
251    unreachable!()
252}
253
254/// Check user's permissions for a file.
255#[cfg(have_syscall = "faccessat")]
256#[inline(always)]
257pub unsafe fn faccessat(dirfd: int, pathname: *const char, mode: int) -> Result<int> {
258    syscall!(raw::FACCESSAT, dirfd, pathname, mode)
259}
260
261/// Check user's permissions for a file.
262#[cfg(have_syscall = "faccessat2")]
263#[inline(always)]
264pub unsafe fn faccessat2(dirfd: int, pathname: *const char, mode: int, flags: int) -> Result<int> {
265    syscall!(raw::FACCESSAT2, dirfd, pathname, mode, flags)
266}
267
268/// Change working directory.
269#[cfg(have_syscall = "fchdir")]
270#[inline(always)]
271pub unsafe fn fchdir(fd: int) -> Result<int> {
272    syscall!(raw::FCHDIR, fd)
273}
274
275/// Change permissions of a file.
276#[cfg(have_syscall = "fchmod")]
277#[inline(always)]
278pub unsafe fn fchmod(fd: int, mode: mode_t) -> Result<int> {
279    syscall!(raw::FCHMOD, fd, mode)
280}
281
282/// Change permissions of a file.
283#[cfg(have_syscall = "fchmodat")]
284#[inline(always)]
285pub unsafe fn fchmodat(dirfd: int, pathname: *const char, mode: mode_t) -> Result<int> {
286    syscall!(raw::FCHMODAT, dirfd, pathname, mode)
287}
288
289/// Change ownership of a file.
290#[cfg(have_syscall = "fchown")]
291#[inline(always)]
292pub unsafe fn fchown(fd: int, owner: uid_t, group: gid_t) -> Result<int> {
293    syscall!(raw::FCHOWN, fd, owner, group)
294}
295
296/// Change ownership of a file.
297#[cfg(have_syscall = "fchownat")]
298#[inline(always)]
299pub unsafe fn fchownat(
300    dirfd: int,
301    pathname: *const char,
302    owner: uid_t,
303    group: gid_t,
304) -> Result<int> {
305    syscall!(raw::FCHOWN, dirfd, pathname, owner, group)
306}
307
308/// Manipulate characteristics of a file descriptor.
309///
310/// This system call is _particularly_ unsafe, because the final argument
311/// gets interpreted in very different ways depending on the value of
312/// the `cmd` argument. Callers must take care to ensure that `arg` is of
313/// an appropriate type and value for the selected `cmd`.
314///
315/// Set `arg` to `()` (empty tuple) for commands whose argument is specified
316/// as "void" in the documentation.
317#[cfg(have_syscall = "fcntl")]
318#[inline(always)]
319pub unsafe fn fcntl(fd: int, cmd: int, arg: impl crate::args::AsRawV) -> Result<int> {
320    if arg.raw_is_void() {
321        syscall!(raw::FCNTL, fd, cmd)
322    } else {
323        syscall!(raw::FCNTL, fd, cmd, arg)
324    }
325}
326
327/// Synchronize a file's in-core state with storage device.
328#[cfg(have_syscall = "fdatasync")]
329#[inline(always)]
330pub unsafe fn fdatasync(fd: int) -> Result<int> {
331    syscall!(raw::FDATASYNC, fd)
332}
333
334/// Synchronize a file's in-core state with storage device.
335#[cfg(have_syscall = "fsync")]
336#[inline(always)]
337pub unsafe fn fsync(fd: int) -> Result<int> {
338    syscall!(raw::FSYNC, fd)
339}
340
341/// Truncate a file to a specified length.
342#[cfg(have_syscall = "ftruncate")]
343#[inline(always)]
344pub unsafe fn ftruncate(fd: int, length: off_t) -> Result<int> {
345    syscall!(raw::FTRUNCATE, fd, length)
346}
347
348/// Interact with the kernel's "fast userspace locking" mechanism.
349#[cfg(have_syscall = "futex")]
350#[inline(always)]
351pub unsafe fn futex(
352    uaddr: *const u32,
353    futex_op: int,
354    val: impl crate::args::AsRawV,
355    val2: impl crate::args::AsRawV,
356    uaddr2: *const u32,
357    val3: impl crate::args::AsRawV,
358) -> Result<int> {
359    syscall!(raw::FUTEX, uaddr, futex_op, val, val2, uaddr2, val3)
360}
361
362/// Determine CPU and NUMA node on which the calling thread is running.
363#[cfg(have_syscall = "getcpu")]
364#[inline(always)]
365pub unsafe fn getcpu(cpu: *const uint, node: *const uint) -> Result<int> {
366    syscall!(raw::GETCPU, cpu, node)
367}
368
369/// Get current working directory.
370#[cfg(have_syscall = "getcwd")]
371#[inline(always)]
372pub unsafe fn getcwd(buf: *mut char, size: size_t) -> Result<*mut char> {
373    syscall!(raw::GETCWD, buf, size)
374}
375
376/// Get directory entries.
377///
378/// Up to `count` bytes will be written starting at pointer `dirp`. The data
379/// written there will be a series of variable-sized [`linux_dirent`] values,
380/// and the return value is the number of bytes of the buffer that represent
381/// valid entries of that type.
382#[cfg(have_syscall = "getdents")]
383#[inline(always)]
384pub unsafe fn getdents(fd: int, dirp: *mut void, count: int) -> Result<int> {
385    syscall!(raw::GETDENTS, fd, dirp as *mut void, count)
386}
387
388/// Get directory entries using the new 64-bit structure type.
389///
390/// Up to `count` bytes will be written starting at pointer `dirp`. The data
391/// written there will be a series of variable-sized [`linux_dirent64`] values,
392/// and the return value is the number of bytes of the buffer that represent
393/// valid entries of that type.
394#[cfg(have_syscall = "getdents64")]
395#[inline(always)]
396pub unsafe fn getdents64(fd: int, dirp: *mut void, count: int) -> Result<int> {
397    syscall!(raw::GETDENTS64, fd, dirp as *mut void, count)
398}
399
400/// Get the effective group ID of the current process.
401#[cfg(have_syscall = "getegid")]
402#[inline(always)]
403pub unsafe fn getegid() -> gid_t {
404    raw::syscall0(raw::GETEGID) as gid_t
405}
406
407/// Get the effective user ID of the current process.
408#[cfg(have_syscall = "geteuid")]
409#[inline(always)]
410pub unsafe fn geteuid() -> uid_t {
411    raw::syscall0(raw::GETEUID) as uid_t
412}
413
414/// Get the real group ID of the current process.
415#[cfg(have_syscall = "getgid")]
416#[inline(always)]
417pub unsafe fn getgid() -> gid_t {
418    raw::syscall0(raw::GETGID) as gid_t
419}
420
421/// Get the supplementary group IDs of the current process.
422///
423/// `size` is the number of `gid_t` values that could fit in the buffer that
424/// `list` points to. The return value is the number of values actually written.
425#[cfg(have_syscall = "getgroups")]
426#[inline(always)]
427pub unsafe fn getgroups(size: int, list: *mut gid_t) -> Result<int> {
428    syscall!(raw::GETGROUPS, size, list)
429}
430
431/// Get the address of the peer connected to a socket.
432///
433/// Socket addresses have varying lengths depending on address family. Callers
434/// should pass a buffer of the appropriate size for the socket's address
435/// family and indicate that buffer size in `addrlen`.
436///
437/// Updates the value at `addrlen` to reflect the number of bytes actually
438/// needed, which might be longer than the given `addrlen` if the given buffer
439/// is too short for the address, in which case the value written to `addr` is
440/// truncated to fit.
441#[cfg(have_syscall = "getpeername")]
442#[inline(always)]
443pub unsafe fn getpeername(
444    sockfd: int,
445    addr: *mut sockaddr,
446    addrlen: *mut socklen_t,
447) -> Result<int> {
448    syscall!(raw::GETPEERNAME, sockfd, addr as *mut void, addrlen)
449}
450
451/// Get the process id (PID) of the current process.
452#[cfg(have_syscall = "getpid")]
453#[inline(always)]
454pub unsafe fn getpid() -> pid_t {
455    raw::syscall0(raw::GETPID) as pid_t
456}
457
458/// Get the process id (PID) of the parent of the current process.
459#[cfg(have_syscall = "getppid")]
460#[inline(always)]
461pub unsafe fn getppid() -> pid_t {
462    raw::syscall0(raw::GETPPID) as pid_t
463}
464
465/// Get random bytes from the kernel.
466#[cfg(have_syscall = "getrandom")]
467#[inline(always)]
468pub unsafe fn getrandom(buf: *mut void, buflen: size_t, flags: uint) -> Result<int> {
469    syscall!(raw::GETRANDOM, buf, buflen, flags)
470}
471
472/// Get the real GID, the effective GID, and the saved set-group-ID of the
473/// current process.
474#[cfg(all(have_syscall = "getresgid", not(have_syscall = "getresgid32")))]
475#[inline(always)]
476pub unsafe fn getresgid(rgid: *mut gid_t, egid: *mut gid_t, sgid: *mut gid_t) -> Result<int> {
477    syscall!(raw::GETRESGID, rgid, egid, sgid)
478}
479
480/// Get the real UID, the effective UID, and the saved set-user-ID of the
481/// current process.
482///
483/// On this platform this function actually wraps the `getresgid32` system call.
484#[cfg(all(have_syscall = "getresgid32"))]
485#[inline(always)]
486pub unsafe fn getresgid(rgid: *mut gid_t, egid: *mut gid_t, sgid: *mut gid_t) -> Result<int> {
487    syscall!(raw::GETRESGID32, rgid, egid, sgid)
488}
489
490/// Get the real UID, the effective UID, and the saved set-user-ID of the
491/// current process.
492#[cfg(all(have_syscall = "getresuid", not(have_syscall = "getresuid32")))]
493#[inline(always)]
494pub unsafe fn getresuid(ruid: *mut uid_t, euid: *mut uid_t, suid: *mut uid_t) -> Result<int> {
495    syscall!(raw::GETRESUID, ruid, euid, suid)
496}
497
498/// Get the real UID, the effective UID, and the saved set-user-ID of the
499/// current process.
500///
501/// On this platform this function actually wraps the `getresuid32` system call.
502#[cfg(all(have_syscall = "getresuid32"))]
503#[inline(always)]
504pub unsafe fn getresuid(ruid: *mut uid_t, euid: *mut uid_t, suid: *mut uid_t) -> Result<int> {
505    syscall!(raw::GETRESUID32, ruid, euid, suid)
506}
507
508/// Get the session ID of a process, or of the current process if `pid` is zero.
509#[cfg(have_syscall = "getsid")]
510#[inline(always)]
511pub unsafe fn getsid(pid: pid_t) -> Result<pid_t> {
512    syscall!(raw::GETSID, pid)
513}
514
515/// Get the address that a socket is bound to.
516///
517/// Socket addresses have varying lengths depending on address family. Callers
518/// should pass a buffer of the appropriate size for the socket's address
519/// family and indicate that buffer size in `addrlen`.
520///
521/// Updates the value at `addrlen` to reflect the number of bytes actually
522/// needed, which might be longer than the given `addrlen` if the given buffer
523/// is too short for the address, in which case the value written to `addr` is
524/// truncated to fit.
525#[cfg(have_syscall = "getsockname")]
526#[inline(always)]
527pub unsafe fn getsockname(
528    sockfd: int,
529    addr: *mut sockaddr,
530    addrlen: *mut socklen_t,
531) -> Result<int> {
532    syscall!(raw::GETSOCKNAME, sockfd, addr as *mut void, addrlen)
533}
534
535/// Get a socket option.
536#[cfg(have_syscall = "getsockopt")]
537#[inline(always)]
538pub unsafe fn getsockopt(
539    sockfd: int,
540    level: int,
541    optname: int,
542    optval: *mut void,
543    optlen: *mut socklen_t,
544) -> Result<int> {
545    syscall!(raw::GETSOCKOPT, sockfd, level, optname, optval, optlen)
546}
547
548/// Get the thread id (TID) of the current process.
549#[cfg(have_syscall = "gettid")]
550#[inline(always)]
551pub unsafe fn gettid() -> pid_t {
552    raw::syscall0(raw::GETTID) as pid_t
553}
554
555/// Get the real user ID of the current process.
556#[cfg(all(have_syscall = "getuid", not(have_syscall = "getuid32")))]
557#[inline(always)]
558pub unsafe fn getuid() -> uid_t {
559    raw::syscall0(raw::GETUID) as uid_t
560}
561
562/// Get the real user ID of the current process.
563///
564/// On this platform this function actually wraps the `getuid` system call.
565#[cfg(have_syscall = "getuid32")]
566#[inline(always)]
567pub unsafe fn getuid() -> uid_t {
568    raw::syscall0(raw::GETUID32) as uid_t
569}
570
571/// Adds a new watch, or modifies an existing watch, to an inotify event queue.
572///
573/// The return value is a "watch descriptor", which you can use to later remove
574/// the same watch with [`inotify_rm_watch`].
575#[cfg(have_syscall = "inotify_add_watch")]
576#[inline(always)]
577pub unsafe fn inotify_add_watch(fd: int, pathname: *const char, mask: u32) -> Result<int> {
578    syscall!(raw::INOTIFY_ADD_WATCH, fd, pathname, mask)
579}
580
581/// Initializes a new inotify instance and returns a file descriptor associated
582/// with a new inotify event queue.
583#[cfg(have_syscall = "inotify_init")]
584#[inline(always)]
585pub unsafe fn inotify_init() -> Result<int> {
586    syscall!(raw::INOTIFY_INIT)
587}
588
589/// Removes an existing watch from an inotify event queue.
590///
591/// `wd` is a "watch descriptor" returned from an earlier call to
592/// [`inotify_add_watch`].
593#[cfg(have_syscall = "inotify_rm_watch")]
594#[inline(always)]
595pub unsafe fn inotify_rm_watch(fd: int, wd: int) -> Result<int> {
596    syscall!(raw::INOTIFY_RM_WATCH, fd, wd)
597}
598
599/// Initializes a new inotify instance and returns a file descriptor associated
600/// with a new inotify event queue.
601#[cfg(have_syscall = "inotify_init1")]
602#[inline(always)]
603pub unsafe fn inotify_init1(flags: int) -> Result<int> {
604    syscall!(raw::INOTIFY_INIT1, flags)
605}
606
607/// Initiate and complete I/O using the shared submission and completion queues
608/// for an io_uring instance.
609#[cfg(have_syscall = "io_uring_enter")]
610#[inline(always)]
611pub unsafe fn io_uring_enter(
612    fd: int,
613    to_submit: uint,
614    min_complete: uint,
615    flags: uint,
616    sig: *mut sigset_t,
617) -> Result<int> {
618    syscall!(raw::IO_URING_ENTER, fd, to_submit, min_complete, flags, sig)
619}
620
621/// Initiate and complete I/O using the shared submission and completion queues
622/// for an io_uring instance.
623#[cfg(have_syscall = "io_uring_enter2")]
624#[inline(always)]
625pub unsafe fn io_uring_enter2(
626    fd: int,
627    to_submit: uint,
628    min_complete: uint,
629    flags: uint,
630    sig: *mut sigset_t,
631    sz: size_t,
632) -> Result<int> {
633    syscall!(
634        raw::IO_URING_ENTER2,
635        fd,
636        to_submit,
637        min_complete,
638        flags,
639        sig,
640        sz,
641    )
642}
643
644/// Registers resources for use with an io_uring instance.
645#[cfg(have_syscall = "io_uring_register")]
646#[inline(always)]
647pub unsafe fn io_uring_register(
648    fd: int,
649    opcode: uint,
650    arg: *mut void,
651    nr_args: uint,
652) -> Result<int> {
653    syscall!(raw::IO_URING_REGISTER, fd, opcode, arg, nr_args)
654}
655
656/// Sets up an io_uring instance.
657///
658/// The instance will have submission and completion queues of at least
659/// `entries` entries. The result is a file descriptor to be used with [`mmap`]
660/// to establish the shared memory buffers, and with [`io_uring_enter`] and
661/// [`io_uring_register`].
662#[cfg(have_syscall = "io_uring_setup")]
663#[inline(always)]
664pub unsafe fn io_uring_setup(entries: u32, p: *mut io_uring_params) -> Result<int> {
665    syscall!(raw::IO_URING_SETUP, entries, p)
666}
667
668/// Arbitrary requests for file descriptors representing devices.
669///
670/// This system call is _particularly_ unsafe, because the final argument
671/// gets interpreted in very different ways depending on the value of
672/// the `request` argument. Callers must take care to ensure that `request` is
673/// of an appropriate type and value for the selected `request`.
674///
675/// Set `arg` to `()` (empty tuple) for requests whose argument is specified
676/// as "void" in the documentation.
677#[cfg(have_syscall = "ioctl")]
678#[inline(always)]
679pub unsafe fn ioctl(fd: int, request: ulong, arg: impl crate::args::AsRawV) -> Result<int> {
680    if arg.raw_is_void() {
681        syscall!(raw::IOCTL, fd, request)
682    } else {
683        syscall!(raw::IOCTL, fd, request, arg)
684    }
685}
686
687/// Send a signal to a process.
688#[cfg(have_syscall = "kill")]
689#[inline(always)]
690pub unsafe fn kill(pid: pid_t, sig: int) -> Result<int> {
691    syscall!(raw::KILL, pid, sig)
692}
693
694/// Change ownership of a file without dereferencing symbolic links.
695#[cfg(all(have_syscall = "lchown", not(have_syscall = "lchown32")))]
696#[inline(always)]
697pub unsafe fn lchown(pathname: *const char, owner: uid_t, group: gid_t) -> Result<int> {
698    syscall!(raw::LCHOWN, pathname, owner, group)
699}
700
701/// Change ownership of a file without dereferencing symbolic links.
702///
703/// On this platform this is actually a wrapper around the `lchown32` system call.
704#[cfg(have_syscall = "lchown32")]
705#[inline(always)]
706pub unsafe fn lchown(pathname: *const char, owner: uid_t, group: gid_t) -> Result<int> {
707    syscall!(raw::LCHOWN32, pathname, owner, group)
708}
709
710/// Create a new link (a "hard link") for an existing file.
711#[cfg(have_syscall = "link")]
712#[inline(always)]
713pub unsafe fn link(oldpath: *const char, newpath: *const char) -> Result<int> {
714    syscall!(raw::LINK, oldpath, newpath)
715}
716
717/// Create a new link (a "hard link") for an existing file relative to
718/// directory file descriptors.
719#[cfg(have_syscall = "linkat")]
720#[inline(always)]
721pub unsafe fn linkat(
722    olddirfd: int,
723    oldpath: *const char,
724    newdirfd: int,
725    newpath: *const char,
726    flags: int,
727) -> Result<int> {
728    syscall!(raw::LINKAT, olddirfd, oldpath, newdirfd, newpath, flags)
729}
730
731/// Listen for connections on a socket.
732#[cfg(have_syscall = "listen")]
733#[inline(always)]
734pub unsafe fn listen(fd: int, backlog: int) -> Result<int> {
735    syscall!(raw::LISTEN, fd, backlog)
736}
737
738/// Reposition the read/write offset for a file.
739#[cfg(have_syscall = "lseek")]
740#[inline(always)]
741pub unsafe fn lseek(fd: int, offset: off_t, whence: int) -> Result<off_t> {
742    syscall!(raw::LSEEK, fd, offset, whence)
743}
744
745/// Map a file or device into memory.
746#[cfg(all(have_syscall = "mmap", not(have_syscall = "mmap2")))]
747#[inline(always)]
748pub unsafe fn mmap(
749    addr: *mut void,
750    length: size_t,
751    prot: int,
752    flags: int,
753    fd: int,
754    offset: off_t,
755) -> Result<*mut void> {
756    syscall!(raw::MMAP, addr, length, prot, flags, fd, offset)
757}
758
759/// Map a file or device into memory.
760///
761/// On this platform this actually wraps the `mmap2` system call, with the
762/// given offset adjusted to be a page-based rather than byte-based offset.
763#[cfg(have_syscall = "mmap2")]
764#[inline(always)]
765pub unsafe fn mmap(
766    addr: *mut void,
767    length: size_t,
768    prot: int,
769    flags: int,
770    fd: int,
771    offset: off_t,
772) -> Result<*mut void> {
773    // Note: Technically is isn't correct to just assume the page size is 4096,
774    // but in practice it is on all of the architectures we currently support
775    // that have MMAP2, so we can avoid the overhead of asking the kernel for
776    // its page size.
777    syscall!(raw::MMAP2, addr, length, prot, flags, fd, offset / 4096)
778}
779
780/// Remove a mapping previously created with [`mmap`].
781#[cfg(have_syscall = "munmap")]
782#[inline(always)]
783pub unsafe fn munmap(addr: *mut void, length: size_t) -> Result<*mut void> {
784    syscall!(raw::MUNMAP, addr, length)
785}
786
787/// Change a memory mapping previously created with [`mmap`].
788///
789/// The `new_address` argument is used only if `flags` includes `MREMAP_FIXED`.
790/// Set it to null if unused.
791#[cfg(have_syscall = "mremap")]
792#[inline(always)]
793pub unsafe fn mremap(
794    old_address: *mut void,
795    old_size: size_t,
796    new_size: size_t,
797    flags: int,
798    new_address: *mut void,
799) -> Result<*mut void> {
800    syscall!(
801        raw::MREMAP,
802        old_address,
803        old_size,
804        new_size,
805        flags,
806        new_address
807    )
808}
809
810/// Pause the current process until a signal is delivered.
811#[cfg(have_syscall = "pause")]
812#[inline(always)]
813pub unsafe fn pause() -> Result<int> {
814    syscall!(raw::PAUSE)
815}
816
817/// Open a file.
818///
819/// **Warning:** This function is not available on architectures recently added
820/// to the kernel. Use [`openat`] instead (using [`crate::AT_FDCWD`] as `dirfd`) for
821/// better portability.
822#[cfg(have_syscall = "open")]
823#[inline(always)]
824pub unsafe fn open(pathname: *const char, flags: int, mode: mode_t) -> Result<int> {
825    syscall!(raw::OPEN, pathname, flags, mode)
826}
827
828/// Open a file.
829#[cfg(have_syscall = "openat")]
830#[inline(always)]
831pub unsafe fn openat(dirfd: int, pathname: *const char, flags: int, mode: mode_t) -> Result<int> {
832    syscall!(raw::OPENAT, dirfd, pathname, flags, mode)
833}
834
835/// Create a file descriptor representing a process.
836#[cfg(have_syscall = "pidfd_open")]
837#[inline(always)]
838pub unsafe fn pidfd_open(pid: pid_t, flags: uint) -> Result<int> {
839    syscall!(raw::PIDFD_OPEN, pid, flags)
840}
841
842/// Create pipe.
843#[cfg(have_syscall = "pipe")]
844#[inline(always)]
845pub unsafe fn pipe(fds: *mut int) -> Result<int> {
846    syscall!(raw::PIPE, fds)
847}
848
849/// Create pipe.
850#[cfg(have_syscall = "pipe2")]
851#[inline(always)]
852pub unsafe fn pipe2(fds: *mut int, flags: int) -> Result<int> {
853    syscall!(raw::PIPE2, fds, flags)
854}
855
856/// Changes the root mount in the mount namespace of the calling process.
857#[cfg(have_syscall = "pivot_root")]
858#[inline(always)]
859pub unsafe fn pivot_root(new_root: *const char, put_old: *const char) -> Result<int> {
860    syscall!(raw::PIVOT_ROOT, new_root, put_old)
861}
862
863/// Wait for events on one or more file descriptors.
864#[cfg(have_syscall = "poll")]
865#[inline(always)]
866pub unsafe fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: int) -> Result<int> {
867    syscall!(raw::POLL, fds, nfds, timeout)
868}
869
870/// Wait for events on one or more file descriptors while also awaiting signals.
871#[cfg(have_syscall = "ppoll")]
872#[inline(always)]
873pub unsafe fn ppoll(
874    fds: *mut pollfd,
875    nfds: nfds_t,
876    tmo_p: *const timespec,
877    sigmask: *const sigset_t,
878) -> Result<int> {
879    syscall!(raw::PPOLL, fds, nfds, tmo_p, sigmask)
880}
881
882/// Manipulates various aspects of the behavior of the calling thread or process.
883#[cfg(have_syscall = "prctl")]
884#[inline(always)]
885pub unsafe fn prctl(
886    option: int,
887    arg2: ulong,
888    arg3: ulong,
889    arg4: ulong,
890    arg5: ulong,
891) -> Result<int> {
892    syscall!(raw::PRCTL, option, arg2, arg3, arg4, arg5)
893}
894
895/// Read from a file descriptor.
896#[cfg(have_syscall = "read")]
897#[inline(always)]
898pub unsafe fn read(fd: int, buf: *mut void, count: size_t) -> Result<ssize_t> {
899    syscall!(raw::READ, fd, buf, count)
900}
901
902/// Read value of a symbolic link.
903#[cfg(have_syscall = "readlink")]
904#[inline(always)]
905pub unsafe fn readlink(path: *const char, buf: *const char, bufsiz: size_t) -> Result<int> {
906    syscall!(raw::READLINK, path, buf, bufsiz)
907}
908
909/// Read value of a symbolic link relative to a directory file descriptor.
910#[cfg(have_syscall = "readlinkat")]
911#[inline(always)]
912pub unsafe fn readlinkat(
913    dirfd: int,
914    pathname: *const char,
915    buf: *mut char,
916    bufsiz: size_t,
917) -> Result<int> {
918    syscall!(raw::READLINKAT, dirfd, pathname, buf, bufsiz)
919}
920
921/// Read from a file descriptor into multiple buffers.
922#[cfg(have_syscall = "readv")]
923#[inline(always)]
924pub unsafe fn readv(fd: int, iov: *mut iovec, iovcount: int) -> Result<size_t> {
925    syscall!(raw::READV, fd, iov, iovcount)
926}
927
928/// Set a socket option.
929#[cfg(have_syscall = "setsockopt")]
930#[inline(always)]
931pub unsafe fn setsockopt(
932    sockfd: int,
933    level: int,
934    optname: int,
935    optval: *const void,
936    optlen: socklen_t,
937) -> Result<int> {
938    syscall!(raw::SETSOCKOPT, sockfd, level, optname, optval, optlen)
939}
940
941/// Copies data between one file descriptor and another.
942#[cfg(have_syscall = "sendfile")]
943#[inline(always)]
944pub unsafe fn sendfile(out_fd: int, in_fd: int, offset: *mut off_t, count: size_t) -> Result<int> {
945    syscall!(raw::SENDFILE, out_fd, in_fd, offset, count)
946}
947
948/// Copies data between one file descriptor and another.
949#[cfg(have_syscall = "sendfile64")]
950#[inline(always)]
951pub unsafe fn sendfile64(
952    out_fd: int,
953    in_fd: int,
954    offset: *mut loff_t,
955    count: size_t,
956) -> Result<int> {
957    syscall!(raw::SENDFILE64, out_fd, in_fd, offset, count)
958}
959
960/// Create a socket endpoint for communication.
961#[cfg(have_syscall = "socket")]
962#[inline(always)]
963pub unsafe fn socket(family: sa_family_t, typ: sock_type, protocol: int) -> Result<int> {
964    syscall!(raw::SOCKET, family, typ as u32, protocol)
965}
966
967/// Create an unnamed pair of connected sockets.
968#[cfg(have_syscall = "socketpair")]
969#[inline(always)]
970pub unsafe fn socketpair(
971    family: sa_family_t,
972    typ: sock_type,
973    protocol: int,
974    sv: *mut [int; 2],
975) -> Result<int> {
976    syscall!(raw::SOCKETPAIR, family, typ as u32, protocol, sv)
977}
978
979/// Moves data between two file descriptors without copying between kernel
980/// address space and user address space.
981#[cfg(have_syscall = "splice")]
982#[inline(always)]
983pub unsafe fn splice(
984    fd_in: int,
985    off_in: *mut off64_t,
986    fd_out: int,
987    off_out: *mut off64_t,
988    len: size_t,
989    flags: uint,
990) -> Result<int> {
991    syscall!(raw::SPLICE, fd_in, off_in, fd_out, off_out, len, flags)
992}
993
994/// Get file status, extended.
995#[cfg(have_syscall = "statx")]
996#[inline(always)]
997pub unsafe fn statx(
998    dirfd: int,
999    pathname: *const char,
1000    flags: int,
1001    mask: uint,
1002    statxbuf: *mut statx,
1003) -> Result<int> {
1004    syscall!(raw::STATX, dirfd, pathname, flags, mask, statxbuf)
1005}
1006
1007/// Commit all filesystem caches to disk.
1008#[cfg(have_syscall = "sync")]
1009#[inline(always)]
1010pub unsafe fn sync() {
1011    raw::syscall0(raw::SYNC);
1012}
1013
1014/// Commit filesystem caches to disk for the filesystem containing a particular file.
1015#[cfg(have_syscall = "syncfs")]
1016#[inline(always)]
1017pub unsafe fn syncfs(fd: int) -> Result<int> {
1018    syscall!(raw::SYNCFS, fd)
1019}
1020
1021/// Duplicates data between file descriptors without consuming the data at the source.
1022#[cfg(have_syscall = "tee")]
1023#[inline(always)]
1024pub unsafe fn tee(fd_in: int, fd_out: int, len: size_t, flags: uint) -> Result<int> {
1025    syscall!(raw::TEE, fd_in, fd_out, len, flags)
1026}
1027
1028/// Truncate a file to a specified length.
1029#[cfg(have_syscall = "truncate")]
1030#[inline(always)]
1031pub unsafe fn truncate(path: *const char, length: off_t) -> Result<int> {
1032    syscall!(raw::TRUNCATE, path, length)
1033}
1034
1035/// Write to a file descriptor.
1036#[cfg(have_syscall = "write")]
1037#[inline(always)]
1038pub unsafe fn write(fd: int, buf: *const ffi::c_void, count: size_t) -> Result<ssize_t> {
1039    syscall!(raw::WRITE, fd, buf, count)
1040}
1041
1042/// Write to a file descriptor from multiple buffers.
1043#[cfg(have_syscall = "writev")]
1044#[inline(always)]
1045pub unsafe fn writev(fd: int, iov: *const iovec, iovcount: int) -> Result<size_t> {
1046    syscall!(raw::WRITEV, fd, iov, iovcount)
1047}
1048
1049/// A special variant of [`lseek`] for 32-bit platforms that need the 64-bit
1050/// offset split into two arguments.
1051///
1052/// This function is not available at all on 64-bit platforms, because
1053/// `lseek` is sufficient for 64-bit offsets there.
1054#[cfg(have_syscall = "_llseek")]
1055#[inline(always)]
1056pub unsafe fn _llseek(
1057    fd: int,
1058    offset_high: ffi::c_ulong,
1059    offset_low: ffi::c_ulong,
1060    result: *mut loff_t,
1061    whence: uint,
1062) -> Result<int> {
1063    syscall!(raw::_LLSEEK, fd, offset_high, offset_low, result, whence)
1064}