inotify-ffi-dev 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.md +11 -0
  2. data/inotify-ffi-dev.gemspec +26 -0
  3. data/lib/inotify-ffi.rb +178 -0
  4. metadata +57 -0
@@ -0,0 +1,11 @@
1
+ # inotify-ffi
2
+
3
+ Blatant, unashamed rip-off of [samples/inotify.rb](http://github.com/ffi/ffi/blob/master/samples/inotify.rb)
4
+
5
+ Now a gem.
6
+
7
+ ## Install
8
+ gem install inotify-ffi
9
+
10
+ ## Thanks
11
+ halorgium for async_each_event
@@ -0,0 +1,26 @@
1
+ Gem::Specification.new do |s|
2
+ s.specification_version = 2 if s.respond_to? :specification_version=
3
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
+
5
+ s.name = 'inotify-ffi-dev'
6
+ s.version = '0.1.0'
7
+ s.date = '2009-11-19'
8
+
9
+ s.description = "ffi interface for inotify"
10
+ s.summary = s.description
11
+
12
+ s.authors = ["Blake Mizerany"]
13
+ s.email = "blake.mizerany@gmail.com"
14
+
15
+ s.files = %w[
16
+ README.md
17
+ inotify-ffi-dev.gemspec
18
+ lib/inotify-ffi.rb
19
+ ]
20
+
21
+ s.extra_rdoc_files = %w[README.md]
22
+
23
+ s.homepage = "http://github.com/bmizerany/inotify-ffi/"
24
+ s.require_paths = %w[lib]
25
+ s.rubygems_version = '1.1.1'
26
+ end
@@ -0,0 +1,178 @@
1
+ require 'ffi'
2
+
3
+ module Inotify
4
+ extend FFI::Library
5
+
6
+ attach_function :init, :inotify_init, [ ], :int
7
+ attach_function :add_watch, :inotify_add_watch, [ :int, :string, :uint ], :int
8
+ attach_function :rm_watch, :inotify_rm_watch, [ :int, :uint ], :int
9
+ attach_function :read, [ :int, :buffer_out, :uint ], :int
10
+
11
+ def self.watch(path, event_mask = IN_ALL_EVENTS)
12
+ Watcher.setup(path, event_mask)
13
+ end
14
+
15
+ class Watcher
16
+ def self.setup(path, event_mask)
17
+ new(path, event_mask).setup
18
+ end
19
+
20
+ def initialize(path, event_mask)
21
+ @path, @event_mask = path, event_mask
22
+ end
23
+ attr_reader :io
24
+
25
+ def setup
26
+ @fd = Inotify.init
27
+ @wd = Inotify.add_watch(@fd, @path, @event_mask)
28
+ @io = FFI::IO.for_fd(@fd)
29
+ self
30
+ end
31
+
32
+ def each_event
33
+ loop do
34
+ ready = IO.select([ @io ], nil, nil, nil)
35
+ yield Inotify.process_event(@fd)
36
+ end
37
+ end
38
+
39
+ def async_each_event(&blk)
40
+ mod = Module.new do
41
+ include Connection
42
+ define_method(:notify_event, &blk)
43
+ end
44
+ EM.watch(@io, mod) do |c|
45
+ c.notify_readable = true
46
+ end
47
+ end
48
+ end
49
+
50
+ def self.process_event(fd)
51
+ buf = FFI::Buffer.alloc_out(EventStruct.size + 4096, 1, false)
52
+ ev = EventStruct.new(buf)
53
+ n = Inotify.read(fd, buf, buf.total)
54
+ Event.new(ev, buf)
55
+ end
56
+
57
+ module Connection
58
+ def notify_readable
59
+ notify_event(Inotify.process_event(@fd))
60
+ end
61
+
62
+ def notify_event(ev)
63
+ raise "Implement #notify_event on #{self.class}"
64
+ end
65
+ end
66
+
67
+ class Event
68
+ def initialize(struct, buf)
69
+ @struct, @buf = struct, buf
70
+ end
71
+
72
+ def mask ; @struct[:mask] ; end
73
+ def wd ; @struct[:wd] ; end
74
+ def len ; @struct[:len] ; end
75
+
76
+ def is?(*c)
77
+ c.all? {|c| (mask & c) > 0 }
78
+ end
79
+
80
+ def inspect
81
+ "<%s: wd:%s mask:%s len=%s>" % [
82
+ name,
83
+ @struct[:wd],
84
+ @struct[:mask],
85
+ @struct[:len]
86
+ ]
87
+ end
88
+
89
+ def mask_names
90
+ Const.constants.select do |const|
91
+ value = Const.const_get(const)
92
+ @struct[:mask] & value > 0
93
+ end
94
+ end
95
+
96
+ def name
97
+ @struct[:len] >= 0 ? @buf.get_string(@struct[:len]) : '<unknown>'
98
+ end
99
+
100
+ end
101
+
102
+ class EventStruct < FFI::Struct
103
+ layout \
104
+ :wd, :int,
105
+ :mask, :uint,
106
+ :cookie, :uint,
107
+ :len, :uint
108
+ end
109
+
110
+ module Const
111
+ IN_ACCESS = 0x00000001
112
+ IN_MODIFY = 0x00000002
113
+ IN_ATTRIB = 0x00000004
114
+ IN_CLOSE_WRITE = 0x00000008
115
+ IN_CLOSE_NOWRITE = 0x00000010
116
+ IN_OPEN = 0x00000020
117
+ IN_MOVED_FROM = 0x00000040
118
+ IN_MOVED_TO = 0x00000080
119
+ IN_CREATE = 0x00000100
120
+ IN_DELETE = 0x00000200
121
+ IN_DELETE_SELF = 0x00000400
122
+ IN_MOVE_SELF = 0x00000800
123
+ # Events sent by the kernel.
124
+ IN_UNMOUNT = 0x00002000
125
+ IN_Q_OVERFLOW = 0x00004000
126
+ IN_IGNORED = 0x00008000
127
+ IN_ONLYDIR = 0x01000000
128
+ IN_DONT_FOLLOW = 0x02000000
129
+ IN_MASK_ADD = 0x20000000
130
+ IN_ISDIR = 0x40000000
131
+ IN_ONESHOT = 0x80000000
132
+ end
133
+ include Const
134
+
135
+ IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO)
136
+ IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
137
+ IN_ALL_EVENTS = (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE \
138
+ | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM \
139
+ | IN_MOVED_TO | IN_CREATE | IN_DELETE \
140
+ | IN_DELETE_SELF | IN_MOVE_SELF)
141
+ end
142
+
143
+ if $0 == __FILE__
144
+ ######
145
+ require 'pp'
146
+ require 'eventmachine'
147
+
148
+ watcher = Inotify.watch("/tmp")
149
+ if ENV["EM"]
150
+ module Callback
151
+ include Inotify::Connection
152
+
153
+ def notify_event(ev)
154
+ puts ev.inspect
155
+ pp ev.mask_names
156
+ end
157
+ end
158
+
159
+ EM.run do
160
+ EM.watch(watcher.io, Callback) do |c|
161
+ c.notify_readable = true
162
+ end
163
+ end
164
+ elsif ENV["EM2"]
165
+ EM.run do
166
+ watcher.async_each_event do |ev|
167
+ puts ev.inspect
168
+ pp ev.mask_names
169
+ end
170
+ end
171
+ else
172
+ watcher.each_event do |ev|
173
+ puts ev.inspect
174
+ pp ev.mask_names
175
+ end
176
+ end
177
+ ######
178
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inotify-ffi-dev
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Blake Mizerany
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-19 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: ffi interface for inotify
17
+ email: blake.mizerany@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.md
24
+ files:
25
+ - README.md
26
+ - inotify-ffi-dev.gemspec
27
+ - lib/inotify-ffi.rb
28
+ has_rdoc: true
29
+ homepage: http://github.com/bmizerany/inotify-ffi/
30
+ licenses: []
31
+
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project:
52
+ rubygems_version: 1.3.5
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: ffi interface for inotify
56
+ test_files: []
57
+