Repository: uutils/coreutils (Rust)

Issue:
mkdir: does not respect umask
GNU mkdir:
```
$ umask 000
$ mkdir a
$ ls -ld a
drwxrwxrwx 2 jeffrey jeffrey 4096 Feb 11 22:11 a
```

uutils mkdir:
```
$ umask 000
$ ./target/debug/mkdir a
$ ls -ld a
drwxr-xr-x 2 jeffrey jeffrey 4096 Feb 11 22:11 a
```


Discussion:
Should not be hard to fix :)

Hi! I'd like to work on this.
Sure! Go ahead!
I'm still new to rust, but I will try my hand at this.



Patch:
diff --git a/src/uu/mkdir/src/mkdir.rs b/src/uu/mkdir/src/mkdir.rs
index 35078d296be..2860be64956 100644
--- a/src/uu/mkdir/src/mkdir.rs
+++ b/src/uu/mkdir/src/mkdir.rs
@@ -64,7 +64,10 @@ fn get_mode(matches: &ArgMatches, mode_had_minus_prefix: bool) -> Result<u32, St
             }
             Ok(new_mode)
         }
-        None => Ok(DEFAULT_PERM),
+        None => {
+            // If no mode argument is specified return the mode derived from umask
+            Ok(!mode::get_umask() & 0o0777)
+        }
     }
 }
 
@@ -115,7 +118,7 @@ pub fn uu_app<'a>() -> Command<'a> {
                 .short('m')
                 .long(options::MODE)
                 .help("set file mode (not implemented on windows)")
-                .default_value("755"),
+                .takes_value(true),
         )
         .arg(
             Arg::new(options::PARENTS)


Test patch:
diff --git a/tests/by-util/test_mkdir.rs b/tests/by-util/test_mkdir.rs
index 675ca6bea41..be7a95af2e7 100644
--- a/tests/by-util/test_mkdir.rs
+++ b/tests/by-util/test_mkdir.rs
@@ -1,6 +1,10 @@
 use crate::common::util::*;
 #[cfg(not(windows))]
 use std::os::unix::fs::PermissionsExt;
+#[cfg(not(windows))]
+extern crate libc;
+#[cfg(not(windows))]
+use self::libc::{mode_t, umask};
 
 static TEST_DIR1: &str = "mkdir_test1";
 static TEST_DIR2: &str = "mkdir_test2";
@@ -13,6 +17,8 @@ static TEST_DIR8: &str = "mkdir_test8/mkdir_test8_1/mkdir_test8_2";
 static TEST_DIR9: &str = "mkdir_test9/../mkdir_test9_1/../mkdir_test9_2";
 static TEST_DIR10: &str = "mkdir_test10/.";
 static TEST_DIR11: &str = "mkdir_test11/..";
+#[cfg(not(windows))]
+static TEST_DIR12: &str = "mkdir_test12";
 
 #[test]
 fn test_mkdir_mkdir() {
@@ -151,3 +157,26 @@ fn test_mkdir_trailing_dot() {
     let result = scene2.cmd("ls").arg("-al").run();
     println!("ls dest {}", result.stdout_str());
 }
+
+#[test]
+#[cfg(not(windows))]
+fn test_umask_compliance() {
+    fn test_single_case(umask_set: mode_t) {
+        let (at, mut ucmd) = at_and_ucmd!();
+
+        let original_umask = unsafe { umask(umask_set) };
+
+        ucmd.arg(TEST_DIR12).succeeds();
+        let perms = at.metadata(TEST_DIR12).permissions().mode() as mode_t;
+
+        assert_eq!(perms, (!umask_set & 0o0777) + 0o40000); // before compare, add the set GUID, UID bits
+        unsafe {
+            umask(original_umask);
+        } // set umask back to original
+    }
+
+    for i in 0o0..0o027 {
+        // tests all permission combinations
+        test_single_case(i as mode_t);
+    }
+}
diff --git a/tests/by-util/test_pwd.rs b/tests/by-util/test_pwd.rs
index bc08ddbb0df..950a148a306 100644
--- a/tests/by-util/test_pwd.rs
+++ b/tests/by-util/test_pwd.rs
@@ -26,7 +26,7 @@ fn test_deleted_dir() {
     let output = Command::new("sh")
         .arg("-c")
         .arg(format!(
-            "cd '{}'; mkdir foo; cd foo; rmdir ../foo; exec {} {}",
+            "cd '{}'; mkdir foo; cd foo; rmdir ../foo; exec '{}' {}",
             at.root_dir_resolved(),
             ts.bin_path.to_str().unwrap(),
             ts.util_name,