@@ -33,6 +33,23 @@ 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+ }
3653#[ cfg( windows) ]
3754fn get_mode ( _matches : & ArgMatches , _mode_had_minus_prefix : bool ) -> Result < u32 , String > {
3855 Ok ( DEFAULT_PERM )
@@ -98,14 +115,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
98115 let context = matches. get_one :: < String > ( options:: CONTEXT ) ;
99116
100117 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- ) ,
118+ Ok ( mode) => {
119+ let config = Config {
120+ recursive,
121+ mode,
122+ verbose,
123+ set_selinux_context : set_selinux_context || context. is_some ( ) ,
124+ context,
125+ } ;
126+ exec ( dirs, & config)
127+ }
109128 Err ( f) => Err ( USimpleError :: new ( 1 , f) ) ,
110129 }
111130}
@@ -159,26 +178,12 @@ pub fn uu_app() -> Command {
159178/**
160179 * Create the list of new directories
161180 */
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 < ( ) > {
181+ fn exec ( dirs : ValuesRef < OsString > , config : & Config ) -> UResult < ( ) > {
170182 for dir in dirs {
171183 let path_buf = PathBuf :: from ( dir) ;
172184 let path = path_buf. as_path ( ) ;
173185
174- show_if_err ! ( mkdir(
175- path,
176- recursive,
177- mode,
178- verbose,
179- set_selinux_context,
180- context
181- ) ) ;
186+ show_if_err ! ( mkdir( path, config) ) ;
182187 }
183188 Ok ( ( ) )
184189}
@@ -196,14 +201,7 @@ fn exec(
196201///
197202/// To match the GNU behavior, a path with the last directory being a single dot
198203/// (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 < ( ) > {
204+ pub fn mkdir ( path : & Path , config : & Config ) -> UResult < ( ) > {
207205 if path. as_os_str ( ) . is_empty ( ) {
208206 return Err ( USimpleError :: new (
209207 1 ,
@@ -216,15 +214,7 @@ pub fn mkdir(
216214 // std::fs::create_dir("foo/."); fails in pure Rust
217215 let path_buf = dir_strip_dot_for_creation ( path) ;
218216 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- )
217+ create_dir ( path, false , config)
228218}
229219
230220#[ cfg( any( unix, target_os = "redox" ) ) ]
@@ -245,17 +235,9 @@ fn chmod(_path: &Path, _mode: u32) -> UResult<()> {
245235// Return true if the directory at `path` has been created by this call.
246236// `is_parent` argument is not used on windows
247237#[ 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 < ( ) > {
238+ fn create_dir ( path : & Path , is_parent : bool , config : & Config ) -> UResult < ( ) > {
257239 let path_exists = path. exists ( ) ;
258- if path_exists && !recursive {
240+ if path_exists && !config . recursive {
259241 return Err ( USimpleError :: new (
260242 1 ,
261243 format ! ( "{}: File exists" , path. display( ) ) ,
@@ -265,17 +247,9 @@ fn create_dir(
265247 return Ok ( ( ) ) ;
266248 }
267249
268- if recursive {
250+ if config . recursive {
269251 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- ) ?,
252+ Some ( p) => create_dir ( p, true , config) ?,
279253 None => {
280254 USimpleError :: new ( 1 , "failed to create whole tree" ) ;
281255 }
@@ -284,7 +258,7 @@ fn create_dir(
284258
285259 match std:: fs:: create_dir ( path) {
286260 Ok ( ( ) ) => {
287- if verbose {
261+ if config . verbose {
288262 println ! (
289263 "{}: created directory {}" ,
290264 uucore:: util_name( ) ,
@@ -294,7 +268,7 @@ fn create_dir(
294268
295269 #[ cfg( all( unix, target_os = "linux" ) ) ]
296270 let new_mode = if path_exists {
297- mode
271+ config . mode
298272 } else {
299273 // TODO: Make this macos and freebsd compatible by creating a function to get permission bits from
300274 // acl in extended attributes
@@ -303,24 +277,24 @@ fn create_dir(
303277 if is_parent {
304278 ( !mode:: get_umask ( ) & 0o777 ) | 0o300 | acl_perm_bits
305279 } else {
306- mode | acl_perm_bits
280+ config . mode | acl_perm_bits
307281 }
308282 } ;
309283 #[ cfg( all( unix, not( target_os = "linux" ) ) ) ]
310284 let new_mode = if is_parent {
311285 ( !mode:: get_umask ( ) & 0o777 ) | 0o300
312286 } else {
313- mode
287+ config . mode
314288 } ;
315289 #[ cfg( windows) ]
316- let new_mode = mode;
290+ let new_mode = config . mode ;
317291
318292 chmod ( path, new_mode) ?;
319293
320294 // 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)
295+ #[ cfg( feature = "selinux " ) ]
296+ if config . set_selinux_context {
297+ if let Err ( e) = uucore:: selinux :: set_selinux_security_context ( path, config . context )
324298 {
325299 return Err ( USimpleError :: new (
326300 1 ,
0 commit comments