summary refs log tree commit diff
path: root/sys_util/src/ioctl.rs
diff options
context:
space:
mode:
authorStephen Barber <smbarber@chromium.org>2017-07-10 18:33:19 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-07-13 22:03:30 -0700
commitc4968f7de9841c0013170534888fe4484d1a2d73 (patch)
tree022fd86e74d5b3d033d997f9b4708282796f9913 /sys_util/src/ioctl.rs
parent8686d9ff5b11d3b72be1d05cff4bc62e41a02db7 (diff)
downloadcrosvm-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.rs126
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());
+    }
+}