pub struct Ioctl<T: ?Sized = NoArgs> { /* private fields */ }Expand description
An ioctl.
Ioctl can represent ioctls 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 ioctls that require passing more than one argument to the
ioctl(2) function, Linux doesn’t have any ioctls 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 0x541BFrom 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) };Sourcepub const fn request(self) -> u32
pub const fn request(self) -> u32
Returns the ioctl request code.
This is passed to ioctl(2) as its second argument.
Note that the second argument of ioctl(2) may be int or unsigned long, depending on
target platform. Ioctl::ioctl will convert the type as needed, but user code that uses
Ioctl::request may have to do it manually.
This library always uses u32 in its interface because u32 is the smallest
platform-independent type capable of encoding every ioctl number used in Linux’ encoding
scheme.
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 ioctls 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 ioctls.
§Example
uinput defines several ioctls 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, that T
denotes the correct argument type, and that fd is valid (open) and 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, that T
denotes the correct argument type, and that fd is valid (open) and belongs to the driver
it expects.