1 | //! Filesystem-oriented `ioctl` functions. |
2 | |
3 | #![allow (unsafe_code)] |
4 | |
5 | #[cfg (linux_kernel)] |
6 | use { |
7 | crate::fd::AsFd, |
8 | crate::{backend, io, ioctl}, |
9 | backend::c, |
10 | }; |
11 | |
12 | #[cfg (all(linux_kernel, not(any(target_arch = "sparc" , target_arch = "sparc64" ))))] |
13 | use crate::fd::{AsRawFd, BorrowedFd}; |
14 | |
15 | /// `ioctl(fd, BLKSSZGET)`—Returns the logical block size of a block device. |
16 | /// |
17 | /// This is mentioned in the [Linux `openat` manual page]. |
18 | /// |
19 | /// [Linux `openat` manual page]: https://man7.org/linux/man-pages/man2/openat.2.html |
20 | #[cfg (linux_kernel)] |
21 | #[inline ] |
22 | #[doc (alias = "BLKSSZGET" )] |
23 | pub fn ioctl_blksszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> { |
24 | // SAFETY: BLZSSZGET is a getter opcode that gets a u32. |
25 | unsafe { |
26 | let ctl: Getter, u32> = ioctl::Getter::<ioctl::BadOpcode<{ c::BLKSSZGET }>, c::c_uint>::new(); |
27 | ioctl::ioctl(fd, ioctl:ctl) |
28 | } |
29 | } |
30 | |
31 | /// `ioctl(fd, BLKPBSZGET)`—Returns the physical block size of a block device. |
32 | #[cfg (linux_kernel)] |
33 | #[inline ] |
34 | #[doc (alias = "BLKPBSZGET" )] |
35 | pub fn ioctl_blkpbszget<Fd: AsFd>(fd: Fd) -> io::Result<u32> { |
36 | // SAFETY: BLKPBSZGET is a getter opcode that gets a u32. |
37 | unsafe { |
38 | let ctl: Getter, u32> = ioctl::Getter::<ioctl::BadOpcode<{ c::BLKPBSZGET }>, c::c_uint>::new(); |
39 | ioctl::ioctl(fd, ioctl:ctl) |
40 | } |
41 | } |
42 | |
43 | /// `ioctl(fd, FICLONE, src_fd)`—Share data between open files. |
44 | /// |
45 | /// This ioctl is not available on Sparc platforms |
46 | /// |
47 | /// # References |
48 | /// - [Linux] |
49 | /// |
50 | /// [Linux]: https://man7.org/linux/man-pages/man2/ioctl_ficlone.2.html |
51 | #[cfg (all(linux_kernel, not(any(target_arch = "sparc" , target_arch = "sparc64" ))))] |
52 | #[inline ] |
53 | #[doc (alias = "FICLONE" )] |
54 | pub fn ioctl_ficlone<Fd: AsFd, SrcFd: AsFd>(fd: Fd, src_fd: SrcFd) -> io::Result<()> { |
55 | unsafe { ioctl::ioctl(fd, ioctl:Ficlone(src_fd.as_fd())) } |
56 | } |
57 | |
58 | /// `ioctl(fd, EXT4_IOC_RESIZE_FS, blocks)`—Resize ext4 filesystem on fd. |
59 | #[cfg (linux_kernel)] |
60 | #[inline ] |
61 | #[doc (alias = "EXT4_IOC_RESIZE_FS" )] |
62 | pub fn ext4_ioc_resize_fs<Fd: AsFd>(fd: Fd, blocks: u64) -> io::Result<()> { |
63 | // SAFETY: EXT4_IOC_RESIZE_FS is a pointer setter opcode. |
64 | unsafe { |
65 | let ctl: Setter, …> = ioctl::Setter::<ioctl::BadOpcode<{ backend::fs::EXT4_IOC_RESIZE_FS }>, u64>::new( |
66 | input:blocks, |
67 | ); |
68 | ioctl::ioctl(fd, ioctl:ctl) |
69 | } |
70 | } |
71 | |
72 | #[cfg (all(linux_kernel, not(any(target_arch = "sparc" , target_arch = "sparc64" ))))] |
73 | struct Ficlone<'a>(BorrowedFd<'a>); |
74 | |
75 | #[cfg (all(linux_kernel, not(any(target_arch = "sparc" , target_arch = "sparc64" ))))] |
76 | unsafe impl ioctl::Ioctl for Ficlone<'_> { |
77 | type Output = (); |
78 | |
79 | const IS_MUTATING: bool = false; |
80 | const OPCODE: ioctl::Opcode = ioctl::Opcode::old(raw:c::FICLONE as ioctl::RawOpcode); |
81 | |
82 | fn as_ptr(&mut self) -> *mut c::c_void { |
83 | self.0.as_raw_fd() as *mut c::c_void |
84 | } |
85 | |
86 | unsafe fn output_from_ptr( |
87 | _: ioctl::IoctlOutput, |
88 | _: *mut c::c_void, |
89 | ) -> io::Result<Self::Output> { |
90 | Ok(()) |
91 | } |
92 | } |
93 | |