| 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 | |
| 11 | use crate::{backend, io, ioctl}; |
| 12 | use backend::c; |
| 13 | use backend::fd::AsFd; |
| 14 | |
| 15 | /// `ioctl(fd, FIOCLEX, NULL)`—Set the close-on-exec flag. |
| 16 | /// |
| 17 | /// This is similar to `fcntl(fd, F_SETFD, FD_CLOEXEC)`, except that it avoids |
| 18 | /// clearing any other flags that might be set. |
| 19 | #[cfg (apple)] |
| 20 | #[inline ] |
| 21 | #[doc (alias = "FIOCLEX" )] |
| 22 | #[doc (alias = "FD_CLOEXEC" )] |
| 23 | pub fn ioctl_fioclex<Fd: AsFd>(fd: Fd) -> io::Result<()> { |
| 24 | // SAFETY: `FIOCLEX` is a no-argument setter opcode. |
| 25 | unsafe { |
| 26 | let ctl = ioctl::NoArg::<ioctl::BadOpcode<{ c::FIOCLEX }>>::new(); |
| 27 | ioctl::ioctl(fd, ctl) |
| 28 | } |
| 29 | } |
| 30 | |
| 31 | /// `ioctl(fd, FIONBIO, &value)`—Enables or disables non-blocking mode. |
| 32 | /// |
| 33 | /// # References |
| 34 | /// - [Winsock] |
| 35 | /// - [NetBSD] |
| 36 | /// - [OpenBSD] |
| 37 | /// |
| 38 | /// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes |
| 39 | /// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS |
| 40 | /// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS |
| 41 | #[inline ] |
| 42 | #[doc (alias = "FIONBIO" )] |
| 43 | pub fn ioctl_fionbio<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> { |
| 44 | // SAFETY: `FIONBIO` is a pointer setter opcode. |
| 45 | unsafe { |
| 46 | let ctl: Setter, i32> = ioctl::Setter::<ioctl::BadOpcode<{ c::FIONBIO }>, c::c_int>::new(input:value.into()); |
| 47 | ioctl::ioctl(fd, ioctl:ctl) |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | /// `ioctl(fd, FIONREAD)`—Returns the number of bytes ready to be read. |
| 52 | /// |
| 53 | /// The result of this function gets silently coerced into a C `int` by the OS, |
| 54 | /// so it may contain a wrapped value. |
| 55 | /// |
| 56 | /// # References |
| 57 | /// - [Linux] |
| 58 | /// - [Winsock] |
| 59 | /// - [FreeBSD] |
| 60 | /// - [NetBSD] |
| 61 | /// - [OpenBSD] |
| 62 | /// |
| 63 | /// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_tty.2.html |
| 64 | /// [Winsock]: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#unix-ioctl-codes |
| 65 | /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=ioctl&sektion=2#GENERIC%09IOCTLS |
| 66 | /// [NetBSD]: https://man.netbsd.org/ioctl.2#GENERIC%20IOCTLS |
| 67 | /// [OpenBSD]: https://man.openbsd.org/ioctl.2#GENERIC_IOCTLS |
| 68 | #[cfg (not(any(target_os = "espidf" , target_os = "horizon" , target_os = "vita" )))] |
| 69 | #[inline ] |
| 70 | #[doc (alias = "FIONREAD" )] |
| 71 | pub fn ioctl_fionread<Fd: AsFd>(fd: Fd) -> io::Result<u64> { |
| 72 | // SAFETY: `FIONREAD` is a getter opcode that gets a `c_int`. |
| 73 | unsafe { |
| 74 | let ctl: Getter, i32> = ioctl::Getter::<ioctl::BadOpcode<{ c::FIONREAD }>, c::c_int>::new(); |
| 75 | ioctl::ioctl(fd, ctl).map(|n: i32| n as u64) |
| 76 | } |
| 77 | } |
| 78 | |