• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
8 
9 use data_model::VolatileSlice;
10 
11 use libc::{c_void, read, write};
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 similar to `Read` and `Write`, but uses volatile memory as buffers.
45 pub trait FileReadWriteVolatile {
46     /// Read bytes from this file into the given slice, returning the number of bytes read on
47     /// success.
read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>48     fn read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>;
49 
50     /// Reads bytes from this into the given slice until all bytes in the slice are written, or an
51     /// error is returned.
read_exact_volatile(&mut self, mut slice: VolatileSlice) -> Result<()>52     fn read_exact_volatile(&mut self, mut slice: VolatileSlice) -> Result<()> {
53         while slice.size() > 0 {
54             let bytes_read = self.read_volatile(slice)?;
55             if bytes_read == 0 {
56                 return Err(Error::from(ErrorKind::UnexpectedEof));
57             }
58             // Will panic if read_volatile read more bytes than we gave it, which would be worthy of
59             // a panic.
60             slice = slice.offset(bytes_read as u64).unwrap();
61         }
62         Ok(())
63     }
64 
65     /// Write bytes from the slice to the given file, returning the number of bytes written on
66     /// success.
write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>67     fn write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>;
68 
69     /// Write bytes from the slice to the given file until all the bytes from the slice have been
70     /// written, or an error is returned.
write_all_volatile(&mut self, mut slice: VolatileSlice) -> Result<()>71     fn write_all_volatile(&mut self, mut slice: VolatileSlice) -> Result<()> {
72         while slice.size() > 0 {
73             let bytes_written = self.write_volatile(slice)?;
74             if bytes_written == 0 {
75                 return Err(Error::from(ErrorKind::WriteZero));
76             }
77             // Will panic if read_volatile read more bytes than we gave it, which would be worthy of
78             // a panic.
79             slice = slice.offset(bytes_written as u64).unwrap();
80         }
81         Ok(())
82     }
83 }
84 
85 impl FileReadWriteVolatile for File {
read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>86     fn read_volatile(&mut self, slice: VolatileSlice) -> Result<usize> {
87         // Safe because only bytes inside the slice are accessed and the kernel is expected to
88         // handle arbitrary memory for I/O.
89         let ret = unsafe {
90             read(
91                 self.as_raw_fd(),
92                 slice.as_ptr() as *mut c_void,
93                 slice.size() as usize,
94             )
95         };
96         if ret >= 0 {
97             Ok(ret as usize)
98         } else {
99             Err(Error::last_os_error())
100         }
101     }
102 
write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>103     fn write_volatile(&mut self, slice: VolatileSlice) -> Result<usize> {
104         // Safe because only bytes inside the slice are accessed and the kernel is expected to
105         // handle arbitrary memory for I/O.
106         let ret = unsafe {
107             write(
108                 self.as_raw_fd(),
109                 slice.as_ptr() as *const c_void,
110                 slice.size() as usize,
111             )
112         };
113         if ret >= 0 {
114             Ok(ret as usize)
115         } else {
116             Err(Error::last_os_error())
117         }
118     }
119 }
120