Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the ioctl API and documentation #833

Merged
merged 3 commits into from
Apr 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#825](https://github.com/nix-rust/nix/pull/825))
- Added `fchmod`, `fchmodat`.
([#857](https://github.com/nix-rust/nix/pull/857))
- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD
([#833](https://github.com/nix-rust/nix/pull/833))

### Changed
- Display and Debug for SysControlAddr now includes all fields.
Expand All @@ -37,6 +39,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- Properly exposed 460800 and 921600 baud rates on NetBSD
([#837](https://github.com/nix-rust/nix/pull/837))
- Fixed `ioctl_write_int!` on FreeBSD/DragonFlyBSD
([#833](https://github.com/nix-rust/nix/pull/833))
- `ioctl_write_int!` now properly supports passing a `c_ulong` as the parameter on Linux non-musl targets
([#833](https://github.com/nix-rust/nix/pull/833))

### Removed
- Removed explicit support for the `bytes` crate from the `sys::aio` module.
Expand Down
102 changes: 102 additions & 0 deletions src/sys/ioctl/bsd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/// The datatype used for the ioctl number
#[doc(hidden)]
pub type ioctl_num_type = ::libc::c_ulong;
/// The datatype used for the 3rd argument
#[doc(hidden)]
pub type ioctl_param_type = ::libc::c_int;

mod consts {
use ::sys::ioctl::ioctl_num_type;
#[doc(hidden)]
pub const VOID: ioctl_num_type = 0x2000_0000;
#[doc(hidden)]
pub const OUT: ioctl_num_type = 0x4000_0000;
#[doc(hidden)]
pub const IN: ioctl_num_type = 0x8000_0000;
#[doc(hidden)]
pub const INOUT: ioctl_num_type = (IN|OUT);
#[doc(hidden)]
pub const IOCPARM_MASK: ioctl_num_type = 0x1fff;
}

pub use self::consts::*;

#[macro_export]
#[doc(hidden)]
macro_rules! ioc {
($inout:expr, $group:expr, $num:expr, $len:expr) => (
$inout | (($len as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::IOCPARM_MASK) << 16) | (($group as $crate::sys::ioctl::ioctl_num_type) << 8) | ($num as $crate::sys::ioctl::ioctl_num_type)
)
}

/// Generate an ioctl request code for a command that passes no data.
///
/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_none!()` directly.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate nix;
/// const KVMIO: u8 = 0xAE;
/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! request_code_none {
($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0))
}

/// Generate an ioctl request code for a command that passes an integer
///
/// This is equivalent to the `_IOWINT()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_write_int!()` directly.
#[macro_export]
macro_rules! request_code_write_int {
($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, ::std::mem::size_of::<$crate::libc::c_int>()))
}

/// Generate an ioctl request code for a command that reads.
///
/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_read!()` directly.
///
/// The read/write direction is relative to userland, so this
/// command would be userland is reading and the kernel is
/// writing.
#[macro_export]
macro_rules! request_code_read {
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::OUT, $g, $n, $len))
}

/// Generate an ioctl request code for a command that writes.
///
/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_write!()` directly.
///
/// The read/write direction is relative to userland, so this
/// command would be userland is writing and the kernel is
/// reading.
#[macro_export]
macro_rules! request_code_write {
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::IN, $g, $n, $len))
}

/// Generate an ioctl request code for a command that reads and writes.
///
/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
#[macro_export]
macro_rules! request_code_readwrite {
($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::INOUT, $g, $n, $len))
}
71 changes: 48 additions & 23 deletions src/sys/ioctl/platform/linux.rs → src/sys/ioctl/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ pub type ioctl_num_type = ::libc::c_int;
#[cfg(not(any(target_os = "android", target_env = "musl")))]
#[doc(hidden)]
pub type ioctl_num_type = ::libc::c_ulong;
/// The datatype used for the 3rd argument
#[doc(hidden)]
pub type ioctl_param_type = ::libc::c_ulong;

#[doc(hidden)]
pub const NRBITS: ioctl_num_type = 8;
Expand All @@ -25,17 +28,6 @@ mod consts {
pub const DIRBITS: u8 = 3;
}

#[cfg(not(any(target_arch = "powerpc",
target_arch = "mips",
target_arch = "mips64",
target_arch = "x86",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "powerpc64",
target_arch = "s390x",
target_arch = "aarch64")))]
use this_arch_not_supported;

// "Generic" ioctl protocol
#[cfg(any(target_arch = "x86",
target_arch = "arm",
Expand Down Expand Up @@ -86,30 +78,63 @@ macro_rules! ioc {
(($sz as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::SIZEMASK) << $crate::sys::ioctl::SIZESHIFT))
}

/// Encode an ioctl command that has no associated data.
/// Generate an ioctl request code for a command that passes no data.
///
/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_none!()` directly.
///
/// # Example
///
/// ```
/// # #[macro_use] extern crate nix;
/// const KVMIO: u8 = 0xAE;
/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
/// # fn main() {}
/// ```
#[macro_export]
#[doc(hidden)]
macro_rules! io {
macro_rules! request_code_none {
($ty:expr, $nr:expr) => (ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0))
}

/// Encode an ioctl command that reads.
/// Generate an ioctl request code for a command that reads.
///
/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_read!()` directly.
///
/// The read/write direction is relative to userland, so this
/// command would be userland is reading and the kernel is
/// writing.
#[macro_export]
#[doc(hidden)]
macro_rules! ior {
macro_rules! request_code_read {
($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz))
}

/// Encode an ioctl command that writes.
/// Generate an ioctl request code for a command that writes.
///
/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_write!()` directly.
///
/// The read/write direction is relative to userland, so this
/// command would be userland is writing and the kernel is
/// reading.
#[macro_export]
#[doc(hidden)]
macro_rules! iow {
macro_rules! request_code_write {
($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz))
}

/// Encode an ioctl command that both reads and writes.
/// Generate an ioctl request code for a command that reads and writes.
///
/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
///
/// You should only use this macro directly if the `ioctl` you're working
/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
#[macro_export]
#[doc(hidden)]
macro_rules! iorw {
macro_rules! request_code_readwrite {
($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz))
}
Loading