diff --git a/Cargo.lock b/Cargo.lock index eb641725a0d..56dc45b143c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4228,7 +4228,8 @@ version = "0.8.0" dependencies = [ "clap", "fluent", - "nix", + "libc", + "rustix", "uucore", "windows-sys 0.61.2", ] diff --git a/src/uu/sync/Cargo.toml b/src/uu/sync/Cargo.toml index 21df8266dce..70dda7bc55c 100644 --- a/src/uu/sync/Cargo.toml +++ b/src/uu/sync/Cargo.toml @@ -24,7 +24,8 @@ uucore = { workspace = true, features = ["wide"] } fluent = { workspace = true } [target.'cfg(unix)'.dependencies] -nix = { workspace = true } +libc = { workspace = true } +rustix = { workspace = true, features = ["fs"] } [target.'cfg(target_os = "windows")'.dependencies] windows-sys = { workspace = true, features = [ diff --git a/src/uu/sync/src/sync.rs b/src/uu/sync/src/sync.rs index b34d0ac0bd1..188e75daf9c 100644 --- a/src/uu/sync/src/sync.rs +++ b/src/uu/sync/src/sync.rs @@ -6,12 +6,6 @@ /* Last synced with: sync (GNU coreutils) 8.13 */ use clap::{Arg, ArgAction, Command}; -#[cfg(any(target_os = "linux", target_os = "android"))] -use nix::errno::Errno; -#[cfg(any(target_os = "linux", target_os = "android"))] -use nix::fcntl::{OFlag, open}; -#[cfg(any(target_os = "linux", target_os = "android"))] -use nix::sys::stat::Mode; use std::path::Path; use uucore::display::Quotable; use uucore::error::{UResult, USimpleError, get_exit_code, set_exit_code}; @@ -28,14 +22,11 @@ static ARG_FILES: &str = "files"; #[cfg(unix)] mod platform { - #[cfg(any(target_os = "linux", target_os = "android"))] - use nix::fcntl::{FcntlArg, OFlag, fcntl}; - use nix::unistd::sync; - #[cfg(any(target_os = "linux", target_os = "android"))] - use nix::unistd::{fdatasync, syncfs}; #[cfg(any(target_os = "linux", target_os = "android"))] use std::fs::{File, OpenOptions}; #[cfg(any(target_os = "linux", target_os = "android"))] + use std::os::fd::AsFd; + #[cfg(any(target_os = "linux", target_os = "android"))] use std::os::unix::fs::OpenOptionsExt; #[cfg(any(target_os = "linux", target_os = "android"))] use uucore::display::Quotable; @@ -51,7 +42,7 @@ mod platform { reason = "fn sig must match on all platforms" )] pub fn do_sync() -> UResult<()> { - sync(); + rustix::fs::sync(); Ok(()) } @@ -62,17 +53,17 @@ mod platform { fn open_and_reset_nonblock(path: &str) -> UResult { let f = OpenOptions::new() .read(true) - .custom_flags(OFlag::O_NONBLOCK.bits()) + .custom_flags(libc::O_NONBLOCK) .open(path) .map_err_context(|| path.to_string())?; // Reset O_NONBLOCK flag if it was set (matches GNU behavior) // This is non-critical, so we log errors but don't fail - if let Err(e) = fcntl(&f, FcntlArg::F_SETFL(OFlag::empty())) { + if let Err(e) = rustix::fs::fcntl_setfl(f.as_fd(), rustix::fs::OFlags::empty()) { use std::io::{Write, stderr}; let _ = writeln!( stderr(), "sync: {}", - translate!("sync-warning-fcntl-failed", "file" => path, "error" => e.to_string()) + translate!("sync-warning-fcntl-failed", "file" => path, "error" => std::io::Error::from(e).to_string()) ); uucore::error::set_exit_code(1); } @@ -83,9 +74,11 @@ mod platform { pub fn do_syncfs(files: Vec) -> UResult<()> { for path in files { let f = open_and_reset_nonblock(&path)?; - syncfs(f).map_err_context( - || translate!("sync-error-syncing-file", "file" => path.quote()), - )?; + rustix::fs::syncfs(f.as_fd()) + .map_err(std::io::Error::from) + .map_err_context( + || translate!("sync-error-syncing-file", "file" => path.quote()), + )?; } Ok(()) } @@ -94,9 +87,11 @@ mod platform { pub fn do_fdatasync(files: Vec) -> UResult<()> { for path in files { let f = open_and_reset_nonblock(&path)?; - fdatasync(f).map_err_context( - || translate!("sync-error-syncing-file", "file" => path.quote()), - )?; + rustix::fs::fdatasync(f.as_fd()) + .map_err(std::io::Error::from) + .map_err_context( + || translate!("sync-error-syncing-file", "file" => path.quote()), + )?; } Ok(()) } @@ -231,17 +226,26 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } for f in &files { - // Use the Nix open to be able to set the NONBLOCK flags for fifo files + // Use open with O_NONBLOCK to be able to handle fifo files #[cfg(any(target_os = "linux", target_os = "android"))] { let path = Path::new(&f); - if let Err(e) = open(path, OFlag::O_NONBLOCK, Mode::empty()) { - if e != Errno::EACCES || (e == Errno::EACCES && path.is_dir()) { - show_error!( - "{}", - translate!("sync-error-opening-file", "file" => f.quote(), "err" => e.desc()) - ); - set_exit_code(1); + match rustix::fs::open( + path, + rustix::fs::OFlags::NONBLOCK, + rustix::fs::Mode::empty(), + ) { + Ok(_fd) => { /* OwnedFd auto-closes on drop */ } + Err(e) => { + let is_eacces = e == rustix::io::Errno::ACCESS; + if !is_eacces || path.is_dir() { + let err = std::io::Error::from(e); + show_error!( + "{}", + translate!("sync-error-opening-file", "file" => f.quote(), "err" => err) + ); + set_exit_code(1); + } } } }