class SleepyPenguin::Inotify

Inotify objects are used for monitoring file system events, it can monitor individual files or directories. When a directory is monitored it will return events for the directory itself and all files inside the directory.

Inotify IO objects can be watched using IO.select or Epoll. IO#close may be called on the object when it is no longer needed.

Inotify is available on Linux 2.6.13 or later.

require "sleepy_penguin/sp"
ino = SP::Inotify.new
ino.add_watch("/path/to/foo", :OPEN)
ino.each do |event|
  p event.events # => [ :OPEN ]
end

Public Class Methods

new([flags]) → Inotify IO object click to toggle source

Flags may be any of the following as an Array of Symbols or Integer mask:

  • :NONBLOCK - sets the non-blocking flag on the descriptor watched.

  • :CLOEXEC - sets the close-on-exec flag

static VALUE s_new(int argc, VALUE *argv, VALUE klass)
{
        VALUE _flags, rv;
        int flags;
        int fd;

        rb_scan_args(argc, argv, "01", &_flags);
        flags = rb_sp_get_flags(klass, _flags, RB_SP_CLOEXEC(IN_CLOEXEC));

        fd = inotify_init1(flags);
        if (fd < 0) {
                if (rb_sp_gc_for_fd(errno))
                        fd = inotify_init1(flags);
                if (fd < 0)
                        rb_sys_fail("inotify_init1");
        }

        rv = INT2FIX(fd);
        rv = rb_call_super(1, &rv);
        rb_ivar_set(rv, id_inotify_tmp, rb_ary_new());

        return rv;
}

Public Instance Methods

add_watch(path, flags) → Integer click to toggle source

Adds a watch on an object specified by its mask, returns an unsigned Integer watch descriptor. flags may be a mask of the following Inotify constants or array of their symbolic names.

  • :ACCESS - File was accessed (read) (*)

  • :ATTRIB - Metadata changed.

  • :CLOSE_WRITE - File opened for writing was closed (*)

  • :CLOSE_NOWRITE - File not opened for writing was closed (*)

  • :CREATE - File/directory created in watched directory (*)

  • :DELETE - File/directory deleted from watched directory (*)

  • :DELETE_SELF - Watched file/directory was itself deleted

  • :MODIFY - File was modified (*)

  • :MOVE_SELF - Watched file/directory was itself moved

  • :MOVED_FROM - File moved out of watched directory (*)

  • :MOVED_TO - File moved into watched directory (*)

  • :OPEN - File was opened (*)

When monitoring a directory, the events marked with an asterisk (*) above can occur for files in the directory, in which case the name field in the Event structure identifies the name of the file in the directory.

Shortcut flags:

  • :ALL_EVENTS - a bitmask of all the above events

  • :MOVE - :MOVED_FROM or :MOVED_TO

  • :CLOSE - :CLOSE_WRITE or :CLOSE_NOWRITE

The following watch attributes may also be included in flags:

  • :DONT_FOLLOW - don't dereference symlinks (since Linux 2.6.15)

  • :EXCL_UNLINK - don't generate unlink events for children (since 2.6.36)

  • :MASK_ADD - add events to an existing watch mask if it exists

  • :ONESHOT - monitor for one event and then remove it from the watch

  • :ONLYDIR - only watch the pathname if it is a directory

static VALUE add_watch(VALUE self, VALUE path, VALUE vmask)
{
        int fd = rb_sp_fileno(self);
        const char *pathname = StringValueCStr(path);
        uint32_t mask = rb_sp_get_uflags(self, vmask);
        int rc = inotify_add_watch(fd, pathname, mask);

        if (rc < 0)
                rb_sys_fail("inotify_add_watch");

        return UINT2NUM((uint32_t)rc);
}
each { |event| ... } → ino click to toggle source

Yields each Inotify::Event received in a blocking fashion.

static VALUE each(VALUE self)
{
        VALUE argv = Qfalse;

        while (1)
                rb_yield(take(0, &argv, self));

        return self;
}
rm_watch(watch_descriptor) → 0 click to toggle source

Removes a watch based on a watch descriptor Integer. The watch descriptor is a return value given by Inotify#add_watch

static VALUE rm_watch(VALUE self, VALUE vwd)
{
        uint32_t wd = NUM2UINT(vwd);
        int fd = rb_sp_fileno(self);
        int rc = inotify_rm_watch(fd, wd);

        if (rc < 0)
                rb_sys_fail("inotify_rm_watch");
        return INT2NUM(rc);
}
take([nonblock]) → Inotify::Event or nil click to toggle source

Returns the next Inotify::Event processed. May return nil if nonblock is true.

static VALUE take(int argc, VALUE *argv, VALUE self)
{
        struct inread_args args;
        VALUE nonblock;

        args.tmp = rb_ivar_get(self, id_inotify_tmp);
        if (RARRAY_LEN(args.tmp) > 0)
                return rb_ary_shift(args.tmp);

        rb_scan_args(argc, argv, "01", &nonblock);

        args.self = self;
        args.fd = rb_sp_fileno(self);
        args.size = 128;
        args.nonblock_p = RTEST(nonblock);

        if (args.nonblock_p)
                rb_sp_set_nonblock(args.fd);

        args.buf = 0;
        return rb_ensure(do_take, (VALUE)&args,
                         rb_sp_puttlsbuf, (VALUE)args.buf);
}