mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
sync: open file with nonblock (#10765)
* open file with nonblock and add test * fix spellcheck * remove libc dependency; improve errors --------- Co-authored-by: Sylvestre Ledru <sylvestre@debian.org>
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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 }
|
||||
|
||||
+16
-4
@@ -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"))]
|
||||
@@ -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())) {
|
||||
@@ -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(())
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user