Skip to content

Commit e2ce73c

Browse files
committed
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.
1 parent 16ae3e8 commit e2ce73c

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

src/sys/ioctl/mod.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,22 @@
8080
//! The return value for `ioctl` functions generated by the `ioctl!` macro are `nix::Error`s.
8181
//! These are generated by assuming the return value of the ioctl is `-1` on error and everything
8282
//! else is a valid return value. If this is not the case, `Result::map` can be used to map some
83-
//! of the range of "good" values (-2..-Inf, 0..Inf) into a smaller range in a helper function.
83+
//! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function.
84+
//!
85+
//! Writing `ioctl`s generally use pointers as their data source and these should use the
86+
//! `write_ptr` variant. But in some cases an `int` is passed directly. For these `ioctl`s use the
87+
//! `write_int` variant of the `ioctl!` macro. This variant does not take a type as the last argument:
88+
//!
89+
//! ```
90+
//! # #[macro_use] extern crate nix;
91+
//! const HCI_IOC_MAGIC: u8 = b'k';
92+
//! const HCI_IOC_HCIDEVUP: u8 = 1;
93+
//! ioctl!(write_int hci_dev_up with HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
94+
//! # fn main() {}
95+
//! ```
96+
//!
97+
//! Some `ioctl`s don't transfer any data, and those should use the `none` variant. This variant
98+
//! doesn't take a type and so it is declared similar to the `write_int` variant shown above.
8499
//!
85100
//! The mode for a given `ioctl` should be clear from the documentation if it has good
86101
//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl`
@@ -196,13 +211,20 @@ macro_rules! ioctl {
196211
convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
197212
}
198213
);
199-
(write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
214+
(write_ptr $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
200215
pub unsafe fn $name(fd: $crate::libc::c_int,
201-
data: $ty)
216+
data: *const $ty)
202217
-> $crate::Result<$crate::libc::c_int> {
203218
convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
204219
}
205220
);
221+
(write_int $name:ident with $ioty:expr, $nr:expr) => (
222+
pub unsafe fn $name(fd: $crate::libc::c_int,
223+
data: $crate::libc::c_int)
224+
-> $crate::Result<$crate::libc::c_int> {
225+
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))
226+
}
227+
);
206228
(readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
207229
pub unsafe fn $name(fd: $crate::libc::c_int,
208230
data: *mut $ty)

test/sys/test_ioctl.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ ioctl!(bad do_bad with 0x1234);
55
ioctl!(bad none do_bad_none with 0x1234);
66
ioctl!(none do_none with 0, 0);
77
ioctl!(read read_test with 0, 0; u32);
8-
ioctl!(write write_test with 0, 0; u64);
8+
ioctl!(write_int write_ptr_int with 0, 0);
9+
ioctl!(write_ptr write_ptr_u8 with 0, 0; u8);
10+
ioctl!(write_ptr write_ptr_u32 with 0, 0; u32);
11+
ioctl!(write_ptr write_ptr_u64 with 0, 0; u64);
912
ioctl!(readwrite readwrite_test with 0, 0; u64);
1013
ioctl!(read buf readbuf_test with 0, 0; u32);
11-
ioctl!(write buf writebuf_test with 0, 0; u32);
14+
ioctl!(write buf writebuf_test_u8 with 0, 0; u8);
15+
ioctl!(write buf writebuf_test_u32 with 0, 0; u32);
16+
ioctl!(write buf writebuf_test_u64 with 0, 0; u64);
1217
ioctl!(readwrite buf readwritebuf_test with 0, 0; u32);
1318

1419
// See C code for source of values for op calculations (does NOT work for mips/powerpc):

0 commit comments

Comments
 (0)