| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Linux::Inotify; |
|
2
|
|
|
|
|
|
|
our $VERSION = '0.05'; |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
=pod |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=head1 NAME |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
Linux::Inotify - Classes for supporting inotify in Linux Kernel >= 2.6.13 |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
Linux::Inotify supports the new inotify interface of Linux which is a |
|
13
|
|
|
|
|
|
|
replacement of dnotify. Beside the class Linux::Inotify there two helper |
|
14
|
|
|
|
|
|
|
classes -- Linux::Inotify::Watch and Linux::Inotify::Event. |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head2 class Linux::Inotify |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
The following code |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
use Linux::Inotify; |
|
23
|
|
|
|
|
|
|
my $notifier = Linux::Inotify->new(); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
returns a new notifier. |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $watch = $notifier->add_watch('filename', Linux::Inotify::MASK); |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
adds a watch to filename (see below), where MASK is one of ACCESS, MODIFY, |
|
30
|
|
|
|
|
|
|
ATTRIB, CLOSE_WRITE, CLOSE_NOWRITE, OPEN, MOVED_FROM, MOVED_TO, CREATE, DELETE, |
|
31
|
|
|
|
|
|
|
DELETE_SELF, UNMOUNT, Q_OVERFLOW, IGNORED, ISDIR, ONESHOT, CLOSE, MOVE or |
|
32
|
|
|
|
|
|
|
ALL_EVENTS. |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
my @events = $notifier->read(); |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
reads and decodes all available data and returns an array of |
|
37
|
|
|
|
|
|
|
Linux::Inotify::Event objects (see below). |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
$notifier->close(); |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
destroys the notifier and closes the associated file descriptor. |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=head2 class Linux::Inotify::Watch |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
The constructor new is usually not called directly but via the add_watch method |
|
46
|
|
|
|
|
|
|
of the notifier. An alternative contructor |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
my $watch_clone = $watch->clone('filename'); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
creates an new watch for filename but shares the same $notifier and MASK. This |
|
51
|
|
|
|
|
|
|
is indirectly used for recursing into subdirectories (see below). The |
|
52
|
|
|
|
|
|
|
destructor |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
$watch->remove() |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
destroys the watch safely. It does not matter if the kernel has already removed |
|
57
|
|
|
|
|
|
|
the watch itself, which may happen when the watched object has been deleted. |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head2 class Linux::Inotify::Event |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
The constructor is not called directly but through the read method of |
|
62
|
|
|
|
|
|
|
Linux::Inotify that returns an array of event objects. An |
|
63
|
|
|
|
|
|
|
Linux::Inotify::Event object has some interesting data members: mask, cookie |
|
64
|
|
|
|
|
|
|
and name. The method |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
$event->fullname(); |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
returns the full name of the file or directory not only the name relative to |
|
69
|
|
|
|
|
|
|
the watch like the name member does contain. |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
$event->print(); |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
prints the event to stdout in a human readable form. |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
my $new_watch = $event->add_watch(); |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
creates a new watch for the file/directory of the event and shares the notifier |
|
78
|
|
|
|
|
|
|
and MASK of the original watch, that has generated the event. That is useful |
|
79
|
|
|
|
|
|
|
for recursing into subdirectories. |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head1 AUTHOR |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
Copyright 2005 by Torsten Werner . The code is licensed |
|
85
|
|
|
|
|
|
|
under the same license as perl: L or L. |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=cut |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
|
90
|
1
|
|
|
1
|
|
58989
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
30
|
|
|
91
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
26
|
|
|
92
|
1
|
|
|
1
|
|
4
|
use Carp; |
|
|
1
|
|
|
|
|
9
|
|
|
|
1
|
|
|
|
|
50
|
|
|
93
|
1
|
|
|
1
|
|
751
|
use POSIX; |
|
|
1
|
|
|
|
|
7631
|
|
|
|
1
|
|
|
|
|
6
|
|
|
94
|
1
|
|
|
1
|
|
2876
|
use Config; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
294
|
|
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
my %syscall_init = ( |
|
97
|
|
|
|
|
|
|
alpha => 444, |
|
98
|
|
|
|
|
|
|
arm => 316, |
|
99
|
|
|
|
|
|
|
i386 => 291, |
|
100
|
|
|
|
|
|
|
ia64 => 1277, |
|
101
|
|
|
|
|
|
|
powerpc => 275, |
|
102
|
|
|
|
|
|
|
powerpc64 => 275, |
|
103
|
|
|
|
|
|
|
s390 => 284, |
|
104
|
|
|
|
|
|
|
sh => 290, |
|
105
|
|
|
|
|
|
|
sparc => 151, |
|
106
|
|
|
|
|
|
|
sparc_64 => 151, |
|
107
|
|
|
|
|
|
|
x86_64 => 253, |
|
108
|
|
|
|
|
|
|
); |
|
109
|
|
|
|
|
|
|
my ($arch) = ($Config{archname} =~ m{([^-]+)-}); |
|
110
|
|
|
|
|
|
|
die "unsupported architecture: $arch\n" unless exists $syscall_init{$arch}; |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub syscall_init { |
|
113
|
1
|
|
|
1
|
0
|
19
|
syscall $syscall_init{$arch}; |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub syscall_add_watch { |
|
117
|
1
|
|
|
1
|
0
|
25
|
syscall $syscall_init{$arch} + 1, @_; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub syscall_rm_watch { |
|
121
|
0
|
0
|
|
0
|
0
|
0
|
unless ($arch =~ m{sparc}) { |
|
122
|
0
|
|
|
|
|
0
|
syscall $syscall_init{$arch} + 2, @_; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
else { |
|
125
|
|
|
|
|
|
|
# that's my favourite syscall: |
|
126
|
0
|
|
|
|
|
0
|
syscall $syscall_init{$arch} + 5, @_; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub new($) { |
|
131
|
1
|
|
|
1
|
0
|
731
|
my $class = shift; |
|
132
|
1
|
|
|
|
|
5
|
my $self = { |
|
133
|
|
|
|
|
|
|
fd => syscall_init |
|
134
|
|
|
|
|
|
|
}; |
|
135
|
1
|
50
|
|
|
|
29
|
croak "Linux::Inotify::init() failed: $!" if $self->{fd} == -1; |
|
136
|
1
|
|
|
|
|
5
|
return bless $self, $class; |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub add_watch($$$) { |
|
140
|
1
|
|
|
1
|
0
|
24
|
my $self = shift; |
|
141
|
1
|
|
|
1
|
|
580
|
use Linux::Inotify::Watch; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
215
|
|
|
142
|
1
|
|
|
|
|
10
|
my $watch = Linux::Inotify::Watch->new($self, @_); |
|
143
|
1
|
|
|
|
|
6
|
$self->{wd}->{$watch->{wd}} = $watch; |
|
144
|
1
|
|
|
|
|
3
|
return $watch; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub find($$) { |
|
148
|
3
|
|
|
3
|
0
|
4
|
my $self = shift; |
|
149
|
3
|
|
|
|
|
4
|
my $wd = shift; |
|
150
|
3
|
|
|
|
|
11
|
return $self->{wd}->{$wd}; |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub close($) { |
|
154
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
155
|
0
|
|
|
|
|
0
|
for my $watch (values %{$self->{wd}}) { |
|
|
0
|
|
|
|
|
0
|
|
|
156
|
0
|
|
|
|
|
0
|
$watch->remove; |
|
157
|
|
|
|
|
|
|
} |
|
158
|
0
|
|
|
|
|
0
|
my $ret = POSIX::close($self->{fd}); |
|
159
|
0
|
0
|
|
|
|
0
|
croak "Linux::Inotify::close() failed: $!" unless defined $ret; |
|
160
|
|
|
|
|
|
|
} |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
use constant { |
|
163
|
1
|
|
|
|
|
273
|
ACCESS => 0x00000001, |
|
164
|
|
|
|
|
|
|
MODIFY => 0x00000002, |
|
165
|
|
|
|
|
|
|
ATTRIB => 0x00000004, |
|
166
|
|
|
|
|
|
|
CLOSE_WRITE => 0x00000008, |
|
167
|
|
|
|
|
|
|
CLOSE_NOWRITE => 0x00000010, |
|
168
|
|
|
|
|
|
|
OPEN => 0x00000020, |
|
169
|
|
|
|
|
|
|
MOVED_FROM => 0x00000040, |
|
170
|
|
|
|
|
|
|
MOVED_TO => 0x00000080, |
|
171
|
|
|
|
|
|
|
CREATE => 0x00000100, |
|
172
|
|
|
|
|
|
|
DELETE => 0x00000200, |
|
173
|
|
|
|
|
|
|
DELETE_SELF => 0x00000400, |
|
174
|
|
|
|
|
|
|
UNMOUNT => 0x00002000, |
|
175
|
|
|
|
|
|
|
Q_OVERFLOW => 0x00004000, |
|
176
|
|
|
|
|
|
|
IGNORED => 0x00008000, |
|
177
|
|
|
|
|
|
|
ISDIR => 0x40000000, |
|
178
|
|
|
|
|
|
|
ONESHOT => 0x80000000, |
|
179
|
|
|
|
|
|
|
CLOSE => 0x00000018, |
|
180
|
|
|
|
|
|
|
MOVE => 0x000000c0, |
|
181
|
|
|
|
|
|
|
ALL_EVENTS => 0x00000fff |
|
182
|
1
|
|
|
1
|
|
4
|
}; |
|
|
1
|
|
|
|
|
12
|
|
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
sub read($) { |
|
185
|
2
|
|
|
2
|
0
|
346
|
my $self = shift; |
|
186
|
2
|
|
|
|
|
33
|
my $bytes = POSIX::read($self->{fd}, my $raw_events, 65536); |
|
187
|
2
|
50
|
|
|
|
7
|
croak "Linux::Inotify::read: read only $bytes bytes: $!" if $bytes < 16; |
|
188
|
2
|
|
|
|
|
4
|
my @all_events; |
|
189
|
2
|
|
|
|
|
2
|
do { |
|
190
|
1
|
|
|
1
|
|
461
|
use Linux::Inotify::Event; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
114
|
|
|
191
|
3
|
|
|
|
|
16
|
my $event = Linux::Inotify::Event->new($self, $raw_events); |
|
192
|
3
|
|
|
|
|
4
|
push @all_events, $event; |
|
193
|
3
|
|
|
|
|
16
|
$raw_events = substr($raw_events, 16 + $event->{len}); |
|
194
|
|
|
|
|
|
|
} while(length $raw_events >= 16); |
|
195
|
2
|
|
|
|
|
15
|
return @all_events; |
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
1; |
|
199
|
|
|
|
|
|
|
|