xref: /aosp_15_r20/external/crosvm/base/src/file_traits.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Error;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::io::ErrorKind;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Result;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use crate::VolatileSlice;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker /// A trait for flushing the contents of a file to disk.
13*bb4ee6a4SAndroid Build Coastguard Worker /// This is equivalent to File's `sync_all` and `sync_data` methods, but wrapped in a trait so that
14*bb4ee6a4SAndroid Build Coastguard Worker /// it can be implemented for other types.
15*bb4ee6a4SAndroid Build Coastguard Worker pub trait FileSync {
16*bb4ee6a4SAndroid Build Coastguard Worker     // Flush buffers related to this file to disk.
fsync(&self) -> Result<()>17*bb4ee6a4SAndroid Build Coastguard Worker     fn fsync(&self) -> Result<()>;
18*bb4ee6a4SAndroid Build Coastguard Worker 
19*bb4ee6a4SAndroid Build Coastguard Worker     // Flush buffers related to this file's data to disk, avoiding updating extra metadata. Note
20*bb4ee6a4SAndroid Build Coastguard Worker     // that an implementation may simply implement fsync for fdatasync.
fdatasync(&self) -> Result<()>21*bb4ee6a4SAndroid Build Coastguard Worker     fn fdatasync(&self) -> Result<()>;
22*bb4ee6a4SAndroid Build Coastguard Worker }
23*bb4ee6a4SAndroid Build Coastguard Worker 
24*bb4ee6a4SAndroid Build Coastguard Worker impl FileSync for File {
fsync(&self) -> Result<()>25*bb4ee6a4SAndroid Build Coastguard Worker     fn fsync(&self) -> Result<()> {
26*bb4ee6a4SAndroid Build Coastguard Worker         self.sync_all()
27*bb4ee6a4SAndroid Build Coastguard Worker     }
28*bb4ee6a4SAndroid Build Coastguard Worker 
fdatasync(&self) -> Result<()>29*bb4ee6a4SAndroid Build Coastguard Worker     fn fdatasync(&self) -> Result<()> {
30*bb4ee6a4SAndroid Build Coastguard Worker         self.sync_data()
31*bb4ee6a4SAndroid Build Coastguard Worker     }
32*bb4ee6a4SAndroid Build Coastguard Worker }
33*bb4ee6a4SAndroid Build Coastguard Worker 
34*bb4ee6a4SAndroid Build Coastguard Worker /// A trait for setting the size of a file.
35*bb4ee6a4SAndroid Build Coastguard Worker /// This is equivalent to File's `set_len` method, but
36*bb4ee6a4SAndroid Build Coastguard Worker /// wrapped in a trait so that it can be implemented for
37*bb4ee6a4SAndroid Build Coastguard Worker /// other types.
38*bb4ee6a4SAndroid Build Coastguard Worker pub trait FileSetLen {
39*bb4ee6a4SAndroid Build Coastguard Worker     // Set the size of this file.
40*bb4ee6a4SAndroid Build Coastguard Worker     // This is the moral equivalent of `ftruncate()`.
set_len(&self, _len: u64) -> Result<()>41*bb4ee6a4SAndroid Build Coastguard Worker     fn set_len(&self, _len: u64) -> Result<()>;
42*bb4ee6a4SAndroid Build Coastguard Worker }
43*bb4ee6a4SAndroid Build Coastguard Worker 
44*bb4ee6a4SAndroid Build Coastguard Worker impl FileSetLen for File {
set_len(&self, len: u64) -> Result<()>45*bb4ee6a4SAndroid Build Coastguard Worker     fn set_len(&self, len: u64) -> Result<()> {
46*bb4ee6a4SAndroid Build Coastguard Worker         File::set_len(self, len)
47*bb4ee6a4SAndroid Build Coastguard Worker     }
48*bb4ee6a4SAndroid Build Coastguard Worker }
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker /// A trait for allocating disk space in a sparse file.
51*bb4ee6a4SAndroid Build Coastguard Worker /// This is equivalent to fallocate() with no special flags.
52*bb4ee6a4SAndroid Build Coastguard Worker pub trait FileAllocate {
53*bb4ee6a4SAndroid Build Coastguard Worker     /// Allocate storage for the region of the file starting at `offset` and extending `len` bytes.
allocate(&self, offset: u64, len: u64) -> Result<()>54*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate(&self, offset: u64, len: u64) -> Result<()>;
55*bb4ee6a4SAndroid Build Coastguard Worker }
56*bb4ee6a4SAndroid Build Coastguard Worker 
57*bb4ee6a4SAndroid Build Coastguard Worker /// A trait for getting the size of a file.
58*bb4ee6a4SAndroid Build Coastguard Worker /// This is equivalent to File's metadata().len() method,
59*bb4ee6a4SAndroid Build Coastguard Worker /// but wrapped in a trait so that it can be implemented for
60*bb4ee6a4SAndroid Build Coastguard Worker /// other types.
61*bb4ee6a4SAndroid Build Coastguard Worker pub trait FileGetLen {
62*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the current length of the file in bytes.
get_len(&self) -> Result<u64>63*bb4ee6a4SAndroid Build Coastguard Worker     fn get_len(&self) -> Result<u64>;
64*bb4ee6a4SAndroid Build Coastguard Worker }
65*bb4ee6a4SAndroid Build Coastguard Worker 
66*bb4ee6a4SAndroid Build Coastguard Worker impl FileGetLen for File {
get_len(&self) -> Result<u64>67*bb4ee6a4SAndroid Build Coastguard Worker     fn get_len(&self) -> Result<u64> {
68*bb4ee6a4SAndroid Build Coastguard Worker         Ok(self.metadata()?.len())
69*bb4ee6a4SAndroid Build Coastguard Worker     }
70*bb4ee6a4SAndroid Build Coastguard Worker }
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker /// A trait similar to `Read` and `Write`, but uses volatile memory as buffers.
73*bb4ee6a4SAndroid Build Coastguard Worker pub trait FileReadWriteVolatile {
74*bb4ee6a4SAndroid Build Coastguard Worker     /// Read bytes from this file into the given slice, returning the number of bytes read on
75*bb4ee6a4SAndroid Build Coastguard Worker     /// success.
read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>76*bb4ee6a4SAndroid Build Coastguard Worker     fn read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>;
77*bb4ee6a4SAndroid Build Coastguard Worker 
78*bb4ee6a4SAndroid Build Coastguard Worker     /// Like `read_volatile`, except it reads to a slice of buffers. Data is copied to fill each
79*bb4ee6a4SAndroid Build Coastguard Worker     /// buffer in order, with the final buffer written to possibly being only partially filled. This
80*bb4ee6a4SAndroid Build Coastguard Worker     /// method must behave as a single call to `read_volatile` with the buffers concatenated would.
81*bb4ee6a4SAndroid Build Coastguard Worker     /// The default implementation calls `read_volatile` with either the first nonempty buffer
82*bb4ee6a4SAndroid Build Coastguard Worker     /// provided, or returns `Ok(0)` if none exists.
read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize>83*bb4ee6a4SAndroid Build Coastguard Worker     fn read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> {
84*bb4ee6a4SAndroid Build Coastguard Worker         bufs.iter()
85*bb4ee6a4SAndroid Build Coastguard Worker             .find(|b| b.size() > 0)
86*bb4ee6a4SAndroid Build Coastguard Worker             .map(|&b| self.read_volatile(b))
87*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or(Ok(0))
88*bb4ee6a4SAndroid Build Coastguard Worker     }
89*bb4ee6a4SAndroid Build Coastguard Worker 
90*bb4ee6a4SAndroid Build Coastguard Worker     /// Reads bytes from this into the given slice until all bytes in the slice are written, or an
91*bb4ee6a4SAndroid Build Coastguard Worker     /// error is returned.
read_exact_volatile(&mut self, mut slice: VolatileSlice) -> Result<()>92*bb4ee6a4SAndroid Build Coastguard Worker     fn read_exact_volatile(&mut self, mut slice: VolatileSlice) -> Result<()> {
93*bb4ee6a4SAndroid Build Coastguard Worker         while slice.size() > 0 {
94*bb4ee6a4SAndroid Build Coastguard Worker             let bytes_read = self.read_volatile(slice)?;
95*bb4ee6a4SAndroid Build Coastguard Worker             if bytes_read == 0 {
96*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(Error::from(ErrorKind::UnexpectedEof));
97*bb4ee6a4SAndroid Build Coastguard Worker             }
98*bb4ee6a4SAndroid Build Coastguard Worker             // Will panic if read_volatile read more bytes than we gave it, which would be worthy of
99*bb4ee6a4SAndroid Build Coastguard Worker             // a panic.
100*bb4ee6a4SAndroid Build Coastguard Worker             slice = slice.offset(bytes_read).unwrap();
101*bb4ee6a4SAndroid Build Coastguard Worker         }
102*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
103*bb4ee6a4SAndroid Build Coastguard Worker     }
104*bb4ee6a4SAndroid Build Coastguard Worker 
105*bb4ee6a4SAndroid Build Coastguard Worker     /// Write bytes from the slice to the given file, returning the number of bytes written on
106*bb4ee6a4SAndroid Build Coastguard Worker     /// success.
write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>107*bb4ee6a4SAndroid Build Coastguard Worker     fn write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>;
108*bb4ee6a4SAndroid Build Coastguard Worker 
109*bb4ee6a4SAndroid Build Coastguard Worker     /// Like `write_volatile`, except that it writes from a slice of buffers. Data is copied from
110*bb4ee6a4SAndroid Build Coastguard Worker     /// each buffer in order, with the final buffer read from possibly being only partially
111*bb4ee6a4SAndroid Build Coastguard Worker     /// consumed. This method must behave as a call to `write_volatile` with the buffers
112*bb4ee6a4SAndroid Build Coastguard Worker     /// concatenated would. The default implementation calls `write_volatile` with either the first
113*bb4ee6a4SAndroid Build Coastguard Worker     /// nonempty buffer provided, or returns `Ok(0)` if none exists.
write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize>114*bb4ee6a4SAndroid Build Coastguard Worker     fn write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> {
115*bb4ee6a4SAndroid Build Coastguard Worker         bufs.iter()
116*bb4ee6a4SAndroid Build Coastguard Worker             .find(|b| b.size() > 0)
117*bb4ee6a4SAndroid Build Coastguard Worker             .map(|&b| self.write_volatile(b))
118*bb4ee6a4SAndroid Build Coastguard Worker             .unwrap_or(Ok(0))
119*bb4ee6a4SAndroid Build Coastguard Worker     }
120*bb4ee6a4SAndroid Build Coastguard Worker 
121*bb4ee6a4SAndroid Build Coastguard Worker     /// Write bytes from the slice to the given file until all the bytes from the slice have been
122*bb4ee6a4SAndroid Build Coastguard Worker     /// written, or an error is returned.
write_all_volatile(&mut self, mut slice: VolatileSlice) -> Result<()>123*bb4ee6a4SAndroid Build Coastguard Worker     fn write_all_volatile(&mut self, mut slice: VolatileSlice) -> Result<()> {
124*bb4ee6a4SAndroid Build Coastguard Worker         while slice.size() > 0 {
125*bb4ee6a4SAndroid Build Coastguard Worker             let bytes_written = self.write_volatile(slice)?;
126*bb4ee6a4SAndroid Build Coastguard Worker             if bytes_written == 0 {
127*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(Error::from(ErrorKind::WriteZero));
128*bb4ee6a4SAndroid Build Coastguard Worker             }
129*bb4ee6a4SAndroid Build Coastguard Worker             // Will panic if read_volatile read more bytes than we gave it, which would be worthy of
130*bb4ee6a4SAndroid Build Coastguard Worker             // a panic.
131*bb4ee6a4SAndroid Build Coastguard Worker             slice = slice.offset(bytes_written).unwrap();
132*bb4ee6a4SAndroid Build Coastguard Worker         }
133*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
134*bb4ee6a4SAndroid Build Coastguard Worker     }
135*bb4ee6a4SAndroid Build Coastguard Worker }
136*bb4ee6a4SAndroid Build Coastguard Worker 
137*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: FileReadWriteVolatile + ?Sized> FileReadWriteVolatile for &'a mut T {
read_volatile(&mut self, slice: VolatileSlice) -> Result<usize>138*bb4ee6a4SAndroid Build Coastguard Worker     fn read_volatile(&mut self, slice: VolatileSlice) -> Result<usize> {
139*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_volatile(slice)
140*bb4ee6a4SAndroid Build Coastguard Worker     }
141*bb4ee6a4SAndroid Build Coastguard Worker 
read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize>142*bb4ee6a4SAndroid Build Coastguard Worker     fn read_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> {
143*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_vectored_volatile(bufs)
144*bb4ee6a4SAndroid Build Coastguard Worker     }
145*bb4ee6a4SAndroid Build Coastguard Worker 
read_exact_volatile(&mut self, slice: VolatileSlice) -> Result<()>146*bb4ee6a4SAndroid Build Coastguard Worker     fn read_exact_volatile(&mut self, slice: VolatileSlice) -> Result<()> {
147*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_exact_volatile(slice)
148*bb4ee6a4SAndroid Build Coastguard Worker     }
149*bb4ee6a4SAndroid Build Coastguard Worker 
write_volatile(&mut self, slice: VolatileSlice) -> Result<usize>150*bb4ee6a4SAndroid Build Coastguard Worker     fn write_volatile(&mut self, slice: VolatileSlice) -> Result<usize> {
151*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_volatile(slice)
152*bb4ee6a4SAndroid Build Coastguard Worker     }
153*bb4ee6a4SAndroid Build Coastguard Worker 
write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize>154*bb4ee6a4SAndroid Build Coastguard Worker     fn write_vectored_volatile(&mut self, bufs: &[VolatileSlice]) -> Result<usize> {
155*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_vectored_volatile(bufs)
156*bb4ee6a4SAndroid Build Coastguard Worker     }
157*bb4ee6a4SAndroid Build Coastguard Worker 
write_all_volatile(&mut self, slice: VolatileSlice) -> Result<()>158*bb4ee6a4SAndroid Build Coastguard Worker     fn write_all_volatile(&mut self, slice: VolatileSlice) -> Result<()> {
159*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_all_volatile(slice)
160*bb4ee6a4SAndroid Build Coastguard Worker     }
161*bb4ee6a4SAndroid Build Coastguard Worker }
162*bb4ee6a4SAndroid Build Coastguard Worker 
163*bb4ee6a4SAndroid Build Coastguard Worker /// A trait similar to the unix `ReadExt` and `WriteExt` traits, but for volatile memory.
164*bb4ee6a4SAndroid Build Coastguard Worker pub trait FileReadWriteAtVolatile {
165*bb4ee6a4SAndroid Build Coastguard Worker     /// Reads bytes from this file at `offset` into the given slice, returning the number of bytes
166*bb4ee6a4SAndroid Build Coastguard Worker     /// read on success. On Windows file pointer will update with the read, but on Linux the
167*bb4ee6a4SAndroid Build Coastguard Worker     /// file pointer will not change.
read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>168*bb4ee6a4SAndroid Build Coastguard Worker     fn read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>;
169*bb4ee6a4SAndroid Build Coastguard Worker 
170*bb4ee6a4SAndroid Build Coastguard Worker     /// Like `read_at_volatile`, except it reads to a slice of buffers. Data is copied to fill each
171*bb4ee6a4SAndroid Build Coastguard Worker     /// buffer in order, with the final buffer written to possibly being only partially filled. This
172*bb4ee6a4SAndroid Build Coastguard Worker     /// method must behave as a single call to `read_at_volatile` with the buffers concatenated
173*bb4ee6a4SAndroid Build Coastguard Worker     /// would. The default implementation calls `read_at_volatile` with either the first nonempty
174*bb4ee6a4SAndroid Build Coastguard Worker     /// buffer provided, or returns `Ok(0)` if none exists.
175*bb4ee6a4SAndroid Build Coastguard Worker     /// On Windows file pointer will update with the read, but on Linux the file pointer will not
176*bb4ee6a4SAndroid Build Coastguard Worker     /// change.
read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>177*bb4ee6a4SAndroid Build Coastguard Worker     fn read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
178*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(&slice) = bufs.first() {
179*bb4ee6a4SAndroid Build Coastguard Worker             self.read_at_volatile(slice, offset)
180*bb4ee6a4SAndroid Build Coastguard Worker         } else {
181*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
182*bb4ee6a4SAndroid Build Coastguard Worker         }
183*bb4ee6a4SAndroid Build Coastguard Worker     }
184*bb4ee6a4SAndroid Build Coastguard Worker 
185*bb4ee6a4SAndroid Build Coastguard Worker     /// Reads bytes from this file at `offset` into the given slice until all bytes in the slice are
186*bb4ee6a4SAndroid Build Coastguard Worker     /// read, or an error is returned. On Windows file pointer will update with the read, but on
187*bb4ee6a4SAndroid Build Coastguard Worker     /// Linux the file pointer will not change.
read_exact_at_volatile(&self, mut slice: VolatileSlice, mut offset: u64) -> Result<()>188*bb4ee6a4SAndroid Build Coastguard Worker     fn read_exact_at_volatile(&self, mut slice: VolatileSlice, mut offset: u64) -> Result<()> {
189*bb4ee6a4SAndroid Build Coastguard Worker         while slice.size() > 0 {
190*bb4ee6a4SAndroid Build Coastguard Worker             match self.read_at_volatile(slice, offset) {
191*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(0) => return Err(Error::from(ErrorKind::UnexpectedEof)),
192*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(n) => {
193*bb4ee6a4SAndroid Build Coastguard Worker                     slice = slice.offset(n).unwrap();
194*bb4ee6a4SAndroid Build Coastguard Worker                     offset = offset.checked_add(n as u64).unwrap();
195*bb4ee6a4SAndroid Build Coastguard Worker                 }
196*bb4ee6a4SAndroid Build Coastguard Worker                 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
197*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => return Err(e),
198*bb4ee6a4SAndroid Build Coastguard Worker             }
199*bb4ee6a4SAndroid Build Coastguard Worker         }
200*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
201*bb4ee6a4SAndroid Build Coastguard Worker     }
202*bb4ee6a4SAndroid Build Coastguard Worker 
203*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes bytes to this file at `offset` from the given slice, returning the number of bytes
204*bb4ee6a4SAndroid Build Coastguard Worker     /// written on success. On Windows file pointer will update with the write, but on Linux the
205*bb4ee6a4SAndroid Build Coastguard Worker     /// file pointer will not change.
write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>206*bb4ee6a4SAndroid Build Coastguard Worker     fn write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>;
207*bb4ee6a4SAndroid Build Coastguard Worker 
208*bb4ee6a4SAndroid Build Coastguard Worker     /// Like `write_at_volatile`, except that it writes from a slice of buffers. Data is copied
209*bb4ee6a4SAndroid Build Coastguard Worker     /// from each buffer in order, with the final buffer read from possibly being only partially
210*bb4ee6a4SAndroid Build Coastguard Worker     /// consumed. This method must behave as a call to `write_at_volatile` with the buffers
211*bb4ee6a4SAndroid Build Coastguard Worker     /// concatenated would. The default implementation calls `write_at_volatile` with either the
212*bb4ee6a4SAndroid Build Coastguard Worker     /// first nonempty buffer provided, or returns `Ok(0)` if none exists.
213*bb4ee6a4SAndroid Build Coastguard Worker     /// On Windows file pointer will update with the write, but on Linux the file pointer will not
214*bb4ee6a4SAndroid Build Coastguard Worker     /// change.
write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>215*bb4ee6a4SAndroid Build Coastguard Worker     fn write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
216*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(&slice) = bufs.first() {
217*bb4ee6a4SAndroid Build Coastguard Worker             self.write_at_volatile(slice, offset)
218*bb4ee6a4SAndroid Build Coastguard Worker         } else {
219*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0)
220*bb4ee6a4SAndroid Build Coastguard Worker         }
221*bb4ee6a4SAndroid Build Coastguard Worker     }
222*bb4ee6a4SAndroid Build Coastguard Worker 
223*bb4ee6a4SAndroid Build Coastguard Worker     /// Writes bytes to this file at `offset` from the given slice until all bytes in the slice
224*bb4ee6a4SAndroid Build Coastguard Worker     /// are written, or an error is returned. On Windows file pointer will update with the write,
225*bb4ee6a4SAndroid Build Coastguard Worker     /// but on Linux the file pointer will not change.
write_all_at_volatile(&self, mut slice: VolatileSlice, mut offset: u64) -> Result<()>226*bb4ee6a4SAndroid Build Coastguard Worker     fn write_all_at_volatile(&self, mut slice: VolatileSlice, mut offset: u64) -> Result<()> {
227*bb4ee6a4SAndroid Build Coastguard Worker         while slice.size() > 0 {
228*bb4ee6a4SAndroid Build Coastguard Worker             match self.write_at_volatile(slice, offset) {
229*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(0) => return Err(Error::from(ErrorKind::WriteZero)),
230*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(n) => {
231*bb4ee6a4SAndroid Build Coastguard Worker                     slice = slice.offset(n).unwrap();
232*bb4ee6a4SAndroid Build Coastguard Worker                     offset = offset.checked_add(n as u64).unwrap();
233*bb4ee6a4SAndroid Build Coastguard Worker                 }
234*bb4ee6a4SAndroid Build Coastguard Worker                 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
235*bb4ee6a4SAndroid Build Coastguard Worker                 Err(e) => return Err(e),
236*bb4ee6a4SAndroid Build Coastguard Worker             }
237*bb4ee6a4SAndroid Build Coastguard Worker         }
238*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
239*bb4ee6a4SAndroid Build Coastguard Worker     }
240*bb4ee6a4SAndroid Build Coastguard Worker }
241*bb4ee6a4SAndroid Build Coastguard Worker 
242*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: FileReadWriteAtVolatile + ?Sized> FileReadWriteAtVolatile for &'a mut T {
read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>243*bb4ee6a4SAndroid Build Coastguard Worker     fn read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize> {
244*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_at_volatile(slice, offset)
245*bb4ee6a4SAndroid Build Coastguard Worker     }
246*bb4ee6a4SAndroid Build Coastguard Worker 
read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>247*bb4ee6a4SAndroid Build Coastguard Worker     fn read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
248*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_vectored_at_volatile(bufs, offset)
249*bb4ee6a4SAndroid Build Coastguard Worker     }
250*bb4ee6a4SAndroid Build Coastguard Worker 
read_exact_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()>251*bb4ee6a4SAndroid Build Coastguard Worker     fn read_exact_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()> {
252*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_exact_at_volatile(slice, offset)
253*bb4ee6a4SAndroid Build Coastguard Worker     }
254*bb4ee6a4SAndroid Build Coastguard Worker 
write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>255*bb4ee6a4SAndroid Build Coastguard Worker     fn write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize> {
256*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_at_volatile(slice, offset)
257*bb4ee6a4SAndroid Build Coastguard Worker     }
258*bb4ee6a4SAndroid Build Coastguard Worker 
write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>259*bb4ee6a4SAndroid Build Coastguard Worker     fn write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
260*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_vectored_at_volatile(bufs, offset)
261*bb4ee6a4SAndroid Build Coastguard Worker     }
262*bb4ee6a4SAndroid Build Coastguard Worker 
write_all_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()>263*bb4ee6a4SAndroid Build Coastguard Worker     fn write_all_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()> {
264*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_all_at_volatile(slice, offset)
265*bb4ee6a4SAndroid Build Coastguard Worker     }
266*bb4ee6a4SAndroid Build Coastguard Worker }
267*bb4ee6a4SAndroid Build Coastguard Worker 
268*bb4ee6a4SAndroid Build Coastguard Worker impl<'a, T: FileReadWriteAtVolatile + ?Sized> FileReadWriteAtVolatile for &'a T {
read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>269*bb4ee6a4SAndroid Build Coastguard Worker     fn read_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize> {
270*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_at_volatile(slice, offset)
271*bb4ee6a4SAndroid Build Coastguard Worker     }
272*bb4ee6a4SAndroid Build Coastguard Worker 
read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>273*bb4ee6a4SAndroid Build Coastguard Worker     fn read_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
274*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_vectored_at_volatile(bufs, offset)
275*bb4ee6a4SAndroid Build Coastguard Worker     }
276*bb4ee6a4SAndroid Build Coastguard Worker 
read_exact_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()>277*bb4ee6a4SAndroid Build Coastguard Worker     fn read_exact_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()> {
278*bb4ee6a4SAndroid Build Coastguard Worker         (**self).read_exact_at_volatile(slice, offset)
279*bb4ee6a4SAndroid Build Coastguard Worker     }
280*bb4ee6a4SAndroid Build Coastguard Worker 
write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize>281*bb4ee6a4SAndroid Build Coastguard Worker     fn write_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<usize> {
282*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_at_volatile(slice, offset)
283*bb4ee6a4SAndroid Build Coastguard Worker     }
284*bb4ee6a4SAndroid Build Coastguard Worker 
write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize>285*bb4ee6a4SAndroid Build Coastguard Worker     fn write_vectored_at_volatile(&self, bufs: &[VolatileSlice], offset: u64) -> Result<usize> {
286*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_vectored_at_volatile(bufs, offset)
287*bb4ee6a4SAndroid Build Coastguard Worker     }
288*bb4ee6a4SAndroid Build Coastguard Worker 
write_all_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()>289*bb4ee6a4SAndroid Build Coastguard Worker     fn write_all_at_volatile(&self, slice: VolatileSlice, offset: u64) -> Result<()> {
290*bb4ee6a4SAndroid Build Coastguard Worker         (**self).write_all_at_volatile(slice, offset)
291*bb4ee6a4SAndroid Build Coastguard Worker     }
292*bb4ee6a4SAndroid Build Coastguard Worker }
293*bb4ee6a4SAndroid Build Coastguard Worker 
294*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
295*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
296*bb4ee6a4SAndroid Build Coastguard Worker     use std::io::Read;
297*bb4ee6a4SAndroid Build Coastguard Worker     use std::io::Seek;
298*bb4ee6a4SAndroid Build Coastguard Worker     use std::io::SeekFrom;
299*bb4ee6a4SAndroid Build Coastguard Worker     use std::io::Write;
300*bb4ee6a4SAndroid Build Coastguard Worker 
301*bb4ee6a4SAndroid Build Coastguard Worker     use tempfile::tempfile;
302*bb4ee6a4SAndroid Build Coastguard Worker 
303*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
304*bb4ee6a4SAndroid Build Coastguard Worker 
305*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
read_file() -> Result<()>306*bb4ee6a4SAndroid Build Coastguard Worker     fn read_file() -> Result<()> {
307*bb4ee6a4SAndroid Build Coastguard Worker         let mut f = tempfile()?;
308*bb4ee6a4SAndroid Build Coastguard Worker         f.write_all(b"AAAAAAAAAAbbbbbbbbbbAAAAA")
309*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to write bytes");
310*bb4ee6a4SAndroid Build Coastguard Worker         f.seek(SeekFrom::Start(0))?;
311*bb4ee6a4SAndroid Build Coastguard Worker 
312*bb4ee6a4SAndroid Build Coastguard Worker         let mut omem = [0u8; 30];
313*bb4ee6a4SAndroid Build Coastguard Worker         let om = &mut omem[..];
314*bb4ee6a4SAndroid Build Coastguard Worker         let buf = VolatileSlice::new(om);
315*bb4ee6a4SAndroid Build Coastguard Worker         f.read_volatile(buf).expect("read_volatile failed.");
316*bb4ee6a4SAndroid Build Coastguard Worker 
317*bb4ee6a4SAndroid Build Coastguard Worker         f.seek(SeekFrom::Start(0))?;
318*bb4ee6a4SAndroid Build Coastguard Worker 
319*bb4ee6a4SAndroid Build Coastguard Worker         let mut mem = [0u8; 30];
320*bb4ee6a4SAndroid Build Coastguard Worker         let (m1, rest) = mem.split_at_mut(10);
321*bb4ee6a4SAndroid Build Coastguard Worker         let (m2, m3) = rest.split_at_mut(10);
322*bb4ee6a4SAndroid Build Coastguard Worker         let buf1 = VolatileSlice::new(m1);
323*bb4ee6a4SAndroid Build Coastguard Worker         let buf2 = VolatileSlice::new(m2);
324*bb4ee6a4SAndroid Build Coastguard Worker         let buf3 = VolatileSlice::new(m3);
325*bb4ee6a4SAndroid Build Coastguard Worker         let bufs = [buf1, buf2, buf3];
326*bb4ee6a4SAndroid Build Coastguard Worker 
327*bb4ee6a4SAndroid Build Coastguard Worker         f.read_vectored_volatile(&bufs)
328*bb4ee6a4SAndroid Build Coastguard Worker             .expect("read_vectored_volatile failed.");
329*bb4ee6a4SAndroid Build Coastguard Worker 
330*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&mem[..], b"AAAAAAAAAAbbbbbbbbbbAAAAA\0\0\0\0\0");
331*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
332*bb4ee6a4SAndroid Build Coastguard Worker     }
333*bb4ee6a4SAndroid Build Coastguard Worker 
334*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
write_file() -> Result<()>335*bb4ee6a4SAndroid Build Coastguard Worker     fn write_file() -> Result<()> {
336*bb4ee6a4SAndroid Build Coastguard Worker         let mut f = tempfile()?;
337*bb4ee6a4SAndroid Build Coastguard Worker 
338*bb4ee6a4SAndroid Build Coastguard Worker         let mut omem = [0u8; 25];
339*bb4ee6a4SAndroid Build Coastguard Worker         let om = &mut omem[..];
340*bb4ee6a4SAndroid Build Coastguard Worker         let buf = VolatileSlice::new(om);
341*bb4ee6a4SAndroid Build Coastguard Worker         buf.write_bytes(65);
342*bb4ee6a4SAndroid Build Coastguard Worker         f.write_volatile(buf).expect("write_volatile failed.");
343*bb4ee6a4SAndroid Build Coastguard Worker 
344*bb4ee6a4SAndroid Build Coastguard Worker         f.seek(SeekFrom::Start(0))?;
345*bb4ee6a4SAndroid Build Coastguard Worker 
346*bb4ee6a4SAndroid Build Coastguard Worker         let mut filebuf = [0u8; 25];
347*bb4ee6a4SAndroid Build Coastguard Worker         f.read_exact(&mut filebuf).expect("Failed to read filebuf");
348*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&filebuf, b"AAAAAAAAAAAAAAAAAAAAAAAAA");
349*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
350*bb4ee6a4SAndroid Build Coastguard Worker     }
351*bb4ee6a4SAndroid Build Coastguard Worker 
352*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
write_vectored_file() -> Result<()>353*bb4ee6a4SAndroid Build Coastguard Worker     fn write_vectored_file() -> Result<()> {
354*bb4ee6a4SAndroid Build Coastguard Worker         let mut f = tempfile()?;
355*bb4ee6a4SAndroid Build Coastguard Worker 
356*bb4ee6a4SAndroid Build Coastguard Worker         let mut mem = [0u8; 30];
357*bb4ee6a4SAndroid Build Coastguard Worker         let (m1, rest) = mem.split_at_mut(10);
358*bb4ee6a4SAndroid Build Coastguard Worker         let (m2, m3) = rest.split_at_mut(10);
359*bb4ee6a4SAndroid Build Coastguard Worker         let buf1 = VolatileSlice::new(m1);
360*bb4ee6a4SAndroid Build Coastguard Worker         let buf2 = VolatileSlice::new(m2);
361*bb4ee6a4SAndroid Build Coastguard Worker         let buf3 = VolatileSlice::new(m3);
362*bb4ee6a4SAndroid Build Coastguard Worker         buf1.write_bytes(65);
363*bb4ee6a4SAndroid Build Coastguard Worker         buf2.write_bytes(98);
364*bb4ee6a4SAndroid Build Coastguard Worker         buf3.write_bytes(65);
365*bb4ee6a4SAndroid Build Coastguard Worker         let bufs = [buf1, buf2, buf3];
366*bb4ee6a4SAndroid Build Coastguard Worker         f.write_vectored_volatile(&bufs)
367*bb4ee6a4SAndroid Build Coastguard Worker             .expect("write_vectored_volatile failed.");
368*bb4ee6a4SAndroid Build Coastguard Worker 
369*bb4ee6a4SAndroid Build Coastguard Worker         f.seek(SeekFrom::Start(0))?;
370*bb4ee6a4SAndroid Build Coastguard Worker 
371*bb4ee6a4SAndroid Build Coastguard Worker         let mut filebuf = [0u8; 30];
372*bb4ee6a4SAndroid Build Coastguard Worker         f.read_exact(&mut filebuf).expect("Failed to read filebuf.");
373*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&filebuf, b"AAAAAAAAAAbbbbbbbbbbAAAAAAAAAA");
374*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
375*bb4ee6a4SAndroid Build Coastguard Worker     }
376*bb4ee6a4SAndroid Build Coastguard Worker 
377*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
read_at_file() -> Result<()>378*bb4ee6a4SAndroid Build Coastguard Worker     fn read_at_file() -> Result<()> {
379*bb4ee6a4SAndroid Build Coastguard Worker         let mut f = tempfile()?;
380*bb4ee6a4SAndroid Build Coastguard Worker         f.write_all(b"AAAAAAAAAAbbbbbbbbbbAAAAA")
381*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to write bytes.");
382*bb4ee6a4SAndroid Build Coastguard Worker 
383*bb4ee6a4SAndroid Build Coastguard Worker         let mut omem = [0u8; 20];
384*bb4ee6a4SAndroid Build Coastguard Worker         let om = &mut omem[..];
385*bb4ee6a4SAndroid Build Coastguard Worker         let buf = VolatileSlice::new(om);
386*bb4ee6a4SAndroid Build Coastguard Worker         f.read_at_volatile(buf, 10)
387*bb4ee6a4SAndroid Build Coastguard Worker             .expect("read_at_volatile failed.");
388*bb4ee6a4SAndroid Build Coastguard Worker 
389*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(om, b"bbbbbbbbbbAAAAA\0\0\0\0\0");
390*bb4ee6a4SAndroid Build Coastguard Worker 
391*bb4ee6a4SAndroid Build Coastguard Worker         let mut mem = [0u8; 20];
392*bb4ee6a4SAndroid Build Coastguard Worker         let (m1, m2) = mem.split_at_mut(10);
393*bb4ee6a4SAndroid Build Coastguard Worker         let buf1 = VolatileSlice::new(m1);
394*bb4ee6a4SAndroid Build Coastguard Worker         let buf2 = VolatileSlice::new(m2);
395*bb4ee6a4SAndroid Build Coastguard Worker         let bufs = [buf1, buf2];
396*bb4ee6a4SAndroid Build Coastguard Worker 
397*bb4ee6a4SAndroid Build Coastguard Worker         f.read_vectored_at_volatile(&bufs, 10)
398*bb4ee6a4SAndroid Build Coastguard Worker             .expect("read_vectored_at_volatile failed.");
399*bb4ee6a4SAndroid Build Coastguard Worker 
400*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&mem[..], b"bbbbbbbbbbAAAAA\0\0\0\0\0");
401*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
402*bb4ee6a4SAndroid Build Coastguard Worker     }
403*bb4ee6a4SAndroid Build Coastguard Worker 
404*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
write_at_file() -> Result<()>405*bb4ee6a4SAndroid Build Coastguard Worker     fn write_at_file() -> Result<()> {
406*bb4ee6a4SAndroid Build Coastguard Worker         let mut f = tempfile()?;
407*bb4ee6a4SAndroid Build Coastguard Worker         f.write_all(b"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ")
408*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to write bytes");
409*bb4ee6a4SAndroid Build Coastguard Worker 
410*bb4ee6a4SAndroid Build Coastguard Worker         let mut omem = [0u8; 15];
411*bb4ee6a4SAndroid Build Coastguard Worker         let om = &mut omem[..];
412*bb4ee6a4SAndroid Build Coastguard Worker         let buf = VolatileSlice::new(om);
413*bb4ee6a4SAndroid Build Coastguard Worker         buf.write_bytes(65);
414*bb4ee6a4SAndroid Build Coastguard Worker         f.write_at_volatile(buf, 10)
415*bb4ee6a4SAndroid Build Coastguard Worker             .expect("write_at_volatile failed.");
416*bb4ee6a4SAndroid Build Coastguard Worker 
417*bb4ee6a4SAndroid Build Coastguard Worker         f.seek(SeekFrom::Start(0))?;
418*bb4ee6a4SAndroid Build Coastguard Worker 
419*bb4ee6a4SAndroid Build Coastguard Worker         let mut filebuf = [0u8; 30];
420*bb4ee6a4SAndroid Build Coastguard Worker         f.read_exact(&mut filebuf).expect("Failed to read filebuf.");
421*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&filebuf, b"ZZZZZZZZZZAAAAAAAAAAAAAAAZZZZZ");
422*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
423*bb4ee6a4SAndroid Build Coastguard Worker     }
424*bb4ee6a4SAndroid Build Coastguard Worker 
425*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
write_vectored_at_file() -> Result<()>426*bb4ee6a4SAndroid Build Coastguard Worker     fn write_vectored_at_file() -> Result<()> {
427*bb4ee6a4SAndroid Build Coastguard Worker         let mut f = tempfile()?;
428*bb4ee6a4SAndroid Build Coastguard Worker         f.write_all(b"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ")
429*bb4ee6a4SAndroid Build Coastguard Worker             .expect("Failed to write bytes");
430*bb4ee6a4SAndroid Build Coastguard Worker 
431*bb4ee6a4SAndroid Build Coastguard Worker         let mut mem = [0u8; 30];
432*bb4ee6a4SAndroid Build Coastguard Worker         let (m1, m2) = mem.split_at_mut(10);
433*bb4ee6a4SAndroid Build Coastguard Worker         let buf1 = VolatileSlice::new(m1);
434*bb4ee6a4SAndroid Build Coastguard Worker         let buf2 = VolatileSlice::new(m2);
435*bb4ee6a4SAndroid Build Coastguard Worker         buf1.write_bytes(65);
436*bb4ee6a4SAndroid Build Coastguard Worker         buf2.write_bytes(98);
437*bb4ee6a4SAndroid Build Coastguard Worker         let bufs = [buf1, buf2];
438*bb4ee6a4SAndroid Build Coastguard Worker         f.write_vectored_at_volatile(&bufs, 10)
439*bb4ee6a4SAndroid Build Coastguard Worker             .expect("write_vectored_at_volatile failed.");
440*bb4ee6a4SAndroid Build Coastguard Worker 
441*bb4ee6a4SAndroid Build Coastguard Worker         f.seek(SeekFrom::Start(0))?;
442*bb4ee6a4SAndroid Build Coastguard Worker 
443*bb4ee6a4SAndroid Build Coastguard Worker         let mut filebuf = [0u8; 30];
444*bb4ee6a4SAndroid Build Coastguard Worker         f.read_exact(&mut filebuf).expect("Failed to read filebuf.");
445*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(&filebuf, b"ZZZZZZZZZZAAAAAAAAAAbbbbbbbbbb");
446*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
447*bb4ee6a4SAndroid Build Coastguard Worker     }
448*bb4ee6a4SAndroid Build Coastguard Worker }
449