diff --git a/Cargo.lock b/Cargo.lock index 91e2f1762..7eaaa4bec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -582,7 +582,7 @@ dependencies = [ "bitflags", "crossterm_winapi", "libc", - "mio", + "mio 0.7.7", "parking_lot", "signal-hook", "signal-hook-mio", @@ -783,6 +783,25 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" +[[package]] +name = "fsevent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +dependencies = [ + "bitflags", + "fsevent-sys", +] + +[[package]] +name = "fsevent-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" +dependencies = [ + "libc", +] + [[package]] name = "fts-sys" version = "0.2.1" @@ -799,6 +818,22 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "funty" version = "1.1.0" @@ -933,6 +968,26 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46dbcb333e86939721589d25a3557e180b52778cb33c7fdfe9e0158ff790d5ec" +[[package]] +name = "inotify" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + [[package]] name = "instant" version = "0.1.10" @@ -948,6 +1003,15 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c429fffa658f288669529fc26565f728489a2e39bc7b24a428aaaf51355182e" +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "itertools" version = "0.8.2" @@ -1073,6 +1137,25 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow 0.2.2", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.7.7" @@ -1081,11 +1164,35 @@ checksum = "e50ae3f04d169fcc9bde0b547d1c205219b7157e07ded9c5aff03e0637cb3ed7" dependencies = [ "libc", "log", - "miow", + "miow 0.3.7", "ntapi", "winapi 0.3.9", ] +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio 0.6.23", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "miow" version = "0.3.7" @@ -1095,6 +1202,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "net2" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "nix" version = "0.19.1" @@ -1150,6 +1268,24 @@ dependencies = [ "version_check", ] +[[package]] +name = "notify" +version = "4.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" +dependencies = [ + "bitflags", + "filetime", + "fsevent", + "fsevent-sys", + "inotify", + "libc", + "mio 0.6.23", + "mio-extras", + "walkdir", + "winapi 0.3.9", +] + [[package]] name = "ntapi" version = "0.3.6" @@ -1829,7 +1965,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" dependencies = [ "libc", - "mio", + "mio 0.7.7", "signal-hook", ] @@ -1842,6 +1978,12 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" + [[package]] name = "smallvec" version = "0.6.14" @@ -3036,6 +3178,7 @@ dependencies = [ "clap", "libc", "nix 0.20.0", + "notify", "redox_syscall", "uucore", "uucore_procs", @@ -3371,6 +3514,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "wyz" version = "0.2.0" diff --git a/src/uu/tail/Cargo.toml b/src/uu/tail/Cargo.toml index 6fd05b1a9..0565ec72f 100644 --- a/src/uu/tail/Cargo.toml +++ b/src/uu/tail/Cargo.toml @@ -16,6 +16,7 @@ path = "src/tail.rs" [dependencies] clap = { version = "2.33", features = ["wrap_help"] } +notify = "4.0.17" libc = "0.2.42" uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["ringbuffer"] } uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" } diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index f3b73ccef..a7cab6d19 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -25,7 +25,7 @@ use std::fmt; use std::fs::{File, Metadata}; use std::io::{stdin, stdout, BufRead, BufReader, Read, Seek, SeekFrom, Write}; use std::path::Path; -use std::thread::sleep; +use std::sync::mpsc::channel; use std::time::Duration; use uucore::display::Quotable; use uucore::parse_size::{parse_size, ParseSizeError}; @@ -36,6 +36,20 @@ use crate::platform::stdin_is_pipe_or_fifo; #[cfg(unix)] use std::os::unix::fs::MetadataExt; +#[cfg(target_os = "linux")] +pub static BACKEND: &str = "Disable 'inotify' support and use polling instead"; +#[cfg(target_os = "macos")] +pub static BACKEND: &str = "Disable 'FSEvents' support and use polling instead"; +#[cfg(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "dragonflybsd", + target_os = "netbsd", +))] +pub static BACKEND: &str = "Disable 'kqueue' support and use polling instead"; +#[cfg(target_os = "windows")] +pub static BACKEND: &str = "Disable 'ReadDirectoryChanges' support and use polling instead"; + pub mod options { pub mod verbosity { pub static QUIET: &str = "quiet"; @@ -47,6 +61,7 @@ pub mod options { pub static PID: &str = "pid"; pub static SLEEP_INT: &str = "sleep-interval"; pub static ZERO_TERM: &str = "zero-terminated"; + pub static DISABLE_INOTIFY_TERM: &str = "disable-inotify"; pub static ARG_FILES: &str = "files"; } @@ -60,6 +75,7 @@ struct Settings { sleep_sec: Duration, beginning: bool, follow: bool, + force_polling: bool, pid: platform::Pid, } @@ -70,6 +86,7 @@ impl Default for Settings { sleep_sec: Duration::from_secs_f32(1.0), beginning: false, follow: false, + force_polling: false, pid: 0, } } @@ -124,6 +141,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 { settings.mode = mode_and_beginning.0; settings.beginning = mode_and_beginning.1; + settings.force_polling = matches.is_present(options::DISABLE_INOTIFY_TERM); + if matches.is_present(options::ZERO_TERM) { if let FilterMode::Lines(count, _) = settings.mode { settings.mode = FilterMode::Lines(count, 0); @@ -283,6 +302,11 @@ pub fn uu_app() -> App<'static, 'static> { .long(options::ZERO_TERM) .help("Line delimiter is NUL, not newline"), ) + .arg( + Arg::with_name(options::DISABLE_INOTIFY_TERM) + .long(options::DISABLE_INOTIFY_TERM) + .help(BACKEND), + ) .arg( Arg::with_name(options::ARG_FILES) .multiple(true) @@ -301,8 +325,30 @@ fn follow(readers: &mut [(T, &String)], settings: &Settings) { let mut read_some = false; let mut process = platform::ProcessChecker::new(settings.pid); + use notify::{PollWatcher, RecursiveMode, Watcher}; + let (tx, rx) = channel(); + + let mut watcher; + if dbg!(settings.force_polling) { + watcher = PollWatcher::new(tx, settings.sleep_sec).unwrap(); + } else { + // The trait `Watcher` cannot be made into an object because it requires `Self: Sized`. + // watcher = watcher(tx, setting.sleep_sec).unwrap(); + todo!(); + }; + + for (_, path) in readers.iter() { + watcher.watch(path, RecursiveMode::NonRecursive).unwrap(); + } + loop { - sleep(settings.sleep_sec); + // std::thread::sleep(settings.sleep_sec); + let _result = rx.recv(); + // TODO: + // match rx.recv() { + // Ok(event) => println!("\n{:?}", event), + // Err(e) => println!("watch error: {:?}", e), + // } let pid_is_dead = !read_some && settings.pid != 0 && process.is_dead(); read_some = false;