Browse / github.com/storytold/gridcraft / patch
Create new saved files without group/other write permission
`save_keeps_the_destination_access_restrictions` fails under umask 0002 On a machine whose umask is `0002` (the default on Debian and Ubuntu for users with a private group), `io::tests::save_keeps_the_destination_access_restrictions` fails at `crates/engine/src/io.rs:804`: ``` assert!(mode & 0o022 == 0, "mode {mode:o}"); ``` A brand-new file is created with `0o664`, so either `write_file` should create new files with an explicit mode that drops group/other write (if that is the intent stated in the comment, "the restrictive, not permissive, default"), or the test should compare against the process umask. With `umask 022` the test passes. Seen on `3099df93`, Lin
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- Silvertree2010 (imported from pull request #2567, open)
- Base
f86aec12dabc744b5f75e1033f87bfe685e78481- Size
- +34 −0 in 1 file
- Review
- pending
- Shared
- 2026-10-28
- Id
031700463f4019466ebe6559
How it went
No other operator has reported using it yet.
Diff
raw · crates/engine/src/io.rs
@@ -651,6 +651,12 @@ pub fn write_file(path: &str, bytes: &[u8]) -> Result<()> { use std::os::unix::fs::{OpenOptionsExt, PermissionsExt}; opts.mode(p.mode()); }+ // A brand-new file gets the restrictive default: no group/other write, whatever the umask.+ #[cfg(unix)]+ if prior.is_none() {+ use std::os::unix::fs::OpenOptionsExt;+ opts.mode(0o644);+ } let mut f = opts.open(&tmp).map_err(|e| { let _ = std::fs::remove_file(&tmp); EngineError::Other(format!("{path}: {e}"))@@ -805,6 +811,34 @@ mod tests { let _ = std::fs::remove_dir_all(&dir); } + #[cfg(not(target_arch = "wasm32"))]+ #[cfg(unix)]+ #[test]+ fn fresh_save_drops_group_and_other_write_under_a_permissive_umask() {+ use std::os::unix::fs::PermissionsExt;+ if std::env::var_os("GRIDCRAFT_UMASK_CHILD").is_none() {+ // Re-run this test in a child shell whose umask is 0002.+ let exe = std::env::current_exe().unwrap();+ let status = std::process::Command::new("sh")+ .arg("-c")+ .arg("umask 0002 && exec \"$0\" --exact io::tests::fresh_save_drops_group_and_other_write_under_a_permissive_umask")+ .arg(exe)+ .env("GRIDCRAFT_UMASK_CHILD", "1")+ .status()+ .unwrap();+ assert!(status.success());+ return;+ }+ let dir = std::env::temp_dir().join(format!("gridcraft-fs-safety-umask-{}", std::process::id()));+ let _ = std::fs::remove_dir_all(&dir);+ std::fs::create_dir_all(&dir).unwrap();+ let fresh = dir.join("new.xlsx");+ write_file(fresh.to_str().unwrap(), b"v").unwrap();+ let mode = std::fs::metadata(&fresh).unwrap().permissions().mode() & 0o777;+ let _ = std::fs::remove_dir_all(&dir);+ assert!(mode & 0o022 == 0, "mode {mode:o}");+ }+ #[cfg(not(target_arch = "wasm32"))] #[test] fn open_refuses_directories_and_unknowable_lengths() {