Alioth Code Coverage

ioctl.rs18.56%

1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::mem::size_of;
16
17const IOC_NONN: u32 = 0;
18const IOC_WRITE: u32 = 1;
19const IOC_READ: u32 = 2;
20
21const IOC_NRSHIFT: usize = 0;
22const IOC_TYPESHIFT: usize = 8;
23const IOC_SIZESHIFT: usize = 16;
24const IOC_DIRSHIFT: usize = 30;
25
26const fn ioctl_ioc(dir: u32, type_: u8, nr: u8, size: u32) -> u32 {8x
27 (dir << IOC_DIRSHIFT)8x
28 | (size << IOC_SIZESHIFT)8x
29 | ((type_ as u32) << IOC_TYPESHIFT)8x
30 | ((nr as u32) << IOC_NRSHIFT)8x
31}8x
32
33pub const fn ioctl_io(type_: u8, nr: u8) -> u32 {2x
34 ioctl_ioc(IOC_NONN, type_, nr, 0)2x
35}2x
36
37pub const fn ioctl_ior<T>(type_: u8, nr: u8) -> u32 {2x
38 ioctl_ioc(IOC_READ, type_, nr, size_of::<T>() as u32)2x
39}2x
40
41pub const fn ioctl_iow<T>(type_: u8, nr: u8) -> u32 {2x
42 ioctl_ioc(IOC_WRITE, type_, nr, size_of::<T>() as u32)2x
43}2x
44
45pub const fn ioctl_iowr<T>(type_: u8, nr: u8) -> u32 {2x
46 ioctl_ioc(IOC_WRITE | IOC_READ, type_, nr, size_of::<T>() as u32)2x
47}2x
48
49#[macro_export]
50macro_rules! ioctl_none {
51 ($name:ident, $type_:expr, $nr:expr) => {
52 #[allow(clippy::missing_safety_doc)]
53 pub unsafe fn $name<F: ::std::os::fd::AsFd>(fd: &F) -> ::std::io::Result<libc::c_int> {
54 let op = $crate::sys::ioctl::ioctl_io($type_, $nr);
55 $crate::ffi!(unsafe {
56 ::libc::ioctl(::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()), op as _, 0)
57 })
58 }
59 };
60}
61
62#[macro_export]
63macro_rules! ioctl_write_val {
64 ($name:ident, $code:expr, $ty:ty) => {
65 #[allow(clippy::missing_safety_doc)]
66 pub unsafe fn $name<F: ::std::os::fd::AsFd>(
67 fd: &F,
68 val: $ty,
69 ) -> ::std::io::Result<libc::c_int> {
70 let op = $code;
71 $crate::ffi!(unsafe {
72 ::libc::ioctl(::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()), op as _, val)
73 })
74 }
75 };
76 ($name:ident, $type_:expr, $nr:expr, $ty:ty) => {
77 $crate::ioctl_write_val!($name, $crate::sys::ioctl::ioctl_io($type_, $nr), $ty);
78 };
79}
80
81#[macro_export]
82macro_rules! ioctl_write_ptr {
83 ($name:ident, $code:expr, $ty:ty) => {
84 #[allow(clippy::missing_safety_doc)]
85 pub unsafe fn $name<F: ::std::os::fd::AsFd>(
86 fd: &F,
87 val: &$ty,
88 ) -> ::std::io::Result<libc::c_int> {
89 let op = $code;
90 $crate::ffi!(unsafe {
91 ::libc::ioctl(
92 ::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),
93 op as _,
94 val as *const $ty,
95 )
96 })
97 }
98 };
99 ($name:ident, $type_:expr, $nr:expr, $ty:ty) => {
100 $crate::ioctl_write_ptr!(
101 $name,
102 $crate::sys::ioctl::ioctl_iow::<$ty>($type_, $nr),
103 $ty
104 );
105 };
106}
107
108#[macro_export]
109macro_rules! ioctl_write_buf {
110 ($name:ident, $code:expr, $ty:ident) => {
111 #[allow(clippy::missing_safety_doc)]
112 pub unsafe fn $name<F: ::std::os::fd::AsFd, const N: usize>(
113 fd: &F,
114 val: &$ty<N>,
115 ) -> ::std::io::Result<libc::c_int> {
116 let op = $code;
117 $crate::ffi!(unsafe {
118 ::libc::ioctl(
119 ::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),
120 op as _,
121 val as *const $ty<N>,
122 )
123 })
124 }
125 };
126 ($name:ident, $type_:expr, $nr:expr, $ty:ident) => {
127 $crate::ioctl_write_buf!(
128 $name,
129 $crate::sys::ioctl::ioctl_iow::<$ty<0>>($type_, $nr),
130 $ty
131 );
132 };
133}
134
135#[macro_export]
136macro_rules! ioctl_writeread {
137 ($name:ident, $code:expr, $ty:ty) => {
138 #[allow(clippy::missing_safety_doc)]
139 pub unsafe fn $name<F: ::std::os::fd::AsFd>(
140 fd: &F,
141 val: &mut $ty,
142 ) -> ::std::io::Result<libc::c_int> {
143 let op = $code;
144 $crate::ffi!(unsafe {
145 ::libc::ioctl(
146 ::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),
147 op as _,
148 val as *mut $ty,
149 )
150 })
151 }
152 };
153 ($name:ident, $type_:expr, $nr:expr, $ty:ty) => {
154 $crate::ioctl_writeread!(
155 $name,
156 $crate::sys::ioctl::ioctl_iowr::<$ty>($type_, $nr),
157 $ty
158 );
159 };
160 ($name:ident, $code:expr) => {
161 #[allow(clippy::missing_safety_doc)]
162 pub unsafe fn $name<F: ::std::os::fd::AsFd, T>(
163 fd: &F,
164 val: &mut T,
165 ) -> ::std::io::Result<libc::c_int> {
166 let op = $code;
167 $crate::ffi!(unsafe {
168 ::libc::ioctl(
169 ::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),
170 op as _,
171 val as *mut T,
172 )
173 })
174 }
175 };
176}
177
178#[macro_export]
179macro_rules! ioctl_writeread_buf {
180 ($name:ident, $code:expr, $ty:ident) => {
181 #[allow(clippy::missing_safety_doc)]
182 pub unsafe fn $name<F: ::std::os::fd::AsFd, const N: usize>(
183 fd: &F,
184 val: &mut $ty<N>,
185 ) -> ::std::io::Result<libc::c_int> {
186 let op = $code;
187 $crate::ffi!(unsafe {
188 ::libc::ioctl(
189 ::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),
190 op as _,
191 val as *mut $ty<N>,
192 )
193 })
194 }
195 };
196 ($name:ident, $type_:expr, $nr:expr, $ty:ident) => {
197 $crate::ioctl_writeread_buf!(
198 $name,
199 $crate::sys::ioctl::ioctl_iowr::<$ty<0>>($type_, $nr),
200 $ty
201 );
202 };
203}
204
205#[macro_export]
206macro_rules! ioctl_read {
207 ($name:ident, $code:expr, $ty:ty) => {
208 #[allow(clippy::missing_safety_doc)]
209 pub unsafe fn $name<F: ::std::os::fd::AsFd>(fd: &F) -> ::std::io::Result<$ty> {
210 let mut val = ::core::mem::MaybeUninit::<$ty>::uninit();
211 let op = $code;
212 $crate::ffi!(unsafe {
213 ::libc::ioctl(
214 ::std::os::fd::AsRawFd::as_raw_fd(&fd.as_fd()),
215 op as _,
216 val.as_mut_ptr(),
217 )
218 })?;
219 ::std::io::Result::Ok(unsafe { val.assume_init() })
220 }
221 };
222 ($name:ident, $type_:expr, $nr:expr, $ty:ty) => {
223 $crate::ioctl_read!(
224 $name,
225 $crate::sys::ioctl::ioctl_ior::<$ty>($type_, $nr),
226 $ty
227 );
228 };
229}
230
231#[cfg(test)]
232#[path = "ioctl_test.rs"]
233mod tests;
234