Skip to content

Commit e5a24d6

Browse files
committed
Add 'bad' prefixes for read, write, and readwrite ioctls
1 parent de726c4 commit e5a24d6

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed

src/sys/ioctl/mod.rs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,15 @@
9191
//!
9292
//! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev).
9393
//!
94-
//! ```text
95-
//! pub unsafe fn $NAME(fd: c_int, data: *mut u8, len: usize) -> Result<c_int>;
96-
//! ```
94+
//! Using hard-coded ioctl numbers
95+
//! ------------------------------
9796
//!
9897
//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of
9998
//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the `bad`
10099
//! form of the `ioctl!` macro (there is no data transfer direction used with `bad`). The naming of
101-
//! this comes from the Linux kernel which refers to these `ioctl`s as "bad".
100+
//! this comes from the Linux kernel which refers to these `ioctl`s as "bad". These are a different
101+
//! form as they bypass calling the macro that generates that ioctl number and instead use the
102+
//! defined value directly. These are supported by the `bad` prefix with the `ioctl!` macro.
102103
//!
103104
//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor.
104105
//! It can be implemented as:
@@ -108,18 +109,20 @@
108109
//! # #[cfg(any(target_os = "android", target_os = "linux"))]
109110
//! # use nix::libc::TCGETS as TCGETS;
110111
//! # #[cfg(any(target_os = "android", target_os = "linux"))]
111-
//! ioctl!(bad tcgets with TCGETS);
112+
//! # use nix::libc::termios as termios;
113+
//! # #[cfg(any(target_os = "android", target_os = "linux"))]
114+
//! ioctl!(bad read tcgets with TCGETS; termios);
112115
//! # fn main() {}
113116
//! ```
114117
//!
115118
//! The generated function has the same form as that generated by `read`:
116119
//!
117120
//! ```text
118-
//! pub unsafe fn tcgets(fd: c_int, data: *mut u8) -> Result<c_int>;
121+
//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>;
119122
//! ```
120123
//!
121-
//! There is also a `bad none` form for use with hard-coded `ioctl`s that do not transfer data.
122-
//! The `TIOCEXCL` `ioctl` that's part of the termios API can be implemented as:
124+
//! There is also a `bad none`, `bad write`, and `bad readwrite` form that work similar to the
125+
//! standard `none`, `write`, and `readwrite` forms.
123126
//!
124127
//! ```
125128
//! # #[macro_use] extern crate nix;
@@ -168,17 +171,31 @@ macro_rules! convert_ioctl_res {
168171
/// Generates ioctl functions. See [::sys::ioctl](sys/ioctl/index.html).
169172
#[macro_export]
170173
macro_rules! ioctl {
171-
(bad $name:ident with $nr:expr) => (
174+
(bad none $name:ident with $nr:expr) => (
175+
pub unsafe fn $name(fd: $crate::libc::c_int)
176+
-> $crate::Result<$crate::libc::c_int> {
177+
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
178+
}
179+
);
180+
(bad read $name:ident with $nr:expr; $ty:ty) => (
172181
pub unsafe fn $name(fd: $crate::libc::c_int,
173-
data: *mut u8)
182+
data: *mut $ty)
174183
-> $crate::Result<$crate::libc::c_int> {
175184
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
176185
}
177186
);
178-
(bad none $name:ident with $nr:expr) => (
179-
pub unsafe fn $name(fd: $crate::libc::c_int)
187+
(bad write $name:ident with $nr:expr; $ty:ty) => (
188+
pub unsafe fn $name(fd: $crate::libc::c_int,
189+
data: *const $ty)
180190
-> $crate::Result<$crate::libc::c_int> {
181-
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
191+
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
192+
}
193+
);
194+
(bad readwrite $name:ident with $nr:expr; $ty:ty) => (
195+
pub unsafe fn $name(fd: $crate::libc::c_int,
196+
data: *mut $ty)
197+
-> $crate::Result<$crate::libc::c_int> {
198+
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
182199
}
183200
);
184201
(none $name:ident with $ioty:expr, $nr:expr) => (

test/sys/test_ioctl.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#![allow(dead_code)]
22

33
// Simple tests to ensure macro generated fns compile
4-
ioctl!(bad do_bad with 0x1234);
5-
ioctl!(bad none do_bad_none with 0x1234);
4+
ioctl!(bad none do_bad with 0x1234);
5+
ioctl!(bad read do_bad_read with 0x1234; u16);
6+
ioctl!(bad write do_bad_write with 0x1234; u8);
7+
ioctl!(bad readwrite do_bad_readwrite with 0x1234; u32);
68
ioctl!(none do_none with 0, 0);
79
ioctl!(read read_test with 0, 0; u32);
810
ioctl!(write write_test_u8 with 0, 0; u8);

0 commit comments

Comments
 (0)