mirror of
https://github.com/uutils/coreutils
synced 2024-12-12 22:32:53 +00:00
tail: use same-file crate to get a handle of stdin redirected file
This commit is contained in:
parent
942928b0ea
commit
74f359bd76
5 changed files with 23 additions and 21 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2816,6 +2816,7 @@ dependencies = [
|
|||
"libc",
|
||||
"nix",
|
||||
"notify",
|
||||
"same-file",
|
||||
"uucore",
|
||||
"winapi",
|
||||
"winapi-util",
|
||||
|
|
|
@ -20,6 +20,7 @@ clap = { version = "3.2", features = ["wrap_help", "cargo"] }
|
|||
libc = "0.2.132"
|
||||
notify = { version = "=5.0.0-pre.16", features=["macos_kqueue"]}
|
||||
uucore = { version=">=0.0.15", package="uucore", path="../../uucore", features=["ringbuffer", "lines"] }
|
||||
same-file = "1.0.6"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version="0.3", features=["fileapi", "handleapi", "processthreadsapi", "synchapi", "winbase"] }
|
||||
|
|
|
@ -30,7 +30,11 @@ pub struct ReverseChunks<'a> {
|
|||
|
||||
impl<'a> ReverseChunks<'a> {
|
||||
pub fn new(file: &'a mut File) -> ReverseChunks<'a> {
|
||||
let current = file.seek(SeekFrom::Current(0)).unwrap();
|
||||
let current = if cfg!(unix) {
|
||||
file.seek(SeekFrom::Current(0)).unwrap()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let size = file.seek(SeekFrom::End(0)).unwrap() - current;
|
||||
let max_blocks_to_read = (size as f64 / BLOCK_SIZE as f64).ceil() as usize;
|
||||
let block_idx = 0;
|
||||
|
|
|
@ -318,6 +318,18 @@ fn uu_tail(mut settings: Settings) -> UResult<()> {
|
|||
));
|
||||
}
|
||||
|
||||
settings.stdin_redirect = dash.handle_redirect();
|
||||
if cfg!(unix) && settings.stdin_is_pipe_or_fifo {
|
||||
// Save the current seek position/offset of a stdin redirected file.
|
||||
// This is needed to pass "gnu/tests/tail-2/start-middle.sh"
|
||||
use same_file::Handle;
|
||||
if let Ok(mut stdin_handle) = Handle::stdin() {
|
||||
if let Ok(offset) = stdin_handle.as_file_mut().seek(SeekFrom::Current(0)) {
|
||||
settings.stdin_offset = offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add '-' to paths
|
||||
if !settings.paths.contains(&dash) && settings.stdin_is_pipe_or_fifo
|
||||
|| settings.paths.is_empty() && !settings.stdin_is_pipe_or_fifo
|
||||
|
@ -325,15 +337,6 @@ fn uu_tail(mut settings: Settings) -> UResult<()> {
|
|||
settings.paths.push_front(dash);
|
||||
}
|
||||
|
||||
if cfg!(unix) && settings.stdin_is_pipe_or_fifo {
|
||||
settings.stdin_redirect = PathBuf::from(text::STDIN_HEADER).handle_redirect();
|
||||
use std::os::unix::io::FromRawFd;
|
||||
let mut stdin_handle = unsafe { std::fs::File::from_raw_fd(0) };
|
||||
if let Ok(offset) = stdin_handle.seek(SeekFrom::Current(0)) {
|
||||
settings.stdin_offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: is there a better way to check for a readable stdin?
|
||||
let mut buf = [0; 0]; // empty buffer to check if stdin().read().is_err()
|
||||
let stdin_read_possible = settings.stdin_is_pipe_or_fifo && stdin().read(&mut buf).is_ok();
|
||||
|
@ -455,7 +458,7 @@ fn uu_tail(mut settings: Settings) -> UResult<()> {
|
|||
|
||||
let metadata = path.metadata().ok();
|
||||
|
||||
if display_name.is_stdin() && path_is_tailable && !path.is_file() {
|
||||
if display_name.is_stdin() && !path.is_file() {
|
||||
if settings.verbose {
|
||||
files.print_header(&display_name, !first_header);
|
||||
first_header = false;
|
||||
|
@ -500,11 +503,8 @@ fn uu_tail(mut settings: Settings) -> UResult<()> {
|
|||
}
|
||||
|
||||
let mut reader;
|
||||
if file.is_seekable(if display_name.is_stdin() {
|
||||
settings.stdin_offset
|
||||
} else {
|
||||
0
|
||||
}) && metadata.as_ref().unwrap().get_block_size() > 0
|
||||
if file.is_seekable(settings.stdin_offset)
|
||||
&& metadata.as_ref().unwrap().get_block_size() > 0
|
||||
{
|
||||
bounded_tail(&mut file, &settings);
|
||||
reader = BufReader::new(file);
|
||||
|
|
|
@ -107,11 +107,7 @@ fn test_stdin_redirect_offset() {
|
|||
let mut fh = std::fs::File::open(at.plus("k")).unwrap();
|
||||
fh.seek(SeekFrom::Start(2)).unwrap();
|
||||
|
||||
ts.ucmd()
|
||||
.set_stdin(fh)
|
||||
.run()
|
||||
.stdout_is("2\n")
|
||||
.succeeded();
|
||||
ts.ucmd().set_stdin(fh).run().stdout_is("2\n").succeeded();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue