summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryant Mairs <bryant@mai.rs>2017-07-18 09:36:49 -0700
committerMarcin Mielniczuk <marmistrz.dev@zoho.eu>2017-07-25 09:09:52 +0200
commit3cf4cc68174ebe126a537ba8f29c29243201d917 (patch)
tree678f2958a9f4fdab2d05002d2ebd5e5b618a3926
parent7b078473b8ab52742c7ce46e338fc1ad98355dc8 (diff)
downloadnix-3cf4cc68174ebe126a537ba8f29c29243201d917.zip
Split ioctl!(write ...) into write_ptr and write_int
There two different write semantics used with ioctls: one involves passing a pointer the other involves passing an int. Previously the ioctl! macro did not distinguish between these cases and left it up to the user to set the proper datatype. This previous version was not type safe and prone to errors. The solution here is to split the "write" variant into a "write_ptr" and "write_int" variant that makes the semantics more explicit and improves type safety by specifying arguments better.
-rw-r--r--src/sys/ioctl/mod.rs28
-rw-r--r--test/sys/test_ioctl.rs9
2 files changed, 32 insertions, 5 deletions
diff --git a/src/sys/ioctl/mod.rs b/src/sys/ioctl/mod.rs
index 43114a5c..058fc60a 100644
--- a/src/sys/ioctl/mod.rs
+++ b/src/sys/ioctl/mod.rs
@@ -80,7 +80,22 @@
//! The return value for `ioctl` functions generated by the `ioctl!` macro are `nix::Error`s.
//! These are generated by assuming the return value of the ioctl is `-1` on error and everything
//! else is a valid return value. If this is not the case, `Result::map` can be used to map some
-//! of the range of "good" values (-2..-Inf, 0..Inf) into a smaller range in a helper function.
+//! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function.
+//!
+//! Writing `ioctl`s generally use pointers as their data source and these should use the
+//! `write_ptr` variant. But in some cases an `int` is passed directly. For these `ioctl`s use the
+//! `write_int` variant of the `ioctl!` macro. This variant does not take a type as the last argument:
+//!
+//! ```
+//! # #[macro_use] extern crate nix;
+//! const HCI_IOC_MAGIC: u8 = b'k';
+//! const HCI_IOC_HCIDEVUP: u8 = 1;
+//! ioctl!(write_int hci_dev_up with HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
+//! # fn main() {}
+//! ```
+//!
+//! Some `ioctl`s don't transfer any data, and those should use the `none` variant. This variant
+//! doesn't take a type and so it is declared similar to the `write_int` variant shown above.
//!
//! The mode for a given `ioctl` should be clear from the documentation if it has good
//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl`
@@ -196,13 +211,20 @@ macro_rules! ioctl {
convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
}
);
- (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
+ (write_ptr $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
pub unsafe fn $name(fd: $crate::libc::c_int,
- data: $ty)
+ data: *const $ty)
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
}
);
+ (write_int $name:ident with $ioty:expr, $nr:expr) => (
+ 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, iow!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
+ }
+ );
(readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
diff --git a/test/sys/test_ioctl.rs b/test/sys/test_ioctl.rs
index c0ae078a..7f0018d3 100644
--- a/test/sys/test_ioctl.rs
+++ b/test/sys/test_ioctl.rs
@@ -5,10 +5,15 @@ ioctl!(bad do_bad with 0x1234);
ioctl!(bad none do_bad_none 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);
+ioctl!(write_int write_ptr_int with 0, 0);
+ioctl!(write_ptr write_ptr_u8 with 0, 0; u8);
+ioctl!(write_ptr write_ptr_u32 with 0, 0; u32);
+ioctl!(write_ptr write_ptr_u64 with 0, 0; u64);
ioctl!(readwrite readwrite_test with 0, 0; u64);
ioctl!(read buf readbuf_test with 0, 0; u32);
-ioctl!(write buf writebuf_test with 0, 0; u32);
+ioctl!(write buf writebuf_test_u8 with 0, 0; u8);
+ioctl!(write buf writebuf_test_u32 with 0, 0; u32);
+ioctl!(write buf writebuf_test_u64 with 0, 0; u64);
ioctl!(readwrite buf readwritebuf_test with 0, 0; u32);
// See C code for source of values for op calculations (does NOT work for mips/powerpc):