1//! The Unix `fcntl` function is effectively lots of different functions
2//! hidden behind a single dynamic dispatch interface. In order to provide
3//! a type-safe API, rustix makes them all separate functions so that they
4//! can have dedicated static type signatures.
5
6#[cfg(not(any(
7 target_os = "emscripten",
8 target_os = "fuchsia",
9 target_os = "redox",
10 target_os = "wasi"
11)))]
12use crate::fs::FlockOperation;
13use crate::{backend, io};
14use backend::fd::AsFd;
15use backend::fs::types::OFlags;
16
17// These `fcntl` functions like in the `io` module because they're not specific
18// to files, directories, or memfd objects. We re-export them here in the `fs`
19// module because the other the `fcntl` functions are here.
20#[cfg(not(target_os = "wasi"))]
21pub use crate::io::fcntl_dupfd_cloexec;
22pub use crate::io::{fcntl_getfd, fcntl_setfd};
23
24/// `fcntl(fd, F_GETFL)`—Returns a file descriptor's access mode and status.
25///
26/// # References
27/// - [POSIX]
28/// - [Linux]
29///
30/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
31/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
32#[inline]
33#[doc(alias = "F_GETFL")]
34pub fn fcntl_getfl<Fd: AsFd>(fd: Fd) -> io::Result<OFlags> {
35 backend::fs::syscalls::fcntl_getfl(fd.as_fd())
36}
37
38/// `fcntl(fd, F_SETFL, flags)`—Sets a file descriptor's status.
39///
40/// # References
41/// - [POSIX]
42/// - [Linux]
43///
44/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
45/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
46#[inline]
47#[doc(alias = "F_SETFL")]
48pub fn fcntl_setfl<Fd: AsFd>(fd: Fd, flags: OFlags) -> io::Result<()> {
49 backend::fs::syscalls::fcntl_setfl(fd.as_fd(), flags)
50}
51
52/// `fcntl(fd, F_GET_SEALS)`
53///
54/// # References
55/// - [Linux]
56///
57/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
58#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))]
59#[inline]
60#[doc(alias = "F_GET_SEALS")]
61pub fn fcntl_get_seals<Fd: AsFd>(fd: Fd) -> io::Result<SealFlags> {
62 backend::fs::syscalls::fcntl_get_seals(fd.as_fd())
63}
64
65#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))]
66pub use backend::fs::types::SealFlags;
67
68/// `fcntl(fd, F_ADD_SEALS)`
69///
70/// # References
71/// - [Linux]
72///
73/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
74#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "fuchsia"))]
75#[inline]
76#[doc(alias = "F_ADD_SEALS")]
77pub fn fcntl_add_seals<Fd: AsFd>(fd: Fd, seals: SealFlags) -> io::Result<()> {
78 backend::fs::syscalls::fcntl_add_seals(fd.as_fd(), seals)
79}
80
81/// `fcntl(fd, F_SETLK)`—Acquire or release an `fcntl`-style lock.
82///
83/// This function doesn't currently have an offset or len; it currently always
84/// sets the `l_len` field to 0, which is a special case that means the entire
85/// file should be locked.
86///
87/// Unlike `flock`-style locks, `fcntl`-style locks are process-associated,
88/// meaning that they don't guard against being acquired by two threads in
89/// the same process.
90///
91/// # References
92/// - [POSIX]
93/// - [Linux]
94///
95/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html
96/// [Linux]: https://man7.org/linux/man-pages/man2/fcntl.2.html
97#[cfg(not(any(
98 target_os = "emscripten",
99 target_os = "fuchsia",
100 target_os = "redox",
101 target_os = "wasi"
102)))]
103#[inline]
104#[doc(alias = "F_SETLK")]
105#[doc(alias = "F_SETLKW")]
106pub fn fcntl_lock<Fd: AsFd>(fd: Fd, operation: FlockOperation) -> io::Result<()> {
107 backend::fs::syscalls::fcntl_lock(fd.as_fd(), operation)
108}
109