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