Skip to content

Commit e1a5e47

Browse files
committed
tac: skip mmap for non-regular files to match GNU 9.9 behavior
1 parent dc982b1 commit e1a5e47

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

src/uu/tac/src/tac.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -362,20 +362,19 @@ fn tac(filenames: &[OsString], before: bool, regex: bool, separator: &str) -> UR
362362
}
363363
} else {
364364
let path = Path::new(filename);
365-
if path.is_dir() {
366-
let e: Box<dyn UError> =
367-
TacError::InvalidDirectoryArgument(filename.clone()).into();
368-
show!(e);
365+
let Ok(metadata) = path.metadata() else {
366+
show!(TacError::FileNotFound(filename.clone()));
369367
continue;
370-
}
368+
};
371369

372-
if path.metadata().is_err() {
373-
let e: Box<dyn UError> = TacError::FileNotFound(filename.clone()).into();
370+
if metadata.is_dir() {
371+
let e: Box<dyn UError> =
372+
TacError::InvalidDirectoryArgument(filename.clone()).into();
374373
show!(e);
375374
continue;
376375
}
377376

378-
if let Some(mmap1) = try_mmap_path(path) {
377+
if let Some(mmap1) = metadata.is_file().then(|| try_mmap_path(path)).flatten() {
379378
mmap = mmap1;
380379
&mmap
381380
} else {

tests/by-util/test_tac.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,43 @@ fn test_regular_end_anchor() {
416416
.succeeds()
417417
.stdout_is("\nccc\nbbaaa\nb");
418418
}
419+
420+
#[test]
421+
#[cfg(target_os = "linux")]
422+
fn test_non_regular_files() {
423+
use std::process::Stdio;
424+
425+
new_ucmd!().arg("/dev/null").succeeds().no_output();
426+
427+
let content = std::fs::read_to_string("/proc/version").unwrap();
428+
new_ucmd!()
429+
.arg("/proc/version")
430+
.succeeds()
431+
.stdout_is(&content);
432+
433+
let scene = TestScenario::new(util_name!());
434+
let at = &scene.fixtures;
435+
at.mkfifo("fifo");
436+
let fifo_path = at.plus("fifo");
437+
let writer = std::thread::spawn(move || std::fs::write(fifo_path, b"a\nb\nc\n").unwrap());
438+
scene.ucmd().arg("fifo").succeeds().stdout_is("c\nb\na\n");
439+
writer.join().unwrap();
440+
441+
for dev in &["/dev/zero", "/dev/urandom"] {
442+
let mut child = new_ucmd!()
443+
.arg(dev)
444+
.set_stdout(Stdio::piped())
445+
.run_no_wait();
446+
child.make_assertion_with_delay(500).is_alive();
447+
child.kill();
448+
}
449+
450+
at.symlink_file("/dev/urandom", "sym_urandom");
451+
let mut child = scene
452+
.ucmd()
453+
.arg("sym_urandom")
454+
.set_stdout(Stdio::piped())
455+
.run_no_wait();
456+
child.make_assertion_with_delay(500).is_alive();
457+
child.kill();
458+
}

0 commit comments

Comments
 (0)