lib/inotify/inotify_native.rb in ruby-inotify-1.0.0 vs lib/inotify/inotify_native.rb in ruby-inotify-1.0.1

- old
+ new

@@ -1,97 +1,177 @@ require 'rubygems' require 'ffi' + # The Inotify class is a simple wrapper around the inotify functionality provided by the OS class Inotify + VERSION = "1.0.1" # :nodoc: + extend FFI::Library ffi_lib FFI::Platform::LIBC - MAX_NAME_SIZE = 4096 + # The maximum supported size of the name argument in the inotify event structure + MAX_NAME_SIZE = 4096 # :nodoc: + # File was accessed (read) (*) ACCESS = 0x00000001 + # File was modified (*) MODIFY = 0x00000002 - ATTRIB = 0x00000004 - CLOSE_WRITE = 0x00000008 + # Metadata changed, e.g., permissions, timestamps, + # extended attributes, link count (since Linux 2.6.25), + # UID, GID, etc. (*) + ATTRIB = 0x00000004 + # File opened for writing was closed (*) + CLOSE_WRITE = 0x00000008 + # File not opened for writing was closed (*) CLOSE_NOWRITE = 0x00000010 + # File was opened (*) OPEN = 0x00000020 + # File moved out of watched directory (*) MOVED_FROM = 0x00000040 + # File moved into watched directory (*) MOVED_TO = 0x00000080 + # File/directory created in watched directory (*) CREATE = 0x00000100 + # File/directory deleted from watched directory (*) DELETE = 0x00000200 + # Watched file/directory was itself deleted DELETE_SELF = 0x00000400 + # Watched file/directory was itself moved MOVE_SELF = 0x00000800 - # Events sent by the kernel. + # File system containing watched object was unmounted UNMOUNT = 0x00002000 + # Event queue overflowed (wd is -1 for this event) Q_OVERFLOW = 0x00004000 + # Watch was removed explicitly (inotify_rm_watch(2)) or + # automatically (file was deleted, or file system was + # unmounted) IGNORED = 0x00008000 + # (since Linux 2.6.15) Only watch pathname if it is a directory ONLYDIR = 0x01000000 + # (since Linux 2.6.15) Don't dereference pathname if it is a symbolic link DONT_FOLLOW = 0x02000000 - MASK_ADD = 0x20000000 - # special flags + # (since Linux 2.6.36) + # By default, when watching events on the children of a + # directory, events are generated for children even after + # they have been unlinked from the directory. This can + # result in large numbers of uninteresting events for some + # applications (e.g., if watching /tmp, in which many + # applications create temporary files whose names are + # immediately unlinked). Specifying IN_EXCL_UNLINK + # changes the default behavior, so that events are not + # generated for children after they have been unlinked + # from the watched directory. + EXCL_UNLINK = 0x04000000 + # Add (OR) events to watch mask for this pathname if it + # already exists (instead of replacing mask) + MASK_ADD = 0x20000000 + # Subject of this event is a directory ISDIR = 0x40000000 + # Monitor pathname for one event, then remove from watch list ONESHOT = 0x80000000 - # helper events - CLOSE = (CLOSE_WRITE | CLOSE_NOWRITE) - MOVE = (MOVED_FROM | MOVED_TO) + # Both of the close events + CLOSE = (CLOSE_WRITE | CLOSE_NOWRITE) + # Both of the move events + MOVE = (MOVED_FROM | MOVED_TO) #All of the events ALL_EVENTS = (ACCESS | MODIFY | ATTRIB | CLOSE_WRITE | \ CLOSE_NOWRITE | OPEN | MOVED_FROM | \ MOVED_TO | CREATE | DELETE | DELETE_SELF | MOVE_SELF) attach_function :inotify_init, [], :int attach_function :inotify_add_watch, [:int, :string, :uint32], :int attach_function :inotify_rm_watch, [:int, :uint32], :int attach_function :read, [:int, :pointer, :size_t], :ssize_t attach_function :inotify_close, :close, [:int], :int - def initialize + + # When creating a new instance of this class, an inotify instance is created in the OS. + def initialize # :nodoc: @fd = self.inotify_init @io = FFI::IO.for_fd(@fd) end - def add_watch(string, uint32) - self.inotify_add_watch(@fd, string, uint32) + + # add_watch() adds a new watch, or modifies an existing watch, for the + # file whose location is specified in pathname; the caller must have read + # permission for this file. The events to be + # monitored for pathname are specified in the mask bit-mask argument. + # On success, inotify_add_watch() returns a nonnegative watch descriptor (wd), or + # -1 if an error occurred. + def add_watch(pathname, mask) + self.inotify_add_watch(@fd, pathname, mask) end - def rm_watch(uint32) - self.inotify_rm_watch(@fd, uint32) + + # rm_watch() removes the watch associated with the watch descriptor wd. + # On success, returns zero, or -1 if an error occurred. + def rm_watch(wd) + self.inotify_rm_watch(@fd, wd) end + + # close() stops the processing of events and closes the + # inotify instance in the OS def close self.inotify_close(@fd) end + + # each_event() provides an easy way to loop over all events as they occur def each_event loop do ready = IO.select([@io], nil, nil, nil) - yield self.read_event + event = self.read_event + yield event end end - def read_event + + # read_event() attempts to read the next inotify event from the OS + def read_event # :nodoc: buf = FFI::Buffer.alloc_out(EventStruct.size + MAX_NAME_SIZE, 1, false) ev = EventStruct.new(buf) n = self.read(@fd, buf, buf.total) Event.new(ev, buf) end - class EventStruct < FFI::Struct + # Internal class needed for FFI support + class EventStruct < FFI::Struct # :nodoc: layout( :wd, :int, :mask, :uint32, :cookie, :uint32, :len, :uint32) end + # The Inotify::Event class is used by Inotify when calling Inotify each_event method class Event - def initialize(struct, buf) + + def initialize(struct, buf) # :nodoc: @struct, @buf = struct, buf end - define_method(:wd) { @struct[:wd] } - define_method(:mask) { @struct[:mask] } - define_method(:cookie) { @struct[:cookie] } - define_method(:len) { @struct[:len] } + # Returns the watch descriptor (wd) associated with the event + def wd + @struct[:wd] + end + + # Returns the mask describing the event + def mask + @struct[:mask] + end + + # Returns the cookie associated with the event. If multiple events are triggered from the + # same action (such as renaming a file or directory), this value will be the same. + def cookie + @struct[:cookie] + end + + def len # :nodoc: + @struct[:len] + end + + # Returns the file name associated with the event, if applicable def name @struct[:len] > 0 ? @buf.get_string(16, @struct[:len]) : '' end - def inspect + def inspect # :nodoc: "<%s name=%s mask=%s wd=%s>" % [ self.class, self.name, self.mask, self.wd \ No newline at end of file