# Version 0.2.3 (2005-01-18) # function ignore_dir : was added # # Version 0.2.2 (2005-01-18) # cleanning code (big thanks to gnome at #ruby-lang) # rename next_event in each_event (thanks kig) # # Version 0.2.1 (2005-01-18) # class Events : use real mask # # Version 0.2.0 (2005-01-18) # function watch_dir : only watch # function next_event : was added # function watch_dir_recursively : was added # # Version 0.1.1 (2005-01-17) # Correct IN_ var for inotify 0.18 module INotify require 'find' INOTIFY_WATCH = 0x80085101 INOTIFY_IGNORE = 0x80045102 Mask = Struct::new(:value, :name) Masks = { :IN_ACCESS => Mask::new(0x00000001, 'access'), :IN_MODIFY => Mask::new(0x00000002, 'modify'), :IN_ATTRIB => Mask::new(0x00000004, 'attrib'), :IN_CLOSE_WRITE => Mask::new(0x00000008, 'close_write'), :IN_CLOSE_NOWRITE => Mask::new(0x00000010, 'close_nowrite'), :IN_OPEN => Mask::new(0x00000020, 'open'), :IN_MOVED_FROM => Mask::new(0x00000040, 'moved_from'), :IN_MOVED_TO => Mask::new(0x00000080, 'moved_to'), :IN_DELETE_SUBDIR => Mask::new(0x00000100, 'delete_subdir'), :IN_DELETE_FILE => Mask::new(0x00000200, 'delete_file'), :IN_CREATE_SUBDIR => Mask::new(0x00000400, 'create_subdir'), :IN_CREATE_FILE => Mask::new(0x00000800, 'create_file'), :IN_DELETE_SELF => Mask::new(0x00001000, 'delete_self'), :IN_UNMOUNT => Mask::new(0x00002000, 'unmount'), :IN_Q_OVERFLOW => Mask::new(0x00004000, 'q_overflow'), :IN_IGNORED => Mask::new(0x00008000, 'ignored'), :IN_ALL_EVENTS => Mask::new(0xffffffff, 'all_events') } Masks.each {|key, value| const_set(key, value) } class INotify def initialize @watch_dir = Array.new @io = File.open('/dev/inotify') end def close @io.close end def watch_dir (dir, option) arg = [dir, option.value] arg = arg.pack("PL") wd = @io.ioctl(INOTIFY_WATCH, arg) if (wd >= 0) @watch_dir[wd] = dir else return -1 end end def ignore_dir (dir) @io.ioctk(INOTIFY_IGNORE, dir) end def watch_dir_recursively (dir, option) Find.find(dir) {|sub_dir| watch_dir(sub_dir, option) if (File::directory?(sub_dir) == true) } end def each_event loop { begin read_cnt = @io.sysread(268) wd, event, cookie, filename = read_cnt.unpack('lLLZ*') end while ((event & IN_Q_OVERFLOW.value) != 0 && sleep(0.05)) evts = Events.new(path(wd), event, cookie, filename) evts.each {|event| yield event } } end def path (wd) @watch_dir[wd] end end class Events def initialize (path, event, cookie, filename) @event_list = Array.new Masks.each_value {|mask| next if mask.value == IN_ALL_EVENTS.value if ((mask.value & event) != 0) @event_list.push Event.new(path, mask.name, cookie, filename) end } end def each @event_list.each {|event| yield event} end end class Event attr_reader :filename, :event, :path def initialize (path, event, cookie, filename) @path = path @event = event @cookie = cookie @filename = filename end def dump "path: "+@path.to_s+" event: "+event.to_s+" cookie: "+@cookie.to_s+" filename: "+@filename.to_s end end end