# Version 0.1.1
# Correct IN_ var for inotify 0.18

class INotify

	INOTIFY_WATCH    = 0x80085101
	INOTIFY_IGNORE   = 0x80045102

	IN_ACCESS        = 0x00000001
	IN_MODIFY        = 0x00000002
	IN_ATTRIB        = 0x00000004
	IN_CLOSE_WRITE   = 0x00000008
	IN_CLOSE_NOWRITE = 0x00000010
	IN_OPEN          = 0x00000020
	IN_MOVED_FROM    = 0x00000040
	IN_MOVED_TO      = 0x00000080
	IN_DELETE_SUBDIR = 0x00000100
	IN_DELETE_FILE   = 0x00000200
	IN_CREATE_SUBDIR = 0x00000400
	IN_CREATE_FILE   = 0x00000800
	IN_DELETE_SELF   = 0x00001000
	IN_UNMOUNT       = 0x00002000
	IN_Q_OVERFLOW    = 0x00004000
	IN_IGNORED       = 0x00008000
	IN_ALL_EVENTS    = 0xffffffff
	
	
	def watch_dir (dir, option)
		@io = File.open('/dev/inotify')
		arg = [dir, option]
		arg = arg.pack("PL")
		@io.ioctl(INOTIFY_WATCH, arg)
		loop {
			read_cnt = @io.sysread(268)
			wd, mask, cookie, filename = read_cnt.unpack('lLLZ*')
			evt = Event.new(wd, mask, cookie, filename)
			yield(evt)
		}
		@io.close
	end

end

class Event
	attr_reader :filename, :mask

	def initialize (wd, mask, cookie, filename)
		@wd       = wd
		@mask     = mask
		@cookie   = cookie
		@filename = filename
	end

	def dump
		puts @wd.to_s+" "+@mask.to_s+" "+@cookie.to_s+" "+@filename+" = "+mask_name
	end

	def mask_name
		case @mask
			when INotify::IN_ACCESS
				return 'access'
			when INotify::IN_MODIFY
				return 'modify'
			when INotify::IN_ATTRIB
				return 'attrib'
			when INotify::IN_CLOSE_WRITE
				return 'close_write'
			when INotify::IN_CLOSE_NOWRITE
				return 'close_nowrite'
			when INotify::IN_OPEN
				return 'open'
			when INotify::IN_MOVED_FROM
				return 'moved_from'
			when INotify::IN_MOVED_TO
				return 'moved_to'
			when INotify::IN_DELETE_SUBDIR
				return 'delete_subdir'
			when INotify::IN_DELETE_FILE
				return 'delete_file'
			when INotify::IN_CREATE_SUBDIR
				return 'create_subdir'
			when INotify::IN_CREATE_FILE
				return 'create_file'
			when INotify::IN_DELETE_SELF
				return 'delete_self'
			when INotify::IN_Q_OVERFLOW
				return 'event_queued_overflow'
			when INotify::IN_UNMOUNT
				return 'unmount'
			else
				return 'unknown'
		end
	end
end
