Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add moved_from

  • Loading branch information...
commit 96b217c53a9c1121cf0dfaea3c54af1beda524f7 1 parent b6c7d68
@mj41 authored
Showing with 47 additions and 36 deletions.
  1. +1 −1  inot.pl
  2. +46 −35 lib/Linux/Inotify2/Recur.pm
View
2  inot.pl
@@ -44,7 +44,7 @@
};
my $my_event_handle = sub {
- my ( $time, $fullname, $e, $ver ) = @_;
+ my ( $time, $fullname, $e, $ver, $moved_from ) = @_;
if ( $e->IN_ISDIR ) {
print "====> my_event_handle: Directory '$fullname'.\n" if $ver >= 3;
View
81 lib/Linux/Inotify2/Recur.pm
@@ -17,11 +17,11 @@ Linux::Inotify2::Recur - recursive directory/file change notification
=head2 Callback Interface
use Linux::Inotify2::Recur;
-
+
# create a new object
my $inotify = new Linux::Inotify2::Recur({
'ver' => $ver,
-
+
}) or die "Unable to create new inotify object: $!\n";
# manual event loop
@@ -36,18 +36,18 @@ Linux::Inotify2::Recur - recursive directory/file change notification
...
8 ... all debug info
9 ... too many debug info
-
+
=cut
sub new {
my ( $class, $conf ) = @_;
my $self = $class->SUPER::new();
-
+
# Verbosity level
$self->{ver} = 3;
$self->{ver} = $conf->{ver} if defined $conf->{ver};
-
+
# User defined subroutine to filter directories to watch.
$self->{grep_dirs_sub} = undef;
$self->{grep_dirs_sub} = $conf->{grep_dirs_sub} if defined $conf->{grep_dirs_sub};
@@ -61,14 +61,14 @@ sub new {
$self->load_ev_names() if $self->{ver} >= 3;
$self->set_watcher_sub();
-
+
return $self;
}
sub load_ev_names {
my ( $self ) = @_;
-
+
print "Events:\n" if $self->{ver} >= 5;
no strict 'refs';
for my $name (@Linux::Inotify2::EXPORT) {
@@ -104,6 +104,7 @@ sub inotify_watch {
print "Watching '$dir'\n" if $self->{ver} >= 4;
+ $! = undef;
my $watcher = $self->watch(
$dir,
( IN_MODIFY | IN_CLOSE_WRITE | IN_MOVED_TO | IN_MOVED_FROM | IN_CREATE | IN_DELETE | IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF ),
@@ -125,7 +126,7 @@ sub watch_this {
my ( $self, $dir ) = @_;
return 0 unless -d $dir;
-
+
if ( defined $self->{grep_dirs_sub} ) {
return 0 unless $self->{grep_dirs_sub}->( $dir );
}
@@ -157,7 +158,7 @@ sub items_to_watch_recursive {
sub item_to_remove_by_name {
my ( $self, $item_torm_base, $recursive ) = @_;
-
+
my $ret_code = 1;
# Removing by name.
@@ -166,8 +167,8 @@ sub item_to_remove_by_name {
my $remove = 0;
my $item_name = $watch->{name};
if ( $recursive ) {
- if ( length($item_name) >= $item_torm_len
- && substr($item_name,0,$item_torm_len) eq $item_torm_base
+ if ( length($item_name) >= $item_torm_len
+ && substr($item_name,0,$item_torm_len) eq $item_torm_base
) {
$remove = 1;
}
@@ -175,7 +176,7 @@ sub item_to_remove_by_name {
} else {
$remove = 1 if $item_name eq $item_torm_base;
}
-
+
if ( $remove ) {
print "Stopping watching $item_name (by name '$item_torm_base', rec: $recursive).\n" if $self->{ver} >= 4;
my $tmp_ret_code = $watch->cancel;
@@ -183,7 +184,7 @@ sub item_to_remove_by_name {
$ret_code = 0 unless $tmp_ret_code;
}
}
-
+
return $ret_code;
}
@@ -220,6 +221,12 @@ sub set_watcher_sub {
# Print event info.
if ( $self->{ver} >= 2 ) {
+ # Print line separator only each second.
+ if ( int($time) != $last_time ) {
+ print "-" x 80 . "\n" if $self->{ver} >= 3;
+ $last_time = int($time);
+ }
+
my @lt = localtime($time);
my $dt = sprintf("%02d.%02d.%04d %02d:%02d:%02d -", $lt[3], ($lt[4] + 1),( $lt[5] + 1900), $lt[2], $lt[1], $lt[0] );
print $dt;
@@ -246,24 +253,29 @@ sub set_watcher_sub {
print "\n";
}
-
- if ( $e->IN_ISDIR ) {
- if ( $e->IN_CREATE ) {
+ my $is_dir = ( $e->{mask} & IN_ISDIR );
+ my $moved_from = undef;
+ if ( $e->IN_CREATE ) {
+ if ( $is_dir ) {
$self->items_to_watch_recursive( [ $fullname ], 0 );
-
- } elsif ( $e->IN_MOVED_TO ) {
- my $cookie = $e->{cookie};
- if ( exists $self->{cookies_to_rm}->{$cookie} ) {
+ }
+
+ } elsif ( $e->IN_MOVED_TO ) {
+ my $cookie = $e->{cookie};
+ if ( exists $self->{cookies_to_rm}->{$cookie} ) {
+ if ( $self->{cookies_to_rm}->{$cookie}->[0] ) {
# Check if we want to watch new name.
if ( $self->watch_this($fullname) ) {
# Update path inside existing watch.
$self->items_to_watch_recursive( [ $fullname ], 0 );
+ $moved_from = $self->{cookies_to_rm}->{$cookie}->[1];
delete $self->{cookies_to_rm}->{$cookie};
# Remove old watch if exists.
} elsif ( defined $self->{cookies_to_rm}->{$cookie} ) {
my $c_fullname = $self->{cookies_to_rm}->{$cookie};
$self->item_to_remove_by_name( $c_fullname, 1 );
+ $moved_from = $self->{cookies_to_rm}->{$cookie}->[1];
delete $self->{cookies_to_rm}->{$cookie};
# Remember new cookie.
@@ -272,32 +284,30 @@ sub set_watcher_sub {
}
} else {
- $self->items_to_watch_recursive( [ $fullname ], 0 );
+ $moved_from = delete $self->{cookies_to_rm}->{$cookie}->[1];
}
+
+ } else {
+ $self->items_to_watch_recursive( [ $fullname ], 0 );
}
}
if ( defined $self->{my_event_handle} ) {
- $self->{my_event_handle}->(
+ $self->{my_event_handle}->(
$time,
$fullname,
$e,
- $self->{ver}
+ $self->{ver},
+ $moved_from
);
}
- # Print line separator only each second.
- if ( int($time) != $last_time ) {
- print "-" x 80 . "\n" if $self->{ver} >= 3;
- $last_time = int($time);
- }
-
# Event on directory, but item inside changed.
if ( length($e->{name}) ) {
# Directory moved away.
- if ( $e->{mask} & ( IN_MOVED_FROM & IN_ISDIR ) ) {
+ if ( $e->{mask} & IN_MOVED_FROM ) {
my $cookie = $e->{cookie};
if ( exists $self->{cookies_to_rm}->{$cookie} ) {
# Nothing to do. See assumption a).
@@ -305,7 +315,8 @@ sub set_watcher_sub {
} else {
# We don't know new name yet, so we can't decide what to do (update or remove watch).
# See assumption b).
- $self->{cookies_to_rm}->{ $cookie } = $fullname;
+ my $is_watched = $is_dir;
+ $self->{cookies_to_rm}->{ $cookie } = [ $is_watched, $fullname ];
}
}
@@ -345,9 +356,10 @@ sub cleanup_moved_out {
return 1 unless scalar keys %{ $self->{cookies_to_rm} };
- # Remove all IN_MOVE_FROM without IN_MOVE_TO. See assumption c).
+ # Remove all IN_MOVE_FROM without IN_MOVE_TO.
foreach my $cookie ( keys %{ $self->{cookies_to_rm} } ) {
if ( defined $self->{cookies_to_rm}->{$cookie} ) {
+ next unless $self->{cookies_to_rm}->{$cookie}->[0]; # check is_watched
my $fullname = $self->{cookies_to_rm}->{$cookie};
print "After loop cleanup - fullname '$fullname'.\n" if $self->{ver} >= 5;
$self->item_to_remove_by_name( $fullname, 0 );
@@ -362,14 +374,14 @@ sub cleanup_moved_out {
sub pool {
my ( $self ) = @_;
-
+
$! = undef;
my @events = $self->read;
if ( @events > 0 ) {
$self->cleanup_moved_out();
return 1;
}
-
+
print "Error: Event read error - $!\n" if $self->{ver} >= 1 && $!;
return 1;
}
@@ -378,7 +390,6 @@ sub pool {
a) No MOVED_TO, MOVED_FROM order.
b) No items related events between MOVED_FROM and MOVED_TO.
- c) MOVED_FROM and MOVED_TO not in two separated "$inotify->read"s.
=head1 Troubleshooting
Please sign in to comment.
Something went wrong with that request. Please try again.