@@ -264,6 +264,7 @@ fn copy_direntry(
264264 copied_destinations : & HashSet < PathBuf > ,
265265 copied_files : & mut HashMap < FileInformation , PathBuf > ,
266266 created_parent_dirs : & mut HashSet < PathBuf > ,
267+ #[ cfg( unix) ] orig_umask : u32 ,
267268) -> CopyResult < bool > {
268269 let source_is_symlink = entry_is_symlink;
269270 let source_is_dir = if source_is_symlink && !options. dereference {
@@ -280,12 +281,7 @@ fn copy_direntry(
280281 return if entry. target_is_file {
281282 Err ( translate ! ( "cp-error-cannot-overwrite-non-directory-with-directory" ) . into ( ) )
282283 } else {
283- build_dir (
284- & entry. local_to_target ,
285- false ,
286- options,
287- Some ( & entry. source_absolute ) ,
288- ) ?;
284+ build_dir ( & entry. local_to_target , false ) ?;
289285 if options. verbose {
290286 println ! (
291287 "{}" ,
@@ -308,6 +304,8 @@ fn copy_direntry(
308304 copied_files,
309305 created_parent_dirs,
310306 false ,
307+ #[ cfg( unix) ]
308+ orig_umask,
311309 ) {
312310 if preserve_hard_links {
313311 if !source_is_symlink {
@@ -361,6 +359,7 @@ pub(crate) fn copy_directory(
361359 copied_files : & mut HashMap < FileInformation , PathBuf > ,
362360 created_parent_dirs : & mut HashSet < PathBuf > ,
363361 source_in_command_line : bool ,
362+ #[ cfg( unix) ] orig_umask : u32 ,
364363) -> CopyResult < ( ) > {
365364 // if no-dereference is enabled and this is a symlink, copy it as a file
366365 if !options. dereference ( source_in_command_line) && root. is_symlink ( ) {
@@ -374,6 +373,8 @@ pub(crate) fn copy_directory(
374373 copied_files,
375374 created_parent_dirs,
376375 source_in_command_line,
376+ #[ cfg( unix) ]
377+ orig_umask,
377378 ) ;
378379 }
379380
@@ -399,7 +400,7 @@ pub(crate) fn copy_directory(
399400 let tmp = if options. parents {
400401 if let Some ( parent) = root. parent ( ) {
401402 let new_target = target. join ( parent) ;
402- build_dir ( & new_target, true , options , None ) ?;
403+ build_dir ( & new_target, true ) ?;
403404 if options. verbose {
404405 // For example, if copying file `a/b/c` and its parents
405406 // to directory `d/`, then print
@@ -469,6 +470,8 @@ pub(crate) fn copy_directory(
469470 copied_destinations,
470471 copied_files,
471472 created_parent_dirs,
473+ #[ cfg( unix) ]
474+ orig_umask,
472475 ) ?;
473476
474477 // We omit certain permissions when creating directories
@@ -492,6 +495,8 @@ pub(crate) fn copy_directory(
492495 & entry. local_to_target ,
493496 & options. attributes ,
494497 false ,
498+ #[ cfg( unix) ]
499+ orig_umask,
495500 ) ?;
496501 continue ;
497502 }
@@ -534,6 +539,8 @@ pub(crate) fn copy_directory(
534539 & entry. local_to_target ,
535540 & options. attributes ,
536541 false ,
542+ #[ cfg( unix) ]
543+ orig_umask,
537544 ) ?;
538545 }
539546 }
@@ -550,7 +557,14 @@ pub(crate) fn copy_directory(
550557 // Fix permissions for all directories we created
551558 // This ensures that even sibling directories get their permissions fixed
552559 for dir in dirs_needing_permissions {
553- copy_attributes ( & dir. source , & dir. dest , & options. attributes , dir. was_created ) ?;
560+ copy_attributes (
561+ & dir. source ,
562+ & dir. dest ,
563+ & options. attributes ,
564+ dir. was_created ,
565+ #[ cfg( unix) ]
566+ orig_umask,
567+ ) ?;
554568 }
555569
556570 // Also fix permissions for parent directories,
@@ -559,7 +573,14 @@ pub(crate) fn copy_directory(
559573 let dest = target. join ( root. file_name ( ) . unwrap ( ) ) ;
560574 for ( x, y) in aligned_ancestors ( root, dest. as_path ( ) ) {
561575 if let Ok ( src) = canonicalize ( x, MissingHandling :: Normal , ResolveMode :: Physical ) {
562- copy_attributes ( & src, y, & options. attributes , false ) ?;
576+ copy_attributes (
577+ & src,
578+ y,
579+ & options. attributes ,
580+ false ,
581+ #[ cfg( unix) ]
582+ orig_umask,
583+ ) ?;
563584 }
564585 }
565586 }
@@ -593,57 +614,12 @@ pub fn path_has_prefix(p1: &Path, p2: &Path) -> io::Result<bool> {
593614
594615/// Builds a directory at the specified path with the given options.
595616///
596- /// # Notes
597- /// - If `copy_attributes_from` is `Some`, the new directory's attributes will be
598- /// copied from the provided file. Otherwise, the new directory will have the default
599- /// attributes for the current user.
600- /// - This method excludes certain permissions if ownership or special mode bits could
601- /// potentially change. (See `test_dir_perm_race_with_preserve_mode_and_ownership`)
602- /// - The `recursive` flag determines whether parent directories should be created
603- /// if they do not already exist.
604- // we need to allow unused_variable since `options` might be unused in non unix systems
605- #[ allow( unused_variables) ]
606- fn build_dir (
607- path : & PathBuf ,
608- recursive : bool ,
609- options : & Options ,
610- copy_attributes_from : Option < & Path > ,
611- ) -> CopyResult < ( ) > {
617+ /// The `recursive` flag determines whether parent directories should be created if they do not
618+ /// already exist.
619+ #[ inline]
620+ fn build_dir ( path : & PathBuf , recursive : bool ) -> CopyResult < ( ) > {
612621 let mut builder = fs:: DirBuilder :: new ( ) ;
613622 builder. recursive ( recursive) ;
614-
615- // To prevent unauthorized access before the folder is ready,
616- // exclude certain permissions if ownership or special mode bits
617- // could potentially change.
618- #[ cfg( unix) ]
619- {
620- use crate :: Preserve ;
621- use std:: os:: unix:: fs:: PermissionsExt ;
622-
623- // we need to allow trivial casts here because some systems like linux have u32 constants in
624- // in libc while others don't.
625- #[ allow( clippy:: unnecessary_cast) ]
626- let mut excluded_perms = if matches ! ( options. attributes. ownership, Preserve :: Yes { .. } ) {
627- libc:: S_IRWXG | libc:: S_IRWXO // exclude rwx for group and other
628- } else if matches ! ( options. attributes. mode, Preserve :: Yes { .. } ) {
629- libc:: S_IWGRP | libc:: S_IWOTH //exclude w for group and other
630- } else {
631- 0
632- } as u32 ;
633-
634- let umask = if let ( Some ( from) , Preserve :: Yes { .. } ) =
635- ( copy_attributes_from, options. attributes . mode )
636- {
637- !fs:: symlink_metadata ( from) ?. permissions ( ) . mode ( )
638- } else {
639- uucore:: mode:: get_umask ( )
640- } ;
641-
642- excluded_perms |= umask;
643- let mode = !excluded_perms & 0o777 ; //use only the last three octet bits
644- std:: os:: unix:: fs:: DirBuilderExt :: mode ( & mut builder, mode) ;
645- }
646-
647623 builder. create ( path) ?;
648624 Ok ( ( ) )
649625}
0 commit comments