aboutsummaryrefslogtreecommitdiff
path: root/src/platform/macos/config_file_tests.rs
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-09-14 23:13:52 +0300
committerGitHub <noreply@github.com>2026-09-14 22:13:52 +0200
commit5e38e5fb5fc2cc5d30844df71432a60742bcb572 (patch)
tree31896855b510cf03c57e19e4e3ef454bef028a59 /src/platform/macos/config_file_tests.rs
parentb0f21ed2cb85613050b794bf6c78a7c367a94e0d (diff)
fix: protect integration configs from failed writes (#3973)
* fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 * fix: atomically write integration configs refs #3970 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Diffstat (limited to 'src/platform/macos/config_file_tests.rs')
-rw-r--r--src/platform/macos/config_file_tests.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/platform/macos/config_file_tests.rs b/src/platform/macos/config_file_tests.rs
new file mode 100644
index 00000000..f08d6c2a
--- /dev/null
+++ b/src/platform/macos/config_file_tests.rs
@@ -0,0 +1,44 @@
+use super::*;
+
+#[test]
+fn config_replacement_preserves_macos_acl() {
+ let dir = std::env::temp_dir().join(format!("herdr-config-acl-{}", std::process::id()));
+ std::fs::create_dir(&dir).unwrap();
+ let source = dir.join("source");
+ let temporary = dir.join("temporary");
+ std::fs::write(&source, b"original").unwrap();
+ assert!(Command::new("chmod")
+ .args(["+a", "everyone deny execute"])
+ .arg(&source)
+ .status()
+ .unwrap()
+ .success());
+ let acl = |path: &Path| {
+ let output = Command::new("ls").arg("-le").arg(path).output().unwrap();
+ assert!(output.status.success());
+ String::from_utf8(output.stdout)
+ .unwrap()
+ .lines()
+ .skip(1)
+ .collect::<Vec<_>>()
+ .join("\n")
+ };
+ let original = acl(&source);
+ assert!(original.contains("everyone deny execute"));
+ assert!(Command::new("chmod")
+ .args(["+a", "everyone allow read,file_inherit"])
+ .arg(&dir)
+ .status()
+ .unwrap()
+ .success());
+ drop(create_config_temporary(&temporary, true).unwrap());
+ assert!(
+ acl(&temporary).is_empty(),
+ "staging must not inherit allow ACEs"
+ );
+ write_config_temporary(Some(&source), &temporary, b"new").unwrap();
+ assert_eq!(acl(&temporary), original);
+ assert_eq!(std::fs::read(&source).unwrap(), b"original");
+ assert_eq!(std::fs::read(&temporary).unwrap(), b"new");
+ std::fs::remove_dir_all(dir).unwrap();
+}