Skip to content

Commit 44c9a97

Browse files
committed
Add 'bad' prefixes for read, write_*, and readwrite ioctls
1 parent e2ce73c commit 44c9a97

File tree

2 files changed

+44
-18
lines changed

2 files changed

+44
-18
lines changed

src/sys/ioctl/mod.rs

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -108,35 +108,37 @@
108108
//!
109109
//! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev).
110110
//!
111-
//! ```text
112-
//! pub unsafe fn $NAME(fd: c_int, data: *mut u8, len: usize) -> Result<c_int>;
113-
//! ```
111+
//! Using hard-coded ioctl numbers
112+
//! ------------------------------
114113
//!
115114
//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of
116-
//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the `bad`
117-
//! form of the `ioctl!` macro (there is no data transfer direction used with `bad`). The naming of
118-
//! this comes from the Linux kernel which refers to these `ioctl`s as "bad".
115+
//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the `bad *`
116+
//! variants of the `ioctl!` macro. This naming comes from the Linux kernel which refers to these
117+
//! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates
118+
//! the ioctl number and instead use the defined value directly.
119119
//!
120120
//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor.
121-
//! It can be implemented as:
121+
//! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as:
122122
//!
123123
//! ```
124124
//! # #[macro_use] extern crate nix;
125125
//! # #[cfg(any(target_os = "android", target_os = "linux"))]
126126
//! # use nix::libc::TCGETS as TCGETS;
127127
//! # #[cfg(any(target_os = "android", target_os = "linux"))]
128-
//! ioctl!(bad tcgets with TCGETS);
128+
//! # use nix::libc::termios as termios;
129+
//! # #[cfg(any(target_os = "android", target_os = "linux"))]
130+
//! ioctl!(bad read tcgets with TCGETS; termios);
129131
//! # fn main() {}
130132
//! ```
131133
//!
132134
//! The generated function has the same form as that generated by `read`:
133135
//!
134136
//! ```text
135-
//! pub unsafe fn tcgets(fd: c_int, data: *mut u8) -> Result<c_int>;
137+
//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>;
136138
//! ```
137139
//!
138-
//! There is also a `bad none` form for use with hard-coded `ioctl`s that do not transfer data.
139-
//! The `TIOCEXCL` `ioctl` that's part of the termios API can be implemented as:
140+
//! There is also a `bad none`, `bad write_int`/`bad write_ptr`, and `bad readwrite` variant that work
141+
//! similar to the standard `none`, `write_int`/`write_ptr`, and `readwrite` variants.
140142
//!
141143
//! ```
142144
//! # #[macro_use] extern crate nix;
@@ -185,17 +187,38 @@ macro_rules! convert_ioctl_res {
185187
/// Generates ioctl functions. See [::sys::ioctl](sys/ioctl/index.html).
186188
#[macro_export]
187189
macro_rules! ioctl {
188-
(bad $name:ident with $nr:expr) => (
190+
(bad none $name:ident with $nr:expr) => (
191+
pub unsafe fn $name(fd: $crate::libc::c_int)
192+
-> $crate::Result<$crate::libc::c_int> {
193+
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
194+
}
195+
);
196+
(bad read $name:ident with $nr:expr; $ty:ty) => (
189197
pub unsafe fn $name(fd: $crate::libc::c_int,
190-
data: *mut u8)
198+
data: *mut $ty)
191199
-> $crate::Result<$crate::libc::c_int> {
192200
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
193201
}
194202
);
195-
(bad none $name:ident with $nr:expr) => (
196-
pub unsafe fn $name(fd: $crate::libc::c_int)
203+
(bad write_ptr $name:ident with $nr:expr; $ty:ty) => (
204+
pub unsafe fn $name(fd: $crate::libc::c_int,
205+
data: *const $ty)
197206
-> $crate::Result<$crate::libc::c_int> {
198-
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
207+
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
208+
}
209+
);
210+
(bad write_int $name:ident with $nr:expr) => (
211+
pub unsafe fn $name(fd: $crate::libc::c_int,
212+
data: $crate::libc::c_int)
213+
-> $crate::Result<$crate::libc::c_int> {
214+
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
215+
}
216+
);
217+
(bad readwrite $name:ident with $nr:expr; $ty:ty) => (
218+
pub unsafe fn $name(fd: $crate::libc::c_int,
219+
data: *mut $ty)
220+
-> $crate::Result<$crate::libc::c_int> {
221+
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
199222
}
200223
);
201224
(none $name:ident with $ioty:expr, $nr:expr) => (

test/sys/test_ioctl.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
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_int do_bad_write_int with 0x1234);
7+
ioctl!(bad write_ptr do_bad_write_ptr with 0x1234; u8);
8+
ioctl!(bad readwrite do_bad_readwrite with 0x1234; u32);
69
ioctl!(none do_none with 0, 0);
710
ioctl!(read read_test with 0, 0; u32);
811
ioctl!(write_int write_ptr_int with 0, 0);

0 commit comments

Comments
 (0)