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