3
3
// For the full copyright and license information, please view the LICENSE
4
4
// file that was distributed with this source code.
5
5
use crate :: common:: util:: { AtPath , TestScenario , UCommand } ;
6
- use once_cell:: sync:: Lazy ;
7
6
use std:: fs:: { metadata, set_permissions, OpenOptions , Permissions } ;
8
7
use std:: os:: unix:: fs:: { OpenOptionsExt , PermissionsExt } ;
9
- use std:: sync:: Mutex ;
10
-
11
- use libc:: umask;
12
8
13
9
static TEST_FILE : & str = "file" ;
14
10
static REFERENCE_FILE : & str = "reference" ;
15
11
static REFERENCE_PERMS : u32 = 0o247 ;
16
- static UMASK_MUTEX : Lazy < Mutex < ( ) > > = Lazy :: new ( || Mutex :: new ( ( ) ) ) ;
17
12
18
13
struct TestCase {
19
14
args : Vec < & ' static str > ,
20
15
before : u32 ,
21
16
after : u32 ,
17
+ umask : Option < libc:: mode_t > ,
22
18
}
23
19
24
20
fn make_file ( file : & str , mode : u32 ) {
@@ -45,6 +41,9 @@ fn run_single_test(test: &TestCase, at: &AtPath, mut ucmd: UCommand) {
45
41
46
42
for arg in & test. args {
47
43
ucmd. arg ( arg) ;
44
+ if let Some ( umask) = test. umask {
45
+ ucmd. umask ( umask) ;
46
+ }
48
47
}
49
48
let r = ucmd. run ( ) ;
50
49
if !r. succeeded ( ) {
@@ -73,46 +72,55 @@ fn test_chmod_octal() {
73
72
args: vec![ "0700" , TEST_FILE ] ,
74
73
before: 0o100000 ,
75
74
after: 0o100700 ,
75
+ umask: None ,
76
76
} ,
77
77
TestCase {
78
78
args: vec![ "0070" , TEST_FILE ] ,
79
79
before: 0o100000 ,
80
80
after: 0o100070 ,
81
+ umask: None ,
81
82
} ,
82
83
TestCase {
83
84
args: vec![ "0007" , TEST_FILE ] ,
84
85
before: 0o100000 ,
85
86
after: 0o100007 ,
87
+ umask: None ,
86
88
} ,
87
89
TestCase {
88
90
args: vec![ "-0700" , TEST_FILE ] ,
89
91
before: 0o100700 ,
90
92
after: 0o100000 ,
93
+ umask: None ,
91
94
} ,
92
95
TestCase {
93
96
args: vec![ "-0070" , TEST_FILE ] ,
94
97
before: 0o100060 ,
95
98
after: 0o100000 ,
99
+ umask: None ,
96
100
} ,
97
101
TestCase {
98
102
args: vec![ "-0007" , TEST_FILE ] ,
99
103
before: 0o100001 ,
100
104
after: 0o100000 ,
105
+ umask: None ,
101
106
} ,
102
107
TestCase {
103
108
args: vec![ "+0100" , TEST_FILE ] ,
104
109
before: 0o100600 ,
105
110
after: 0o100700 ,
111
+ umask: None ,
106
112
} ,
107
113
TestCase {
108
114
args: vec![ "+0020" , TEST_FILE ] ,
109
115
before: 0o100050 ,
110
116
after: 0o100070 ,
117
+ umask: None ,
111
118
} ,
112
119
TestCase {
113
120
args: vec![ "+0004" , TEST_FILE ] ,
114
121
before: 0o100003 ,
115
122
after: 0o100007 ,
123
+ umask: None ,
116
124
} ,
117
125
] ;
118
126
run_tests ( tests) ;
@@ -122,86 +130,94 @@ fn test_chmod_octal() {
122
130
#[ allow( clippy:: unreadable_literal) ]
123
131
// spell-checker:disable-next-line
124
132
fn test_chmod_ugoa ( ) {
125
- let _guard = UMASK_MUTEX . lock ( ) ;
126
-
127
- let last = unsafe { umask ( 0 ) } ;
128
133
let tests = vec ! [
129
134
TestCase {
130
135
args: vec![ "u=rwx" , TEST_FILE ] ,
131
136
before: 0o100000 ,
132
137
after: 0o100700 ,
138
+ umask: Some ( 0 ) ,
133
139
} ,
134
140
TestCase {
135
141
args: vec![ "g=rwx" , TEST_FILE ] ,
136
142
before: 0o100000 ,
137
143
after: 0o100070 ,
144
+ umask: Some ( 0 ) ,
138
145
} ,
139
146
TestCase {
140
147
args: vec![ "o=rwx" , TEST_FILE ] ,
141
148
before: 0o100000 ,
142
149
after: 0o100007 ,
150
+ umask: Some ( 0 ) ,
143
151
} ,
144
152
TestCase {
145
153
args: vec![ "a=rwx" , TEST_FILE ] ,
146
154
before: 0o100000 ,
147
155
after: 0o100777 ,
156
+ umask: Some ( 0 ) ,
148
157
} ,
149
158
TestCase {
150
159
args: vec![ "-r" , TEST_FILE ] ,
151
160
before: 0o100777 ,
152
161
after: 0o100333 ,
162
+ umask: Some ( 0 ) ,
153
163
} ,
154
164
TestCase {
155
165
args: vec![ "-w" , TEST_FILE ] ,
156
166
before: 0o100777 ,
157
167
after: 0o100555 ,
168
+ umask: Some ( 0 ) ,
158
169
} ,
159
170
TestCase {
160
171
args: vec![ "-x" , TEST_FILE ] ,
161
172
before: 0o100777 ,
162
173
after: 0o100666 ,
174
+ umask: Some ( 0 ) ,
163
175
} ,
164
176
] ;
165
177
run_tests ( tests) ;
166
178
167
- unsafe {
168
- umask ( 0o022 ) ;
169
- }
170
179
let tests = vec ! [
171
180
TestCase {
172
181
args: vec![ "u=rwx" , TEST_FILE ] ,
173
182
before: 0o100000 ,
174
183
after: 0o100700 ,
184
+ umask: Some ( 0o022 ) ,
175
185
} ,
176
186
TestCase {
177
187
args: vec![ "g=rwx" , TEST_FILE ] ,
178
188
before: 0o100000 ,
179
189
after: 0o100070 ,
190
+ umask: Some ( 0o022 ) ,
180
191
} ,
181
192
TestCase {
182
193
args: vec![ "o=rwx" , TEST_FILE ] ,
183
194
before: 0o100000 ,
184
195
after: 0o100007 ,
196
+ umask: Some ( 0o022 ) ,
185
197
} ,
186
198
TestCase {
187
199
args: vec![ "a=rwx" , TEST_FILE ] ,
188
200
before: 0o100000 ,
189
201
after: 0o100777 ,
202
+ umask: Some ( 0o022 ) ,
190
203
} ,
191
204
TestCase {
192
205
args: vec![ "+rw" , TEST_FILE ] ,
193
206
before: 0o100000 ,
194
207
after: 0o100644 ,
208
+ umask: Some ( 0o022 ) ,
195
209
} ,
196
210
TestCase {
197
211
args: vec![ "=rwx" , TEST_FILE ] ,
198
212
before: 0o100000 ,
199
213
after: 0o100755 ,
214
+ umask: Some ( 0o022 ) ,
200
215
} ,
201
216
TestCase {
202
217
args: vec![ "-x" , TEST_FILE ] ,
203
218
before: 0o100777 ,
204
219
after: 0o100666 ,
220
+ umask: Some ( 0o022 ) ,
205
221
} ,
206
222
] ;
207
223
run_tests ( tests) ;
@@ -219,10 +235,6 @@ fn test_chmod_ugoa() {
219
235
metadata( at. plus( "file" ) ) . unwrap( ) . permissions( ) . mode( ) ,
220
236
0o100577
221
237
) ;
222
-
223
- unsafe {
224
- umask ( last) ;
225
- }
226
238
}
227
239
228
240
#[ test]
@@ -233,26 +245,31 @@ fn test_chmod_ugo_copy() {
233
245
args: vec![ "u=g" , TEST_FILE ] ,
234
246
before: 0o100070 ,
235
247
after: 0o100770 ,
248
+ umask: None ,
236
249
} ,
237
250
TestCase {
238
251
args: vec![ "g=o" , TEST_FILE ] ,
239
252
before: 0o100005 ,
240
253
after: 0o100055 ,
254
+ umask: None ,
241
255
} ,
242
256
TestCase {
243
257
args: vec![ "o=u" , TEST_FILE ] ,
244
258
before: 0o100200 ,
245
259
after: 0o100202 ,
260
+ umask: None ,
246
261
} ,
247
262
TestCase {
248
263
args: vec![ "u-g" , TEST_FILE ] ,
249
264
before: 0o100710 ,
250
265
after: 0o100610 ,
266
+ umask: None ,
251
267
} ,
252
268
TestCase {
253
269
args: vec![ "u+g" , TEST_FILE ] ,
254
270
before: 0o100250 ,
255
271
after: 0o100750 ,
272
+ umask: None ,
256
273
} ,
257
274
] ;
258
275
run_tests ( tests) ;
@@ -261,18 +278,13 @@ fn test_chmod_ugo_copy() {
261
278
#[ test]
262
279
#[ allow( clippy:: unreadable_literal) ]
263
280
fn test_chmod_many_options ( ) {
264
- let _guard = UMASK_MUTEX . lock ( ) ;
265
-
266
- let original_umask = unsafe { umask ( 0 ) } ;
267
281
let tests = vec ! [ TestCase {
268
282
args: vec![ "-r,a+w" , TEST_FILE ] ,
269
283
before: 0o100444 ,
270
284
after: 0o100222 ,
285
+ umask: Some ( 0 ) ,
271
286
} ] ;
272
287
run_tests ( tests) ;
273
- unsafe {
274
- umask ( original_umask) ;
275
- }
276
288
}
277
289
278
290
#[ test]
@@ -283,11 +295,13 @@ fn test_chmod_reference_file() {
283
295
args : vec ! [ "--reference" , REFERENCE_FILE , TEST_FILE ] ,
284
296
before : 0o100070 ,
285
297
after : 0o100247 ,
298
+ umask : None ,
286
299
} ,
287
300
TestCase {
288
301
args : vec ! [ "a-w" , "--reference" , REFERENCE_FILE , TEST_FILE ] ,
289
302
before : 0o100070 ,
290
303
after : 0o100247 ,
304
+ umask : None ,
291
305
} ,
292
306
] ;
293
307
let ( at, ucmd) = at_and_ucmd ! ( ) ;
@@ -318,14 +332,16 @@ fn test_permission_denied() {
318
332
#[ test]
319
333
#[ allow( clippy:: unreadable_literal) ]
320
334
fn test_chmod_recursive ( ) {
321
- let _guard = UMASK_MUTEX . lock ( ) ;
322
-
323
- let original_umask = unsafe { umask ( 0 ) } ;
324
335
let ( at, mut ucmd) = at_and_ucmd ! ( ) ;
325
336
at. mkdir ( "a" ) ;
326
337
at. mkdir ( "a/b" ) ;
327
338
at. mkdir ( "a/b/c" ) ;
328
339
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
+
329
345
make_file ( & at. plus_as_string ( "a/a" ) , 0o100444 ) ;
330
346
make_file ( & at. plus_as_string ( "a/b/b" ) , 0o100444 ) ;
331
347
make_file ( & at. plus_as_string ( "a/b/c/c" ) , 0o100444 ) ;
@@ -338,6 +354,7 @@ fn test_chmod_recursive() {
338
354
. arg ( "-r,a+w" )
339
355
. arg ( "a" )
340
356
. arg ( "z" )
357
+ . umask ( 0 )
341
358
. fails ( )
342
359
. stderr_is ( "chmod: Permission denied\n " ) ;
343
360
@@ -346,12 +363,8 @@ fn test_chmod_recursive() {
346
363
assert_eq ! ( at. metadata( "a/b/b" ) . permissions( ) . mode( ) , 0o100444 ) ;
347
364
assert_eq ! ( at. metadata( "a/b/c/c" ) . permissions( ) . mode( ) , 0o100444 ) ;
348
365
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) ;
355
368
}
356
369
357
370
#[ test]
@@ -550,6 +563,7 @@ fn test_mode_after_dash_dash() {
550
563
args : vec ! [ "--" , "-r" , TEST_FILE ] ,
551
564
before : 0o100_777 ,
552
565
after : 0o100_333 ,
566
+ umask : None ,
553
567
} ,
554
568
& at,
555
569
ucmd,
0 commit comments