File Coverage

blib/lib/Linux/Inotify.pm
Criterion Covered Total %
statement 46 55 83.6
branch 2 8 25.0
condition n/a
subroutine 14 16 87.5
pod 0 8 0.0
total 62 87 71.2


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