Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 17 additions & 22 deletions src/uu/sync/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,10 @@ static ARG_FILES: &str = "files";

#[cfg(unix)]
mod platform {
#[cfg(any(target_os = "linux", target_os = "android"))]
use std::fs::{File, OpenOptions};
#[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;
#[cfg(any(target_os = "linux", target_os = "android"))]
use uucore::error::FromIo;
#[cfg(any(target_os = "linux", target_os = "android"))]
use uucore::translate;

use uucore::error::UResult;
Expand All @@ -45,7 +40,6 @@ mod platform {
/// Opens a file and resets its `O_NONBLOCK` flag to match GNU behavior.
/// Returns the opened file or an error if opening fails.
/// Logs a warning if fcntl fails but doesn't abort the operation.
#[cfg(any(target_os = "linux", target_os = "android"))]
fn open_and_reset_nonblock(path: &str) -> UResult<File> {
let f = OpenOptions::new()
.read(true)
Expand All @@ -63,14 +57,13 @@ mod platform {
Ok(f)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn do_sync_with<F>(files: &[String], op: F) -> UResult<()>
where
F: Fn(File) -> Result<(), rustix::io::Errno>,
F: Fn(File) -> std::io::Result<()>,
{
for path in files {
let f = open_and_reset_nonblock(path)?;
op(f).map_err(std::io::Error::from).map_err_context(
op(f).map_err_context(
|| translate!("sync-error-syncing-file", "file" => path.quote()),
)?;
}
Expand All @@ -79,12 +72,13 @@ mod platform {

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn do_syncfs(files: &[String]) -> UResult<()> {
do_sync_with(files, rustix::fs::syncfs)
do_sync_with(files, |f| {
rustix::fs::syncfs(f).map_err(std::io::Error::from)
})
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn do_fdatasync(files: &[String]) -> UResult<()> {
do_sync_with(files, rustix::fs::fdatasync)
do_sync_with(files, |f| f.sync_data())
}
}

Expand Down Expand Up @@ -213,22 +207,23 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {

for f in &files {
// open with O_NONBLOCK to handle fifo files
#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(unix)]
{
use std::os::unix::fs::OpenOptionsExt as _;
use uucore::error::strip_errno;
let path = Path::new(f);
if let Err(e) = rustix::fs::open(
path,
rustix::fs::OFlags::NONBLOCK,
rustix::fs::Mode::empty(),
) && (e != rustix::io::Errno::ACCESS || path.is_dir())
if let Err(e) = std::fs::OpenOptions::new()
.read(true)
.custom_flags(rustix::fs::OFlags::NONBLOCK.bits() as _)
.open(path)
&& (e.kind() != std::io::ErrorKind::PermissionDenied || path.is_dir())
{
let msg = translate!("sync-error-opening-file", "file" => f.quote(), "err" => strip_errno(&std::io::Error::from(e)));
let msg = translate!("sync-error-opening-file", "file" => f.quote(), "err" => strip_errno(&e));
show_error!("{msg}");
set_exit_code(1);
}
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
#[cfg(not(unix))]
{
if !Path::new(&f).exists() {
show_error!(
Expand All @@ -253,7 +248,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
syncfs(&files)?;
}
} else if matches.get_flag(options::DATA) {
#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(unix)]
fdatasync(&files)?;
} else {
sync()?;
Expand Down Expand Up @@ -300,7 +295,7 @@ fn syncfs(files: &[String]) -> UResult<()> {
platform::do_syncfs(files)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[cfg(unix)]
fn fdatasync(files: &[String]) -> UResult<()> {
platform::do_fdatasync(files)
}
Loading