use std::io;
use std::path::Path;
pub(crate) const MAX_RC_FILE_BYTES: usize = 1024 * 1024;
pub(crate) fn read_rc_content(path: &Path) -> String {
use std::io::Read;
#[cfg(unix)]
let mut file = {
use std::os::unix::fs::OpenOptionsExt;
match std::fs::OpenOptions::new()
.read(true)
.custom_flags(libc::O_NOFOLLOW | libc::O_NONBLOCK)
.open(path)
{
Ok(f) => f,
Err(_) => return String::new(),
}
};
#[cfg(not(unix))]
let mut file = match std::fs::File::open(path) {
Ok(f) => f,
Err(_) => return String::new(),
};
let meta = match file.metadata() {
Ok(m) => m,
Err(_) => return String::new(),
};
if !meta.is_file() {
return String::new();
}
if meta.len() > MAX_RC_FILE_BYTES as u64 {
return String::new();
}
let mut content = String::new();
file.read_to_string(&mut content).unwrap_or_default();
content
}
pub(crate) const MAX_CONFIRM_BYTES: usize = 1_024;
pub(crate) fn prompt_confirm_from(reader: &mut impl io::BufRead) -> bool {
use io::{BufRead as _, Read as _};
let mut input = String::new();
let mut limited = reader.by_ref().take(MAX_CONFIRM_BYTES as u64 + 1);
match limited.read_line(&mut input) {
Err(_) => return false,
Ok(0) => return false,
Ok(_) => {}
}
if input.len() > MAX_CONFIRM_BYTES {
return false;
}
matches!(input.trim().to_ascii_lowercase().as_str(), "y" | "yes")
}
pub(crate) fn prompt_confirm(msg: &str) -> bool {
use std::io::Write as _;
eprint!("{msg} [y/N] ");
let _ = io::stderr().flush();
let stdin = io::stdin();
let mut reader = io::BufReader::new(stdin.lock());
prompt_confirm_from(&mut reader)
}