use std::{
borrow::Cow,
fs::OpenOptions,
io::{self, Write},
path::Path,
process::Output,
};
pub fn write_file(path: &Path, data: &[u8], _mode: u32) -> io::Result<()> {
let mut opts = OpenOptions::new();
opts.create(true).write(true).truncate(true);
#[cfg(unix)]
{
use std::os::unix::fs::OpenOptionsExt;
opts.mode(_mode);
}
let mut file = opts.open(path)?;
file.write_all(data)?;
file.sync_all()
}
#[cfg(not(feature = "encoding"))]
pub fn wrap_output(output: Output) -> std::io::Result<Output> {
if output.status.success() {
Ok(output)
} else {
let mut msg = String::from_utf8_lossy(&output.stderr);
if msg.trim().is_empty() {
msg = String::from_utf8_lossy(&output.stdout);
}
if msg.is_empty() {
msg = Cow::Borrowed("Failed to execute command with no output");
}
Err(io::Error::new(
io::ErrorKind::Other,
format!(
"Command failed with exit code {}: {}",
output.status.code().unwrap_or(-1),
msg
),
))
}
}
#[cfg(feature = "encoding")]
pub fn wrap_output(output: Output) -> std::io::Result<Output> {
use encoding::decode;
if output.status.success() {
Ok(output)
} else {
let mut msg = decode(&output.stderr).unwrap_or_default();
if msg.trim().is_empty() {
msg = decode(&output.stdout).unwrap_or_default();
}
if msg.is_empty() {
msg = Cow::Borrowed("Failed to execute command with no output");
}
Err(io::Error::new(
io::ErrorKind::Other,
format!(
"Command failed with exit code {}: {}",
output.status.code().unwrap_or(-1),
msg
),
))
}
}
#[cfg(feature = "encoding")]
pub mod encoding {
use encoding_rs::UTF_8;
#[cfg(windows)]
use encoding_utils::windows::current_acp_encoding_no_replacement;
use std::borrow::Cow;
use std::io::{Error, ErrorKind};
pub fn decode(bytes: &[u8]) -> Result<Cow<'_, str>, Error> {
#[cfg(windows)]
let encoding = current_acp_encoding_no_replacement().unwrap_or(UTF_8);
#[cfg(not(windows))]
let encoding = &UTF_8;
let (result, _, had_errors) = encoding.decode(bytes);
if had_errors {
Err(Error::new(
ErrorKind::InvalidData,
"Failed to decode the bytes",
))
} else {
Ok(result)
}
}
}