Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/base/src/sys/unix/file_traits.rs
5394 views
1
// Copyright 2018 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
//! FileReadWriteAtVolatile is implemented in terms of `pread` and `pwrite`. These are provided by
6
//! platform-specific imports. On Linux they resolve to the 64-bit versions, while on MacOS the
7
//! base versions are already 64-bit.
8
9
use std::fs::File;
10
use std::os::unix::io::AsRawFd;
11
use std::os::unix::net::UnixStream;
12
13
use crate::FileReadWriteAtVolatile;
14
use crate::FileReadWriteVolatile;
15
16
// This module allows the below macros to refer to $crate::unix::file_traits::lib::X and ensures
17
// other crates don't need to add additional crates to their Cargo.toml.
18
pub mod lib {
19
pub use libc::c_int;
20
pub use libc::c_void;
21
pub use libc::iovec;
22
pub use libc::read;
23
pub use libc::readv;
24
pub use libc::size_t;
25
pub use libc::write;
26
pub use libc::writev;
27
}
28
29
#[macro_export]
30
macro_rules! volatile_impl {
31
($ty:ty) => {
32
impl FileReadWriteVolatile for $ty {
33
fn read_volatile(&mut self, slice: $crate::VolatileSlice) -> std::io::Result<usize> {
34
// SAFETY:
35
// Safe because only bytes inside the slice are accessed and the kernel is expected
36
// to handle arbitrary memory for I/O.
37
let ret = unsafe {
38
$crate::unix::file_traits::lib::read(
39
self.as_raw_fd(),
40
slice.as_mut_ptr() as *mut std::ffi::c_void,
41
slice.size() as usize,
42
)
43
};
44
if ret >= 0 {
45
Ok(ret as usize)
46
} else {
47
Err(std::io::Error::last_os_error())
48
}
49
}
50
51
fn read_vectored_volatile(
52
&mut self,
53
bufs: &[$crate::VolatileSlice],
54
) -> std::io::Result<usize> {
55
let iobufs = $crate::VolatileSlice::as_iobufs(bufs);
56
let iovecs = $crate::IoBufMut::as_iobufs(iobufs);
57
58
if iovecs.is_empty() {
59
return Ok(0);
60
}
61
62
// SAFETY:
63
// Safe because only bytes inside the buffers are accessed and the kernel is
64
// expected to handle arbitrary memory for I/O.
65
let ret = unsafe {
66
$crate::unix::file_traits::lib::readv(
67
self.as_raw_fd(),
68
iovecs.as_ptr(),
69
iovecs.len() as std::os::raw::c_int,
70
)
71
};
72
if ret >= 0 {
73
Ok(ret as usize)
74
} else {
75
Err(std::io::Error::last_os_error())
76
}
77
}
78
79
fn write_volatile(&mut self, slice: $crate::VolatileSlice) -> std::io::Result<usize> {
80
// SAFETY:
81
// Safe because only bytes inside the slice are accessed and the kernel is expected
82
// to handle arbitrary memory for I/O.
83
let ret = unsafe {
84
$crate::unix::file_traits::lib::write(
85
self.as_raw_fd(),
86
slice.as_ptr() as *const std::ffi::c_void,
87
slice.size() as usize,
88
)
89
};
90
if ret >= 0 {
91
Ok(ret as usize)
92
} else {
93
Err(std::io::Error::last_os_error())
94
}
95
}
96
97
fn write_vectored_volatile(
98
&mut self,
99
bufs: &[$crate::VolatileSlice],
100
) -> std::io::Result<usize> {
101
let iobufs = $crate::VolatileSlice::as_iobufs(bufs);
102
let iovecs = $crate::IoBufMut::as_iobufs(iobufs);
103
104
if iovecs.is_empty() {
105
return Ok(0);
106
}
107
108
// SAFETY:
109
// Safe because only bytes inside the buffers are accessed and the kernel is
110
// expected to handle arbitrary memory for I/O.
111
let ret = unsafe {
112
$crate::unix::file_traits::lib::writev(
113
self.as_raw_fd(),
114
iovecs.as_ptr(),
115
iovecs.len() as std::os::raw::c_int,
116
)
117
};
118
if ret >= 0 {
119
Ok(ret as usize)
120
} else {
121
Err(std::io::Error::last_os_error())
122
}
123
}
124
}
125
};
126
}
127
128
#[macro_export]
129
macro_rules! volatile_at_impl {
130
($ty:ty) => {
131
impl FileReadWriteAtVolatile for $ty {
132
fn read_at_volatile(
133
&self,
134
slice: $crate::VolatileSlice,
135
offset: u64,
136
) -> std::io::Result<usize> {
137
// SAFETY:
138
// Safe because only bytes inside the slice are accessed and the kernel is expected
139
// to handle arbitrary memory for I/O.
140
let ret = unsafe {
141
$crate::platform::pread(
142
self.as_raw_fd(),
143
slice.as_mut_ptr() as *mut std::ffi::c_void,
144
slice.size() as usize,
145
offset as $crate::platform::off_t,
146
)
147
};
148
149
if ret >= 0 {
150
Ok(ret as usize)
151
} else {
152
Err(std::io::Error::last_os_error())
153
}
154
}
155
156
fn read_vectored_at_volatile(
157
&self,
158
bufs: &[$crate::VolatileSlice],
159
offset: u64,
160
) -> std::io::Result<usize> {
161
let iobufs = $crate::VolatileSlice::as_iobufs(bufs);
162
let iovecs = $crate::IoBufMut::as_iobufs(iobufs);
163
164
if iovecs.is_empty() {
165
return Ok(0);
166
}
167
168
// SAFETY:
169
// Safe because only bytes inside the buffers are accessed and the kernel is
170
// expected to handle arbitrary memory for I/O.
171
let ret = unsafe {
172
$crate::platform::preadv(
173
self.as_raw_fd(),
174
iovecs.as_ptr(),
175
iovecs.len() as std::os::raw::c_int,
176
offset as $crate::platform::off_t,
177
)
178
};
179
if ret >= 0 {
180
Ok(ret as usize)
181
} else {
182
Err(std::io::Error::last_os_error())
183
}
184
}
185
186
fn write_at_volatile(
187
&self,
188
slice: $crate::VolatileSlice,
189
offset: u64,
190
) -> std::io::Result<usize> {
191
// SAFETY:
192
// Safe because only bytes inside the slice are accessed and the kernel is expected
193
// to handle arbitrary memory for I/O.
194
let ret = unsafe {
195
$crate::platform::pwrite(
196
self.as_raw_fd(),
197
slice.as_ptr() as *const std::ffi::c_void,
198
slice.size() as usize,
199
offset as $crate::platform::off_t,
200
)
201
};
202
203
if ret >= 0 {
204
Ok(ret as usize)
205
} else {
206
Err(std::io::Error::last_os_error())
207
}
208
}
209
210
fn write_vectored_at_volatile(
211
&self,
212
bufs: &[$crate::VolatileSlice],
213
offset: u64,
214
) -> std::io::Result<usize> {
215
let iobufs = $crate::VolatileSlice::as_iobufs(bufs);
216
let iovecs = $crate::IoBufMut::as_iobufs(iobufs);
217
218
if iovecs.is_empty() {
219
return Ok(0);
220
}
221
222
// SAFETY:
223
// Safe because only bytes inside the buffers are accessed and the kernel is
224
// expected to handle arbitrary memory for I/O.
225
let ret = unsafe {
226
$crate::platform::pwritev(
227
self.as_raw_fd(),
228
iovecs.as_ptr(),
229
iovecs.len() as std::os::raw::c_int,
230
offset as $crate::platform::off_t,
231
)
232
};
233
if ret >= 0 {
234
Ok(ret as usize)
235
} else {
236
Err(std::io::Error::last_os_error())
237
}
238
}
239
}
240
};
241
}
242
243
volatile_impl!(File);
244
volatile_at_impl!(File);
245
volatile_impl!(UnixStream);
246
247