@@ -356,37 +356,56 @@ 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 nix:: fcntl:: { AT_FDCWD , RenameFlags , renameat2} ;
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 ;
360368
361369 // Use renameat2 to atomically exchange the files
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( ) ) ;
372- }
373- Ok ( ( ) )
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( ) ) ;
374384 }
375- Err ( err) => match err {
376- nix:: Error :: ENOTSUP | nix:: Error :: EINVAL => Err ( USimpleError :: new (
385+ Ok ( ( ) )
386+ } else {
387+ let errno = unsafe { * libc:: __errno_location ( ) } ;
388+ match errno {
389+ libc:: ENOTSUP | libc:: EINVAL => Err ( USimpleError :: new (
377390 1 ,
378391 translate ! ( "--exchange is not supported on this filesystem" ) ,
379392 ) ) ,
380- nix :: Error :: ENOENT => {
393+ libc :: ENOENT => {
381394 let missing_path = if path1. exists ( ) { path2 } else { path1 } ;
382395 Err ( MvError :: NoSuchFile ( missing_path. display ( ) . to_string ( ) ) . into ( ) )
383396 }
384- nix :: Error :: EXDEV => Err ( USimpleError :: new (
397+ libc :: EXDEV => Err ( USimpleError :: new (
385398 1 ,
386399 translate ! ( "--exchange cannot exchange files across different filesystems" ) ,
387400 ) ) ,
388- _ => Err ( USimpleError :: new ( 1 , format ! ( "exchange failed: {err}" ) ) ) ,
389- } ,
401+ _ => {
402+ let error_msg = io:: Error :: from_raw_os_error ( errno) ;
403+ Err ( USimpleError :: new (
404+ 1 ,
405+ format ! ( "exchange failed: {error_msg}" ) ,
406+ ) )
407+ }
408+ }
390409 }
391410}
392411
0 commit comments