]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/FakeInotify.pm
No ext_urls
[public-inbox.git] / lib / PublicInbox / FakeInotify.pm
index 644f5b5b7229316f7ae48745d0e1421b1203668b..45b80f505557a95ed0cd157b36667477bee3fdc9 100644 (file)
@@ -1,19 +1,21 @@
-# Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
+# Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 
 # for systems lacking Linux::Inotify2 or IO::KQueue, just emulates
 # enough of Linux::Inotify2
 package PublicInbox::FakeInotify;
-use strict;
-use v5.10.1;
+use v5.12;
 use parent qw(Exporter);
 use Time::HiRes qw(stat);
 use PublicInbox::DS qw(add_timer);
 sub IN_MODIFY () { 0x02 } # match Linux inotify
+# my $IN_MOVED_FROM     0x00000040     /* File was moved from X.  */
 # my $IN_MOVED_TO = 0x80;
 # my $IN_CREATE = 0x100;
 sub MOVED_TO_OR_CREATE () { 0x80 | 0x100 }
-sub IN_DELETE () { 0x00000200 }
+sub IN_DELETE () { 0x200 }
+sub IN_DELETE_SELF () { 0x400 }
+sub IN_MOVE_SELF () { 0x800 }
 
 our @EXPORT_OK = qw(fill_dirlist on_dir_change);
 
@@ -44,7 +46,7 @@ sub watch {
 
 # also used by KQNotify since it kevent requires readdir on st_nlink
 # count changes.
-sub on_dir_change ($$$$;$) {
+sub on_dir_change ($$$$$) {
        my ($events, $dh, $path, $old_ctime, $dirlist) = @_;
        my $oldlist = $dirlist->{$path};
        my $newlist = $oldlist ? {} : undef;
@@ -79,7 +81,14 @@ sub read {
        my @watch_gone;
        for my $x (keys %$watch) {
                my ($path, $mask) = split(/\0/, $x, 2);
-               my @now = stat($path) or next;
+               my @now = stat($path);
+               if (!@now && $!{ENOENT} && ($mask & IN_DELETE_SELF)) {
+                       push @$events, bless(\$path,
+                               'PublicInbox::FakeInotify::SelfGoneEvent');
+                       push @watch_gone, $x;
+                       delete $self->{dirlist}->{$path};
+               }
+               next if !@now;
                my $old_ctime = $watch->{$x};
                $watch->{$x} = $now[10];
                next if $old_ctime == $now[10];
@@ -92,6 +101,7 @@ sub read {
                                                $self->{dirlist});
                        } elsif ($!{ENOENT}) {
                                push @watch_gone, $x;
+                               delete $self->{dirlist}->{$path};
                        } else {
                                warn "W: opendir $path: $!\n";
                        }
@@ -108,7 +118,7 @@ sub poll_once {
 }
 
 package PublicInbox::FakeInotify::Watch;
-use strict;
+use v5.12;
 
 sub cancel {
        my ($self) = @_;
@@ -121,16 +131,25 @@ sub name {
 }
 
 package PublicInbox::FakeInotify::Event;
-use strict;
+use v5.12;
 
 sub fullname { ${$_[0]} }
 
 sub IN_DELETE { 0 }
+sub IN_MOVED_FROM { 0 }
+sub IN_DELETE_SELF { 0 }
 
 package PublicInbox::FakeInotify::GoneEvent;
-use strict;
+use v5.12;
 our @ISA = qw(PublicInbox::FakeInotify::Event);
 
 sub IN_DELETE { 1 }
+sub IN_MOVED_FROM { 0 }
+
+package PublicInbox::FakeInotify::SelfGoneEvent;
+use v5.12;
+our @ISA = qw(PublicInbox::FakeInotify::GoneEvent);
+
+sub IN_DELETE_SELF { 1 }
 
 1;