inotify 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/inotify.rb +242 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65fcbfaefdda68499dd8e77c1617901f991bf6f9
4
+ data.tar.gz: 36e9bea27f4407be2e365a93ea43062e658fa533
5
+ SHA512:
6
+ metadata.gz: 0b47d2d241741bbaea1ad016a7b62c01a9deab02a61ea8d3e3cac2def963815fa697887fc2ec6a06756fb12007aa7117ceacbef54c3e268551104c5d85c3a598
7
+ data.tar.gz: 10d2ffabb1e2db35521c0339d5b2b028db0bba9ef6f4253a006624714cad0b60c433d62f73e5a7581be3f50523364fbfa4b894c95cdc5b0952832302809bbdfa
data/lib/inotify.rb ADDED
@@ -0,0 +1,242 @@
1
+ # lib/inotify.rb
2
+ # (C) 2013 jtRIPper
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 1, or (at your option)
7
+ # any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+
18
+ require 'fiddle'
19
+
20
+ # Constants for each inotify event found in /usr/include/sys/inotify.h, descriptions from inotify man page (7), (note: 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 returned inotify_event structure identifies the name of the file within the directory.)
21
+ module InotifyEvents
22
+ # File was accessed (read) (*).
23
+ IN_ACCESS = 0x00000001
24
+ # File was modified (*).
25
+ IN_MODIFY = 0x00000002
26
+ # Metadata changed, e.g., permissions, timestamps, extended attributes, link count (since Linux 2.6.25), UID, GID, etc. (*).
27
+ IN_ATTRIB = 0x00000004
28
+ # File opened for writing was closed (*).
29
+ IN_CLOSE_WRITE = 0x00000008
30
+ # File not opened for writing was closed (*).
31
+ IN_CLOSE_NOWRITE = 0x00000010
32
+ # File was closed (*).
33
+ IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
34
+ # File was opened (*).
35
+ IN_OPEN = 0x00000020
36
+ # Generated for the directory containing the old filename when a file is renamed (*).
37
+ IN_MOVED_FROM = 0x00000040
38
+ # Generated for the directory containing the new filename when a file is renamed (*).
39
+ IN_MOVED_TO = 0x00000080
40
+ # Generated when a file is moved (*).
41
+ IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO)
42
+ # File/directory created in watched directory (*).
43
+ IN_CREATE = 0x00000100
44
+ # File/directory deleted from watched directory (*).
45
+ IN_DELETE = 0x00000200
46
+ # Watched file/directory was itself deleted.
47
+ IN_DELETE_SELF = 0x00000400
48
+ # Watched file/directory was itself moved.
49
+ IN_MOVE_SELF = 0x00000800
50
+ # Filesystem containing watched object was unmounted.
51
+ IN_UNMOUNT = 0x00002000
52
+ # Event queue overfloved.
53
+ IN_Q_OVERFLOW = 0x00004000
54
+ # Watch was removed explicitly (inotify_rm_watch(2)) or automatically (file was deleted, or filesystem was unmounted).
55
+ IN_IGNORED = 0x00008000
56
+ # Only watch pathname if it is a directory.
57
+ IN_ONLYDIR = 0x01000000
58
+ # Don't dereference pathname if it is a symbolic link.
59
+ IN_DONT_FOLLOW = 0x02000000
60
+ # 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.
61
+ IN_EXCL_UNLINK = 0x04000000
62
+ # Add (OR) events to watch mask for this pathname if it already exists (instead of replacing mask).
63
+ IN_MASK_ADD = 0x20000000
64
+ # Subject of this event is a directory.
65
+ IN_ISDIR = 0x40000000
66
+ # Monitor pathname for one event, then remove from watch list.
67
+ IN_ONESHOT = 0x80000000
68
+ # Set all events.
69
+ IN_ALL_EVENTS = (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE \
70
+ | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM \
71
+ | IN_MOVED_TO | IN_CREATE | IN_DELETE \
72
+ | IN_DELETE_SELF | IN_MOVE_SELF)
73
+ end
74
+
75
+ # The basic ctypes for every function required by inotify
76
+ module InotifyCtypes
77
+ # open libc
78
+ $libc = Fiddle.dlopen('/lib/libc.so.6')
79
+
80
+ # import required functions
81
+ $__inotify_init = Fiddle::Function.new(
82
+ $libc['inotify_init'],
83
+ [],
84
+ Fiddle::TYPE_INT
85
+ )
86
+
87
+ $__inotify_add_watch = Fiddle::Function.new(
88
+ $libc['inotify_add_watch'],
89
+ [ Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT ],
90
+ Fiddle::TYPE_INT
91
+ )
92
+
93
+ $__inotify_rm_watch = Fiddle::Function.new(
94
+ $libc['inotify_rm_watch'],
95
+ [ Fiddle::TYPE_INT, Fiddle::TYPE_INT ],
96
+ Fiddle::TYPE_INT
97
+ )
98
+
99
+ $__read = Fiddle::Function.new(
100
+ $libc['read'],
101
+ [ Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT ],
102
+ Fiddle::TYPE_INT
103
+ )
104
+
105
+ $__close = Fiddle::Function.new(
106
+ $libc['close'],
107
+ [ Fiddle::TYPE_INT ],
108
+ Fiddle::TYPE_INT
109
+ )
110
+
111
+ # Parse the result of read on an inotify file descriptor.
112
+ def inotify_event(buffer)
113
+ wd, mask, cookie, len, name = buffer.unpack("lLLLZ*")
114
+ event = Hash.new
115
+ event["wd"] = wd
116
+ event["mask"] = mask
117
+ event["cookie"] = cookie
118
+ event["len"] = len
119
+ event["name"] = name
120
+ event
121
+ end
122
+
123
+ # Open inotify file descriptor.
124
+ def inotify_init
125
+ $__inotify_init.call
126
+ end
127
+
128
+ # Add a path to the inotify watch.
129
+ def inotify_add_watch(fd, path, mask)
130
+ $__inotify_add_watch.call(fd, path, mask)
131
+ end
132
+
133
+ # Remove a watch descriptor from the inotify watch.
134
+ def inotify_rm_watch(fd, wd)
135
+ $__inotify_rm_watch.call(fd, wd)
136
+ end
137
+
138
+ # Allocate a buffer, call read and then parse the result.
139
+ def inotify_read(fd)
140
+ max_len = 20 + 1024 + 1
141
+ cbuff = Fiddle::Pointer.malloc(max_len)
142
+ max_len.times { |index| cbuff[index] = 0 }
143
+ len = $__read.call(fd, cbuff, max_len)
144
+ inotify_event(cbuff.to_s(len))
145
+ end
146
+
147
+ # Close inotify file descriptor.
148
+ def inotify_close(fd)
149
+ $__close.call(fd)
150
+ end
151
+ end
152
+
153
+ # High-level class for using inotify in ruby.
154
+ # puts "Watching #{ARGV[0]}"
155
+ #
156
+ # inotify = Inotify.new
157
+ # inotify.add_watch(ARGV[0], InotifyEvents::IN_CREATE|InotifyEvents::IN_MODIFY)
158
+ #
159
+ # inotify.wait_for_event() { |path, mask, name|
160
+ # puts "#{path}/#{name}"
161
+ # if inotify.event?(mask, InotifyEvents::IN_CREATE)
162
+ # puts " * created"
163
+ # end
164
+ # if inotify.event?(mask, InotifyEvents::IN_MODIFY)
165
+ # puts " * modified"
166
+ # end
167
+ # }
168
+ #
169
+ # inotify.rm_watch(ARGV[0])
170
+
171
+ class Inotify
172
+ include InotifyCtypes
173
+ include ObjectSpace
174
+
175
+ def initialize
176
+ @fd = inotify_init
177
+ @wds = {}
178
+
179
+ define_finalizer(self, proc { close })
180
+ end
181
+
182
+ # Add a path to inotify watch (events found in InotifyEvents).
183
+ def add_watch(path, event)
184
+ @wds[inotify_add_watch(@fd, path, event)] = path
185
+ end
186
+
187
+ # Remove a path from inotify watch.
188
+ def rm_watch(path)
189
+ wd = @wds.key(path)
190
+ if wd
191
+ inotify_rm_watch(@fd, wd)
192
+ end
193
+ end
194
+
195
+ # Close all watch descriptors.
196
+ def rm_all_watches()
197
+ @wds.values.each { |v| rm_watch(v) }
198
+ end
199
+
200
+ # Recursively add a path to inotify watch.
201
+ def recursive_add_watch(path, event)
202
+ add_watch(path, event)
203
+ Dir.glob("#{path}/**/*/").each { |path|
204
+ add_watch(path, event)
205
+ }
206
+ end
207
+
208
+ # Wait for an inotify event to happen, yields the path, mask, and file name.
209
+ def wait_for_event()
210
+ event = inotify_read(@fd)
211
+ yield @wds[event["wd"]], event["mask"], event["name"]
212
+ end
213
+
214
+ # Check if an event is set in an event mask.
215
+ def event?(mask, event_num)
216
+ return (mask & event_num) != 0
217
+ end
218
+
219
+ # Close the inotify file descriptor.
220
+ def close
221
+ inotify_close(@fd)
222
+ end
223
+ end
224
+
225
+ if __FILE__ == $0
226
+ puts "Watching #{ARGV[0]}"
227
+
228
+ inotify = Inotify.new
229
+ inotify.add_watch(ARGV[0], InotifyEvents::IN_CREATE|InotifyEvents::IN_MODIFY)
230
+
231
+ inotify.wait_for_event() { |path, mask, name|
232
+ puts "#{path}/#{name}"
233
+ if inotify.event?(mask, InotifyEvents::IN_CREATE)
234
+ puts " * created"
235
+ end
236
+ if inotify.event?(mask, InotifyEvents::IN_MODIFY)
237
+ puts " * modified"
238
+ end
239
+ }
240
+
241
+ inotify.rm_watch(ARGV[0])
242
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inotify
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - jtripper
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Inotify wrapper for Ruby.
14
+ email: jack@jtripper.net
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/inotify.rb
20
+ homepage: https://github.com/jtripper/inotify
21
+ licenses:
22
+ - GPLv2
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.0.3
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Inotify wrapper
44
+ test_files: []