@@ -356,54 +356,39 @@ fn determine_overwrite_mode(matches: &ArgMatches) -> OverwriteMode {
356356/// Atomically exchange two files using renameat2 with `RENAME_EXCHANGE`
357357#[ cfg( target_os = "linux" ) ]
358358fn exchange_files ( path1 : & Path , path2 : & Path , opts : & Options ) -> UResult < ( ) > {
359- use std:: ffi:: CString ;
360- use std:: os:: unix:: ffi:: OsStrExt ;
361-
362- // Convert paths to C strings
363- let c_path1 = CString :: new ( path1. as_os_str ( ) . as_bytes ( ) ) . unwrap ( ) ;
364- let c_path2 = CString :: new ( path2. as_os_str ( ) . as_bytes ( ) ) . unwrap ( ) ;
365-
366- // RENAME_EXCHANGE flag for renameat2
367- const RENAME_EXCHANGE : libc:: c_int = 2 ;
359+ use nix:: fcntl:: { AT_FDCWD , RenameFlags , renameat2} ;
368360
369361 // Use renameat2 to atomically exchange the files
370- let result = unsafe {
371- libc:: syscall (
372- libc:: SYS_renameat2 ,
373- libc:: AT_FDCWD ,
374- c_path1. as_ptr ( ) ,
375- libc:: AT_FDCWD ,
376- c_path2. as_ptr ( ) ,
377- RENAME_EXCHANGE ,
378- )
379- } ;
380-
381- if result == 0 {
382- if opts. verbose {
383- println ! ( "exchanged '{}' <-> '{}'" , path1. display( ) , path2. display( ) ) ;
384- }
385- Ok ( ( ) )
386- } else {
387- let errno = unsafe { * libc:: __errno_location ( ) } ;
388- match errno {
389- libc:: ENOTSUP | libc:: EINVAL => Err ( USimpleError :: new (
390- 1 ,
391- translate ! ( "--exchange is not supported on this filesystem" ) ,
392- ) ) ,
393- libc:: ENOENT => {
394- let missing_path = if path1. exists ( ) { path2 } else { path1 } ;
395- Err ( MvError :: NoSuchFile ( missing_path. display ( ) . to_string ( ) ) . into ( ) )
362+ match renameat2 (
363+ AT_FDCWD ,
364+ path1,
365+ AT_FDCWD ,
366+ path2,
367+ RenameFlags :: RENAME_EXCHANGE ,
368+ ) {
369+ Ok ( ( ) ) => {
370+ if opts. verbose {
371+ println ! ( "exchanged '{}' <-> '{}'" , path1. display( ) , path2. display( ) ) ;
396372 }
397- libc:: EXDEV => Err ( USimpleError :: new (
398- 1 ,
399- translate ! ( "--exchange cannot exchange files across different filesystems" ) ,
400- ) ) ,
401- _ => {
402- let error_msg = io:: Error :: from_raw_os_error ( errno) ;
403- Err ( USimpleError :: new (
373+ Ok ( ( ) )
374+ }
375+ Err ( err) => {
376+ use nix:: errno:: Errno ;
377+
378+ match err {
379+ nix:: Error :: ENOTSUP | nix:: Error :: EINVAL => Err ( USimpleError :: new (
380+ 1 ,
381+ translate ! ( "--exchange is not supported on this filesystem" ) ,
382+ ) ) ,
383+ nix:: Error :: ENOENT => {
384+ let missing_path = if path1. exists ( ) { path2 } else { path1 } ;
385+ Err ( MvError :: NoSuchFile ( missing_path. display ( ) . to_string ( ) ) . into ( ) )
386+ }
387+ nix:: Error :: EXDEV => Err ( USimpleError :: new (
404388 1 ,
405- format ! ( "exchange failed: {error_msg}" ) ,
406- ) )
389+ translate ! ( "--exchange cannot exchange files across different filesystems" ) ,
390+ ) ) ,
391+ _ => Err ( USimpleError :: new ( 1 , format ! ( "exchange failed: {err}" ) ) ) ,
407392 }
408393 }
409394 }
0 commit comments