casper_types/
file_utils.rs

1//! Utilities for handling reading from and writing to files.
2
3use std::{
4    fs,
5    io::{self, Write},
6    os::unix::fs::OpenOptionsExt,
7    path::{Path, PathBuf},
8};
9
10use thiserror::Error;
11
12/// Error reading a file.
13#[derive(Debug, Error)]
14#[error("could not read '{0}': {error}", .path.display())]
15pub struct ReadFileError {
16    /// Path that failed to be read.
17    path: PathBuf,
18    /// The underlying OS error.
19    #[source]
20    error: io::Error,
21}
22
23/// Error writing a file
24#[derive(Debug, Error)]
25#[error("could not write to '{0}': {error}", .path.display())]
26pub struct WriteFileError {
27    /// Path that failed to be written to.
28    path: PathBuf,
29    /// The underlying OS error.
30    #[source]
31    error: io::Error,
32}
33
34/// Read complete at `path` into memory.
35///
36/// Wraps `fs::read`, but preserves the filename for better error printing.
37pub fn read_file<P: AsRef<Path>>(filename: P) -> Result<Vec<u8>, ReadFileError> {
38    let path = filename.as_ref();
39    fs::read(path).map_err(|error| ReadFileError {
40        path: path.to_owned(),
41        error,
42    })
43}
44
45/// Write data to `path`.
46///
47/// Wraps `fs::write`, but preserves the filename for better error printing.
48pub(crate) fn write_file<P: AsRef<Path>, B: AsRef<[u8]>>(
49    filename: P,
50    data: B,
51) -> Result<(), WriteFileError> {
52    let path = filename.as_ref();
53    fs::write(path, data.as_ref()).map_err(|error| WriteFileError {
54        path: path.to_owned(),
55        error,
56    })
57}
58
59/// Writes data to `path`, ensuring only the owner can read or write it.
60///
61/// Otherwise functions like [`write_file`].
62pub(crate) fn write_private_file<P: AsRef<Path>, B: AsRef<[u8]>>(
63    filename: P,
64    data: B,
65) -> Result<(), WriteFileError> {
66    let path = filename.as_ref();
67    fs::OpenOptions::new()
68        .write(true)
69        .create(true)
70        .truncate(true)
71        .mode(0o600)
72        .open(path)
73        .and_then(|mut file| file.write_all(data.as_ref()))
74        .map_err(|error| WriteFileError {
75            path: path.to_owned(),
76            error,
77        })
78}