1//! The Unix `ioctl` function is effectively lots of different functions hidden
2//! behind a single dynamic dispatch interface. In order to provide a type-safe
3//! API, rustix makes them all separate functions so that they can have
4//! dedicated static type signatures.
5//!
6//! Some ioctls, such as those related to filesystems, terminals, and
7//! processes, live in other top-level API modules.
8
9#![allow(unsafe_code)]
10
11use crate::{backend, io, ioctl};
12use backend::c;
13use backend::fd::AsFd;
14
15/// `ioctl(fd, FIOCLEX, NULL)`—Set the close-on-exec flag.
16///
17/// Also known as `fcntl(fd, F_SETFD, FD_CLOEXEC)`.
18///
19/// # References
20/// - [Winsock2]
21/// - [NetBSD]
22/// - [OpenBSD]
23///
24/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-ioctlsocket
25/// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS
26/// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS
27#[cfg(apple)]
28#[inline]
29#[doc(alias = "FIOCLEX")]
30#[doc(alias = "FD_CLOEXEC")]
31pub fn ioctl_fioclex<Fd: AsFd>(fd: Fd) -> io::Result<()> {
32 // SAFETY: FIOCLEX is a no-argument setter opcode.
33 unsafe {
34 let ctl = ioctl::NoArg::<ioctl::BadOpcode<{ c::FIOCLEX }>>::new();
35 ioctl::ioctl(fd, ctl)
36 }
37}
38
39/// `ioctl(fd, FIONBIO, &value)`—Enables or disables non-blocking mode.
40///
41/// # References
42/// - [Winsock2]
43/// - [NetBSD]
44/// - [OpenBSD]
45///
46/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes
47/// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS
48/// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS
49#[inline]
50#[doc(alias = "FIONBIO")]
51pub fn ioctl_fionbio<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> {
52 // SAFETY: FIONBIO is a pointer setter opcode.
53 unsafe {
54 let ctl: Setter, …> = ioctl::Setter::<ioctl::BadOpcode<{ c::FIONBIO }>, c::c_int>::new(input:value.into());
55 ioctl::ioctl(fd, ioctl:ctl)
56 }
57}
58
59/// `ioctl(fd, FIONREAD)`—Returns the number of bytes ready to be read.
60///
61/// The result of this function gets silently coerced into a C `int`
62/// by the OS, so it may contain a wrapped value.
63///
64/// # References
65/// - [Linux]
66/// - [Winsock2]
67/// - [FreeBSD]
68/// - [NetBSD]
69/// - [OpenBSD]
70///
71/// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_tty.2.html
72/// [Winsock2]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes
73/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=ioctl&sektion=2#GENERIC%09IOCTLS
74/// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS
75/// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS
76#[cfg(not(target_os = "espidf"))]
77#[inline]
78#[doc(alias = "FIONREAD")]
79pub fn ioctl_fionread<Fd: AsFd>(fd: Fd) -> io::Result<u64> {
80 // SAFETY: FIONREAD is a getter opcode that gets a c_int.
81 unsafe {
82 let ctl: Getter, …> = ioctl::Getter::<ioctl::BadOpcode<{ c::FIONREAD }>, c::c_int>::new();
83 ioctl::ioctl(fd, ctl).map(|n: i32| n as u64)
84 }
85}
86