Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow doc attributes in ioctl #661

Merged
merged 1 commit into from
Jul 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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