summaryrefslogtreecommitdiff
path: root/lib/Linux/FANotify/LowLevel.pm
blob: 90d856844bfed4adf191f68cdd48951af72f2f1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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 => $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;