1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
// Copyright 2019-2024 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT
mod mmap;
pub mod progress_log;
mod writer_checksum;
use std::{
fs::File,
io::{self, prelude::*, Result},
os::unix::fs::OpenOptionsExt,
path::Path,
};
pub use mmap::EitherMmapOrRandomAccessFile;
pub use progress_log::{WithProgress, WithProgressRaw};
pub use writer_checksum::*;
/// Writes bytes to a specified file. Creates the desired path if it does not
/// exist.
/// Note: The file is created with permissions 0600.
/// Note: The file is truncated if it already exists.
pub fn write_new_sensitive_file(message: &[u8], path: &Path) -> Result<()> {
create_new_sensitive_file(path)?.write_all(message)
}
/// Creates a new file with the specified path. The file is created
/// with permissions 0600 and is truncated if it already exists.
pub fn create_new_sensitive_file(path: &Path) -> Result<File> {
std::fs::create_dir_all(
path.parent()
.ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Parent directory not found"))?,
)?;
let file = std::fs::OpenOptions::new()
.mode(0o600)
.write(true)
.create(true)
.truncate(true)
.open(path)?;
use std::os::unix::fs::PermissionsExt;
file.set_permissions(std::fs::Permissions::from_mode(0o600))?;
Ok(file)
}
/// Converts a TOML file represented as a string to `S`
///
/// # Example
/// ```
/// use serde::Deserialize;
/// use forest_filecoin::doctest_private::read_toml;
///
/// #[derive(Deserialize)]
/// struct Config {
/// name: String
/// };
///
/// let toml_string = "name = \"forest\"\n";
/// let config: Config = read_toml(toml_string).unwrap();
/// assert_eq!(config.name, "forest");
/// ```
pub fn read_toml<S>(toml_string: &str) -> anyhow::Result<S>
where
for<'de> S: serde::de::Deserialize<'de>,
{
let new_struct: S = toml::from_str(toml_string)?;
Ok(new_struct)
}
// When reading a password or prompting a yes/no answer, we change the terminal
// settings by hiding the cursor or turning off the character echo.
// Unfortunately, if we're interrupted, these settings are not restored. This
// function attempts to restore terminal settings to sensible values. However,
// if SIGKILL kills Forest, there's nothing we can do, and it'll be up to the
// user to restore their terminal.
pub fn terminal_cleanup() {
#[cfg(unix)]
{
use std::os::fd::AsRawFd;
use termios::*;
let fd = std::io::stdin().as_raw_fd();
if let Ok(mut termios) = Termios::from_fd(fd) {
termios.c_lflag |= ECHO;
let _ = tcsetattr(fd, TCSAFLUSH, &termios);
}
}
let mut stdout = std::io::stdout();
let _ = anes::execute!(&mut stdout, anes::ShowCursor);
}