#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fanotify.h>
#include <unistd.h>
#define BUF_SIZE 65536
int
main( int argc, char ** argv)
{
int fd, ret, event_fd;
ssize_t len, path_len;
char path[ PATH_MAX] ;
char procfd_path[ PATH_MAX] ;
char events_buf[ BUF_SIZE] ;
struct file_handle * file_handle;
struct fanotify_event_metadata * metadata;
struct fanotify_event_info_fid * fid;
if ( argc != 2 ) {
fprintf ( stderr
, "Invalid number of command line arguments.\n " ) ; }
/* Create an fanotify file descriptor with FAN_REPORT_FID as a flag
so that program can receive fid events. */
fd = fanotify_init( FAN_CLASS_NOTIF | FAN_REPORT_FID, 0 ) ;
if ( fd == - 1 ) {
}
/* Place a mark on the filesystem object supplied in argv[1]. */
ret = fanotify_mark( fd, FAN_MARK_ADD | FAN_MARK_FILESYSTEM,
( FAN_CREATE | FAN_DELETE | FAN_MODIFY | FAN_MOVE | FAN_ONDIR | FAN_EVENT_ON_CHILD) ,
AT_FDCWD, argv[ 1 ] ) ;
if ( ret == - 1 ) {
}
printf ( "Listening for events.\n " ) ;
/* Read events from the event queue into a buffer */
len = read( fd, ( void * ) & events_buf, sizeof ( events_buf) ) ;
if ( len == - 1 && errno != EAGAIN) {
}
/* Process all events within the buffer */
for ( metadata = ( struct fanotify_event_metadata * ) events_buf;
FAN_EVENT_OK( metadata, len) ;
metadata = FAN_EVENT_NEXT( metadata, len) ) {
fid = ( struct fanotify_event_info_fid * ) ( metadata + 1 ) ;
file_handle = ( struct file_handle * ) fid-> handle;
if ( metadata-> mask & FAN_CREATE) {
}
if ( metadata-> mask & FAN_DELETE) {
}
if ( metadata-> mask & FAN_MODIFY) {
}
if ( metadata-> mask & FAN_MOVE) {
}
if ( metadata-> mask & FAN_ONDIR) {
}
if ( metadata-> mask & FAN_EVENT_ON_CHILD) {
printf ( "\t FAN_EVENT_ON_CHILD\n " ) ; }
/* Ensure that the event info is of the correct type */
if ( fid-> hdr.info_type != FAN_EVENT_INFO_TYPE_FID) {
fprintf ( stderr
, "Received unexpected event info type.\n " ) ; // exit(EXIT_FAILURE);
}
printf ( "event len %u, FAN_EVENT_METADATA_LEN: %ld\n " , metadata
-> event_len
, FAN_EVENT_METADATA_LEN
) ; printf ( "header len %d\n " , fid
-> hdr.
len ) ; printf ( "enent metadata %p\n " , metadata
) ; printf ( "file handle %p\n " , file_handle
) ;
// if (metadata->mask == FAN_CREATE)
// printf("FAN_CREATE (file created):");
// if (metadata->mask == FAN_CREATE | FAN_ONDIR)
// printf("FAN_CREATE | FAN_ONDIR (subdirectory created):");
/* metadata->fd is set to FAN_NOFD when FAN_REPORT_FID is enabled.
To obtain a file descriptor for the file object corresponding to
an event you can use the struct file_handle that's provided
within the fanotify_event_info_fid in conjunction with the
open_by_handle_at(2) system call. A check for ESTALE is done
to accommodate for the situation where the file handle for the
object was deleted prior to this system call. */
event_fd = open_by_handle_at( AT_FDCWD, file_handle, O_RDONLY) ;
if ( event_fd == - 1 ) {
if ( errno == ESTALE) {
printf ( "File handle is no longer valid. " "File has been deleted\n " ) ;
continue ;
} else {
}
}
snprintf ( procfd_path
, sizeof ( procfd_path
) , "/proc/self/fd/%d" , event_fd) ;
/* Retrieve and print the path of the modified dentry */
path_len = readlink( procfd_path, path, sizeof ( path) - 1 ) ;
if ( path_len == - 1 ) {
}
path[ path_len] = '\0 ' ;
printf ( "\t Directory '%s' has been modified.\n " , path
) ;
/* Close associated file descriptor for this event */
close( event_fd) ;
}
printf ( "All events processed successfully. Program exiting.\n " ) ; }
I2RlZmluZSBfR05VX1NPVVJDRQojaW5jbHVkZSA8ZXJybm8uaD4KI2luY2x1ZGUgPGZjbnRsLmg+CiNpbmNsdWRlIDxsaW1pdHMuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN5cy90eXBlcy5oPgojaW5jbHVkZSA8c3lzL3N0YXQuaD4KI2luY2x1ZGUgPHN5cy9mYW5vdGlmeS5oPgojaW5jbHVkZSA8dW5pc3RkLmg+CgojZGVmaW5lIEJVRl9TSVpFIDY1NTM2CgppbnQKbWFpbihpbnQgYXJnYywgY2hhciAqKmFyZ3YpCnsKICAgaW50IGZkLCByZXQsIGV2ZW50X2ZkOwogICBzc2l6ZV90IGxlbiwgcGF0aF9sZW47CiAgIGNoYXIgcGF0aFtQQVRIX01BWF07CiAgIGNoYXIgcHJvY2ZkX3BhdGhbUEFUSF9NQVhdOwogICBjaGFyIGV2ZW50c19idWZbQlVGX1NJWkVdOwogICBzdHJ1Y3QgZmlsZV9oYW5kbGUgKmZpbGVfaGFuZGxlOwogICBzdHJ1Y3QgZmFub3RpZnlfZXZlbnRfbWV0YWRhdGEgKm1ldGFkYXRhOwogICBzdHJ1Y3QgZmFub3RpZnlfZXZlbnRfaW5mb19maWQgKmZpZDsKCiAgIGlmIChhcmdjICE9IDIpIHsKICAgICAgIGZwcmludGYoc3RkZXJyLCAiSW52YWxpZCBudW1iZXIgb2YgY29tbWFuZCBsaW5lIGFyZ3VtZW50cy5cbiIpOwogICAgICAgZXhpdChFWElUX0ZBSUxVUkUpOwogICB9CgogICAvKiBDcmVhdGUgYW4gZmFub3RpZnkgZmlsZSBkZXNjcmlwdG9yIHdpdGggRkFOX1JFUE9SVF9GSUQgYXMgYSBmbGFnCiAgICAgIHNvIHRoYXQgcHJvZ3JhbSBjYW4gcmVjZWl2ZSBmaWQgZXZlbnRzLiAqLwoKICAgZmQgPSBmYW5vdGlmeV9pbml0KEZBTl9DTEFTU19OT1RJRiB8IEZBTl9SRVBPUlRfRklELCAwKTsKICAgaWYgKGZkID09IC0xKSB7CiAgICAgICBwZXJyb3IoImZhbm90aWZ5X2luaXQiKTsKICAgICAgIGV4aXQoRVhJVF9GQUlMVVJFKTsKICAgfQoKICAgLyogUGxhY2UgYSBtYXJrIG9uIHRoZSBmaWxlc3lzdGVtIG9iamVjdCBzdXBwbGllZCBpbiBhcmd2WzFdLiAqLwoKICAgcmV0ID0gZmFub3RpZnlfbWFyayhmZCwgRkFOX01BUktfQUREIHwgRkFOX01BUktfRklMRVNZU1RFTSwKICAgICAgICAgICAgICAgICAgICAgICAoIEZBTl9DUkVBVEUgfCBGQU5fREVMRVRFIHwgRkFOX01PRElGWSB8IEZBTl9NT1ZFIHwgRkFOX09ORElSIHwgRkFOX0VWRU5UX09OX0NISUxEKSwKICAgICAgICAgICAgICAgICAgICAgICBBVF9GRENXRCwgYXJndlsxXSk7CiAgIGlmIChyZXQgPT0gLTEpIHsKICAgICAgIHBlcnJvcigiZmFub3RpZnlfbWFyayIpOwogICAgICAgZXhpdChFWElUX0ZBSUxVUkUpOwogICB9CgogICBwcmludGYoIkxpc3RlbmluZyBmb3IgZXZlbnRzLlxuIik7CgogICAvKiBSZWFkIGV2ZW50cyBmcm9tIHRoZSBldmVudCBxdWV1ZSBpbnRvIGEgYnVmZmVyICovCgogICBsZW4gPSByZWFkKGZkLCAodm9pZCAqKSAmZXZlbnRzX2J1Ziwgc2l6ZW9mKGV2ZW50c19idWYpKTsKICAgaWYgKGxlbiA9PSAtMSAmJiBlcnJubyAhPSBFQUdBSU4pIHsKICAgICAgIHBlcnJvcigicmVhZCIpOwogICAgICAgZXhpdChFWElUX0ZBSUxVUkUpOwogICB9CgogICAvKiBQcm9jZXNzIGFsbCBldmVudHMgd2l0aGluIHRoZSBidWZmZXIgKi8KCiAgIGZvciAobWV0YWRhdGEgPSAoc3RydWN0IGZhbm90aWZ5X2V2ZW50X21ldGFkYXRhICopIGV2ZW50c19idWY7CiAgICAgICAgICAgRkFOX0VWRU5UX09LKG1ldGFkYXRhLCBsZW4pOwogICAgICAgICAgIG1ldGFkYXRhID0gRkFOX0VWRU5UX05FWFQobWV0YWRhdGEsIGxlbikpIHsKICAgICAgIGZpZCA9IChzdHJ1Y3QgZmFub3RpZnlfZXZlbnRfaW5mb19maWQgKikgKG1ldGFkYXRhICsgMSk7CiAgICAgICBmaWxlX2hhbmRsZSA9IChzdHJ1Y3QgZmlsZV9oYW5kbGUgKikgZmlkLT5oYW5kbGU7CgogICAgICAgIGlmIChtZXRhZGF0YS0+bWFzayAmIEZBTl9DUkVBVEUpIHsKICAgICAgICAgICAgcHJpbnRmICgiXHRGQU5fQ1JFQVRFXG4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKG1ldGFkYXRhLT5tYXNrICYgRkFOX0RFTEVURSkgewogICAgICAgICAgICBwcmludGYgKCJcdEZBTl9ERUxFVEVcbiIpOwogICAgICAgIH0KICAgICAgICBpZiAobWV0YWRhdGEtPm1hc2sgJiBGQU5fTU9ESUZZKSB7CiAgICAgICAgICAgIHByaW50ZiAoIlx0RkFOX01PRElGWVxuIik7CiAgICAgICAgfQogICAgICAgIGlmIChtZXRhZGF0YS0+bWFzayAmIEZBTl9NT1ZFKSB7CiAgICAgICAgICAgIHByaW50ZiAoIlx0RkFOX01PVkVcbiIpOwogICAgICAgIH0KICAgICAgICBpZiAobWV0YWRhdGEtPm1hc2sgJiBGQU5fT05ESVIpIHsKICAgICAgICAgICAgcHJpbnRmICgiXHRGQU5fT05ESVJcbiIpOwogICAgICAgIH0KICAgICAgICBpZiAobWV0YWRhdGEtPm1hc2sgJiBGQU5fRVZFTlRfT05fQ0hJTEQpIHsKICAgICAgICAgICAgcHJpbnRmICgiXHRGQU5fRVZFTlRfT05fQ0hJTERcbiIpOwogICAgICAgIH0KICAgICAgICAgICAgCgogICAgICAgLyogRW5zdXJlIHRoYXQgdGhlIGV2ZW50IGluZm8gaXMgb2YgdGhlIGNvcnJlY3QgdHlwZSAqLwoKICAgICAgIGlmIChmaWQtPmhkci5pbmZvX3R5cGUgIT0gRkFOX0VWRU5UX0lORk9fVFlQRV9GSUQpIHsKICAgICAgICAgICBmcHJpbnRmKHN0ZGVyciwgIlJlY2VpdmVkIHVuZXhwZWN0ZWQgZXZlbnQgaW5mbyB0eXBlLlxuIik7CiAgICAgICAgLy8gICAgZXhpdChFWElUX0ZBSUxVUkUpOwogICAgICAgfQogICAgICAgIHByaW50ZigiZXZlbnQgbGVuICV1LCBGQU5fRVZFTlRfTUVUQURBVEFfTEVOOiAlbGRcbiIsIG1ldGFkYXRhLT5ldmVudF9sZW4sIEZBTl9FVkVOVF9NRVRBREFUQV9MRU4pOwogICAgICAgIHByaW50ZigiaGVhZGVyIGxlbiAlZFxuIiwgZmlkLT5oZHIubGVuKTsKICAgICAgICBwcmludGYoImVuZW50IG1ldGFkYXRhICVwXG4iLCBtZXRhZGF0YSk7CiAgICAgICAgcHJpbnRmKCJmaWQgJXBcbiIsIGZpZCk7CiAgICAgICAgcHJpbnRmKCJmaWxlIGhhbmRsZSAlcFxuIiwgZmlsZV9oYW5kbGUpOwoKICAgIC8vICAgIGlmIChtZXRhZGF0YS0+bWFzayA9PSBGQU5fQ1JFQVRFKQogICAgLy8gICAgICAgIHByaW50ZigiRkFOX0NSRUFURSAoZmlsZSBjcmVhdGVkKToiKTsKCiAgICAvLyAgICBpZiAobWV0YWRhdGEtPm1hc2sgPT0gRkFOX0NSRUFURSB8IEZBTl9PTkRJUikKICAgIC8vICAgICAgICBwcmludGYoIkZBTl9DUkVBVEUgfCBGQU5fT05ESVIgKHN1YmRpcmVjdG9yeSBjcmVhdGVkKToiKTsKCiAgICAgICAvKiBtZXRhZGF0YS0+ZmQgaXMgc2V0IHRvIEZBTl9OT0ZEIHdoZW4gRkFOX1JFUE9SVF9GSUQgaXMgZW5hYmxlZC4KICAgICAgICAgIFRvIG9idGFpbiBhIGZpbGUgZGVzY3JpcHRvciBmb3IgdGhlIGZpbGUgb2JqZWN0IGNvcnJlc3BvbmRpbmcgdG8KICAgICAgICAgIGFuIGV2ZW50IHlvdSBjYW4gdXNlIHRoZSBzdHJ1Y3QgZmlsZV9oYW5kbGUgdGhhdCdzIHByb3ZpZGVkCiAgICAgICAgICB3aXRoaW4gdGhlIGZhbm90aWZ5X2V2ZW50X2luZm9fZmlkIGluIGNvbmp1bmN0aW9uIHdpdGggdGhlCiAgICAgICAgICBvcGVuX2J5X2hhbmRsZV9hdCgyKSBzeXN0ZW0gY2FsbC4gQSBjaGVjayBmb3IgRVNUQUxFIGlzIGRvbmUKICAgICAgICAgIHRvIGFjY29tbW9kYXRlIGZvciB0aGUgc2l0dWF0aW9uIHdoZXJlIHRoZSBmaWxlIGhhbmRsZSBmb3IgdGhlCiAgICAgICAgICBvYmplY3Qgd2FzIGRlbGV0ZWQgcHJpb3IgdG8gdGhpcyBzeXN0ZW0gY2FsbC4gKi8KCiAgICAgICBldmVudF9mZCA9IG9wZW5fYnlfaGFuZGxlX2F0KEFUX0ZEQ1dELCBmaWxlX2hhbmRsZSwgT19SRE9OTFkpOwogICAgICAgaWYgKGV2ZW50X2ZkID09IC0xKSB7CiAgICAgICAgICAgaWYgKGVycm5vID09IEVTVEFMRSkgewogICAgICAgICAgICAgICBwcmludGYoIkZpbGUgaGFuZGxlIGlzIG5vIGxvbmdlciB2YWxpZC4gIgogICAgICAgICAgICAgICAgICAgICAgICJGaWxlIGhhcyBiZWVuIGRlbGV0ZWRcbiIpOwogICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICBwZXJyb3IoIm9wZW5fYnlfaGFuZGxlX2F0Iik7CiAgICAgICAgICAgICAgIGV4aXQoRVhJVF9GQUlMVVJFKTsKICAgICAgICB9CiAgICAgICB9CgogICAgICAgc25wcmludGYocHJvY2ZkX3BhdGgsIHNpemVvZihwcm9jZmRfcGF0aCksICIvcHJvYy9zZWxmL2ZkLyVkIiwKICAgICAgICAgICAgICAgZXZlbnRfZmQpOwoKICAgICAgIC8qIFJldHJpZXZlIGFuZCBwcmludCB0aGUgcGF0aCBvZiB0aGUgbW9kaWZpZWQgZGVudHJ5ICovCgogICAgICAgcGF0aF9sZW4gPSByZWFkbGluayhwcm9jZmRfcGF0aCwgcGF0aCwgc2l6ZW9mKHBhdGgpIC0gMSk7CiAgICAgICBpZiAocGF0aF9sZW4gPT0gLTEpIHsKICAgICAgICAgICBwZXJyb3IoInJlYWRsaW5rIik7CiAgICAgICAgICAgZXhpdChFWElUX0ZBSUxVUkUpOwogICAgICAgfQoKICAgICAgIHBhdGhbcGF0aF9sZW5dID0gJ1wwJzsKICAgICAgIHByaW50ZigiXHREaXJlY3RvcnkgJyVzJyBoYXMgYmVlbiBtb2RpZmllZC5cbiIsIHBhdGgpOwoKICAgICAgIC8qIENsb3NlIGFzc29jaWF0ZWQgZmlsZSBkZXNjcmlwdG9yIGZvciB0aGlzIGV2ZW50ICovCgogICAgICAgY2xvc2UoZXZlbnRfZmQpOwogICB9CgogICBwcmludGYoIkFsbCBldmVudHMgcHJvY2Vzc2VkIHN1Y2Nlc3NmdWxseS4gUHJvZ3JhbSBleGl0aW5nLlxuIik7CiAgIGV4aXQoRVhJVF9TVUNDRVNTKTsKfQ==
compilation info
prog.c: In function ‘main’:
prog.c:34:41: error: ‘FAN_REPORT_FID’ undeclared (first use in this function); did you mean ‘FAN_REPORT_TID’?
fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, 0);
^~~~~~~~~~~~~~
FAN_REPORT_TID
prog.c:34:41: note: each undeclared identifier is reported only once for each function it appears in
prog.c:43:26: error: ‘FAN_CREATE’ undeclared (first use in this function); did you mean ‘DN_CREATE’?
( FAN_CREATE | FAN_DELETE | FAN_MODIFY | FAN_MOVE | FAN_ONDIR | FAN_EVENT_ON_CHILD),
^~~~~~~~~~
DN_CREATE
prog.c:43:39: error: ‘FAN_DELETE’ undeclared (first use in this function); did you mean ‘DN_DELETE’?
( FAN_CREATE | FAN_DELETE | FAN_MODIFY | FAN_MOVE | FAN_ONDIR | FAN_EVENT_ON_CHILD),
^~~~~~~~~~
DN_DELETE
prog.c:43:65: error: ‘FAN_MOVE’ undeclared (first use in this function); did you mean ‘FAN_NOFD’?
( FAN_CREATE | FAN_DELETE | FAN_MODIFY | FAN_MOVE | FAN_ONDIR | FAN_EVENT_ON_CHILD),
^~~~~~~~
FAN_NOFD
prog.c:66:48: error: dereferencing pointer to incomplete type ‘struct fanotify_event_info_fid’
file_handle = (struct file_handle *) fid->handle;
^~
prog.c:90:34: error: ‘FAN_EVENT_INFO_TYPE_FID’ undeclared (first use in this function); did you mean ‘FAN_EVENT_ON_CHILD’?
if (fid->hdr.info_type != FAN_EVENT_INFO_TYPE_FID) {
^~~~~~~~~~~~~~~~~~~~~~~
FAN_EVENT_ON_CHILD
stdout