From 687fbc49c801617b00fa9e61ccb00a4181195c87 Mon Sep 17 00:00:00 2001 From: sarubo <47109823+sarubo@users.noreply.github.com> Date: Fri, 15 Mar 2024 06:43:42 +0900 Subject: [PATCH] Adjust permissions using `umask` in `mkdir` (#12207) # Description With this change, `mkdir` mirrors coreutils works. Closes #12161 I referred to the implementation of `mkdir` in uutils/coreutils. I add `uucore` required for implementation to dependencies. Since `uucore` is already included in dependencies of `uu_mkdir`, I don't think there will be any additional dependencies. # User-Facing Changes - Directories are created according to `umask` except for Windows. # Tests + Formatting I add `mkdir` test considering permissions. The test assumes that the default `umask` is `022`. # After Submitting --- Cargo.lock | 1 + crates/nu-command/Cargo.toml | 3 +++ crates/nu-command/src/filesystem/umkdir.rs | 16 ++++++++++++--- crates/nu-command/tests/commands/umkdir.rs | 23 ++++++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23baafeca5..053bc099e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2940,6 +2940,7 @@ dependencies = [ "uu_mktemp", "uu_mv", "uu_whoami", + "uucore", "uuid", "v_htmlescape", "wax", diff --git a/crates/nu-command/Cargo.toml b/crates/nu-command/Cargo.toml index ced56595f4..e463cb14fa 100644 --- a/crates/nu-command/Cargo.toml +++ b/crates/nu-command/Cargo.toml @@ -100,6 +100,9 @@ chardetng = "0.1.17" [target.'cfg(windows)'.dependencies] winreg = "0.52" +[target.'cfg(not(windows))'.dependencies] +uucore = { version = "0.0.24", features = ["mode"] } + [target.'cfg(unix)'.dependencies] libc = "0.2" umask = "2.1" diff --git a/crates/nu-command/src/filesystem/umkdir.rs b/crates/nu-command/src/filesystem/umkdir.rs index 7f9267bf03..daeb4d39ee 100644 --- a/crates/nu-command/src/filesystem/umkdir.rs +++ b/crates/nu-command/src/filesystem/umkdir.rs @@ -5,15 +5,25 @@ use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Type}; use uu_mkdir::mkdir; +#[cfg(not(windows))] +use uucore::mode; #[derive(Clone)] pub struct UMkdir; const IS_RECURSIVE: bool = true; -// This is the same default as Rust's std uses: -// https://doc.rust-lang.org/nightly/std/os/unix/fs/trait.DirBuilderExt.html#tymethod.mode const DEFAULT_MODE: u32 = 0o777; +#[cfg(not(windows))] +fn get_mode() -> u32 { + DEFAULT_MODE - mode::get_umask() +} + +#[cfg(windows)] +fn get_mode() -> u32 { + DEFAULT_MODE +} + impl Command for UMkdir { fn name(&self) -> &str { "mkdir" @@ -67,7 +77,7 @@ impl Command for UMkdir { } for dir in directories { - if let Err(error) = mkdir(&dir, IS_RECURSIVE, DEFAULT_MODE, is_verbose) { + if let Err(error) = mkdir(&dir, IS_RECURSIVE, get_mode(), is_verbose) { return Err(ShellError::GenericError { error: format!("{}", error), msg: format!("{}", error), diff --git a/crates/nu-command/tests/commands/umkdir.rs b/crates/nu-command/tests/commands/umkdir.rs index e6a74ab51c..0cead39339 100644 --- a/crates/nu-command/tests/commands/umkdir.rs +++ b/crates/nu-command/tests/commands/umkdir.rs @@ -122,3 +122,26 @@ fn creates_directory_three_dots_quotation_marks() { assert!(expected.exists()); }) } + +#[cfg(not(windows))] +#[test] +fn mkdir_umask_permission() { + use std::{fs, os::unix::fs::PermissionsExt}; + + Playground::setup("mkdir_umask_permission", |dirs, _| { + nu!( + cwd: dirs.test(), + "mkdir test_umask_permission" + ); + let actual = fs::metadata(dirs.test().join("test_umask_permission")) + .unwrap() + .permissions() + .mode(); + + assert_eq!( + actual, 0o40755, + "Most *nix systems have 0o00022 as the umask. \ + So directory permission should be 0o40755 = 0o40777 - 0o00022" + ); + }) +}