Skip to content

Commit 922b3b0

Browse files
committed
swapped RENAME_EXCHANGE with nix renameat
1 parent b2461a8 commit 922b3b0

File tree

2 files changed

+30
-44
lines changed

2 files changed

+30
-44
lines changed

src/uu/mv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ windows-sys = { workspace = true, features = [
4040

4141
[target.'cfg(unix)'.dependencies]
4242
libc = { workspace = true }
43+
nix = { workspace = true, features = ["fs"] }
4344

4445
[[bin]]
4546
name = "mv"

src/uu/mv/src/mv.rs

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -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")]
358358
fn 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

Comments
 (0)