Idiomatic inotify wrapper for the Rust programming language

Overview

inotify-rs crates.io Documentation Rust

Idiomatic inotify wrapper for the Rust programming language.

extern crate inotify;


use std::env;

use inotify::{
    EventMask,
    WatchMask,
    Inotify,
};


fn main() {
    let mut inotify = Inotify::init()
        .expect("Failed to initialize inotify");

    let current_dir = env::current_dir()
        .expect("Failed to determine current directory");

    inotify
        .add_watch(
            current_dir,
            WatchMask::MODIFY | WatchMask::CREATE | WatchMask::DELETE,
        )
        .expect("Failed to add inotify watch");

    println!("Watching current directory for activity...");

    let mut buffer = [0u8; 4096];
    loop {
        let events = inotify
            .read_events_blocking(&mut buffer)
            .expect("Failed to read inotify events");

        for event in events {
            if event.mask.contains(EventMask::CREATE) {
                if event.mask.contains(EventMask::ISDIR) {
                    println!("Directory created: {:?}", event.name);
                } else {
                    println!("File created: {:?}", event.name);
                }
            } else if event.mask.contains(EventMask::DELETE) {
                if event.mask.contains(EventMask::ISDIR) {
                    println!("Directory deleted: {:?}", event.name);
                } else {
                    println!("File deleted: {:?}", event.name);
                }
            } else if event.mask.contains(EventMask::MODIFY) {
                if event.mask.contains(EventMask::ISDIR) {
                    println!("Directory modified: {:?}", event.name);
                } else {
                    println!("File modified: {:?}", event.name);
                }
            }
        }
    }
}

Usage

Include it in your Cargo.toml:

[dependencies]
inotify = "0.10"

Please refer to the documentation and the example above, for information on how to use it in your code.

Please note that inotify-rs is a relatively low-level wrapper around the original inotify API. And, of course, it is Linux-specific, just like inotify itself. If you are looking for a higher-level and platform-independent file system notification library, please consider notify.

If you need to access inotify in a way that this wrapper doesn't support, consider using inotify-sys instead.

Documentation

The most important piece of documentation for inotify-rs is the API reference, as it contains a thorough description of the complete API, as well as examples.

Additional examples can be found in the examples directory.

Please also make sure to read the inotify man page. Inotify use can be hard to get right, and this low-level wrapper won't protect you from all mistakes.

License

Copyright (c) Hanno Braun and contributors

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Comments
  • feat: update to tokio 0.2 and futures 0.3

    feat: update to tokio 0.2 and futures 0.3

    (Stability note: this feature depends on nightly rust and alpha releases of tokio 0.2 and futures 0.3. Maybe you want to hold off the merge until they are stable. In which case I will try to make sure that this PR is up to date.)

    This is a minimal and straightforward update to make inotify up to date with std::task, async-await syntax and next versions of tokio and futures.

    API changes

    • EventStream is now a futures 0.3 Stream

      A futures 0.3 Stream can be used with async-await directly (cc #121). See the stream example.

    • The buffer passed to the event_stream method is now required to be Unpin

    Other changes

    • Mandatory dependencies is minimized: only tokio-net, tokio-io and futures-core are mandatory dependencies. And for tokio-net unused features are disabled. The full tokio crate and futures-util are dev-dependencies.

    • The crate is updated to 2018 edition, so that related tests and examples can be written in async/await.

    • The CI config is modified to:

      • Run on nightly
      • Run with --no-default-features as well
    opened by sopium 15
  • feat: Implement `EventStream` using `mio`

    feat: Implement `EventStream` using `mio`

    This branch changes the implementation of Stream for EventStream to use mio and tokio_reactor to register interest in events on the Inotify file descriptor with the reactor, rather than using task::current().notify() to unpark the task in the executor when polling the fd would block.

    Since the reactor is intended to drive all IO resources (such as the inotify FD) and to be the bridge between tasks in the executor and events from the OS, using PollEvented is a more correct way to implement the stream.

    This branch shouldn't result in any noticeable changes in behaviour, but will hopefully allow tokio to manage Inotify's IO events more intelligently.

    opened by hawkw 13
  • `Eq` implementation of `WatchDescriptor` is wrong

    `Eq` implementation of `WatchDescriptor` is wrong

    From Stack Overflow:

    As noted above, inotify watch descriptor values are scoped per parent inotify file descriptor. This makes the use of [derive(Eq)] on WatchDescriptor highly questionable. Looks like a straight-up bug.

    I haven't had the chance to look into the details myself so far, but this seems legit.

    bug 
    opened by hannobraun 12
  • refactor: Add FdGuard responsible for close-on-drop

    refactor: Add FdGuard responsible for close-on-drop

    This commit improves the close-on-drop behaviour for file descriptors, by adding a FdGuard struct that wraps the file descriptor and is responsible for closing it when it is dropped. Rather than having an Inotify own an Arc<RawFd>, and be responsible for clsoing it, Inotify now owns an Arc<FdGuard>, and the FdGuard is responsible for closing the fd.

    This allows us to share the file descriptor between an Inotify and an EventStream, and close the file descriptor only when the Arc is dropped (i.e., when both the Inotify and the EventStream are dropped). This makes the Inotify::into_event_stream I added in #103 unnecessary, so I've gone ahead and deprecated it.

    opened by hawkw 10
  • Implement ToOwned for `Event<&'a OsStr>`

    Implement ToOwned for `Event<&'a OsStr>`

    I am using inotify with calloop and one issue I've noticed is the lack of ability to easily convert an event from the methods into an owned event to pass to calloop. Calloop gets kinda messy when an Event in an event source has a lifetime, so getting an owned copy is typically the best way around this issue.

    I noticed the presence of into_ownedthat is only available with the streams api, I think we could convert this to delegate to an implementation of ToOwned and made always available.

    enhancement status: blocked 
    opened by i509VCB 9
  • add: Hash trait for WatchDescriptor

    add: Hash trait for WatchDescriptor

    I've made a new PR after breaking the previous one due to a clunky rebase/squash.

    I've added the Hash to the WatchDescriptor struct, to allow it to be used for HashMap lookup.

    opened by arsalan86 8
  • Fixed deprecated syntax

    Fixed deprecated syntax

    [0, ..1024] syntax is now deprecated. Fixed using std::iter::repeat.

    I tried out Vec::with_capacity instead and passing buffer.capacity() instead of buffer.len() to get rid of initializing the vec with zeros, but got a failed assertion from slice.rs, so I guess the initialization is necessary.

    opened by Detegr 8
  • deriving traits for WatchDescriptor

    deriving traits for WatchDescriptor

    I've derived the Hash trait for WatchDescriptor, so it can be added to HashMaps and used for lookup.

    I ran into difficulties while implementing inotify-rs in a project that watches a large number of files. Not being able to match an inotify::Event to a file in a database is crippling for me.

    opened by arsalan86 7
  • Base API on futures-rs

    Base API on futures-rs

    The current API offers both synchronous and asynchronous operation, but it would be better to do that based on futures-rs. I've looked into it, but decided to hold off for the moment, until I had a chance to learn a bit more about futures-rs and experience it from a user's perspective (as opposed to that of a library author).

    enhancement 
    opened by hannobraun 7
  • Look into automatic changelog generation

    Look into automatic changelog generation

    I've heard of projects, for example Hyper, automatically generating changelogs from Git commits. I haven't looked into the details yet, but I understand that GitCop can be used to enforce the commit message format that's required for that.

    enhancement 
    opened by hannobraun 7
  • Allow asynchronous closing.

    Allow asynchronous closing.

    Alright, I'm by no means done, but I thought I'd give you a chance to weigh in earlier, rather than later.

    Changes

    • INotify is no longer cloneable. Therefore the API is essentially single-threaded, enforced by ownership semantics.
    • A new method closer() is introduced. Its return value enables asynchronous closing of the inotify fd.
      • To avoid any races, the actual closing is still done by whoever owns the corresponding INotify.
      • This only happens when wait_for_events() is called.
      • To allow wait_for_events() to react to asynchronous closing, it spins in an epoll loop with a smallish timeout.

    TODO

    • [ ] Look at available_events() wrt asynchronous closing. Currently it does not make sense, because the caller can't determine if the inotify fd was closed without calling a blocking method. Maybe expose the state?
    • [ ] Figure out a good epoll timeout (10ms seems a bit high).
    • [x] Go over all the unwrap() calls and figure out how to deal with the potential error conditions.
    • [ ] More tests
    • [ ] Documentation

    (ref #28)

    opened by benschulz 7
  • panic when call event_stream

    panic when call event_stream

    panic info:

       5: std::panicking::begin_panic
                 at ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:505:12
       6: tokio::io::driver::Handle::current
                 at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.3.5/src/io/driver/mod.rs:277:13
       7: tokio::io::async_fd::AsyncFd<T>::with_interest
                 at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.3.5/src/io/async_fd.rs:99:51
       8: tokio::io::async_fd::AsyncFd<T>::new
                 at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.3.5/src/io/async_fd.rs:89:9
       9: inotify::stream::EventStream<T>::new
                 at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/inotify-0.9.1/src/stream.rs:35:17
      10: inotify::inotify::Inotify::event_stream
                 at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/inotify-0.9.1/src/inotify.rs:406:9
      11: controller::sync::Notifier::watch::{{closure}}
                 at ~/work/github/cita-cloud/controller_poc/src/sync.rs:128:26
    

    related source code:

            let mut inotify = Inotify::init().expect("Failed to initialize inotify");
    
            let root_path = Path::new(&self.root);
            let mut wds = Vec::new();
            for dir in SYNC_FOLDERS.iter() {
                let path = root_path.join(dir);
                let wd = inotify.add_watch(path, WatchMask::MOVED_TO).unwrap();
                wds.push(wd);
            }
    
            let mut buffer = vec![0u8; 4096];
            let mut stream = inotify.event_stream(&mut buffer).unwrap();
    
            while let Some(event_or_error) = stream.next().await {
    

    This happend when upgrade inotify to latest version (v0.9.1). After back to v0.8.3, it's ok.

    bug help wanted 
    opened by rink1969 1
  • Async await support

    Async await support

    (This includes changes from #134.)

    This adds an async Inotify type. It has an async fn read_events (close #121):

        pub async fn read_events<'a>(&mut self, buffer: &'a mut [u8])
                               -> io::Result<Events<'a>>
    

    that is basically the same as the original read_events function, but awaits on the read:

        {
            let num_bytes = self.fd.read(buffer).await?;
    
            if num_bytes == 0 {
                return Err(
                    io::Error::new(
                        io::ErrorKind::UnexpectedEof,
                        "`read` return `0`, signaling end-of-file"
                    )
                );
            }
    
            Ok(Events::new(Arc::downgrade(self.fd.get_ref()), buffer, num_bytes))
        }
    

    This addresses the efficiency concern in #112: no additional allocation is required.

    opened by sopium 6
  • Improve documentation of `Inotify::event_stream`

    Improve documentation of `Inotify::event_stream`

    The documentation for Inotify::event_stream is out of date.

    1. It talks about using an internal buffer, but it no longer does.
    2. It could use examples showing the various usage scenarios.

    The examples should document what kinds of values can be passes as a buffer. See this comment in #124 and this comment in #125 for more information.

    help wanted good first issue 
    opened by hannobraun 0
  • Async/Await syntax support

    Async/Await syntax support

    Futures 0.3 will support the Async/Await syntax. One it reaches GA, Tokio will be next. We should investigate what it will require of us to support the new syntax and prepare ourselves for it.

    opened by thedrow 2
  • Consider unifying traditional and future-based APIs

    Consider unifying traditional and future-based APIs

    Currently there are two parallel APIs: The original one, and the new future-based one. I think it would be ideal if we could unify those.

    One problem I see is efficiency. The stream-based API requires one additional heap allocation for every event that has a name. The reason for this are lifetime issues that probably can't be resolved, at least not in safe Rust.

    I think it's best for now to keep things as they are, while keeping a look at how futures develop. Feedback is very welcome!

    enhancement 
    opened by hannobraun 4
  • add a read_events_with_timeout()

    add a read_events_with_timeout()

    That would imply to use a select on the inotify's fd waiting for data in the fd or the timeout.

    The workaround would be to use the nix crate with Inotify's RawFD and do the select in the application.

    enhancement help wanted 
    opened by ceyusa 10
Owner
Hanno Braun
Building Fornjot, a next-generation Code-CAD application.
Hanno Braun
An Interpreter for Brainfuck programming language implemented in the Rust programming language with zero dependencies.

Brainfuck Hello, Visitor! Hey there, welcome to my project showcase website! It's great to have you here. I hope you're ready to check out some awesom

Syed Vilayat Ali Rizvi 7 Mar 31, 2023
nvim-oxi provides safe and idiomatic Rust bindings to the rich API exposed by the Neovim text editor.

?? nvim-oxi nvim-oxi provides safe and idiomatic Rust bindings to the rich API exposed by the Neovim text editor. The project is mostly intended for p

Riccardo Mazzarini 655 Jul 13, 2023
Programming language made by me to learn other people how to make programming languages :3

Spectra programming language Programming language made for my tutorial videos (my youtube channel): Syntax Declaring a variable: var a = 3; Function

Adi Salimgereyev 3 Jul 25, 2023
The Amp programming language: a language designed for building high performance systems.

A language designed for building high performance systems. Platform Support x86_64-pc-windows ✅ x86_64-unknown-linux ⚠️ untested x86_64-unknown-darwin

The Amp Programming Language 5 Mar 17, 2023
Nexa programming language. A language for game developers by a game developer

NexaLang Nexa programming language. A language for game developers by a game developer. Features High-Level: Nexa is an easy high level language Two M

Sabe 3 Aug 21, 2023
Rust API Server: A versatile template for building RESTful interfaces, designed for simplicity in setup and configuration using the Rust programming language.

RUST API SERVER Introduction Welcome to the Rust API Server! This server provides a simple REST interface for your applications. This README will guid

Harry Nguyen 3 Feb 25, 2024
A Text User Interface library for the Rust programming language

Cursive Cursive is a TUI (Text User Interface) library for rust. It uses ncurses by default, but other backends are available. It allows you to build

Alexandre Bury 3.3k Jan 9, 2023
🎄My Advent of Code 2021 solutions in the Rust programming language

Advent of Code 2021 in Rust My Advent of Code 2021 solutions in the Rust programming language. This repository holds a separate Rust project for each

Tim Visée 227 Dec 16, 2022
A Text User Interface library for the Rust programming language

Cursive Cursive is a TUI (Text User Interface) library for rust. It uses ncurses by default, but other backends are available. It allows you to build

Alexandre Bury 3.3k Jan 3, 2023
Notes on learning the Rust programming language syntax.

notes-on-rust Notes on learning the Rust programming language syntax. Resources https://www.rust-lang.org/learn/get-started https://doc.rust-lang.org/

Fred Snyder 1 Jan 2, 2022
A clone of linux cal command, using rust programming language

CLI Calendar command What the project does This command was inspired by Linux Cal command that shows the current month calendar as output (by default)

Mohamed Djoudi Benarfa 2 Nov 16, 2022
A simple lexer which creates over 75 various tokens based on the rust programming language.

Documentation. This complete Lexer/Lexical Scanner produces tokens for a string or a file path entry. The output is a Vector for the user to handle ac

null 1 Nov 27, 2022
An embeddable dynamic programming language for Rust.

rune Visit the site ?? - Read the book ?? An embeddable dynamic programming language for Rust. Contributing If you want to help out, there should be a

The Rune Programming Language 1.1k Dec 27, 2022
Horus is an open source tool for running forensic and administrative tasks at the kernel level using eBPF, a low-overhead in-kernel virtual machine, and the Rust programming language.

Horus Horus is an open-source tool for running forensic and administrative tasks at the kernel level using eBPF, a low-overhead in-kernel virtual mach

null 4 Dec 15, 2022
A comprehensive collection of resources and learning materials for Rust programming, empowering developers to explore and master the modern, safe, and blazingly fast language.

?? Awesome Rust Lang ⛰️ Project Description : Welcome to the Awesome Rust Lang repository! This is a comprehensive collection of resources for Rust, a

Shubham Raj 16 May 29, 2023
Open source programming language written in Rust.

No longer maintained! Tron Programming Language An open-source programming language written in Rust. Installation Before starting the installation, pl

Tron 3 Jul 25, 2023
Open source programming language written in Rust.

Tron Programming Language An open-source programming language written in Rust. Installation Before starting the installation, please make sure that yo

418 3 Jul 26, 2023
Synthia is a lightweight and beginner-friendly interpreted programming language developed in Rust

Synthia is a lightweight and beginner-friendly interpreted programming language developed in Rust. With a simple, intuitive syntax and a focus on ease of use, Synthia is perfect for both newcomers to programming and experienced developers looking for a flexible scripting language

Shiva 3 Oct 5, 2023
🛠️ An experimental functional systems programming language, written in Rust and powered by LLVM as a backend.

An experimental functional systems programming language, written in Rust, and powered by LLVM as a backend. ?? Goal: The intent is to create a program

codex 3 Nov 15, 2023