mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
util: added umask manipulation (#6404)
Co-authored-by: Terts Diepraam <terts.diepraam@gmail.com>
This commit is contained in:
parent
f013d230f8
commit
3c096ee6ac
4 changed files with 113 additions and 94 deletions
|
@ -3,22 +3,18 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
use crate::common::util::{AtPath, TestScenario, UCommand};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::fs::{metadata, set_permissions, OpenOptions, Permissions};
|
||||
use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use libc::umask;
|
||||
|
||||
static TEST_FILE: &str = "file";
|
||||
static REFERENCE_FILE: &str = "reference";
|
||||
static REFERENCE_PERMS: u32 = 0o247;
|
||||
static UMASK_MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
|
||||
|
||||
struct TestCase {
|
||||
args: Vec<&'static str>,
|
||||
before: u32,
|
||||
after: u32,
|
||||
umask: Option<libc::mode_t>,
|
||||
}
|
||||
|
||||
fn make_file(file: &str, mode: u32) {
|
||||
|
@ -45,6 +41,9 @@ fn run_single_test(test: &TestCase, at: &AtPath, mut ucmd: UCommand) {
|
|||
|
||||
for arg in &test.args {
|
||||
ucmd.arg(arg);
|
||||
if let Some(umask) = test.umask {
|
||||
ucmd.umask(umask);
|
||||
}
|
||||
}
|
||||
let r = ucmd.run();
|
||||
if !r.succeeded() {
|
||||
|
@ -73,46 +72,55 @@ fn test_chmod_octal() {
|
|||
args: vec!["0700", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100700,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["0070", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100070,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["0007", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100007,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["-0700", TEST_FILE],
|
||||
before: 0o100700,
|
||||
after: 0o100000,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["-0070", TEST_FILE],
|
||||
before: 0o100060,
|
||||
after: 0o100000,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["-0007", TEST_FILE],
|
||||
before: 0o100001,
|
||||
after: 0o100000,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["+0100", TEST_FILE],
|
||||
before: 0o100600,
|
||||
after: 0o100700,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["+0020", TEST_FILE],
|
||||
before: 0o100050,
|
||||
after: 0o100070,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["+0004", TEST_FILE],
|
||||
before: 0o100003,
|
||||
after: 0o100007,
|
||||
umask: None,
|
||||
},
|
||||
];
|
||||
run_tests(tests);
|
||||
|
@ -122,86 +130,94 @@ fn test_chmod_octal() {
|
|||
#[allow(clippy::unreadable_literal)]
|
||||
// spell-checker:disable-next-line
|
||||
fn test_chmod_ugoa() {
|
||||
let _guard = UMASK_MUTEX.lock();
|
||||
|
||||
let last = unsafe { umask(0) };
|
||||
let tests = vec![
|
||||
TestCase {
|
||||
args: vec!["u=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100700,
|
||||
umask: Some(0),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["g=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100070,
|
||||
umask: Some(0),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["o=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100007,
|
||||
umask: Some(0),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["a=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100777,
|
||||
umask: Some(0),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["-r", TEST_FILE],
|
||||
before: 0o100777,
|
||||
after: 0o100333,
|
||||
umask: Some(0),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["-w", TEST_FILE],
|
||||
before: 0o100777,
|
||||
after: 0o100555,
|
||||
umask: Some(0),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["-x", TEST_FILE],
|
||||
before: 0o100777,
|
||||
after: 0o100666,
|
||||
umask: Some(0),
|
||||
},
|
||||
];
|
||||
run_tests(tests);
|
||||
|
||||
unsafe {
|
||||
umask(0o022);
|
||||
}
|
||||
let tests = vec![
|
||||
TestCase {
|
||||
args: vec!["u=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100700,
|
||||
umask: Some(0o022),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["g=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100070,
|
||||
umask: Some(0o022),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["o=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100007,
|
||||
umask: Some(0o022),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["a=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100777,
|
||||
umask: Some(0o022),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["+rw", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100644,
|
||||
umask: Some(0o022),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["=rwx", TEST_FILE],
|
||||
before: 0o100000,
|
||||
after: 0o100755,
|
||||
umask: Some(0o022),
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["-x", TEST_FILE],
|
||||
before: 0o100777,
|
||||
after: 0o100666,
|
||||
umask: Some(0o022),
|
||||
},
|
||||
];
|
||||
run_tests(tests);
|
||||
|
@ -219,10 +235,6 @@ fn test_chmod_ugoa() {
|
|||
metadata(at.plus("file")).unwrap().permissions().mode(),
|
||||
0o100577
|
||||
);
|
||||
|
||||
unsafe {
|
||||
umask(last);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -233,26 +245,31 @@ fn test_chmod_ugo_copy() {
|
|||
args: vec!["u=g", TEST_FILE],
|
||||
before: 0o100070,
|
||||
after: 0o100770,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["g=o", TEST_FILE],
|
||||
before: 0o100005,
|
||||
after: 0o100055,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["o=u", TEST_FILE],
|
||||
before: 0o100200,
|
||||
after: 0o100202,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["u-g", TEST_FILE],
|
||||
before: 0o100710,
|
||||
after: 0o100610,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["u+g", TEST_FILE],
|
||||
before: 0o100250,
|
||||
after: 0o100750,
|
||||
umask: None,
|
||||
},
|
||||
];
|
||||
run_tests(tests);
|
||||
|
@ -261,18 +278,13 @@ fn test_chmod_ugo_copy() {
|
|||
#[test]
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
fn test_chmod_many_options() {
|
||||
let _guard = UMASK_MUTEX.lock();
|
||||
|
||||
let original_umask = unsafe { umask(0) };
|
||||
let tests = vec![TestCase {
|
||||
args: vec!["-r,a+w", TEST_FILE],
|
||||
before: 0o100444,
|
||||
after: 0o100222,
|
||||
umask: Some(0),
|
||||
}];
|
||||
run_tests(tests);
|
||||
unsafe {
|
||||
umask(original_umask);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -283,11 +295,13 @@ fn test_chmod_reference_file() {
|
|||
args: vec!["--reference", REFERENCE_FILE, TEST_FILE],
|
||||
before: 0o100070,
|
||||
after: 0o100247,
|
||||
umask: None,
|
||||
},
|
||||
TestCase {
|
||||
args: vec!["a-w", "--reference", REFERENCE_FILE, TEST_FILE],
|
||||
before: 0o100070,
|
||||
after: 0o100247,
|
||||
umask: None,
|
||||
},
|
||||
];
|
||||
let (at, ucmd) = at_and_ucmd!();
|
||||
|
@ -318,14 +332,16 @@ fn test_permission_denied() {
|
|||
#[test]
|
||||
#[allow(clippy::unreadable_literal)]
|
||||
fn test_chmod_recursive() {
|
||||
let _guard = UMASK_MUTEX.lock();
|
||||
|
||||
let original_umask = unsafe { umask(0) };
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
at.mkdir("a");
|
||||
at.mkdir("a/b");
|
||||
at.mkdir("a/b/c");
|
||||
at.mkdir("z");
|
||||
|
||||
// create expected permissions by removing read bits and write bits to the current perms
|
||||
let a_perms_expected = (at.metadata("a").permissions().mode() & !0o444) | 0o222;
|
||||
let z_perms_expected = (at.metadata("z").permissions().mode() & !0o444) | 0o222;
|
||||
|
||||
make_file(&at.plus_as_string("a/a"), 0o100444);
|
||||
make_file(&at.plus_as_string("a/b/b"), 0o100444);
|
||||
make_file(&at.plus_as_string("a/b/c/c"), 0o100444);
|
||||
|
@ -338,6 +354,7 @@ fn test_chmod_recursive() {
|
|||
.arg("-r,a+w")
|
||||
.arg("a")
|
||||
.arg("z")
|
||||
.umask(0)
|
||||
.fails()
|
||||
.stderr_is("chmod: Permission denied\n");
|
||||
|
||||
|
@ -346,12 +363,8 @@ fn test_chmod_recursive() {
|
|||
assert_eq!(at.metadata("a/b/b").permissions().mode(), 0o100444);
|
||||
assert_eq!(at.metadata("a/b/c/c").permissions().mode(), 0o100444);
|
||||
println!("mode {:o}", at.metadata("a").permissions().mode());
|
||||
assert_eq!(at.metadata("a").permissions().mode(), 0o40333);
|
||||
assert_eq!(at.metadata("z").permissions().mode(), 0o40333);
|
||||
|
||||
unsafe {
|
||||
umask(original_umask);
|
||||
}
|
||||
assert_eq!(at.metadata("a").permissions().mode(), a_perms_expected);
|
||||
assert_eq!(at.metadata("z").permissions().mode(), z_perms_expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -550,6 +563,7 @@ fn test_mode_after_dash_dash() {
|
|||
args: vec!["--", "-r", TEST_FILE],
|
||||
before: 0o100_777,
|
||||
after: 0o100_333,
|
||||
umask: None,
|
||||
},
|
||||
&at,
|
||||
ucmd,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue