-*.c
+/*.c
*.c.valatmp
*.o
c/*.o
--- /dev/null
+/*
+ * A simple tester of fanotify in the Linux kernel.
+ *
+ * This program is released in the Public Domain.
+ *
+ * Compile with:
+ * $> gcc -o /tmp/fanotify-example fanotify-example.c
+ *
+ * Run as:
+ * $> /tmp/fanotify-example
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/fanotify.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+ int main(int argc, char *argv[]){
+ int fan;
+ char buf[4096];
+ char fdpath[32];
+ char path[PATH_MAX + 1];
+ ssize_t buflen, linklen;
+ struct fanotify_event_metadata *metadata;
+
+ // Init fanotify structure
+// fan = fanotify_init(FAN_REPORT_FID, O_RDWR);
+ // FAN_CLASS_CONTENT << only for root.
+ fan = fanotify_init(FAN_CLOEXEC | FAN_CLASS_NOTIF | FAN_REPORT_FID ,
+ O_RDONLY | O_LARGEFILE);
+
+ if(fan == -1){
+ perror("fanotify_init");
+ // exit(EXIT_FAILURE);
+ }
+
+ int ret = fanotify_mark(fan, FAN_MARK_ADD , FAN_CREATE | FAN_DELETE | FAN_MODIFY | FAN_EVENT_ON_CHILD,
+ AT_FDCWD, "/home/alan/gitlive/gitlive/fanotify"
+ );
+
+
+ if(ret == -1){
+ perror("fanotify_mark");
+ exit(EXIT_FAILURE);
+ }
+
+ while(1){
+ buflen = read(fan, buf, sizeof(buf));
+ metadata = (struct fanotify_event_metadata*)&buf;
+ printf("got something\n");
+ while(FAN_EVENT_OK(metadata, buflen)){
+ if (metadata->mask & FAN_Q_OVERFLOW){
+ printf("Queue overflow!\n");
+ continue;
+ }
+ printf("look at /proc/self/fd/%d\n", metadata->fd);
+ // Resolve path, using automatically opened fd
+ sprintf(fdpath, "/proc/self/fd/%d", metadata->fd);
+ linklen = readlink(fdpath, path, sizeof(path) - 1);
+ path[linklen] = '\0';
+ printf("%s\n", path);
+
+ close(metadata->fd);
+ metadata = FAN_EVENT_NEXT(metadata, buflen);
+ }
+ }
+}
+
+
+
--- /dev/null
+#define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/* Read all available fanotify events from the file descriptor 'fd'. */
+
+#define BUF_SIZE 1024
+
+void fanotify_read(int fd)
+{
+ int ret, event_fd, mount_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;
+ const char *file_name;
+ struct stat sb;
+
+ mount_fd = open("/", O_DIRECTORY | O_RDONLY);
+ if (mount_fd == -1) {
+ perror("cant open mount");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Listening for events.\n");
+
+ /* Read events from the event queue into a buffer. */
+
+ len = read(fd, events_buf, sizeof(events_buf));
+ if (len == -1 && errno != EAGAIN) {
+ perror("read");
+ exit(EXIT_FAILURE);
+ }
+
+ /* 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;
+
+ // Ensure that the event info is of the correct type.
+
+ if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_FID ||
+ fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID) {
+ printf("Got FID or DFID.\n");
+ file_name = NULL;
+ } else if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID_NAME) {
+ file_name = file_handle->f_handle +
+ file_handle->handle_bytes;
+ printf("Got DFID_NAME %s.\n",file_name);
+ } else {
+ fprintf(stderr, "Received unexpected event info type.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (metadata->mask == FAN_CREATE)
+ printf("FAN_CREATE (file created):\n");
+
+ if (metadata->mask == (FAN_CREATE | FAN_ONDIR))
+ printf("FAN_CREATE | FAN_ONDIR (subdirectory created):\n");
+
+
+
+ // what is fsid??
+ /* - from
+ *
+ https://github.com/GNOME/tracker-miners/blob/38596491ead21b1ee6db99f2623ac6f127b6da34/src/miners/fs/tracker-monitor-fanotify.c#L356
+
+ seems to create a hashtable for all monitored files?
+
+ *handle = (HandleData *) &fid->fsid;
+ fid_bytes = create_bytes_for_handle (handle);
+ data = g_hash_table_lookup (monitor->handles, fid_bytes);
+ g_bytes_unref (fid_bytes);
+ *
+
+ /* metadata->fd is set to FAN_NOFD when the group identifies
+ objects by file handles. 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(mount_fd, 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 {
+ perror("open_by_handle_at");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ 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) {
+ perror("readlink");
+ exit(EXIT_FAILURE);
+ }
+
+ path[path_len] = '\0';
+ printf("\tDirectory '%s' has been modified.\n", path);
+
+ if (file_name) {
+ ret = fstatat(event_fd, file_name, &sb, 0);
+ if (ret == -1) {
+ if (errno != ENOENT) {
+ perror("fstatat");
+ exit(EXIT_FAILURE);
+ }
+ printf("\tEntry '%s' does not exist.\n", file_name);
+ } else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
+ printf("\tEntry '%s' is a subdirectory.\n", file_name);
+ } else {
+ printf("\tEntry '%s' is not a subdirectory.\n",
+ file_name);
+ }
+ }
+
+ /* Close associated file descriptor for this event. */
+
+ close(event_fd);
+ }
+
+ printf("All events processed successfully. Program exiting.\n");
+ exit(EXIT_SUCCESS);
+}
\ No newline at end of file
--- /dev/null
+/*
+ * A simple tester of fanotify in the Linux kernel.
+ *
+ * This program is released in the Public Domain.
+ *
+ * Compile with:
+ * $> gcc -o /tmp/fanotify-man fanotify-man.c
+ *
+ * Run as:
+ * $> /tmp/fanotify-example
+ */
+ #define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <limits.h>
+ #include <poll.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <sys/fanotify.h>
+ #include <unistd.h>
+
+ /* Read all available fanotify events from the file descriptor 'fd'. */
+
+ static void
+ handle_events(int fd)
+ {
+ const struct fanotify_event_metadata *metadata;
+ struct fanotify_event_metadata buf[200];
+ ssize_t len;
+ char path[PATH_MAX];
+ ssize_t path_len;
+ char procfd_path[PATH_MAX];
+ struct fanotify_response response;
+
+ /* Loop while events can be read from fanotify file descriptor. */
+
+ for (;;) {
+
+ /* Read some events. */
+
+ len = read(fd, buf, sizeof(buf));
+ if (len == -1 && errno != EAGAIN) {
+ perror("read");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Check if end of available data reached. */
+
+ if (len <= 0)
+ break;
+
+ /* Point to the first event in the buffer. */
+
+ metadata = buf;
+
+ /* Loop over all events in the buffer. */
+
+ while (FAN_EVENT_OK(metadata, len)) {
+
+ /* Check that run-time and compile-time structures match. */
+
+ if (metadata->vers != FANOTIFY_METADATA_VERSION) {
+ fprintf(stderr,
+ "Mismatch of fanotify metadata version.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* metadata->fd contains either FAN_NOFD, indicating a
+ queue overflow, or a file descriptor (a nonnegative
+ integer). Here, we simply ignore queue overflow. */
+
+ if (metadata->fd >= 0) {
+
+ /* Handle open permission event. */
+
+ if (metadata->mask & FAN_OPEN_PERM) {
+ printf("FAN_OPEN_PERM: ");
+
+ /* Allow file to be opened. */
+
+ response.fd = metadata->fd;
+ response.response = FAN_ALLOW;
+ write(fd, &response, sizeof(response));
+ }
+
+ /* Handle closing of writable file event. */
+
+ if (metadata->mask & FAN_CLOSE_WRITE)
+ printf("FAN_CLOSE_WRITE: ");
+
+ /* Retrieve and print pathname of the accessed file. */
+
+ snprintf(procfd_path, sizeof(procfd_path),
+ "/proc/self/fd/%d", metadata->fd);
+ path_len = readlink(procfd_path, path,
+ sizeof(path) - 1);
+ if (path_len == -1) {
+ perror("readlink");
+ exit(EXIT_FAILURE);
+ }
+
+ path[path_len] = '\0';
+ printf("File %s\n", path);
+
+ /* Close the file descriptor of the event. */
+
+ close(metadata->fd);
+ }
+
+ /* Advance to next event. */
+
+ metadata = FAN_EVENT_NEXT(metadata, len);
+ }
+ }
+ }
+
+ int
+ main(int argc, char *argv[])
+ {
+ char buf;
+ int fd, poll_num;
+ nfds_t nfds;
+ struct pollfd fds[2];
+
+ /* Check mount point is supplied. */
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s MOUNT\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Press enter key to terminate.\n");
+
+ /* Create the file descriptor for accessing the fanotify API. */
+
+ fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+ O_RDONLY | O_LARGEFILE);
+ if (fd == -1) {
+ perror("fanotify_init");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Mark the mount for:
+ - permission events before opening files
+ - notification events after closing a write-enabled
+ file descriptor. */
+
+ if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+ FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
+ argv[1]) == -1) {
+ perror("fanotify_mark");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Prepare for polling. */
+
+ nfds = 2;
+
+ fds[0].fd = STDIN_FILENO; /* Console input */
+ fds[0].events = POLLIN;
+
+ fds[1].fd = fd; /* Fanotify input */
+ fds[1].events = POLLIN;
+
+ /* This is the loop to wait for incoming events. */
+
+ printf("Listening for events.\n");
+
+ while (1) {
+ poll_num = poll(fds, nfds, -1);
+ if (poll_num == -1) {
+ if (errno == EINTR) /* Interrupted by a signal */
+ continue; /* Restart poll() */
+
+ perror("poll"); /* Unexpected error */
+ exit(EXIT_FAILURE);
+ }
+
+ if (poll_num > 0) {
+ if (fds[0].revents & POLLIN) {
+
+ /* Console input is available: empty stdin and quit. */
+
+ while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
+ continue;
+ break;
+ }
+
+ if (fds[1].revents & POLLIN) {
+
+ /* Fanotify events are available. */
+
+ handle_events(fd);
+ }
+ }
+ }
+
+ printf("Listening for events stopped.\n");
+ exit(EXIT_SUCCESS);
+ }