1//! Filesystem-oriented `ioctl` functions.
2
3#![allow(unsafe_code)]
4
5#[cfg(linux_kernel)]
6use {
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"))))]
13use 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")]
23pub 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")]
35pub 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")]
54pub 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")]
62pub 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"))))]
73struct Ficlone<'a>(BorrowedFd<'a>);
74
75#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))]
76unsafe 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