1use anyhow::Result;
2use std::path::Path;
3
4pub fn write_sensitive_file(path: &Path, data: impl AsRef<[u8]>) -> Result<()> {
13 #[cfg(unix)]
14 {
15 use std::io::Write;
16 use std::os::unix::fs::PermissionsExt;
17
18 let parent = path
19 .parent()
20 .ok_or_else(|| anyhow::anyhow!("No parent directory for {:?}", path))?;
21
22 let mut tmp = tempfile::NamedTempFile::new_in(parent)?;
23 tmp.write_all(data.as_ref())?;
26 tmp.flush()?;
27
28 let tmp_path = tmp.into_temp_path();
29 std::fs::set_permissions(&tmp_path, std::fs::Permissions::from_mode(0o600))?;
30 tmp_path.persist(path)?;
31
32 Ok(())
33 }
34
35 #[cfg(not(unix))]
36 {
37 log::warn!("Restrictive file permissions not enforced on this platform");
38 std::fs::write(path, data)?;
39 Ok(())
40 }
41}
42
43pub fn create_restricted_dir(path: &Path) -> Result<()> {
48 #[cfg(unix)]
49 {
50 use std::os::unix::fs::{DirBuilderExt, PermissionsExt};
51 if let Some(parent) = path.parent() {
53 std::fs::create_dir_all(parent)?;
54 }
55 std::fs::DirBuilder::new()
56 .mode(0o700)
57 .create(path)
58 .or_else(|e| {
59 if e.kind() == std::io::ErrorKind::AlreadyExists {
60 std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o700))?;
62 Ok(())
63 } else {
64 Err(e.into())
65 }
66 })
67 }
68
69 #[cfg(not(unix))]
70 {
71 log::warn!("Restrictive directory permissions not enforced on this platform");
72 std::fs::create_dir_all(path)?;
73 Ok(())
74 }
75}