package Linux::FANotify; use 5.016; use strict; use warnings; my $ccode; BEGIN { my @constants=qw( FAN_ACCESS FAN_MODIFY FAN_CLOSE_WRITE FAN_CLOSE_NOWRITE FAN_OPEN FAN_Q_OVERFLOW FAN_OPEN_PERM FAN_ACCESS_PERM FAN_ONDIR FAN_EVENT_ON_CHILD FAN_CLOSE FAN_CLOEXEC FAN_NONBLOCK FAN_CLASS_NOTIF FAN_CLASS_CONTENT FAN_CLASS_PRE_CONTENT FAN_ALL_CLASS_BITS FAN_UNLIMITED_QUEUE FAN_UNLIMITED_MARKS FAN_ALL_INIT_FLAGS FAN_MARK_ADD FAN_MARK_REMOVE FAN_MARK_DONT_FOLLOW FAN_MARK_ONLYDIR FAN_MARK_MOUNT FAN_MARK_IGNORED_MASK FAN_MARK_IGNORED_SURV_MODIFY FAN_MARK_FLUSH FAN_ALL_MARK_FLAGS FAN_ALL_EVENTS FAN_ALL_PERM_EVENTS FAN_ALL_OUTGOING_EVENTS FANOTIFY_METADATA_VERSION FAN_ALLOW FAN_DENY FAN_NOFD ); $ccode=< #include #include EOC for my $c (@constants) { my $sub_name = lc($c =~ s{^.*?_}{}r); $ccode .= "long CONST_${sub_name}() { return $c; }\n"; } $ccode.=<mask),0); hv_store(event,"fd",2,newSViv(data->fd),0); hv_store(event,"pid",3,newSViv(data->pid),0); buffer = FAN_EVENT_NEXT(data,len); } return ret; } EOC } use Inline C => $ccode; use POSIX qw(); use Data::Printer; my $fan_fd = perl_fanotify_init(0,0); warn "fan fd: $fan_fd $!"; my $fan_fh;open($fan_fh,'<&=',$fan_fd); my $ret = perl_fanotify_mark($fan_fd, CONST_mark_add | CONST_mark_mount, CONST_open | CONST_close, 0, '/tmp'); if ($ret < 0) { die "WTF? $ret"; } my $buffer;#=perl_memalign(4096,8192); sub program_for_pid { my ($pid) = @_; my $ret = ""; open my $fh,'<',"/proc/$pid/cmdline" or return $ret; my $cmdline = do { local $/;<$fh> };chomp $cmdline; return $cmdline || $ret; } sub print_event { my ($ev) = @_; my $procname = program_for_pid($ev->{pid}); my $filename = readlink "/proc/self/fd/".$ev->{fd}; $filename ||= "{fd})>"; my $mask = $ev->{mask}; print "$procname ($mask) $filename\n"; POSIX::close($ev->{fd}); } while (1) { my $len = sysread($fan_fh,$buffer,8192,0); my $ret = unpack_events($buffer); for my $ev (@$ret) { print_event($ev); } } close $fan_fh;