Skip to content

Commit 3c096ee

Browse files
util: added umask manipulation (#6404)
Co-authored-by: Terts Diepraam <terts.diepraam@gmail.com>
1 parent f013d23 commit 3c096ee

File tree

4 files changed

+113
-94
lines changed

4 files changed

+113
-94
lines changed

tests/by-util/test_chmod.rs

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,18 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55
use crate::common::util::{AtPath, TestScenario, UCommand};
6-
use once_cell::sync::Lazy;
76
use std::fs::{metadata, set_permissions, OpenOptions, Permissions};
87
use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
9-
use std::sync::Mutex;
10-
11-
use libc::umask;
128

139
static TEST_FILE: &str = "file";
1410
static REFERENCE_FILE: &str = "reference";
1511
static REFERENCE_PERMS: u32 = 0o247;
16-
static UMASK_MUTEX: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
1712

1813
struct TestCase {
1914
args: Vec<&'static str>,
2015
before: u32,
2116
after: u32,
17+
umask: Option<libc::mode_t>,
2218
}
2319

2420
fn make_file(file: &str, mode: u32) {
@@ -45,6 +41,9 @@ fn run_single_test(test: &TestCase, at: &AtPath, mut ucmd: UCommand) {
4541

4642
for arg in &test.args {
4743
ucmd.arg(arg);
44+
if let Some(umask) = test.umask {
45+
ucmd.umask(umask);
46+
}
4847
}
4948
let r = ucmd.run();
5049
if !r.succeeded() {
@@ -73,46 +72,55 @@ fn test_chmod_octal() {
7372
args: vec!["0700", TEST_FILE],
7473
before: 0o100000,
7574
after: 0o100700,
75+
umask: None,
7676
},
7777
TestCase {
7878
args: vec!["0070", TEST_FILE],
7979
before: 0o100000,
8080
after: 0o100070,
81+
umask: None,
8182
},
8283
TestCase {
8384
args: vec!["0007", TEST_FILE],
8485
before: 0o100000,
8586
after: 0o100007,
87+
umask: None,
8688
},
8789
TestCase {
8890
args: vec!["-0700", TEST_FILE],
8991
before: 0o100700,
9092
after: 0o100000,
93+
umask: None,
9194
},
9295
TestCase {
9396
args: vec!["-0070", TEST_FILE],
9497
before: 0o100060,
9598
after: 0o100000,
99+
umask: None,
96100
},
97101
TestCase {
98102
args: vec!["-0007", TEST_FILE],
99103
before: 0o100001,
100104
after: 0o100000,
105+
umask: None,
101106
},
102107
TestCase {
103108
args: vec!["+0100", TEST_FILE],
104109
before: 0o100600,
105110
after: 0o100700,
111+
umask: None,
106112
},
107113
TestCase {
108114
args: vec!["+0020", TEST_FILE],
109115
before: 0o100050,
110116
after: 0o100070,
117+
umask: None,
111118
},
112119
TestCase {
113120
args: vec!["+0004", TEST_FILE],
114121
before: 0o100003,
115122
after: 0o100007,
123+
umask: None,
116124
},
117125
];
118126
run_tests(tests);
@@ -122,86 +130,94 @@ fn test_chmod_octal() {
122130
#[allow(clippy::unreadable_literal)]
123131
// spell-checker:disable-next-line
124132
fn test_chmod_ugoa() {
125-
let _guard = UMASK_MUTEX.lock();
126-
127-
let last = unsafe { umask(0) };
128133
let tests = vec![
129134
TestCase {
130135
args: vec!["u=rwx", TEST_FILE],
131136
before: 0o100000,
132137
after: 0o100700,
138+
umask: Some(0),
133139
},
134140
TestCase {
135141
args: vec!["g=rwx", TEST_FILE],
136142
before: 0o100000,
137143
after: 0o100070,
144+
umask: Some(0),
138145
},
139146
TestCase {
140147
args: vec!["o=rwx", TEST_FILE],
141148
before: 0o100000,
142149
after: 0o100007,
150+
umask: Some(0),
143151
},
144152
TestCase {
145153
args: vec!["a=rwx", TEST_FILE],
146154
before: 0o100000,
147155
after: 0o100777,
156+
umask: Some(0),
148157
},
149158
TestCase {
150159
args: vec!["-r", TEST_FILE],
151160
before: 0o100777,
152161
after: 0o100333,
162+
umask: Some(0),
153163
},
154164
TestCase {
155165
args: vec!["-w", TEST_FILE],
156166
before: 0o100777,
157167
after: 0o100555,
168+
umask: Some(0),
158169
},
159170
TestCase {
160171
args: vec!["-x", TEST_FILE],
161172
before: 0o100777,
162173
after: 0o100666,
174+
umask: Some(0),
163175
},
164176
];
165177
run_tests(tests);
166178

167-
unsafe {
168-
umask(0o022);
169-
}
170179
let tests = vec![
171180
TestCase {
172181
args: vec!["u=rwx", TEST_FILE],
173182
before: 0o100000,
174183
after: 0o100700,
184+
umask: Some(0o022),
175185
},
176186
TestCase {
177187
args: vec!["g=rwx", TEST_FILE],
178188
before: 0o100000,
179189
after: 0o100070,
190+
umask: Some(0o022),
180191
},
181192
TestCase {
182193
args: vec!["o=rwx", TEST_FILE],
183194
before: 0o100000,
184195
after: 0o100007,
196+
umask: Some(0o022),
185197
},
186198
TestCase {
187199
args: vec!["a=rwx", TEST_FILE],
188200
before: 0o100000,
189201
after: 0o100777,
202+
umask: Some(0o022),
190203
},
191204
TestCase {
192205
args: vec!["+rw", TEST_FILE],
193206
before: 0o100000,
194207
after: 0o100644,
208+
umask: Some(0o022),
195209
},
196210
TestCase {
197211
args: vec!["=rwx", TEST_FILE],
198212
before: 0o100000,
199213
after: 0o100755,
214+
umask: Some(0o022),
200215
},
201216
TestCase {
202217
args: vec!["-x", TEST_FILE],
203218
before: 0o100777,
204219
after: 0o100666,
220+
umask: Some(0o022),
205221
},
206222
];
207223
run_tests(tests);
@@ -219,10 +235,6 @@ fn test_chmod_ugoa() {
219235
metadata(at.plus("file")).unwrap().permissions().mode(),
220236
0o100577
221237
);
222-
223-
unsafe {
224-
umask(last);
225-
}
226238
}
227239

228240
#[test]
@@ -233,26 +245,31 @@ fn test_chmod_ugo_copy() {
233245
args: vec!["u=g", TEST_FILE],
234246
before: 0o100070,
235247
after: 0o100770,
248+
umask: None,
236249
},
237250
TestCase {
238251
args: vec!["g=o", TEST_FILE],
239252
before: 0o100005,
240253
after: 0o100055,
254+
umask: None,
241255
},
242256
TestCase {
243257
args: vec!["o=u", TEST_FILE],
244258
before: 0o100200,
245259
after: 0o100202,
260+
umask: None,
246261
},
247262
TestCase {
248263
args: vec!["u-g", TEST_FILE],
249264
before: 0o100710,
250265
after: 0o100610,
266+
umask: None,
251267
},
252268
TestCase {
253269
args: vec!["u+g", TEST_FILE],
254270
before: 0o100250,
255271
after: 0o100750,
272+
umask: None,
256273
},
257274
];
258275
run_tests(tests);
@@ -261,18 +278,13 @@ fn test_chmod_ugo_copy() {
261278
#[test]
262279
#[allow(clippy::unreadable_literal)]
263280
fn test_chmod_many_options() {
264-
let _guard = UMASK_MUTEX.lock();
265-
266-
let original_umask = unsafe { umask(0) };
267281
let tests = vec![TestCase {
268282
args: vec!["-r,a+w", TEST_FILE],
269283
before: 0o100444,
270284
after: 0o100222,
285+
umask: Some(0),
271286
}];
272287
run_tests(tests);
273-
unsafe {
274-
umask(original_umask);
275-
}
276288
}
277289

278290
#[test]
@@ -283,11 +295,13 @@ fn test_chmod_reference_file() {
283295
args: vec!["--reference", REFERENCE_FILE, TEST_FILE],
284296
before: 0o100070,
285297
after: 0o100247,
298+
umask: None,
286299
},
287300
TestCase {
288301
args: vec!["a-w", "--reference", REFERENCE_FILE, TEST_FILE],
289302
before: 0o100070,
290303
after: 0o100247,
304+
umask: None,
291305
},
292306
];
293307
let (at, ucmd) = at_and_ucmd!();
@@ -318,14 +332,16 @@ fn test_permission_denied() {
318332
#[test]
319333
#[allow(clippy::unreadable_literal)]
320334
fn test_chmod_recursive() {
321-
let _guard = UMASK_MUTEX.lock();
322-
323-
let original_umask = unsafe { umask(0) };
324335
let (at, mut ucmd) = at_and_ucmd!();
325336
at.mkdir("a");
326337
at.mkdir("a/b");
327338
at.mkdir("a/b/c");
328339
at.mkdir("z");
340+
341+
// create expected permissions by removing read bits and write bits to the current perms
342+
let a_perms_expected = (at.metadata("a").permissions().mode() & !0o444) | 0o222;
343+
let z_perms_expected = (at.metadata("z").permissions().mode() & !0o444) | 0o222;
344+
329345
make_file(&at.plus_as_string("a/a"), 0o100444);
330346
make_file(&at.plus_as_string("a/b/b"), 0o100444);
331347
make_file(&at.plus_as_string("a/b/c/c"), 0o100444);
@@ -338,6 +354,7 @@ fn test_chmod_recursive() {
338354
.arg("-r,a+w")
339355
.arg("a")
340356
.arg("z")
357+
.umask(0)
341358
.fails()
342359
.stderr_is("chmod: Permission denied\n");
343360

@@ -346,12 +363,8 @@ fn test_chmod_recursive() {
346363
assert_eq!(at.metadata("a/b/b").permissions().mode(), 0o100444);
347364
assert_eq!(at.metadata("a/b/c/c").permissions().mode(), 0o100444);
348365
println!("mode {:o}", at.metadata("a").permissions().mode());
349-
assert_eq!(at.metadata("a").permissions().mode(), 0o40333);
350-
assert_eq!(at.metadata("z").permissions().mode(), 0o40333);
351-
352-
unsafe {
353-
umask(original_umask);
354-
}
366+
assert_eq!(at.metadata("a").permissions().mode(), a_perms_expected);
367+
assert_eq!(at.metadata("z").permissions().mode(), z_perms_expected);
355368
}
356369

357370
#[test]
@@ -550,6 +563,7 @@ fn test_mode_after_dash_dash() {
550563
args: vec!["--", "-r", TEST_FILE],
551564
before: 0o100_777,
552565
after: 0o100_333,
566+
umask: None,
553567
},
554568
&at,
555569
ucmd,

tests/by-util/test_cp.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,27 +1718,24 @@ fn test_cp_preserve_links_case_7() {
17181718
#[test]
17191719
#[cfg(unix)]
17201720
fn test_cp_no_preserve_mode() {
1721-
use libc::umask;
17221721
use uucore::fs as uufs;
17231722
let (at, mut ucmd) = at_and_ucmd!();
17241723

17251724
at.touch("a");
17261725
at.set_mode("a", 0o731);
1727-
unsafe { umask(0o077) };
17281726

17291727
ucmd.arg("-a")
17301728
.arg("--no-preserve=mode")
17311729
.arg("a")
17321730
.arg("b")
1731+
.umask(0o077)
17331732
.succeeds();
17341733

17351734
assert!(at.file_exists("b"));
17361735

17371736
let metadata_b = std::fs::metadata(at.subdir.join("b")).unwrap();
17381737
let permission_b = uufs::display_permissions(&metadata_b, false);
17391738
assert_eq!(permission_b, "rw-------".to_string());
1740-
1741-
unsafe { umask(0o022) };
17421739
}
17431740

17441741
#[test]
@@ -2535,8 +2532,6 @@ fn test_copy_symlink_force() {
25352532
fn test_no_preserve_mode() {
25362533
use std::os::unix::prelude::MetadataExt;
25372534

2538-
use uucore::mode::get_umask;
2539-
25402535
const PERMS_ALL: u32 = if cfg!(target_os = "freebsd") {
25412536
// Only the superuser can set the sticky bit on a file.
25422537
0o6777
@@ -2547,14 +2542,15 @@ fn test_no_preserve_mode() {
25472542
let (at, mut ucmd) = at_and_ucmd!();
25482543
at.touch("file");
25492544
set_permissions(at.plus("file"), PermissionsExt::from_mode(PERMS_ALL)).unwrap();
2545+
let umask: u16 = 0o022;
25502546
ucmd.arg("file")
25512547
.arg("dest")
2548+
.umask(umask as libc::mode_t)
25522549
.succeeds()
25532550
.no_stderr()
25542551
.no_stdout();
2555-
let umask = get_umask();
25562552
// remove sticky bit, setuid and setgid bit; apply umask
2557-
let expected_perms = PERMS_ALL & !0o7000 & !umask;
2553+
let expected_perms = PERMS_ALL & !0o7000 & !umask as u32;
25582554
assert_eq!(
25592555
at.plus("dest").metadata().unwrap().mode() & 0o7777,
25602556
expected_perms

0 commit comments

Comments
 (0)