@@ -967,7 +967,8 @@ fn rename_dir_fallback(
967967 ( _, _) => None ,
968968 } ;
969969
970- // Retrieve xattrs using file descriptor to avoid TOCTOU races
970+ // Retrieve xattrs before copying (directories use path-based operations
971+ // since they cannot be opened in write mode for xattr operations)
971972 #[ cfg( all( unix, not( any( target_os = "macos" , target_os = "redox" ) ) ) ) ]
972973 let xattrs = {
973974 use std:: fs:: File ;
@@ -989,12 +990,12 @@ fn rename_dir_fallback(
989990 display_manager,
990991 ) ;
991992
992- // Apply xattrs using file descriptor to avoid TOCTOU races
993+ // Apply xattrs after directory contents are copied, ignoring ENOTSUP errors
994+ // (filesystem doesn't support xattrs, which is acceptable for cross-device moves)
993995 #[ cfg( all( unix, not( any( target_os = "macos" , target_os = "redox" ) ) ) ) ]
994- {
995- use std:: fs:: OpenOptions ;
996- if let Ok ( f) = OpenOptions :: new ( ) . write ( true ) . open ( to) {
997- fsxattr:: apply_xattrs_fd ( & f, xattrs) ?;
996+ if let Err ( e) = fsxattr:: apply_xattrs ( to, xattrs) {
997+ if e. raw_os_error ( ) != Some ( libc:: EOPNOTSUPP ) {
998+ return Err ( e) ;
998999 }
9991000 }
10001001
@@ -1094,7 +1095,16 @@ fn copy_dir_contents_recursive(
10941095 rename_symlink_fallback ( & from_path, & to_path) ?;
10951096 }
10961097
1097- print_verbose ( & from_path, & to_path) ;
1098+ // Print verbose message for symlink
1099+ if verbose {
1100+ let message = translate ! ( "mv-verbose-renamed" , "from" => from_path. quote( ) , "to" => to_path. quote( ) ) ;
1101+ match display_manager {
1102+ Some ( pb) => pb. suspend ( || {
1103+ println ! ( "{message}" ) ;
1104+ } ) ,
1105+ None => println ! ( "{message}" ) ,
1106+ }
1107+ }
10981108 } else if from_path. is_dir ( ) {
10991109 // Recursively copy subdirectory (only real directories, not symlinks)
11001110 fs:: create_dir_all ( & to_path) ?;
0 commit comments