diff options
author | Stephen Barber <smbarber@chromium.org> | 2017-07-10 18:33:19 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-07-13 22:03:30 -0700 |
commit | c4968f7de9841c0013170534888fe4484d1a2d73 (patch) | |
tree | 022fd86e74d5b3d033d997f9b4708282796f9913 /sys_util/src/ioctl.rs | |
parent | 8686d9ff5b11d3b72be1d05cff4bc62e41a02db7 (diff) | |
download | crosvm-c4968f7de9841c0013170534888fe4484d1a2d73.tar crosvm-c4968f7de9841c0013170534888fe4484d1a2d73.tar.gz crosvm-c4968f7de9841c0013170534888fe4484d1a2d73.tar.bz2 crosvm-c4968f7de9841c0013170534888fe4484d1a2d73.tar.lz crosvm-c4968f7de9841c0013170534888fe4484d1a2d73.tar.xz crosvm-c4968f7de9841c0013170534888fe4484d1a2d73.tar.zst crosvm-c4968f7de9841c0013170534888fe4484d1a2d73.zip |
sys_util: add ioctl module
Factor out common ioctl wrappers and macros into their own module. Signed-off-by: Stephen Barber <smbarber@chromium.org> BUG=none TEST=cargo test Change-Id: Ibede8a853f5cc6c6d62565930f312b11024cc5b5 Reviewed-on: https://chromium-review.googlesource.com/566540 Commit-Ready: Stephen Barber <smbarber@chromium.org> Tested-by: Stephen Barber <smbarber@chromium.org> Reviewed-by: Stephen Barber <smbarber@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'sys_util/src/ioctl.rs')
-rw-r--r-- | sys_util/src/ioctl.rs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/sys_util/src/ioctl.rs b/sys_util/src/ioctl.rs new file mode 100644 index 0000000..edfa3be --- /dev/null +++ b/sys_util/src/ioctl.rs @@ -0,0 +1,126 @@ +// Copyright 2017 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//! Macros and wrapper functions for dealing with ioctls. + +use std::os::raw::*; +use std::os::unix::io::AsRawFd; + +use libc; + +/// Raw macro to declare a function that returns an ioctl number. +#[macro_export] +macro_rules! ioctl_ioc_nr { + ($name:ident, $dir:expr, $ty:expr, $nr:expr, $size:expr) => ( + #[allow(non_snake_case)] + pub fn $name() -> ::std::os::raw::c_ulong { + (($dir << $crate::ioctl::_IOC_DIRSHIFT) | + ($ty << $crate::ioctl::_IOC_TYPESHIFT) | + ($nr<< $crate::ioctl::_IOC_NRSHIFT) | + ($size << $crate::ioctl::_IOC_SIZESHIFT)) as ::std::os::raw::c_ulong + } + ) +} + +/// Declare an ioctl that transfers no data. +#[macro_export] +macro_rules! ioctl_io_nr { + ($name:ident, $ty:expr, $nr:expr) => ( + ioctl_ioc_nr!($name, $crate::ioctl::_IOC_NONE, $ty, $nr, 0); + ) +} + +/// Declare an ioctl that reads data. +#[macro_export] +macro_rules! ioctl_ior_nr { + ($name:ident, $ty:expr, $nr:expr, $size:ty) => ( + ioctl_ioc_nr!($name, $crate::ioctl::_IOC_READ, $ty, $nr, ::std::mem::size_of::<$size>() as u32); + ) +} + +/// Declare an ioctl that writes data. +#[macro_export] +macro_rules! ioctl_iow_nr { + ($name:ident, $ty:expr, $nr:expr, $size:ty) => ( + ioctl_ioc_nr!($name, $crate::ioctl::_IOC_WRITE, $ty, $nr, ::std::mem::size_of::<$size>() as u32); + ) +} + +/// Declare an ioctl that reads and writes data. +#[macro_export] +macro_rules! ioctl_iowr_nr { + ($name:ident, $ty:expr, $nr:expr, $size:ty) => ( + ioctl_ioc_nr!($name, $crate::ioctl::_IOC_READ | $crate::ioctl::_IOC_WRITE, $ty, $nr, ::std::mem::size_of::<$size>() as u32); + ) +} + +pub const _IOC_NRBITS: c_uint = 8; +pub const _IOC_TYPEBITS: c_uint = 8; +pub const _IOC_SIZEBITS: c_uint = 14; +pub const _IOC_DIRBITS: c_uint = 2; +pub const _IOC_NRMASK: c_uint = 255; +pub const _IOC_TYPEMASK: c_uint = 255; +pub const _IOC_SIZEMASK: c_uint = 16383; +pub const _IOC_DIRMASK: c_uint = 3; +pub const _IOC_NRSHIFT: c_uint = 0; +pub const _IOC_TYPESHIFT: c_uint = 8; +pub const _IOC_SIZESHIFT: c_uint = 16; +pub const _IOC_DIRSHIFT: c_uint = 30; +pub const _IOC_NONE: c_uint = 0; +pub const _IOC_WRITE: c_uint = 1; +pub const _IOC_READ: c_uint = 2; +pub const IOC_IN: c_uint = 1073741824; +pub const IOC_OUT: c_uint = 2147483648; +pub const IOC_INOUT: c_uint = 3221225472; +pub const IOCSIZE_MASK: c_uint = 1073676288; +pub const IOCSIZE_SHIFT: c_uint = 16; + +/// Run an ioctl with no arguments. +pub unsafe fn ioctl<F: AsRawFd>(fd: &F, nr: c_ulong) -> c_int { + libc::ioctl(fd.as_raw_fd(), nr, 0) +} + +/// Run an ioctl with a single value argument. +pub unsafe fn ioctl_with_val<F: AsRawFd>(fd: &F, nr: c_ulong, arg: c_ulong) -> c_int { + libc::ioctl(fd.as_raw_fd(), nr, arg) +} + +/// Run an ioctl with an immutable reference. +pub unsafe fn ioctl_with_ref<F: AsRawFd, T>(fd: &F, nr: c_ulong, arg: &T) -> c_int { + libc::ioctl(fd.as_raw_fd(), nr, arg as *const T as *const c_void) +} + +/// Run an ioctl with a mutable reference. +pub unsafe fn ioctl_with_mut_ref<F: AsRawFd, T>(fd: &F, nr: c_ulong, arg: &mut T) -> c_int { + libc::ioctl(fd.as_raw_fd(), nr, arg as *mut T as *mut c_void) +} + +/// Run an ioctl with a raw pointer. +pub unsafe fn ioctl_with_ptr<F: AsRawFd, T>(fd: &F, nr: c_ulong, arg: *const T) -> c_int { + libc::ioctl(fd.as_raw_fd(), nr, arg as *const c_void) +} + +/// Run an ioctl with a mutable raw pointer. +pub unsafe fn ioctl_with_mut_ptr<F: AsRawFd, T>(fd: &F, nr: c_ulong, arg: *mut T) -> c_int { + libc::ioctl(fd.as_raw_fd(), nr, arg as *mut c_void) +} + +#[cfg(test)] +mod tests { + const TUNTAP: ::std::os::raw::c_uint = 0x54; + const VHOST: ::std::os::raw::c_uint = 0xaf; + + ioctl_io_nr!(VHOST_SET_OWNER, VHOST, 0x01); + ioctl_ior_nr!(TUNGETFEATURES, TUNTAP, 0xcf, ::std::os::raw::c_uint); + ioctl_iow_nr!(TUNSETQUEUE, TUNTAP, 0xd9, ::std::os::raw::c_int); + ioctl_iowr_nr!(VHOST_GET_VRING_BASE, VHOST, 0x12, ::std::os::raw::c_int); + + #[test] + fn ioctl_macros() { + assert_eq!(0x0000af01, VHOST_SET_OWNER()); + assert_eq!(0x800454cf, TUNGETFEATURES()); + assert_eq!(0x400454d9, TUNSETQUEUE()); + assert_eq!(0xc004af12, VHOST_GET_VRING_BASE()); + } +} |