tail: add check to detect a closed file descriptor

This is WIP or even WONT-FIX because there's a workaround in Rust's
stdlib which prevents us from detecting a closed FD.

see also the discussion at:
https://github.com/uutils/coreutils/issues/2873
This commit is contained in:
Jan Scheer 2022-05-16 22:10:27 +02:00
parent 59827bca1a
commit 5aee95b4e5
No known key found for this signature in database
GPG key ID: C62AD4C29E2B9828
2 changed files with 22 additions and 10 deletions

View file

@ -9,7 +9,9 @@
*/
#[cfg(unix)]
pub use self::unix::{stdin_is_pipe_or_fifo, supports_pid_checks, Pid, ProcessChecker};
pub use self::unix::{
stdin_is_bad_fd, stdin_is_pipe_or_fifo, supports_pid_checks, Pid, ProcessChecker,
};
#[cfg(windows)]
pub use self::windows::{supports_pid_checks, Pid, ProcessChecker};

View file

@ -51,13 +51,23 @@ fn get_errno() -> i32 {
pub fn stdin_is_pipe_or_fifo() -> bool {
let fd = stdin().lock().as_raw_fd();
fd >= 0 // GNU tail checks fd >= 0
&& match fstat(fd) {
Ok(stat) => {
let mode = stat.st_mode as libc::mode_t;
// NOTE: This is probably not the most correct way to check this
(mode & S_IFIFO != 0) || (mode & S_IFSOCK != 0)
}
Err(err) => panic!("{}", err),
}
// GNU tail checks fd >= 0
fd >= 0
&& match fstat(fd) {
Ok(stat) => {
let mode = stat.st_mode as libc::mode_t;
// NOTE: This is probably not the most correct way to check this
(mode & S_IFIFO != 0) || (mode & S_IFSOCK != 0)
}
Err(err) => panic!("{}", err),
}
}
// FIXME: Detect a closed file descriptor, e.g.: `tail <&-`
pub fn stdin_is_bad_fd() -> bool {
let fd = stdin().as_raw_fd();
// this is never `true`, even with `<&-` because stdlib is reopening fds as /dev/null
// see also: https://github.com/uutils/coreutils/issues/2873
// (gnu/tests/tail-2/follow-stdin.sh fails because of this)
unsafe { libc::fcntl(fd, libc::F_GETFD) == -1 && get_errno() == libc::EBADF }
}