From 1a815f11473c1eb91a5613f8fe67d5e97975b3fc Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 28 Jan 2018 19:03:14 -0800 Subject: Implement equivalent for _IOWINT for FreeBSD-like targets ioctls on FreeBSD and DragonflyBSD have a separate request code generation macro `_IOWINT` which is now exposed as `request_code_write_int`. `ioctl_write_int` is also fixed on these platforms to use this new request --- CHANGELOG.md | 4 ++ src/sys/ioctl/bsd.rs | 11 +++++ src/sys/ioctl/mod.rs | 107 +++++++++++++++++++++++++++++++++---------------- test/sys/test_ioctl.rs | 7 ++++ 4 files changed, 95 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8c15867..0e2567ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. @@ -37,6 +39,8 @@ 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)) ### Removed - Removed explicit support for the `bytes` crate from the `sys::aio` module. diff --git a/src/sys/ioctl/bsd.rs b/src/sys/ioctl/bsd.rs index 922d32e8..b7c5345b 100644 --- a/src/sys/ioctl/bsd.rs +++ b/src/sys/ioctl/bsd.rs @@ -46,6 +46,17 @@ 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. diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs index c4ba39c8..9c76fe96 100644 --- a/src/sys/ioctl/mod.rs +++ b/src/sys/ioctl/mod.rs @@ -489,41 +489,80 @@ macro_rules! ioctl_write_ptr_bad { ) } -/// Generates a wrapper function for a ioctl that writes an integer to the kernel. -/// -/// The arguments to this macro are: -/// -/// * The function name -/// * The ioctl identifier -/// * The ioctl sequence number -/// -/// The generated function has the following signature: -/// -/// ```rust,ignore -/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result -/// ``` -/// -/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). -/// -/// # Example -/// -/// ``` -/// # #[macro_use] extern crate nix; -/// const HCI_IOC_MAGIC: u8 = b'k'; -/// const HCI_IOC_HCIDEVUP: u8 = 1; -/// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP); -/// # fn main() {} -/// ``` -#[macro_export] -macro_rules! ioctl_write_int { - ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( - $(#[$attr])* - pub unsafe fn $name(fd: $crate::libc::c_int, - data: $crate::libc::c_int) - -> $crate::Result<$crate::libc::c_int> { - convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data)) +cfg_if!{ + if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] { + /// Generates a wrapper function for a ioctl that writes an integer to the kernel. + /// + /// The arguments to this macro are: + /// + /// * The function name + /// * The ioctl identifier + /// * The ioctl sequence number + /// + /// The generated function has the following signature: + /// + /// ```rust,ignore + /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result + /// ``` + /// + /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). + /// + /// # Example + /// + /// ``` + /// # #[macro_use] extern crate nix; + /// ioctl_write_int!(vt_activate, b'v', 4); + /// # fn main() {} + /// ``` + #[macro_export] + macro_rules! ioctl_write_int { + ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( + $(#[$attr])* + pub unsafe fn $name(fd: $crate::libc::c_int, + data: $crate::libc::c_int) + -> $crate::Result<$crate::libc::c_int> { + convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data)) + } + ) } - ) + } else { + /// Generates a wrapper function for a ioctl that writes an integer to the kernel. + /// + /// The arguments to this macro are: + /// + /// * The function name + /// * The ioctl identifier + /// * The ioctl sequence number + /// + /// The generated function has the following signature: + /// + /// ```rust,ignore + /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result + /// ``` + /// + /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html). + /// + /// # Example + /// + /// ``` + /// # #[macro_use] extern crate nix; + /// const HCI_IOC_MAGIC: u8 = b'k'; + /// const HCI_IOC_HCIDEVUP: u8 = 1; + /// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP); + /// # fn main() {} + /// ``` + #[macro_export] + macro_rules! ioctl_write_int { + ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => ( + $(#[$attr])* + pub unsafe fn $name(fd: $crate::libc::c_int, + data: $crate::libc::c_int) + -> $crate::Result<$crate::libc::c_int> { + convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data)) + } + ) + } + } } /// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel. diff --git a/test/sys/test_ioctl.rs b/test/sys/test_ioctl.rs index ec9d26a3..0a439b33 100644 --- a/test/sys/test_ioctl.rs +++ b/test/sys/test_ioctl.rs @@ -110,6 +110,13 @@ mod bsd { assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF); } + #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] + #[test] + fn test_op_write_int() { + assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604); + assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002); + } + #[test] fn test_op_write() { assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A); -- cgit v1.2.3