diff options
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | src/sys/ioctl/mod.rs | 105 | ||||
-rw-r--r-- | src/sys/ioctl/platform/bsd.rs | 36 | ||||
-rw-r--r-- | src/sys/ioctl/platform/dragonfly.rs | 0 | ||||
-rw-r--r-- | src/sys/ioctl/platform/freebsd.rs | 0 | ||||
-rw-r--r-- | src/sys/ioctl/platform/ios.rs | 0 | ||||
-rw-r--r-- | src/sys/ioctl/platform/linux.rs | 72 | ||||
-rw-r--r-- | src/sys/ioctl/platform/macos.rs | 0 | ||||
-rw-r--r-- | src/sys/ioctl/platform/netbsd.rs | 0 | ||||
-rw-r--r-- | src/sys/ioctl/platform/openbsd.rs | 0 | ||||
-rw-r--r-- | src/sys/mod.rs | 2 | ||||
-rw-r--r-- | test/sys/test_ioctl.rs | 123 |
12 files changed, 206 insertions, 136 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dd85e1c..232128da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added +- Added support for `ioctl` calls on BSD platforms + ([#478](https://github.com/nix-rust/nix/pull/478)) - Added struct `TimeSpec` ([#475](https://github.com/nix-rust/nix/pull/475)) - Added complete definitions for all kqueue-related constants on all supported @@ -24,6 +26,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#457](https://github.com/nix-rust/nix/pull/457)) ### Changed +- Removed the `bad` keyword from the `ioctl!` macro + ([#478](https://github.com/nix-rust/nix/pull/478)) - Changed `TimeVal` into an opaque Newtype ([#475](https://github.com/nix-rust/nix/pull/475)) - `kill`'s signature, defined in `::nix::sys::signal`, changed, so that the diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs index 387024f4..a04e9d39 100644 --- a/src/sys/ioctl/mod.rs +++ b/src/sys/ioctl/mod.rs @@ -104,33 +104,13 @@ #[macro_use] mod platform; -#[cfg(target_os = "macos")] -#[path = "platform/macos.rs"] -#[macro_use] -mod platform; - -#[cfg(target_os = "ios")] -#[path = "platform/ios.rs"] -#[macro_use] -mod platform; - -#[cfg(target_os = "freebsd")] -#[path = "platform/freebsd.rs"] -#[macro_use] -mod platform; - -#[cfg(target_os = "netbsd")] -#[path = "platform/netbsd.rs"] -#[macro_use] -mod platform; - -#[cfg(target_os = "openbsd")] -#[path = "platform/openbsd.rs"] -#[macro_use] -mod platform; - -#[cfg(target_os = "dragonfly")] -#[path = "platform/dragonfly.rs"] +#[cfg(any(target_os = "macos", + target_os = "ios", + target_os = "netbsd", + target_os = "openbsd", + target_os = "freebsd", + target_os = "dragonfly"))] +#[path = "platform/bsd.rs"] #[macro_use] mod platform; @@ -145,3 +125,74 @@ extern "C" { /// A hack to get the macros to work nicely. #[doc(hidden)] pub use ::libc as libc; + +/// Convert raw ioctl return value to a Nix result +#[macro_export] +macro_rules! convert_ioctl_res { + ($w:expr) => ( + { + $crate::Errno::result($w) + } + ); +} + +#[macro_export] +macro_rules! ioctl { + ($name:ident with $nr:expr) => ( + pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, + data: *mut u8) + -> $crate::Result<$crate::sys::ioctl::libc::c_int> { + convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, $nr as $crate::sys::ioctl::libc::c_ulong, data)) + } + ); + (none $name:ident with $ioty:expr, $nr:expr) => ( + pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int) + -> $crate::Result<$crate::sys::ioctl::libc::c_int> { + convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, io!($ioty, $nr) as $crate::sys::ioctl::libc::c_ulong)) + } + ); + (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( + pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, + val: *mut $ty) + -> $crate::Result<$crate::sys::ioctl::libc::c_int> { + convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val)) + } + ); + (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( + pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, + val: *const $ty) + -> $crate::Result<$crate::sys::ioctl::libc::c_int> { + convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val)) + } + ); + (readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( + pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, + val: *mut $ty) + -> $crate::Result<$crate::sys::ioctl::libc::c_int> { + convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val)) + } + ); + (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( + pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, + val: *mut $ty, + len: usize) + -> $crate::Result<$crate::sys::ioctl::libc::c_int> { + convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val)) + } + ); + (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( + pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, + val: *const $ty, + len: usize) -> $crate::Result<$crate::sys::ioctl::libc::c_int> { + convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val)) + } + ); + (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( + pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, + val: *mut $ty, + len: usize) + -> $crate::Result<$crate::sys::ioctl::libc::c_int> { + convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val)) + } + ); +} diff --git a/src/sys/ioctl/platform/bsd.rs b/src/sys/ioctl/platform/bsd.rs new file mode 100644 index 00000000..57b4d637 --- /dev/null +++ b/src/sys/ioctl/platform/bsd.rs @@ -0,0 +1,36 @@ +mod consts { + pub const VOID: u32 = 0x20000000; + pub const OUT: u32 = 0x40000000; + pub const IN: u32 = 0x80000000; + pub const INOUT: u32 = (IN|OUT); + pub const IOCPARM_MASK: u32 = 0x1fff; +} + +pub use self::consts::*; + +#[macro_export] +macro_rules! ioc { + ($inout:expr, $group:expr, $num:expr, $len:expr) => ( + $inout | (($len as u32 & $crate::sys::ioctl::IOCPARM_MASK) << 16) | (($group as u32) << 8) | ($num as u32) + ) +} + +#[macro_export] +macro_rules! io { + ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0)) +} + +#[macro_export] +macro_rules! ior { + ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::OUT, $g, $n, $len)) +} + +#[macro_export] +macro_rules! iow { + ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::IN, $g, $n, $len)) +} + +#[macro_export] +macro_rules! iorw { + ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::INOUT, $g, $n, $len)) +} diff --git a/src/sys/ioctl/platform/dragonfly.rs b/src/sys/ioctl/platform/dragonfly.rs deleted file mode 100644 index e69de29b..00000000 --- a/src/sys/ioctl/platform/dragonfly.rs +++ /dev/null diff --git a/src/sys/ioctl/platform/freebsd.rs b/src/sys/ioctl/platform/freebsd.rs deleted file mode 100644 index e69de29b..00000000 --- a/src/sys/ioctl/platform/freebsd.rs +++ /dev/null diff --git a/src/sys/ioctl/platform/ios.rs b/src/sys/ioctl/platform/ios.rs deleted file mode 100644 index e69de29b..00000000 --- a/src/sys/ioctl/platform/ios.rs +++ /dev/null diff --git a/src/sys/ioctl/platform/linux.rs b/src/sys/ioctl/platform/linux.rs index 3719fd0c..aacea459 100644 --- a/src/sys/ioctl/platform/linux.rs +++ b/src/sys/ioctl/platform/linux.rs @@ -77,78 +77,6 @@ macro_rules! iorw { ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz)) } -/// Convert raw ioctl return value to a Nix result -#[macro_export] -macro_rules! convert_ioctl_res { - ($w:expr) => ( - { - $crate::Errno::result($w) - } - ); -} - -/// Declare a wrapper function around an ioctl. -#[macro_export] -macro_rules! ioctl { - (bad $name:ident with $nr:expr) => ( - pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, - data: *mut u8) - -> $crate::Result<$crate::sys::ioctl::libc::c_int> { - convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, $nr as $crate::sys::ioctl::libc::c_ulong, data)) - } - ); - (none $name:ident with $ioty:expr, $nr:expr) => ( - pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int) - -> $crate::Result<$crate::sys::ioctl::libc::c_int> { - convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, io!($ioty, $nr) as $crate::sys::ioctl::libc::c_ulong)) - } - ); - (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( - pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, - val: *mut $ty) - -> $crate::Result<$crate::sys::ioctl::libc::c_int> { - convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val)) - } - ); - (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( - pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, - val: *const $ty) - -> $crate::Result<$crate::sys::ioctl::libc::c_int> { - convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val)) - } - ); - (readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( - pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, - val: *mut $ty) - -> $crate::Result<$crate::sys::ioctl::libc::c_int> { - convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::libc::c_ulong, val)) - } - ); - (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( - pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, - val: *mut $ty, - len: usize) - -> $crate::Result<$crate::sys::ioctl::libc::c_int> { - convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, ior!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val)) - } - ); - (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( - pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, - val: *const $ty, - len: usize) -> $crate::Result<$crate::sys::ioctl::libc::c_int> { - convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iow!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val)) - } - ); - (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => ( - pub unsafe fn $name(fd: $crate::sys::ioctl::libc::c_int, - val: *mut $ty, - len: usize) - -> $crate::Result<$crate::sys::ioctl::libc::c_int> { - convert_ioctl_res!($crate::sys::ioctl::ioctl(fd, iorw!($ioty, $nr, len) as $crate::sys::ioctl::libc::c_ulong, val)) - } - ); -} - /// Extracts the "direction" (read/write/none) from an encoded ioctl command. #[inline(always)] pub fn ioc_dir(nr: u32) -> u8 { diff --git a/src/sys/ioctl/platform/macos.rs b/src/sys/ioctl/platform/macos.rs deleted file mode 100644 index e69de29b..00000000 --- a/src/sys/ioctl/platform/macos.rs +++ /dev/null diff --git a/src/sys/ioctl/platform/netbsd.rs b/src/sys/ioctl/platform/netbsd.rs deleted file mode 100644 index e69de29b..00000000 --- a/src/sys/ioctl/platform/netbsd.rs +++ /dev/null diff --git a/src/sys/ioctl/platform/openbsd.rs b/src/sys/ioctl/platform/openbsd.rs deleted file mode 100644 index e69de29b..00000000 --- a/src/sys/ioctl/platform/openbsd.rs +++ /dev/null diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 793bc70e..706614dc 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -12,7 +12,7 @@ pub mod eventfd; #[cfg(target_os = "linux")] pub mod memfd; -#[cfg(not(any(target_os = "ios", target_os = "freebsd", target_os = "dragonfly")))] +#[macro_use] pub mod ioctl; #[cfg(any(target_os = "linux", target_os = "android"))] diff --git a/test/sys/test_ioctl.rs b/test/sys/test_ioctl.rs index 94eca447..1d9fbcc8 100644 --- a/test/sys/test_ioctl.rs +++ b/test/sys/test_ioctl.rs @@ -1,9 +1,7 @@ #![allow(dead_code)] -#![cfg(target_os = "linux")] // no ioctl support for osx yet - // Simple tests to ensure macro generated fns compile -ioctl!(bad do_bad with 0x1234); +ioctl!(do_bad with 0x1234); ioctl!(none do_none with 0, 0); ioctl!(read read_test with 0, 0; u32); ioctl!(write write_test with 0, 0; u64); @@ -15,44 +13,97 @@ ioctl!(readwrite buf readwritebuf_test with 0, 0; u32); // See C code for source of values for op calculations: // https://gist.github.com/posborne/83ea6880770a1aef332e -#[test] -fn test_op_none() { - assert_eq!(io!(b'q', 10), 0x0000710A); - assert_eq!(io!(b'a', 255), 0x000061FF); -} +#[cfg(any(target_os = "linux", target_os = "android"))] +mod linux { + #[test] + fn test_op_none() { + assert_eq!(io!(b'q', 10), 0x0000710A); + assert_eq!(io!(b'a', 255), 0x000061FF); + } -#[test] -fn test_op_write() { - assert_eq!(iow!(b'z', 10, 1), 0x40017A0A); - assert_eq!(iow!(b'z', 10, 512), 0x42007A0A); -} + #[test] + fn test_op_write() { + assert_eq!(iow!(b'z', 10, 1), 0x40017A0A); + assert_eq!(iow!(b'z', 10, 512), 0x42007A0A); + } -#[cfg(target_pointer_width = "64")] -#[test] -fn test_op_write_64() { - assert_eq!(iow!(b'z', 10, (1 as u64) << 32), 0x40007A0A); -} + #[cfg(target_pointer_width = "64")] + #[test] + fn test_op_write_64() { + assert_eq!(iow!(b'z', 10, (1 as u64) << 32), 0x40007A0A); + } -#[test] -fn test_op_read() { - assert_eq!(ior!(b'z', 10, 1), 0x80017A0A); - assert_eq!(ior!(b'z', 10, 512), 0x82007A0A); -} + #[test] + fn test_op_read() { + assert_eq!(ior!(b'z', 10, 1), 0x80017A0A); + assert_eq!(ior!(b'z', 10, 512), 0x82007A0A); + } -#[cfg(target_pointer_width = "64")] -#[test] -fn test_op_read_64() { - assert_eq!(ior!(b'z', 10, (1 as u64) << 32), 0x80007A0A); -} + #[cfg(target_pointer_width = "64")] + #[test] + fn test_op_read_64() { + assert_eq!(ior!(b'z', 10, (1 as u64) << 32), 0x80007A0A); + } + + #[test] + fn test_op_read_write() { + assert_eq!(iorw!(b'z', 10, 1), 0xC0017A0A); + assert_eq!(iorw!(b'z', 10, 512), 0xC2007A0A); + } -#[test] -fn test_op_read_write() { - assert_eq!(iorw!(b'z', 10, 1), 0xC0017A0A); - assert_eq!(iorw!(b'z', 10, 512), 0xC2007A0A); + #[cfg(target_pointer_width = "64")] + #[test] + fn test_op_read_write_64() { + assert_eq!(iorw!(b'z', 10, (1 as u64) << 32), 0xC0007A0A); + } } -#[cfg(target_pointer_width = "64")] -#[test] -fn test_op_read_write_64() { - assert_eq!(iorw!(b'z', 10, (1 as u64) << 32), 0xC0007A0A); +#[cfg(any(target_os = "macos", + target_os = "ios", + target_os = "netbsd", + target_os = "openbsd", + target_os = "freebsd", + target_os = "dragonfly"))] +mod bsd { + #[test] + fn test_op_none() { + assert_eq!(io!(b'q', 10), 0x2000710A); + assert_eq!(io!(b'a', 255), 0x200061FF); + } + + #[test] + fn test_op_write() { + assert_eq!(iow!(b'z', 10, 1), 0x80017A0A); + assert_eq!(iow!(b'z', 10, 512), 0x82007A0A); + } + + #[cfg(target_pointer_width = "64")] + #[test] + fn test_op_write_64() { + assert_eq!(iow!(b'z', 10, (1 as u64) << 32), 0x80007A0A); + } + + #[test] + fn test_op_read() { + assert_eq!(ior!(b'z', 10, 1), 0x40017A0A); + assert_eq!(ior!(b'z', 10, 512), 0x42007A0A); + } + + #[cfg(target_pointer_width = "64")] + #[test] + fn test_op_read_64() { + assert_eq!(ior!(b'z', 10, (1 as u64) << 32), 0x40007A0A); + } + + #[test] + fn test_op_read_write() { + assert_eq!(iorw!(b'z', 10, 1), 0xC0017A0A); + assert_eq!(iorw!(b'z', 10, 512), 0xC2007A0A); + } + + #[cfg(target_pointer_width = "64")] + #[test] + fn test_op_read_write_64() { + assert_eq!(iorw!(b'z', 10, (1 as u64) << 32), 0xC0007A0A); + } } |