vmm_sys_util/unix/
file_traits.rs

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
9use std::fs::File;
10use 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.
17pub trait FileSync {
18    /// Flush buffers related to this file to disk.
19    fn fsync(&mut self) -> Result<()>;
20}
21
22impl FileSync for File {
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.
33pub 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.
42    fn set_len(&self, len: u64) -> Result<()>;
43}
44
45impl FileSetLen for File {
46    fn set_len(&self, len: u64) -> Result<()> {
47        File::set_len(self, len)
48    }
49}
50
51#[cfg(test)]
52mod 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]
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]
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]
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}