pub struct Ioctl<T: ?Sized = NoArgs> { /* private fields */ }
Expand description
An ioctl
.
Ioctl
can represent ioctl
s that take either no arguments or a single argument.
If T
is NoArgs
, the ioctl
takes no arguments.
For other values of T
, the ioctl
takes T
as its only argument.
Often, the argument T
is a pointer to a struct that contains the actual arguments.
While Ioctl
cannot handle ioctl
s that require passing more than one argument to the
ioctl(2)
function, Linux doesn’t have any ioctl
s that take more than one argument, and is
unlikely to gain any in the future.
The Ioctl
type is constructed with the free functions _IO
, _IOR
, _IOW
,
_IOWR
, and _IOC
.
For legacy ioctls, it can also be created via Ioctl::from_raw
.
Implementations§
Source§impl<T: ?Sized> Ioctl<T>
impl<T: ?Sized> Ioctl<T>
Sourcepub const fn from_raw(request: u32) -> Self
pub const fn from_raw(request: u32) -> Self
Creates an Ioctl
object from a raw request code and an arbitrary argument type.
This can be used for legacy ioctls that were defined before the _IOx
macros were
introduced.
§Examples
From asm-generic/ioctls.h
:
#define FIONREAD 0x541B
From man 2const FIONREAD
:
DESCRIPTION
FIONREAD
Get the number of bytes in the input buffer.
...
SYNOPSIS
...
int ioctl(int fd, FIONREAD, int *argp);
...
use std::io;
use std::fs::File;
use std::ffi::c_int;
use linux_ioctl::*;
const FIONREAD: Ioctl<*mut c_int> = Ioctl::from_raw(0x541B);
let file = File::open("/dev/ptmx")
.map_err(|e| io::Error::new(e.kind(), format!("failed to open `/dev/ptmx`: {e}")))?;
let mut bytes = c_int::MAX;
unsafe { FIONREAD.ioctl(&file, &mut bytes)? };
assert_ne!(bytes, c_int::MAX);
println!("{} bytes in input buffer", bytes);
Sourcepub const fn with_arg<T2>(self) -> Ioctl<T2>
pub const fn with_arg<T2>(self) -> Ioctl<T2>
Changes the ioctl argument type to T2
.
This can be used for ioctls that incorrectly declare their type, or for ioctls that take
a by-value argument, rather than _IOW
-type ioctls that take their argument indirectly
through a pointer.
Returns an Ioctl
that passes an argument of type T2
to the kernel, while using the
ioctl request code from self
.
§Examples
The KVM_CREATE_VM
ioctl is declared with _IO
, but expects an int
argument to be
passed to ioctl(2)
, specifying the VM type (KVM_VM_*
).
From linux/kvm.h
:
#define KVMIO 0xAE
...
#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */
use std::fs::File;
use std::ffi::c_int;
use linux_ioctl::*;
const KVMIO: u8 = 0xAE;
const KVM_CREATE_VM: Ioctl<c_int> = _IO(KVMIO, 0x01).with_arg::<c_int>();
// The `KVM_CREATE_VM` ioctl takes the VM type as an argument. 0 is a reasonable default on
// most architectures.
let vm_type: c_int = 0;
let file = File::open("/dev/kvm")?;
let vm_fd = unsafe { KVM_CREATE_VM.ioctl(&file, vm_type)? };
println!("created new VM with file descriptor {vm_fd}");
unsafe { libc::close(vm_fd) };
Source§impl<T> Ioctl<*const T>
impl<T> Ioctl<*const T>
Sourcepub const fn with_direct_arg(self) -> Ioctl<T>
pub const fn with_direct_arg(self) -> Ioctl<T>
Changes the Ioctl
argument type to be passed directly instead of behind a pointer.
Does not change the request code.
Many linux headers define ioctl
s like _IOW('U', 100, int)
, but then expect the int
argument to be passed as a direct argument to ioctl(2)
instead of passing a pointer.
This method can be used to bind to these ioctl
s.
§Example
uinput
defines several ioctl
s where this method is useful:
#define UI_SET_EVBIT _IOW(UINPUT_IOCTL_BASE, 100, int)
use std::ffi::c_int;
use linux_ioctl::{Ioctl, _IOW};
const UI_SET_EVBIT: Ioctl<c_int> = _IOW(b'U', 100).with_direct_arg();
Sourcepub const fn cast_mut(self) -> Ioctl<*mut T>
pub const fn cast_mut(self) -> Ioctl<*mut T>
Casts the Ioctl
so that it takes a *mut
pointer instead of a *const
pointer.
This can be used to fix an ioctl
that is incorrectly declared as only reading its
argument through the pointer (with _IOW
), when in reality the kernel can write through
the pointer as well.
An ioctl that writes through its pointer argument, but is incorrectly declared as
Ioctl<*const T>
will generally cause UB when invoked with an immutable reference.
Also see Ioctl::cast_const
for the opposite direction.
§Example
The EVIOCSFF
ioctl from evdev is incorrectly declared with _IOW
, but may write to the
data, as documented here:
“request” must be EVIOCSFF.
“effect” points to a structure describing the effect to upload. The effect is uploaded, but not played. The content of effect may be modified.
https://www.kernel.org/doc/html/latest/input/ff.html
use std::ffi::c_void as ff_effect;
use linux_ioctl::{Ioctl, _IOW};
pub const EVIOCSFF: Ioctl<*mut ff_effect> = _IOW(b'E', 0x80).cast_mut();
Source§impl<T> Ioctl<*mut T>
impl<T> Ioctl<*mut T>
Sourcepub const fn cast_const(self) -> Ioctl<*const T>
pub const fn cast_const(self) -> Ioctl<*const T>
Casts the Ioctl
so that it takes a *const
pointer instead of a *mut
pointer.
This performs the opposite operation of Ioctl::cast_mut
, and can be used when an ioctl
is incorrectly declared as writing to its argument (yielding an Ioctl<*mut T>
) when it
actually only reads from it.
Only use this method if you are sure it is correct! If the ioctl
does write through the
pointer, the result is likely UB!
Source§impl Ioctl<NoArgs>
impl Ioctl<NoArgs>
Sourcepub unsafe fn ioctl(self, fd: &impl AsRawFd) -> Result<c_int>
pub unsafe fn ioctl(self, fd: &impl AsRawFd) -> Result<c_int>
Performs an ioctl that doesn’t take an argument.
On success, returns the value returned by the ioctl
syscall. On error (when ioctl
returns -1), returns the error from errno.
Note that the actual ioctl(2)
call performed will pass 0 as a dummy argument to the
ioctl. This is because some Linux ioctls are declared without an argument, but will fail
unless they receive 0 as their argument (eg. KVM_GET_API_VERSION
). There should be no harm
in passing this argument unconditionally, as the kernel will typically just ignore excess
arguments.
§Safety
This method performs an arbitrary ioctl on an arbitrary file descriptor.
The caller has to ensure that any safety requirements of the ioctl are met, and that fd
belongs to the driver it expects.
Source§impl<T> Ioctl<T>
impl<T> Ioctl<T>
Sourcepub unsafe fn ioctl(self, fd: &impl AsRawFd, arg: T) -> Result<c_int>
pub unsafe fn ioctl(self, fd: &impl AsRawFd, arg: T) -> Result<c_int>
Performs an ioctl that takes an argument of type T
.
Returns the value returned by the ioctl(2)
invocation, or an I/O error if the call failed.
For many ioctls, T
will be a pointer to the actual argument.
The caller must ensure that it points to valid data that conforms to the requirements of the
ioctl.
§Safety
This method performs an arbitrary ioctl on an arbitrary file descriptor.
The caller has to ensure that any safety requirements of the ioctl are met, and that fd
belongs to the driver it expects.