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.
- checksums.yaml +7 -0
- data/lib/inotify.rb +242 -0
- 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: []
|