summaryrefslogtreecommitdiff
path: root/lib/Linux/FANotify/LowLevel.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Linux/FANotify/LowLevel.pm')
-rw-r--r--lib/Linux/FANotify/LowLevel.pm111
1 files changed, 111 insertions, 0 deletions
diff --git a/lib/Linux/FANotify/LowLevel.pm b/lib/Linux/FANotify/LowLevel.pm
new file mode 100644
index 0000000..90d8568
--- /dev/null
+++ b/lib/Linux/FANotify/LowLevel.pm
@@ -0,0 +1,111 @@
+package Linux::FANotify::LowLevel;
+use 5.014;
+use strict;
+use warnings;
+my $ccode;my @exports;
+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=<<EOC;
+#include <sys/fanotify.h>
+#include <stdlib.h>
+#include <string.h>
+EOC
+for my $c (@constants) {
+ my $sub_name = lc($c =~ s{^.*?_}{}r);
+ $ccode .= "long CONST_${sub_name}() { return $c; }\n";
+ push @exports,"CONST_${sub_name}";
+}
+$ccode.=<<EOC;
+int perl_fanotify_init(unsigned int flags, unsigned int event_f_flags) {
+ return fanotify_init(flags,event_f_flags);
+}
+
+int perl_fanotify_mark(int fanotify_fd, unsigned int flags,
+ unsigned long mask, int dfd, const char *pathname) {
+ return fanotify_mark(fanotify_fd, flags, mask, dfd, pathname);
+}
+
+SV* perl_memalign(size_t alignment, size_t size) {
+ void* buffer=NULL;
+ int err;
+ err = posix_memalign(&buffer, alignment, size);
+ if (err != 0 || buffer == NULL) {
+ SV* bang = get_sv("!", 0);
+ sv_setiv(bang, (IV)err);
+ sv_setpvf(bang, "%s", strerror(err)); /* let Perl copy the string */
+ SvIOK_on(bang);
+ return &PL_sv_undef;
+ }
+ return sv_2mortal(newSVpvn(buffer,size));
+}
+AV* unpack_events(SV* svbuffer) {
+ STRLEN len;
+ void * buffer = SvPV(svbuffer,len);
+ AV* ret = newAV();
+ HV* event;
+ struct fanotify_event_metadata *data;
+ data = (struct fanotify_event_metadata *) buffer;
+
+ while(FAN_EVENT_OK(data,len)) {
+ event = newHV();
+ av_push(ret,newRV_noinc((SV*)event));
+ hv_store(event,"mask",4,newSViv(data->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 Sub::Exporter -setup => {
+ exports => [
+ @exports,
+ qw(perl_fanotify_init perl_fanotify_mark perl_memalign unpack_events)
+ ],
+ groups => {
+ constants => \@exports,
+ functions => [qw(perl_fanotify_init perl_fanotify_mark unpack_events)],
+ },
+};
+
+1;