ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Linux-Inotify2/Inotify2.pm
Revision: 1.9
Committed: Tue Aug 23 02:45:23 2005 UTC (18 years, 11 months ago) by root
Branch: MAIN
Changes since 1.8: +2 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     Linux::Inotify2 - scalable directory/file change notification
4    
5     =head1 SYNOPSIS
6    
7     use Linux::Inotify2;
8    
9 root 1.4 # create a new object
10     my $inotify = new Linux::Inotify2
11     or die "Unable to create new inotify object: $!";
12    
13     # for Event:
14     Event->io (fd =>$inotify->fileno, poll => 'r', cb => sub { $inotify->poll });
15     # for Glib:
16     add_watch Glib::IO $inotify->fileno, in => sub { $inotify->poll };
17     # manually:
18     1 while $inotify->poll;
19    
20     # add watchers
21     $inotify->watch ("/etc/passwd", IN_ACCESS, sub {
22     my $e = shift;
23     my $name = $e->fullname;
24     print "$name was accessed\n" if $e->IN_ACCESS;
25     print "$name is no longer mounted\n" if $e->IN_UNMOUNT;
26     print "$name is gone\n" if $e->IN_IGNORED;
27     print "events for $name have been lost\n" if $e->IN_Q_OVERFLOW;
28    
29     # cancel this watcheR: remove no further events
30     $e->w->cancel;
31     });
32    
33 root 1.1 =head1 DESCRIPTION
34    
35 root 1.3 This module implements an interface to the Linux 2.6.13 and later Inotify
36     file/directory change notification sytem.
37 root 1.2
38 root 1.3 It has a number of advantages over the Linux::Inotify module:
39 root 1.2
40     - it is portable (Linux::Inotify only works on x86)
41     - the equivalent of fullname works correctly
42     - it is better documented
43     - it has callback-style interface, which is better suited for
44     integration.
45    
46 root 1.6 =head2 The Linux::Inotify2 Class
47    
48 root 1.1 =over 4
49    
50     =cut
51    
52     package Linux::Inotify2;
53    
54     use Carp ();
55     use Scalar::Util ();
56    
57     use base 'Exporter';
58    
59     BEGIN {
60 root 1.3 $VERSION = 0.2;
61 root 1.1
62     @constants = qw(
63     IN_ACCESS IN_MODIFY IN_ATTRIB IN_CLOSE_WRITE
64     IN_CLOSE_NOWRITE IN_OPEN IN_MOVED_FROM IN_MOVED_TO
65 root 1.9 IN_CREATE IN_DELETE IN_DELETE_SELF IN_MOVE_SELF
66 root 1.1 IN_ALL_EVENTS
67     IN_UNMOUNT IN_Q_OVERFLOW IN_IGNORED
68     IN_CLOSE IN_MOVE
69     IN_ISDIR IN_ONESHOT
70     );
71    
72     @EXPORT = @constants;
73    
74     require XSLoader;
75     XSLoader::load Linux::Inotify2, $VERSION;
76     }
77    
78     =item my $inotify = new Linux::Inotify2
79    
80     Create a new notify object and return it. A notify object is kind of a
81     container that stores watches on filesystem names and is responsible for
82     handling event data.
83    
84     On error, C<undef> is returned and C<$!> will be set accordingly. The followign errors
85     are documented:
86    
87     ENFILE The system limit on the total number of file descriptors has been reached.
88     EMFILE The user limit on the total number of inotify instances has been reached.
89     ENOMEM Insufficient kernel memory is available.
90    
91 root 1.4 Example:
92    
93     my $inotify = new Linux::Inotify2
94     or die "Unable to create new inotify object: $!";
95    
96 root 1.1 =cut
97    
98     sub new {
99     my ($class) = @_;
100    
101     my $fd = inotify_init;
102    
103     return unless $fd >= 0;
104    
105     bless { fd => $fd }, $class
106     }
107    
108 root 1.4 =item $watch = $inotify->watch ($name, $mask, $cb)
109 root 1.1
110     Add a new watcher to the given notifier. The watcher will create events
111     on the pathname C<$name> as given in C<$mask>, which can be any of the
112 root 1.4 following constants (all exported by default) ORed together.
113    
114     "file" refers to any filesystem object in the watch'ed object (always a
115     directory), that is files, directories, symlinks, device nodes etc., while
116     "object" refers to the object the watch has been set on itself:
117    
118     IN_ACCESS object was accessed
119     IN_MODIFY object was modified
120     IN_ATTRIB object metadata changed
121     IN_CLOSE_WRITE writable fd to file / to object was closed
122     IN_CLOSE_NOWRITE readonly fd to file / to object closed
123     IN_OPEN object was opened
124     IN_MOVED_FROM file was moved from this object (directory)
125     IN_MOVED_TO file was moved to this object (directory)
126     IN_CREATE file was created in this object (directory)
127     IN_DELETE file was deleted from this object (directory)
128     IN_DELETE_SELF object itself was deleted
129 root 1.9 IN_MOVE_SELF object itself was moved
130 root 1.4 IN_ALL_EVENTS all of the above events
131 root 1.1
132     IN_ONESHOT only send event once
133    
134 root 1.4 IN_CLOSE same as IN_CLOSE_WRITE | IN_CLOSE_NOWRITE
135     IN_MOVE same as IN_MOVED_FROM | IN_MOVED_TO
136 root 1.1
137     C<$cb> is a perl code reference that is called for each event. It receives
138     a C<Linux::Inotify2::Event> object.
139    
140     The returned C<$watch> object is of class C<Linux::Inotify2::Watch>.
141    
142     On error, C<undef> is returned and C<$!> will be set accordingly. The
143     following errors are documented:
144    
145     EBADF The given file descriptor is not valid.
146     EINVAL The given event mask contains no legal events.
147     ENOMEM Insufficient kernel memory was available.
148     ENOSPC The user limit on the total number of inotify watches was reached or the kernel failed to allocate a needed resource.
149     EACCESS Read access to the given file is not permitted.
150    
151     Example, show when C</etc/passwd> gets accessed and/or modified once:
152    
153     $inotify->watch ("/etc/passwd", IN_ACCESS | IN_MODIFY, sub {
154     my $e = shift;
155     print "$e->{w}{name} was accessed\n" if $e->IN_ACCESS;
156     print "$e->{w}{name} was modified\n" if $e->IN_MODIFY;
157     print "$e->{w}{name} is no longer mounted\n" if $e->IN_UNMOUNT;
158     print "events for $e->{w}{name} have been lost\n" if $e->IN_Q_OVERFLOW;
159    
160     $e->w->cancel;
161     });
162    
163     =cut
164    
165     sub watch {
166     my ($self, $name, $mask, $cb) = @_;
167    
168     my $wd = inotify_add_watch $self->{fd}, $name, $mask;
169    
170     return unless $wd >= 0;
171    
172     my $w = $self->{w}{$wd} = bless {
173     inotify => $self,
174     wd => $wd,
175     name => $name,
176     mask => $mask,
177     cb => $cb,
178     }, Linux::Inotify2::Watch;
179    
180     Scalar::Util::weaken $w->{inotify};
181    
182     $w
183     }
184    
185 root 1.4 =item $inotify->fileno
186 root 1.1
187     Returns the fileno for this notify object. You are responsible for calling
188     the C<poll> method when this fileno becomes ready for reading.
189    
190     =cut
191    
192     sub fileno {
193     $_[0]{fd}
194     }
195    
196 root 1.4 =item $count = $inotify->poll
197 root 1.1
198 root 1.4 Reads events from the kernel and handles them. If the notify fileno is
199     blocking (the default), then this method waits for at least one event
200     (and thus returns true unless an error occurs). Otherwise it returns
201     immediately when no pending events could be read.
202 root 1.1
203     Returns the count of events that have been handled.
204    
205     =cut
206    
207     sub poll {
208     my ($self) = @_;
209    
210 root 1.4 my @ev = inotify_read $self->{fd};
211    
212     for (@ev) {
213     my $w = $_->{w} = $self->{w}{$_->{wd}}
214 root 1.1 or next; # no such watcher
215 root 1.4
216     exists $self->{ignore}{$_->{wd}}
217     and next; # watcher has been canceled
218    
219     $w->{cb}->(bless $_, Linux::Inotify2::Event);
220 root 1.5 # TODO: what about IN_ONESHOT?
221 root 1.4 $w->cancel if $_->{mask} & (IN_IGNORED | IN_UNMOUNT);
222 root 1.1 }
223 root 1.4
224     delete $self->{ignore};
225    
226     scalar @ev
227 root 1.1 }
228    
229     sub DESTROY {
230     inotify_close $_[0]{fd}
231     }
232    
233     =back
234    
235     =head2 The Linux::Inotify2::Event Class
236    
237     Objects of this class are handed as first argument to the watch
238     callback. It has the following members and methods:
239    
240     =over 4
241    
242     =item $event->w
243    
244     =item $event->{w}
245    
246     The watcher object for this event.
247    
248     =item $event->name
249    
250     =item $event->{name}
251    
252     The path of the filesystem object, relative to the watch name.
253    
254     =item $watch->fullname
255    
256     Returns the "full" name of the relevant object, i.e. including the C<name>
257 root 1.7 member of the watcher (if the the watch is on a directory and a dir entry
258     is affected), or simply the C<name> member itself when the object is the
259     watch object itself.
260 root 1.1
261     =item $event->mask
262    
263     =item $event->{mask}
264    
265     The received event mask. In addition the the events described for
266     C<$inotify->watch>, the following flags (exported by default) can be set:
267    
268 root 1.4 IN_ISDIR event object is a directory
269 root 1.1
270 root 1.4 IN_Q_OVERFLOW event queue overflowed
271    
272     # when the following flags are set, then watchers are canceled automatically
273     IN_UNMOUNT filesystem for watch'ed object was unmounted
274     IN_IGNORED file was ignored/is gone (no more events are delivered)
275 root 1.1
276     =item $event->IN_xxx
277    
278     Returns a boolean that returns true if the event mask matches the
279     event. All of the C<IN_xxx> constants can be used as methods.
280    
281     =item $event->cookie
282    
283     =item $event->{cookie}
284    
285 root 1.8 The event cookie to "synchronize two events". Currently, this is always
286     zero, and I have no idea what it's supposed use is. Educate me!
287 root 1.1
288     =back
289    
290     =cut
291    
292     package Linux::Inotify2::Event;
293    
294     sub w { $_[0]{w} }
295     sub name { $_[0]{name} }
296     sub mask { $_[0]{mask} }
297     sub cookie { $_[0]{cookie} }
298    
299     sub fullname {
300     length $_[0]{name}
301     ? "$_[0]{w}{name}/$_[0]{name}"
302     : $_[0]{w}{name};
303     }
304    
305     for my $name (@Linux::Inotify2::constants) {
306     my $mask = &{"Linux::Inotify2::$name"};
307    
308     *$name = sub { ($_[0]{mask} & $mask) == $mask };
309     }
310    
311     =head2 The Linux::Inotify2::Watch Class
312    
313     Watch objects are created by calling the C<watch> method of a notifier.
314    
315     It has the following members and methods:
316    
317     =item $watch->name
318    
319     =item $watch->{name}
320    
321     The name as specified in the C<watch> call. For the object itself, this is
322     the empty string. For directory watches, this is the name of the entry
323     without leading path elements.
324    
325     =item $watch->mask
326    
327     =item $watch->{mask}
328    
329     The mask as specified in the C<watch> call.
330    
331     =item $watch->cb ([new callback])
332    
333     =item $watch->{cb}
334    
335     The callback as specified in the C<watch> call. Can optionally be changed.
336    
337     =item $watch->cancel
338    
339     Cancels/removes this watch. Future events, even if already queued queued,
340     will not be handled and resources will be freed.
341    
342     =cut
343    
344     package Linux::Inotify2::Watch;
345    
346     sub name { $_[0]{name} }
347     sub mask { $_[0]{mask} }
348    
349     sub cb {
350     $_[0]{cb} = $_[1] if @_ > 1;
351     $_[0]{cb}
352     }
353    
354     sub cancel {
355     my ($self) = @_;
356    
357 root 1.4 my $inotify = delete $self->{inotify}
358     or return 1; # already canceled
359    
360     delete $inotify->{w}{$self->{wd}}; # we are no longer there
361     $inotify->{ignore}{$self->{wd}} = 1; # ignore further events for one poll
362    
363     (Linux::Inotify2::inotify_rm_watch $inotify->{fd}, $self->{wd})
364 root 1.1 ? 1 : undef
365     }
366    
367     =head1 SEE ALSO
368    
369     L<Linux::Inotify>.
370    
371     =head1 AUTHOR
372    
373     Marc Lehmann <schmorp@schmorp.de>
374     http://home.schmorp.de/
375    
376     =cut
377    
378     1