use std::fs::OpenOptions;
use std::io::Write as _;
use std::path::Path;
use rc_core::Result;
pub(crate) fn write_private_file(path: &Path, contents: &[u8]) -> Result<()> {
let mut options = OpenOptions::new();
options.write(true).create_new(true);
#[cfg(unix)]
{
use std::os::unix::fs::OpenOptionsExt as _;
options.mode(0o600);
}
let mut file = options.open(path)?;
file.write_all(contents)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn an_existing_file_is_left_alone() {
let directory = tempfile::tempdir().expect("create temp directory");
let path = directory.path().join("private.txt");
std::fs::write(&path, "existing").expect("create existing file");
let error =
write_private_file(&path, b"replacement").expect_err("must not overwrite the file");
assert_eq!(
std::fs::read_to_string(&path).expect("read existing file"),
"existing"
);
assert!(
matches!(
error,
rc_core::Error::Io(ref io)
if io.kind() == std::io::ErrorKind::AlreadyExists
),
"{error:?}"
);
}
#[cfg(unix)]
#[test]
fn a_new_file_is_owner_only() {
use std::os::unix::fs::PermissionsExt as _;
let directory = tempfile::tempdir().expect("create temp directory");
let path = directory.path().join("private.txt");
write_private_file(&path, b"secret").expect("write the file");
let mode = std::fs::metadata(&path)
.expect("metadata")
.permissions()
.mode()
& 0o777;
assert_eq!(mode, 0o600);
assert_eq!(std::fs::read_to_string(&path).expect("read back"), "secret");
}
}