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