package Linux::Inotify;
our $VERSION = '0.02';

=pod

=head1 NAME

Linux::Inotify - Classes for supporting inotify in Linux Kernel >= 2.6.13

=head1 SYNOPSIS

Linux::Inotify supports the new inotify interface of Linux which is a
replacement of dnotify. Beside the class Linux::Inotify there two helper
classes -- Linux::Inotify::Watch and Linux::Inotify::Event.

=head1 DESCRIPTION

=head2 class Linux::Inotify

The following code

   use Linux::Inotify;
   my $notifier = Linux::Inotify->new();

returns a new notifier.

   my $watch = $notifier->add_watch('filename', Linux::Inotify::MASK);

adds a watch to filename (see below), where MASK is one of ACCESS, MODIFY,
ATTRIB, CLOSE_WRITE, CLOSE_NOWRITE, OPEN, MOVED_FROM, MOVED_TO, CREATE, DELETE,
DELETE_SELF, UNMOUNT, Q_OVERFLOW, IGNORED, ISDIR, ONESHOT, CLOSE, MOVE or
ALL_EVENTS.

   my @events = $notifier->read();

reads and decodes all available data and returns an array of
Linux::Inotify::Event objects (see below).

   $notifier->close();

destroys the notifier.

=head2 class Linux::Inotify::Watch

The constructor new is usually not called directly but via the add_watch method
of the notifier. An alternative contructor

   my $watch_clone = $watch->clone('filename');

creates an new watch for filename but shares the same $notifier and MASK. This
is indirectly used for recursing into subdirectories (see below). The
destructor

   $watch->remove()

destroys the watch safely. It does not matter if the kernel has already removed
the watch itself, which may happen when the watched object has been deleted.
   
=head2 class Linux::Inotify::Event

The constructor is not called directly but through the read method of
Linux::Inotify that returns an array of event objects.  An
Linux::Inotify::Event object has some interesting data members: mask, cookie
and name. The method

   $event->fullname();

returns the full name of the file or directory not only the name relative to
the watch like the name member does contain.

   $event->print();

prints the event to stdout in a human readable form.

   my $new_watch = $event->add_watch();

creates a new watch for the file/directory of the event and shares the notifier
and MASK of the original watch, that has generated the event. That is useful
for recursing into subdirectories.


=head1 AUTHOR

Copyright 2005 by Torsten Werner <twerner@debian.org>. The code is licensed
under the same license as perl: L<perlgpl> or L<perlartistic>.

=cut


use strict;
use warnings;
use Carp;
use POSIX;
require 'syscall.ph';

sub new($) {
   my $class = shift;
   my %self = (
      fd => syscall 291
   );
   croak "Linux::Inotify::init() failed: $!" if $self{fd} == -1;
   bless \%self, $class;
   return \%self;
}

sub add_watch($$$) {
   my $self = shift;
   use Linux::Inotify::Watch;
   return Linux::Inotify::Watch->new($self, @_);
}

sub close($) {
   my $self = shift;
   my $ret = POSIX::close($self->{fd});
   croak "Linux::Inotify::close() failed: $!" unless defined $ret;
}

use constant {
   ACCESS        => 0x00000001,
   MODIFY        => 0x00000002,
   ATTRIB        => 0x00000004,
   CLOSE_WRITE   => 0x00000008,
   CLOSE_NOWRITE => 0x00000010,
   OPEN          => 0x00000020,
   MOVED_FROM    => 0x00000040,
   MOVED_TO      => 0x00000080,
   CREATE        => 0x00000100,
   DELETE        => 0x00000200,
   DELETE_SELF   => 0x00000400,
   UNMOUNT       => 0x00002000,
   Q_OVERFLOW    => 0x00004000,
   IGNORED       => 0x00008000,
   ISDIR         => 0x40000000,
   ONESHOT       => 0x80000000,
   CLOSE         => 0x00000018,
   MOVE          => 0x000000c0,
   ALL_EVENTS    => 0xffffffff
};

sub read($) {
   my $self = shift;
   my $bytes = POSIX::read($self->{fd}, my $raw_events, 65536);
   croak "Linux::Inotify::read: read only $bytes bytes: $!" if $bytes < 16;
   my @all_events;
   do {
      use Linux::Inotify::Event;
      my $event = Linux::Inotify::Event->new($raw_events);
      push @all_events, $event;
      $raw_events = substr($raw_events, 16 + $event->{len});
   } while(length $raw_events >= 16);
   return @all_events;
}

1;

