Skip to content

Commit

Permalink
Merge #661
Browse files Browse the repository at this point in the history
661: Allow doc attributes in ioctl r=asomers

fixes #571 . Note that this is a breaking change because it also changes 

```
ioctl!(some_name with 12);
```

to

```
ioctl!(bad some_name with 12);
```

This is to work around a bug in the rust compiler whereby rules around matching idents are overly strict. See rust-lang/rust#24189

It doesn't break anything else though.
  • Loading branch information
bors[bot] committed Jul 23, 2017
2 parents 4b686d8 + 4b8a661 commit ce3b129
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 13 deletions.
67 changes: 54 additions & 13 deletions src/sys/ioctl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,34 @@
//! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IORW`. Some `ioctl`s are
//! documented directly in the headers defining their constants, but others have more extensive
//! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`).
//!
//! Documenting the generated functions
//! ===================================
//!
//! In many cases, users will wish for the functions generated by the `ioctl`
//! macro to be public and documented. For this reason, the generated functions
//! are public by default. If you wish to hide the ioctl, you will need to put
//! them in a private module.
//!
//! For documentation, it is possible to use doc comments inside the `ioctl!`
//! macro. Here is an example :
//!
//! ```
//! # #[macro_use] extern crate nix;
//! # use nix::libc::c_int;
//! ioctl! {
//! /// Make the given terminal the controlling terminal of the calling process. The calling
//! /// process must be a session leader and not have a controlling terminal already. If the
//! /// terminal is already the controlling terminal of a different session group then the
//! /// ioctl will fail with **EPERM**, unless the caller is root (more precisely: has the
//! /// **CAP_SYS_ADMIN** capability) and arg equals 1, in which case the terminal is stolen
//! /// and all processes that had it as controlling terminal lose it.
//! read tiocsctty with b't', 19; c_int
//! }
//!
//! # fn main() {}
//! ```
//!
#[cfg(any(target_os = "linux", target_os = "android"))]
#[path = "platform/linux.rs"]
#[macro_use]
Expand Down Expand Up @@ -228,89 +256,102 @@ macro_rules! convert_ioctl_res {
/// Generates ioctl functions. See [::sys::ioctl](sys/ioctl/index.html).
#[macro_export]
macro_rules! ioctl {
(bad none $name:ident with $nr:expr) => (
($(#[$attr:meta])* bad none $name:ident with $nr:expr) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int)
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
}
);
(bad read $name:ident with $nr:expr; $ty:ty) => (
($(#[$attr:meta])* bad read $name:ident with $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
}
);
(bad write_ptr $name:ident with $nr:expr; $ty:ty) => (
($(#[$attr:meta])* bad write_ptr $name:ident with $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *const $ty)
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
}
);
(bad write_int $name:ident with $nr:expr) => (
($(#[$attr:meta])* bad write_int $name:ident with $nr:expr) => (
$(#[$attr])*
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, $nr as $crate::sys::ioctl::ioctl_num_type, data))
}
);
(bad readwrite $name:ident with $nr:expr; $ty:ty) => (
($(#[$attr:meta])* bad readwrite $name:ident with $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
}
);
(none $name:ident with $ioty:expr, $nr:expr) => (
($(#[$attr:meta])* none $name:ident with $ioty:expr, $nr:expr) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int)
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, io!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type))
}
);
(read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
($(#[$attr:meta])* read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
}
);
(write_ptr $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
($(#[$attr:meta])* write_ptr $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
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) => (
($(#[$attr:meta])* write_int $name:ident with $ioty:expr, $nr:expr) => (
$(#[$attr])*
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) => (
($(#[$attr:meta])* readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
data: *mut $ty)
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
}
);
(read_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
($(#[$attr:meta])* read_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &mut [$ty])
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
}
);
(write_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
($(#[$attr:meta])* write_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &[$ty])
-> $crate::Result<$crate::libc::c_int> {
convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
}
);
(readwrite_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
($(#[$attr:meta])* readwrite_buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
$(#[$attr])*
pub unsafe fn $name(fd: $crate::libc::c_int,
data: &mut [$ty])
-> $crate::Result<$crate::libc::c_int> {
Expand Down
54 changes: 54 additions & 0 deletions test/sys/test_ioctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,60 @@ 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);

// Make sure documentation works
ioctl! {
/// This documents the ioctl function
bad none do_bad_docs with 0x1234
}
ioctl! {
/// This documents the ioctl function
bad read do_bad_read_docs with 0x1234; u16
}
ioctl! {
/// This documents the ioctl function
bad write_int do_bad_write_int_docs with 0x1234
}
ioctl! {
/// This documents the ioctl function
bad write_ptr do_bad_write_ptr_docs with 0x1234; u8
}
ioctl! {
/// This documents the ioctl function
bad readwrite do_bad_readwrite_docs with 0x1234; u32
}
ioctl! {
/// This documents the ioctl function
none do_none_docs with 0, 0
}
ioctl! {
/// This documents the ioctl function
read do_read_docs with 0, 0; u32
}
ioctl! {
/// This documents the ioctl function
write_int do_write_int_docs with 0, 0
}
ioctl! {
/// This documents the ioctl function
write_ptr do_write_ptr_docs with 0, 0; u32
}
ioctl! {
/// This documents the ioctl function
readwrite do_readwrite_docs with 0, 0; u32
}
ioctl! {
/// This documents the ioctl function
read_buf do_read_buf_docs with 0, 0; u32
}
ioctl! {
/// This documents the ioctl function
write_buf do_write_buf_docs with 0, 0; u32
}
ioctl! {
/// This documents the ioctl function
readwrite_buf do_readwrite_buf_docs with 0, 0; u32
}

// See C code for source of values for op calculations (does NOT work for mips/powerpc):
// https://gist.github.com/posborne/83ea6880770a1aef332e
//
Expand Down

0 comments on commit ce3b129

Please sign in to comment.