linux-ioctl 0.2.0

Helpers for invoking `ioctl`s
Documentation
linux-ioctl-0.2.0 has been yanked.

linux-ioctl

Simple porting tools for Linux-style ioctl(2) driver interfaces.

Motivation

I mainly wrote this crate because I was unhappy with the alternatives:

  • libc::ioctl
    • The raw ioctl function provides no built-in error conversion and requires knowing the ioctl request number.
    • libc does provide const fns that mirror the _IOx macros, but they are only exposed on Linux and have no type safety.
  • nix::ioctl_X!
    • Looks nothing like the ioctl definitions found in C headers.
    • Requires very frequent conscious nix updates because it publishes A LOT of breaking changes.
  • Other crates for this are either abandoned or also frequently publish breaking changes that I'd have to consciously migrate to.
    • Instead, I want a crate that tries to only cover ioctls, and has a decently designed API that doesn't see much breakage.
  • Almost none of these alternatives except libc make translation of C headers to Rust very easy.
    • The Rust code required to do the thing often looks completely different to the equivalent C definitions.
    • As ioctls are a low-level interface often accessed by directly porting a C header, it is beneficial if the result is easy to visually compare to the original C code.

Thus, this library was born in an attempt to address these problems.

Example

Let's use uinput to create a userspace input device.

From linux/uinput.h:

/* ioctl */
#define UINPUT_IOCTL_BASE	'U'
#define UI_DEV_CREATE		_IO(UINPUT_IOCTL_BASE, 1)
#define UI_DEV_DESTROY		_IO(UINPUT_IOCTL_BASE, 2)
...
#define UI_DEV_SETUP _IOW(UINPUT_IOCTL_BASE, 3, struct uinput_setup)
use std::{mem, fs::File, ffi::c_char};
use libc::uinput_setup;
use linux_ioctl::{Ioctl, _IO, _IOW};

const UINPUT_IOCTL_BASE: u8 = b'U';
const UI_DEV_CREATE: Ioctl  = _IO(UINPUT_IOCTL_BASE, 1);
const UI_DEV_DESTROY: Ioctl = _IO(UINPUT_IOCTL_BASE, 2);
const UI_DEV_SETUP: Ioctl<*const uinput_setup> = _IOW(UINPUT_IOCTL_BASE, 3);

let uinput = File::options().write(true).open("/dev/uinput")?;

let mut setup: libc::uinput_setup = unsafe { mem::zeroed() };
setup.name[0] = b'A' as c_char; // (must not be blank)
unsafe {
    UI_DEV_SETUP.ioctl(&uinput, &setup)?;
    UI_DEV_CREATE.ioctl(&uinput)?;
    // ...use the device...
    UI_DEV_DESTROY.ioctl(&uinput)?;
}
std::io::Result::Ok(())

Rust Support

This library targets the latest Rust version.

Older Rust versions are supported by equally older versions of this crate. For example, to use a version of Rust that was succeeded 6 months ago, you'd also use an at least 6 month old version of this library.

Compatibility with older Rust versions may be provided on a best-effort basis.