1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::fs::File; 6 use std::io::{Error, ErrorKind, Result}; 7 use std::os::unix::io::{AsRawFd, RawFd}; 8 9 use data_model::VolatileSlice; 10 11 use crate::{fallocate, FallocateMode}; 12 13 /// A trait for flushing the contents of a file to disk. 14 /// This is equivalent to File's `sync_all` method, but 15 /// wrapped in a trait so that it can be implemented for 16 /// other types. 17 pub trait FileSync { 18 // Flush buffers related to this file to disk. fsync(&mut self) -> Result<()>19 fn fsync(&mut self) -> Result<()>; 20 } 21 22 impl FileSync for File { fsync(&mut self) -> Result<()>23 fn fsync(&mut self) -> Result<()> { 24 self.sync_all() 25 } 26 } 27 28 /// A trait for setting the size of a file. 29 /// This is equivalent to File's `set_len` method, but 30 /// wrapped in a trait so that it can be implemented for 31 /// other types. 32 pub trait FileSetLen { 33 // Set the size of this file. 34 // This is the moral equivalent of `ftruncate()`. set_len(&self, _len: u64) -> Result<()>35 fn set_len(&self, _len: u64) -> Result<()>; 36 } 37 38 impl FileSetLen for File { set_len(&self, len: u64) -> Result<()>39 fn set_len(&self, len: u64) -> Result<()> { 40 File::set_len(self, len) 41 } 42 } 43 44 /// A trait for getting the size of a file. 45 /// This is equivalent to File's metadata().len() method, 46 /// but wrapped in a trait so that it can be implemented for 47 /// other types. 48 pub trait FileGetLen { 49 /// Get the current length of the file in bytes. get_len(&self) -> Result<u64>50 fn get_len(&self) -> Result<u64>; 51 } 52 53 impl FileGetLen for File { get_len(&self) -> Result<u64>54 fn get_len(&self) -> Result<u64> { 55 Ok(self.metadata()?.len()) 56 } 57 } 58 59 /// A trait for allocating disk space in a sparse file. 60 /// This is equivalent to fallocate() with no special flags. 61 pub trait FileAllocate { 62 /// Allocate storage for the region of the file starting at `offset` and extending `len` bytes. allocate(&mut self, offset: u64, len: u64) -> Result<()>63 fn allocate(&mut self, offset: u64, len: u64) -> Result<()>; 64 } 65 66 impl FileAllocate for File { allocate(&mut self, offset: u64, len: u64) -> Result<()>67 fn allocate(&mut self, offset: u64, len: u64) -> Result<()> { 68 fallocate(self, FallocateMode::Allocate, true, offset, len) 69 .map_err(|e| Error::from_raw_os_error(e.errno())) 70 } 71 } 72 73 /// A trait similar to `Read` and `Write`, but uses volatile memory as buffers. 74 pub trait FileReadWriteVolatile { 75 /// Read bytes from this file into the given slice, returning the number of bytes read on 76 /// success. read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>77 fn read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>; 78 79 /// Like `read_volatile`, except it reads to a slice of buffers. Data is copied to fill each 80 /// buffer in order, with the final buffer written to possibly being only partially filled. This 81 /// method must behave as a single call to `read_volatile` with the buffers concatenated would. 82 /// The default implementation calls `read_volatile` with either the first nonempty buffer 83 /// provided, or returns `Ok(0)` if none exists. read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize>84 fn read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> { 85 bufs.iter() 86 .find(|b| b.size() > 0) 87 .map(|&b| self.read_volatile(b)) 88 .unwrap_or(Ok(0)) 89 } 90 91 /// Reads bytes from this into the given slice until all bytes in the slice are written, or an 92 /// error is returned. read_exact_volatile(&mut self, mut slice: VolatileSlice) -> Result<()>93 fn read_exact_volatile(&mut self, mut slice: VolatileSlice) -> Result<()> { 94 while slice.size() > 0 { 95 let bytes_read = self.read_volatile(slice)?; 96 if bytes_read == 0 { 97 return Err(Error::from(ErrorKind::UnexpectedEof)); 98 } 99 // Will panic if read_volatile read more bytes than we gave it, which would be worthy of 100 // a panic. 101 slice = slice.offset(bytes_read).unwrap(); 102 } 103 Ok(()) 104 } 105 106 /// Write bytes from the slice to the given file, returning the number of bytes written on 107 /// success. write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>108 fn write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>; 109 110 /// Like `write_volatile`, except that it writes from a slice of buffers. Data is copied from 111 /// each buffer in order, with the final buffer read from possibly being only partially 112 /// consumed. This method must behave as a call to `write_volatile` with the buffers 113 /// concatenated would. The default implementation calls `write_volatile` with either the first 114 /// nonempty buffer provided, or returns `Ok(0)` if none exists. write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize>115 fn write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> { 116 bufs.iter() 117 .find(|b| b.size() > 0) 118 .map(|&b| self.write_volatile(b)) 119 .unwrap_or(Ok(0)) 120 } 121 122 /// Write bytes from the slice to the given file until all the bytes from the slice have been 123 /// written, or an error is returned. write_all_volatile(&mut self, mut slice: VolatileSlice) -> Result<()>124 fn write_all_volatile(&mut self, mut slice: VolatileSlice) -> Result<()> { 125 while slice.size() > 0 { 126 let bytes_written = self.write_volatile(slice)?; 127 if bytes_written == 0 { 128 return Err(Error::from(ErrorKind::WriteZero)); 129 } 130 // Will panic if read_volatile read more bytes than we gave it, which would be worthy of 131 // a panic. 132 slice = slice.offset(bytes_written).unwrap(); 133 } 134 Ok(()) 135 } 136 } 137 138 impl<'a, T: FileReadWriteVolatile + ?Sized> FileReadWriteVolatile for &'a mut T { read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>139 fn read_volatile(&mut self, slice: VolatileSlice) -> Result<usize> { 140 (**self).read_volatile(slice) 141 } 142 read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize>143 fn read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> { 144 (**self).read_vectored_volatile(bufs) 145 } 146 read_exact_volatile(&mut self, slice: VolatileSlice) -> Result<()>147 fn read_exact_volatile(&mut self, slice: VolatileSlice) -> Result<()> { 148 (**self).read_exact_volatile(slice) 149 } 150 write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>151 fn write_volatile(&mut self, slice: VolatileSlice) -> Result<usize> { 152 (**self).write_volatile(slice) 153 } 154 write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize>155 fn write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> { 156 (**self).write_vectored_volatile(bufs) 157 } 158 write_all_volatile(&mut self, slice: VolatileSlice) -> Result<()>159 fn write_all_volatile(&mut self, slice: VolatileSlice) -> Result<()> { 160 (**self).write_all_volatile(slice) 161 } 162 } 163 164 /// A trait similar to the unix `ReadExt` and `WriteExt` traits, but for volatile memory. 165 pub trait FileReadWriteAtVolatile { 166 /// Reads bytes from this file at `offset` into the given slice, returning the number of bytes 167 /// read on success. read_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<usize>168 fn read_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<usize>; 169 170 /// Like `read_at_volatile`, except it reads to a slice of buffers. Data is copied to fill each 171 /// buffer in order, with the final buffer written to possibly being only partially filled. This 172 /// method must behave as a single call to `read_at_volatile` with the buffers concatenated 173 /// would. The default implementation calls `read_at_volatile` with either the first nonempty 174 /// buffer provided, or returns `Ok(0)` if none exists. read_vectored_at_volatile(&mut self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>175 fn read_vectored_at_volatile(&mut self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> { 176 if let Some(&slice) = bufs.first() { 177 self.read_at_volatile(slice, offset) 178 } else { 179 Ok(0) 180 } 181 } 182 183 /// Reads bytes from this file at `offset` into the given slice until all bytes in the slice are 184 /// read, or an error is returned. read_exact_at_volatile(&mut self, mut slice: VolatileSlice, mut offset: u64) -> Result<()>185 fn read_exact_at_volatile(&mut self, mut slice: VolatileSlice, mut offset: u64) -> Result<()> { 186 while slice.size() > 0 { 187 match self.read_at_volatile(slice, offset) { 188 Ok(0) => return Err(Error::from(ErrorKind::UnexpectedEof)), 189 Ok(n) => { 190 slice = slice.offset(n).unwrap(); 191 offset = offset.checked_add(n as u64).unwrap(); 192 } 193 Err(ref e) if e.kind() == ErrorKind::Interrupted => {} 194 Err(e) => return Err(e), 195 } 196 } 197 Ok(()) 198 } 199 200 /// Writes bytes from this file at `offset` into the given slice, returning the number of bytes 201 /// written on success. write_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<usize>202 fn write_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<usize>; 203 204 /// Like `write_at_at_volatile`, except that it writes from a slice of buffers. Data is copied 205 /// from each buffer in order, with the final buffer read from possibly being only partially 206 /// consumed. This method must behave as a call to `write_at_volatile` with the buffers 207 /// concatenated would. The default implementation calls `write_at_volatile` with either the 208 /// first nonempty buffer provided, or returns `Ok(0)` if none exists. write_vectored_at_volatile(&mut self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>209 fn write_vectored_at_volatile(&mut self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> { 210 if let Some(&slice) = bufs.first() { 211 self.write_at_volatile(slice, offset) 212 } else { 213 Ok(0) 214 } 215 } 216 217 /// Writes bytes from this file at `offset` into the given slice until all bytes in the slice 218 /// are written, or an error is returned. write_all_at_volatile(&mut self, mut slice: VolatileSlice, mut offset: u64) -> Result<()>219 fn write_all_at_volatile(&mut self, mut slice: VolatileSlice, mut offset: u64) -> Result<()> { 220 while slice.size() > 0 { 221 match self.write_at_volatile(slice, offset) { 222 Ok(0) => return Err(Error::from(ErrorKind::WriteZero)), 223 Ok(n) => { 224 slice = slice.offset(n).unwrap(); 225 offset = offset.checked_add(n as u64).unwrap(); 226 } 227 Err(ref e) if e.kind() == ErrorKind::Interrupted => {} 228 Err(e) => return Err(e), 229 } 230 } 231 Ok(()) 232 } 233 } 234 235 impl<'a, T: FileReadWriteAtVolatile + ?Sized> FileReadWriteAtVolatile for &'a mut T { read_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<usize>236 fn read_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<usize> { 237 (**self).read_at_volatile(slice, offset) 238 } 239 read_vectored_at_volatile(&mut self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>240 fn read_vectored_at_volatile(&mut self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> { 241 (**self).read_vectored_at_volatile(bufs, offset) 242 } 243 read_exact_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<()>244 fn read_exact_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<()> { 245 (**self).read_exact_at_volatile(slice, offset) 246 } 247 write_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<usize>248 fn write_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<usize> { 249 (**self).write_at_volatile(slice, offset) 250 } 251 write_vectored_at_volatile(&mut self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>252 fn write_vectored_at_volatile(&mut self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> { 253 (**self).write_vectored_at_volatile(bufs, offset) 254 } 255 write_all_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<()>256 fn write_all_at_volatile(&mut self, slice: VolatileSlice, offset: u64) -> Result<()> { 257 (**self).write_all_at_volatile(slice, offset) 258 } 259 } 260 261 // This module allows the below macros to refer to $crate::file_traits::lib::X and ensures other 262 // crates don't need to add additional crates to their Cargo.toml. 263 pub mod lib { 264 pub use libc::{ 265 c_int, c_void, iovec, off64_t, pread64, preadv64, pwrite64, pwritev64, read, readv, size_t, 266 write, writev, 267 }; 268 269 pub use data_model::VolatileSlice; 270 } 271 272 #[macro_export] 273 macro_rules! volatile_impl { 274 ($ty:ty) => { 275 impl FileReadWriteVolatile for $ty { 276 fn read_volatile( 277 &mut self, 278 slice: $crate::file_traits::lib::VolatileSlice, 279 ) -> std::io::Result<usize> { 280 // Safe because only bytes inside the slice are accessed and the kernel is expected 281 // to handle arbitrary memory for I/O. 282 let ret = unsafe { 283 $crate::file_traits::lib::read( 284 self.as_raw_fd(), 285 slice.as_mut_ptr() as *mut std::ffi::c_void, 286 slice.size() as usize, 287 ) 288 }; 289 if ret >= 0 { 290 Ok(ret as usize) 291 } else { 292 Err(std::io::Error::last_os_error()) 293 } 294 } 295 296 fn read_vectored_volatile( 297 &mut self, 298 bufs: &[$crate::file_traits::lib::VolatileSlice], 299 ) -> std::io::Result<usize> { 300 let iovecs = $crate::file_traits::lib::VolatileSlice::as_iobufs(bufs); 301 302 if iovecs.is_empty() { 303 return Ok(0); 304 } 305 306 // Safe because only bytes inside the buffers are accessed and the kernel is 307 // expected to handle arbitrary memory for I/O. 308 let ret = unsafe { 309 $crate::file_traits::lib::readv( 310 self.as_raw_fd(), 311 iovecs.as_ptr(), 312 iovecs.len() as std::os::raw::c_int, 313 ) 314 }; 315 if ret >= 0 { 316 Ok(ret as usize) 317 } else { 318 Err(std::io::Error::last_os_error()) 319 } 320 } 321 322 fn write_volatile( 323 &mut self, 324 slice: $crate::file_traits::lib::VolatileSlice, 325 ) -> std::io::Result<usize> { 326 // Safe because only bytes inside the slice are accessed and the kernel is expected 327 // to handle arbitrary memory for I/O. 328 let ret = unsafe { 329 $crate::file_traits::lib::write( 330 self.as_raw_fd(), 331 slice.as_ptr() as *const std::ffi::c_void, 332 slice.size() as usize, 333 ) 334 }; 335 if ret >= 0 { 336 Ok(ret as usize) 337 } else { 338 Err(std::io::Error::last_os_error()) 339 } 340 } 341 342 fn write_vectored_volatile( 343 &mut self, 344 bufs: &[$crate::file_traits::lib::VolatileSlice], 345 ) -> std::io::Result<usize> { 346 let iovecs = $crate::file_traits::lib::VolatileSlice::as_iobufs(bufs); 347 348 if iovecs.is_empty() { 349 return Ok(0); 350 } 351 352 // Safe because only bytes inside the buffers are accessed and the kernel is 353 // expected to handle arbitrary memory for I/O. 354 let ret = unsafe { 355 $crate::file_traits::lib::writev( 356 self.as_raw_fd(), 357 iovecs.as_ptr(), 358 iovecs.len() as std::os::raw::c_int, 359 ) 360 }; 361 if ret >= 0 { 362 Ok(ret as usize) 363 } else { 364 Err(std::io::Error::last_os_error()) 365 } 366 } 367 } 368 }; 369 } 370 371 #[macro_export] 372 macro_rules! volatile_at_impl { 373 ($ty:ty) => { 374 impl FileReadWriteAtVolatile for $ty { 375 fn read_at_volatile( 376 &mut self, 377 slice: $crate::file_traits::lib::VolatileSlice, 378 offset: u64, 379 ) -> std::io::Result<usize> { 380 // Safe because only bytes inside the slice are accessed and the kernel is expected 381 // to handle arbitrary memory for I/O. 382 let ret = unsafe { 383 $crate::file_traits::lib::pread64( 384 self.as_raw_fd(), 385 slice.as_mut_ptr() as *mut std::ffi::c_void, 386 slice.size() as usize, 387 offset as $crate::file_traits::lib::off64_t, 388 ) 389 }; 390 391 if ret >= 0 { 392 Ok(ret as usize) 393 } else { 394 Err(std::io::Error::last_os_error()) 395 } 396 } 397 398 fn read_vectored_at_volatile( 399 &mut self, 400 bufs: &[$crate::file_traits::lib::VolatileSlice], 401 offset: u64, 402 ) -> std::io::Result<usize> { 403 let iovecs = $crate::file_traits::lib::VolatileSlice::as_iobufs(bufs); 404 405 if iovecs.is_empty() { 406 return Ok(0); 407 } 408 409 // Safe because only bytes inside the buffers are accessed and the kernel is 410 // expected to handle arbitrary memory for I/O. 411 let ret = unsafe { 412 $crate::file_traits::lib::preadv64( 413 self.as_raw_fd(), 414 iovecs.as_ptr(), 415 iovecs.len() as std::os::raw::c_int, 416 offset as $crate::file_traits::lib::off64_t, 417 ) 418 }; 419 if ret >= 0 { 420 Ok(ret as usize) 421 } else { 422 Err(std::io::Error::last_os_error()) 423 } 424 } 425 426 fn write_at_volatile( 427 &mut self, 428 slice: $crate::file_traits::lib::VolatileSlice, 429 offset: u64, 430 ) -> std::io::Result<usize> { 431 // Safe because only bytes inside the slice are accessed and the kernel is expected 432 // to handle arbitrary memory for I/O. 433 let ret = unsafe { 434 $crate::file_traits::lib::pwrite64( 435 self.as_raw_fd(), 436 slice.as_ptr() as *const std::ffi::c_void, 437 slice.size() as usize, 438 offset as $crate::file_traits::lib::off64_t, 439 ) 440 }; 441 442 if ret >= 0 { 443 Ok(ret as usize) 444 } else { 445 Err(std::io::Error::last_os_error()) 446 } 447 } 448 449 fn write_vectored_at_volatile( 450 &mut self, 451 bufs: &[$crate::file_traits::lib::VolatileSlice], 452 offset: u64, 453 ) -> std::io::Result<usize> { 454 let iovecs = $crate::file_traits::lib::VolatileSlice::as_iobufs(bufs); 455 456 if iovecs.is_empty() { 457 return Ok(0); 458 } 459 460 // Safe because only bytes inside the buffers are accessed and the kernel is 461 // expected to handle arbitrary memory for I/O. 462 let ret = unsafe { 463 $crate::file_traits::lib::pwritev64( 464 self.as_raw_fd(), 465 iovecs.as_ptr(), 466 iovecs.len() as std::os::raw::c_int, 467 offset as $crate::file_traits::lib::off64_t, 468 ) 469 }; 470 if ret >= 0 { 471 Ok(ret as usize) 472 } else { 473 Err(std::io::Error::last_os_error()) 474 } 475 } 476 } 477 }; 478 } 479 480 volatile_impl!(File); 481 volatile_at_impl!(File); 482 483 /// A trait similar to `AsRawFd` but supports an arbitrary number of file descriptors. 484 pub trait AsRawFds { as_raw_fds(&self) -> Vec<RawFd>485 fn as_raw_fds(&self) -> Vec<RawFd>; 486 } 487 488 impl<T> AsRawFds for T 489 where 490 T: AsRawFd, 491 { as_raw_fds(&self) -> Vec<RawFd>492 fn as_raw_fds(&self) -> Vec<RawFd> { 493 vec![self.as_raw_fd()] 494 } 495 } 496