1 // Copyright 2019 Intel Corporation. All Rights Reserved. 2 // 3 // Copyright 2018 The Chromium OS Authors. All rights reserved. 4 // 5 // SPDX-License-Identifier: BSD-3-Clause 6 7 //! Traits for handling file synchronization and length. 8 9 use std::fs::File; 10 use std::io::Result; 11 12 /// A trait for flushing the contents of a file to disk. 13 /// 14 /// This is equivalent to 15 /// [`std::fd::File::sync_all`](https://doc.rust-lang.org/std/fs/struct.File.html#method.sync_all) 16 /// method, but wrapped in a trait so that it can be implemented for other types. 17 pub trait FileSync { 18 /// Flush buffers related to this file to disk. fsync(&mut self) -> Result<()>19 fn fsync(&mut self) -> Result<()>; 20 } 21 22 impl FileSync for File { fsync(&mut self) -> Result<()>23 fn fsync(&mut self) -> Result<()> { 24 self.sync_all() 25 } 26 } 27 28 /// A trait for setting the size of a file. 29 /// 30 /// This is equivalent to 31 /// [`std::fd::File::set_len`](https://doc.rust-lang.org/std/fs/struct.File.html#method.set_len) 32 /// method, but wrapped in a trait so that it can be implemented for other types. 33 pub trait FileSetLen { 34 /// Set the size of this file. 35 /// 36 /// This is the moral equivalent of 37 /// [`ftruncate`](http://man7.org/linux/man-pages/man3/ftruncate.3p.html). 38 /// 39 /// # Arguments 40 /// 41 /// * `len`: the size to set for file. set_len(&self, len: u64) -> Result<()>42 fn set_len(&self, len: u64) -> Result<()>; 43 } 44 45 impl FileSetLen for File { set_len(&self, len: u64) -> Result<()>46 fn set_len(&self, len: u64) -> Result<()> { 47 File::set_len(self, len) 48 } 49 } 50 51 #[cfg(test)] 52 mod tests { 53 use super::*; 54 use std::fs::OpenOptions; 55 use std::io::{Seek, SeekFrom, Write}; 56 use std::path::PathBuf; 57 58 use crate::tempdir::TempDir; 59 60 #[test] test_fsync()61 fn test_fsync() { 62 let tempdir = TempDir::new_with_prefix("/tmp/fsync_test").unwrap(); 63 let mut path = PathBuf::from(tempdir.as_path()); 64 path.push("file"); 65 let mut f = OpenOptions::new() 66 .read(true) 67 .write(true) 68 .create(true) 69 .open(&path) 70 .unwrap(); 71 f.write_all(b"Hello, world!").unwrap(); 72 f.fsync().unwrap(); 73 assert_eq!(f.metadata().unwrap().len(), 13); 74 } 75 76 #[test] test_set_len()77 fn test_set_len() { 78 let tempdir = TempDir::new_with_prefix("/tmp/set_len_test").unwrap(); 79 let mut path = PathBuf::from(tempdir.as_path()); 80 path.push("file"); 81 let mut f = OpenOptions::new() 82 .read(true) 83 .write(true) 84 .create(true) 85 .open(&path) 86 .unwrap(); 87 f.set_len(10).unwrap(); 88 assert_eq!(f.seek(SeekFrom::End(0)).unwrap(), 10); 89 } 90 91 #[test] test_set_len_fails_when_file_not_opened_for_writing()92 fn test_set_len_fails_when_file_not_opened_for_writing() { 93 let tempdir = TempDir::new_with_prefix("/tmp/set_len_test").unwrap(); 94 let mut path = PathBuf::from(tempdir.as_path()); 95 path.push("file"); 96 File::create(path.clone()).unwrap(); 97 let f = OpenOptions::new().read(true).open(&path).unwrap(); 98 let result = f.set_len(10); 99 assert!(result.is_err()); 100 } 101 } 102