File tree Expand file tree Collapse file tree 2 files changed +66
-9
lines changed Expand file tree Collapse file tree 2 files changed +66
-9
lines changed Original file line number Diff line number Diff line change @@ -1044,7 +1044,11 @@ fn copy_dir_contents_recursive(
10441044 }
10451045 #[ cfg( not( unix) ) ]
10461046 {
1047- fs:: copy ( & from_path, & to_path) ?;
1047+ if from_path. is_symlink ( ) {
1048+ rename_symlink_fallback ( & from_path, & to_path) ?;
1049+ } else {
1050+ fs:: copy ( & from_path, & to_path) ?;
1051+ }
10481052 }
10491053 }
10501054
@@ -1076,14 +1080,19 @@ fn copy_file_with_hardlinks_helper(
10761080 return Ok ( ( ) ) ;
10771081 }
10781082
1079- // Regular file copy
1080- #[ cfg( all( unix, not( any( target_os = "macos" , target_os = "redox" ) ) ) ) ]
1081- {
1082- fs:: copy ( from, to) . and_then ( |_| fsxattr:: copy_xattrs ( & from, & to) ) ?;
1083- }
1084- #[ cfg( any( target_os = "macos" , target_os = "redox" ) ) ]
1085- {
1086- fs:: copy ( from, to) ?;
1083+ if from. is_symlink ( ) {
1084+ // Symlink copy
1085+ rename_symlink_fallback ( from, to) ?;
1086+ } else {
1087+ // Regular file copy
1088+ #[ cfg( all( unix, not( any( target_os = "macos" , target_os = "redox" ) ) ) ) ]
1089+ {
1090+ fs:: copy ( from, to) . and_then ( |_| fsxattr:: copy_xattrs ( & from, & to) ) ?;
1091+ }
1092+ #[ cfg( any( target_os = "macos" , target_os = "redox" ) ) ]
1093+ {
1094+ fs:: copy ( from, to) ?;
1095+ }
10871096 }
10881097
10891098 Ok ( ( ) )
Original file line number Diff line number Diff line change @@ -621,6 +621,54 @@ fn test_mv_symlink_into_target() {
621621 ucmd. arg ( "dir-link" ) . arg ( "dir" ) . succeeds ( ) ;
622622}
623623
624+ #[ test]
625+ #[ cfg( all( unix, not( target_os = "android" ) ) ) ]
626+ fn test_mv_folder_containing_dangling_symlink_across_fs ( ) {
627+ let scene = TestScenario :: new ( util_name ! ( ) ) ;
628+
629+ scene. fixtures . mkdir ( "foo" ) ;
630+ let mountpoint = scene. fixtures . plus ( "foo" ) ;
631+
632+ let mount = scene
633+ . cmd ( "sudo" )
634+ . args ( & [
635+ "-E" ,
636+ "--non-interactive" ,
637+ "mount" ,
638+ "none" ,
639+ "-t" ,
640+ "tmpfs" ,
641+ mountpoint. to_str ( ) . unwrap ( ) ,
642+ ] )
643+ . run ( ) ;
644+
645+ if !mount. succeeded ( ) {
646+ print ! ( "Test skipped; requires root user" ) ;
647+ return ;
648+ }
649+
650+ scene. fixtures . mkdir ( "bar" ) ;
651+ scene. fixtures . symlink_file ( "nonexistent" , "bar/baz" ) ;
652+
653+ scene
654+ . ucmd ( )
655+ . arg ( "bar" )
656+ . arg ( "foo" )
657+ . succeeds ( )
658+ . no_stderr ( )
659+ . no_stdout ( ) ;
660+
661+ scene
662+ . cmd ( "sudo" )
663+ . args ( & [
664+ "-E" ,
665+ "--non-interactive" ,
666+ "umount" ,
667+ mountpoint. to_str ( ) . unwrap ( ) ,
668+ ] )
669+ . succeeds ( ) ;
670+ }
671+
624672#[ test]
625673#[ cfg( all( unix, not( target_os = "android" ) ) ) ]
626674fn test_mv_hardlink_to_symlink ( ) {
You can’t perform that action at this time.
0 commit comments