Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions src/uu/sync/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sync-help-data = sync only file data, no unneeded metadata (Linux only)
sync-error-data-needs-argument = --data needs at least one argument
sync-error-opening-file = error opening { $file }
sync-error-no-such-file = error opening { $file }: No such file or directory
sync-error-syncing-file = error syncing { $file }
# Warning messages
sync-warning-fcntl-failed = warning: failed to reset O_NONBLOCK flag for { $file }: { $error }
Expand Down
1 change: 1 addition & 0 deletions src/uu/sync/locales/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ sync-help-data = synchroniser seulement les données des fichiers, pas les méta
sync-error-data-needs-argument = --data nécessite au moins un argument
sync-error-opening-file = erreur lors de l'ouverture de { $file }
sync-error-no-such-file = erreur lors de l'ouverture de { $file } : Aucun fichier ou répertoire de ce type
sync-error-syncing-file = erreur lors de la synchronisation de { $file }

# Messages d'avertissement
sync-warning-fcntl-failed = avertissement : échec de la réinitialisation du drapeau O_NONBLOCK pour { $file } : { $error }
Expand Down
20 changes: 16 additions & 4 deletions src/uu/sync/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ mod platform {
#[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;
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"))]
Expand All @@ -57,7 +61,11 @@ mod platform {
/// 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 = File::open(path).map_err_context(|| path.to_string())?;
let f = OpenOptions::new()
.read(true)
.custom_flags(OFlag::O_NONBLOCK.bits())
.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())) {
Expand All @@ -73,7 +81,9 @@ mod platform {
pub fn do_syncfs(files: Vec<String>) -> UResult<()> {
for path in files {
let f = open_and_reset_nonblock(&path)?;
syncfs(f)?;
syncfs(f).map_err_context(
|| translate!("sync-error-syncing-file", "file" => path.quote()),
)?;
}
Ok(())
}
Expand All @@ -82,7 +92,9 @@ mod platform {
pub fn do_fdatasync(files: Vec<String>) -> UResult<()> {
for path in files {
let f = open_and_reset_nonblock(&path)?;
fdatasync(f)?;
fdatasync(f).map_err_context(
|| translate!("sync-error-syncing-file", "file" => path.quote()),
)?;
}
Ok(())
}
Expand Down
21 changes: 21 additions & 0 deletions tests/by-util/test_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,24 @@ fn test_sync_multiple_files() {
// Sync both files
new_ucmd!().arg("--data").arg(&file1).arg(&file2).succeeds();
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn test_sync_data_fifo_fails_immediately() {
use std::time::Duration;
use uutests::util::TestScenario;
use uutests::util_name;

let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;
at.mkfifo("test-fifo");

ts.ucmd()
.arg("--data")
.arg(at.plus_as_string("test-fifo"))
.timeout(Duration::from_secs(2))
.fails()
.stderr_contains("error syncing")
.stderr_contains("test-fifo")
.stderr_contains("Invalid input");
}
Loading