@@ -33,6 +33,24 @@ mod options {
3333 pub const CONTEXT : & str = "context" ;
3434}
3535
36+ /// Configuration for directory creation.
37+ pub struct Config < ' a > {
38+ /// Create parent directories as needed.
39+ pub recursive : bool ,
40+
41+ /// File permissions (octal).
42+ pub mode : u32 ,
43+
44+ /// Print message for each created directory.
45+ pub verbose : bool ,
46+
47+ /// Set SELinux security context.
48+ pub set_selinux_context : bool ,
49+
50+ /// Specific SELinux context.
51+ pub context : Option < & ' a String > ,
52+ }
53+
3654#[ cfg( windows) ]
3755fn get_mode ( _matches : & ArgMatches , _mode_had_minus_prefix : bool ) -> Result < u32 , String > {
3856 Ok ( DEFAULT_PERM )
@@ -98,14 +116,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
98116 let context = matches. get_one :: < String > ( options:: CONTEXT ) ;
99117
100118 match get_mode ( & matches, mode_had_minus_prefix) {
101- Ok ( mode) => exec (
102- dirs,
103- recursive,
104- mode,
105- verbose,
106- set_selinux_context || context. is_some ( ) ,
107- context,
108- ) ,
119+ Ok ( mode) => {
120+ let config = Config {
121+ recursive,
122+ mode,
123+ verbose,
124+ set_selinux_context : set_selinux_context || context. is_some ( ) ,
125+ context,
126+ } ;
127+ exec ( dirs, & config)
128+ }
109129 Err ( f) => Err ( USimpleError :: new ( 1 , f) ) ,
110130 }
111131}
@@ -159,26 +179,12 @@ pub fn uu_app() -> Command {
159179/**
160180 * Create the list of new directories
161181 */
162- fn exec (
163- dirs : ValuesRef < OsString > ,
164- recursive : bool ,
165- mode : u32 ,
166- verbose : bool ,
167- set_selinux_context : bool ,
168- context : Option < & String > ,
169- ) -> UResult < ( ) > {
182+ fn exec ( dirs : ValuesRef < OsString > , config : & Config ) -> UResult < ( ) > {
170183 for dir in dirs {
171184 let path_buf = PathBuf :: from ( dir) ;
172185 let path = path_buf. as_path ( ) ;
173186
174- show_if_err ! ( mkdir(
175- path,
176- recursive,
177- mode,
178- verbose,
179- set_selinux_context,
180- context
181- ) ) ;
187+ show_if_err ! ( mkdir( path, config) ) ;
182188 }
183189 Ok ( ( ) )
184190}
@@ -196,14 +202,7 @@ fn exec(
196202///
197203/// To match the GNU behavior, a path with the last directory being a single dot
198204/// (like `some/path/to/.`) is created (with the dot stripped).
199- pub fn mkdir (
200- path : & Path ,
201- recursive : bool ,
202- mode : u32 ,
203- verbose : bool ,
204- set_selinux_context : bool ,
205- context : Option < & String > ,
206- ) -> UResult < ( ) > {
205+ pub fn mkdir ( path : & Path , config : & Config ) -> UResult < ( ) > {
207206 if path. as_os_str ( ) . is_empty ( ) {
208207 return Err ( USimpleError :: new (
209208 1 ,
@@ -216,15 +215,7 @@ pub fn mkdir(
216215 // std::fs::create_dir("foo/."); fails in pure Rust
217216 let path_buf = dir_strip_dot_for_creation ( path) ;
218217 let path = path_buf. as_path ( ) ;
219- create_dir (
220- path,
221- recursive,
222- verbose,
223- false ,
224- mode,
225- set_selinux_context,
226- context,
227- )
218+ create_dir ( path, false , config)
228219}
229220
230221#[ cfg( any( unix, target_os = "redox" ) ) ]
@@ -245,17 +236,9 @@ fn chmod(_path: &Path, _mode: u32) -> UResult<()> {
245236// Return true if the directory at `path` has been created by this call.
246237// `is_parent` argument is not used on windows
247238#[ allow( unused_variables) ]
248- fn create_dir (
249- path : & Path ,
250- recursive : bool ,
251- verbose : bool ,
252- is_parent : bool ,
253- mode : u32 ,
254- set_selinux_context : bool ,
255- context : Option < & String > ,
256- ) -> UResult < ( ) > {
239+ fn create_dir ( path : & Path , is_parent : bool , config : & Config ) -> UResult < ( ) > {
257240 let path_exists = path. exists ( ) ;
258- if path_exists && !recursive {
241+ if path_exists && !config . recursive {
259242 return Err ( USimpleError :: new (
260243 1 ,
261244 format ! ( "{}: File exists" , path. display( ) ) ,
@@ -265,17 +248,9 @@ fn create_dir(
265248 return Ok ( ( ) ) ;
266249 }
267250
268- if recursive {
251+ if config . recursive {
269252 match path. parent ( ) {
270- Some ( p) => create_dir (
271- p,
272- recursive,
273- verbose,
274- true ,
275- mode,
276- set_selinux_context,
277- context,
278- ) ?,
253+ Some ( p) => create_dir ( p, true , config) ?,
279254 None => {
280255 USimpleError :: new ( 1 , "failed to create whole tree" ) ;
281256 }
@@ -284,7 +259,7 @@ fn create_dir(
284259
285260 match std:: fs:: create_dir ( path) {
286261 Ok ( ( ) ) => {
287- if verbose {
262+ if config . verbose {
288263 println ! (
289264 "{}: created directory {}" ,
290265 uucore:: util_name( ) ,
@@ -294,7 +269,7 @@ fn create_dir(
294269
295270 #[ cfg( all( unix, target_os = "linux" ) ) ]
296271 let new_mode = if path_exists {
297- mode
272+ config . mode
298273 } else {
299274 // TODO: Make this macos and freebsd compatible by creating a function to get permission bits from
300275 // acl in extended attributes
@@ -303,24 +278,24 @@ fn create_dir(
303278 if is_parent {
304279 ( !mode:: get_umask ( ) & 0o777 ) | 0o300 | acl_perm_bits
305280 } else {
306- mode | acl_perm_bits
281+ config . mode | acl_perm_bits
307282 }
308283 } ;
309284 #[ cfg( all( unix, not( target_os = "linux" ) ) ) ]
310285 let new_mode = if is_parent {
311286 ( !mode:: get_umask ( ) & 0o777 ) | 0o300
312287 } else {
313- mode
288+ config . mode
314289 } ;
315290 #[ cfg( windows) ]
316- let new_mode = mode;
291+ let new_mode = config . mode ;
317292
318293 chmod ( path, new_mode) ?;
319294
320295 // Apply SELinux context if requested
321- #[ cfg( target_os = "linux " ) ]
322- if set_selinux_context {
323- if let Err ( e) = uucore:: selinux_support :: set_selinux_security_context ( path, context)
296+ #[ cfg( feature = "selinux " ) ]
297+ if config . set_selinux_context {
298+ if let Err ( e) = uucore:: selinux :: set_selinux_security_context ( path, config . context )
324299 {
325300 return Err ( USimpleError :: new (
326301 1 ,
0 commit comments