mod mmap;
pub mod progress_log;
mod writer_checksum;
use std::{
fs::File,
io::{self, Result, prelude::*},
os::unix::fs::OpenOptionsExt,
path::Path,
};
pub use mmap::EitherMmapOrRandomAccessFile;
pub use progress_log::WithProgress;
pub use writer_checksum::*;
pub fn write_new_sensitive_file(message: &[u8], path: &Path) -> Result<()> {
create_new_sensitive_file(path)?.write_all(message)
}
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)
}
pub async fn skip_bytes<T: tokio::io::AsyncRead + Unpin>(reader: T, n: u64) -> std::io::Result<T> {
use tokio::io::AsyncReadExt as _;
let mut take = reader.take(n);
let n_skipped = tokio::io::copy(&mut take, &mut tokio::io::sink()).await?;
if n == n_skipped {
Ok(take.into_inner())
} else {
Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!("{n_skipped} bytes skipped, {n} expected"),
))
}
}
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)
}
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);
}