RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 23-May-2017 07:54:19 Branch: rpm-5_4 Handle: 2017052305541900 Modified files: (Branch: rpm-5_4) rpm/rpmio Makefile.am fanotify.c Log: - WIP. Summary: Revision Changes Path 1.293.2.81 +4 -1 rpm/rpmio/Makefile.am 1.1.2.4 +205 -265 rpm/rpmio/fanotify.c ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmio/Makefile.am ============================================================================ $ cvs diff -u -r1.293.2.80 -r1.293.2.81 Makefile.am --- rpm/rpmio/Makefile.am 20 May 2017 13:40:40 -0000 1.293.2.80 +++ rpm/rpmio/Makefile.am 23 May 2017 05:54:19 -0000 1.293.2.81 @@ -23,7 +23,7 @@ EXTRA_PROGRAMS += bdes duk thtml tinv tkey tmacro tmq tpw turg noinst_PROGRAMS = tjsmn tmqtt -EXTRA_PROGRAMS += bsdiff bspatch pcrsed rpmborg rpmcurl \ +EXTRA_PROGRAMS += bsdiff bspatch fanotify pcrsed rpmborg rpmcurl \ rpmgenbasedir rpmgenpkglist rpmgensrclist rpmgpg \ rpmpbzip2 rpmpigz \ tasn tbf tcap tder tdir tfts tget tglob thkp tmagic \ @@ -492,6 +492,9 @@ bspatch_SOURCES = bspatch.c bspatch_LDADD = $(RPMIO_LDADD_COMMON) +fanotify_SOURCES = fanotify.c +fanotify_LDADD = $(RPMIO_LDADD_COMMON) + pcrsed_SOURCES = pcrsed.c pcrsed_LDADD = $(RPMIO_LDADD_COMMON) @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/fanotify.c ============================================================================ $ cvs diff -u -r1.1.2.3 -r1.1.2.4 fanotify.c --- rpm/rpmio/fanotify.c 23 May 2017 04:55:11 -0000 1.1.2.3 +++ rpm/rpmio/fanotify.c 23 May 2017 05:54:19 -0000 1.1.2.4 @@ -15,337 +15,277 @@ */ /* Define _GNU_SOURCE, Otherwise we don't get O_LARGEFILE */ +#if !defined(_GNU_SOURCE) #define _GNU_SOURCE +#endif + +#include "system.h" -#include <stdio.h> -#include <signal.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> -#include <poll.h> -#include <errno.h> -#include <limits.h> -#include <sys/stat.h> #include <sys/signalfd.h> -#include <fcntl.h> +#include <sys/fanotify.h> -#include <linux/fanotify.h> +#include "debug.h" /* Structure to keep track of monitored directories */ typedef struct { - /* Path of the directory */ - char *path; + /* Path of the directory */ + char *path; } monitored_t; -/* Size of buffer to use when reading fanotify events */ -#define FANOTIFY_BUFFER_SIZE 8192 - /* Enumerate list of FDs to poll */ enum { - FD_POLL_SIGNAL = 0, - FD_POLL_FANOTIFY, - FD_POLL_MAX + FD_POLL_SIGNAL = 0, + FD_POLL_FANOTIFY, + FD_POLL_MAX }; /* Setup fanotify notifications (FAN) mask. All these defined in fanotify.h. */ -static uint64_t event_mask = - (FAN_ACCESS | /* File accessed */ - FAN_MODIFY | /* File modified */ - FAN_CLOSE_WRITE | /* Writtable file closed */ - FAN_CLOSE_NOWRITE | /* Unwrittable file closed */ - FAN_OPEN | /* File was opened */ - FAN_ONDIR | /* We want to be reported of events in the directory */ - FAN_EVENT_ON_CHILD); /* We want to be reported of events in files of the directory */ +static uint64_t event_mask = ( + FAN_ACCESS | /* File accessed */ + FAN_MODIFY | /* File modified */ + FAN_CLOSE_WRITE | /* Writtable file closed */ + FAN_CLOSE_NOWRITE | /* Unwrittable file closed */ + FAN_OPEN | /* File was opened */ + FAN_ONDIR | /* We want events in the directory */ + FAN_EVENT_ON_CHILD | /* We want events in files of the directory */ + 0); /* Array of directories being monitored */ static monitored_t *monitors; static int n_monitors; -static char * -get_program_name_from_pid (int pid, - char *buffer, - size_t buffer_size) +static char *get_program_name_from_pid(int pid, char *b, size_t nb) { - int fd; - ssize_t len; - char *aux; - - /* Try to get program name by PID */ - sprintf (buffer, "/proc/%d/cmdline", pid); - if ((fd = open (buffer, O_RDONLY)) < 0) - return NULL; - - /* Read file contents into buffer */ - if ((len = read (fd, buffer, buffer_size - 1)) <= 0) - { - close (fd); - return NULL; - } - close (fd); + int fdno; + ssize_t len; + char *aux; + + /* Try to get program name by PID */ + snprintf(b, nb, "/proc/%d/cmdline", pid); + fdno = open(b, O_RDONLY); + if (fdno < 0) + return NULL; + + /* Read file contents into buffer */ + len = read(fdno, b, nb - 1); + close(fdno); + if (len <= 0) + return NULL; + + b[len] = '\0'; + aux = strstr(b, "^@"); + if (aux) + *aux = '\0'; - buffer[len] = '\0'; - aux = strstr (buffer, "^@"); - if (aux) - *aux = '\0'; - - return buffer; + return b; } -static char * -get_file_path_from_fd (int fd, - char *buffer, - size_t buffer_size) +static char *get_file_path_from_fd(int fdno, char *b, size_t nb) { - ssize_t len; + ssize_t len; - if (fd <= 0) - return NULL; + if (fdno <= 0) + return NULL; - sprintf (buffer, "/proc/self/fd/%d", fd); - if ((len = readlink (buffer, buffer, buffer_size - 1)) < 0) - return NULL; + snprintf(b, nb, "/proc/self/fd/%d", fdno); + if ((len = readlink(b, b, nb - 1)) < 0) + return NULL; - buffer[len] = '\0'; - return buffer; + b[len] = '\0'; + return b; } -static void -event_process (struct fanotify_event_metadata *event) +static void event_process(struct fanotify_event_metadata *event) { - char path[PATH_MAX]; + char b[PATH_MAX]; + size_t nb = sizeof(b); - printf ("Received event in path '%s'", - get_file_path_from_fd (event->fd, - path, - PATH_MAX) ? - path : "unknown"); - printf (" pid=%d (%s): \n", - event->pid, - (get_program_name_from_pid (event->pid, - path, - PATH_MAX) ? - path : "unknown")); - - if (event->mask & FAN_OPEN) - printf ("\tFAN_OPEN\n"); - if (event->mask & FAN_ACCESS) - printf ("\tFAN_ACCESS\n"); - if (event->mask & FAN_MODIFY) - printf ("\tFAN_MODIFY\n"); - if (event->mask & FAN_CLOSE_WRITE) - printf ("\tFAN_CLOSE_WRITE\n"); - if (event->mask & FAN_CLOSE_NOWRITE) - printf ("\tFAN_CLOSE_NOWRITE\n"); - fflush (stdout); + printf("Received event in path '%s'", + get_file_path_from_fd(event->fd, b, nb) ? b : "unknown"); + printf(" pid=%d (%s): \n", event->pid, + (get_program_name_from_pid(event->pid, b, nb) ? b : "unknown")); + + if (event->mask & FAN_OPEN) + printf("\tFAN_OPEN\n"); + if (event->mask & FAN_ACCESS) + printf("\tFAN_ACCESS\n"); + if (event->mask & FAN_MODIFY) + printf("\tFAN_MODIFY\n"); + if (event->mask & FAN_CLOSE_WRITE) + printf("\tFAN_CLOSE_WRITE\n"); + if (event->mask & FAN_CLOSE_NOWRITE) + printf("\tFAN_CLOSE_NOWRITE\n"); + fflush(stdout); - close (event->fd); + close(event->fd); } -static void -shutdown_fanotify (int fanotify_fd) +static void shutdown_fanotify(int fdno) { - int i; + int i; - for (i = 0; i < n_monitors; ++i) - { - /* Remove the mark, using same event mask as when creating it */ - fanotify_mark (fanotify_fd, - FAN_MARK_REMOVE, - event_mask, - AT_FDCWD, - monitors[i].path); - free (monitors[i].path); + for (i = 0; i < n_monitors; ++i) { + char * path = monitors[i].path; + monitors[i].path = NULL; + /* Remove the mark, using same event mask as when creating it */ + fanotify_mark(fdno, FAN_MARK_REMOVE, event_mask, AT_FDCWD, path); + free(path); } - free (monitors); - close (fanotify_fd); + free(monitors); + close(fdno); } -static int -initialize_fanotify (int argc, - const char **argv) +static int initialize_fanotify(int argc, const char **argv) { - int i; - int fanotify_fd; + int fdno; + int rc; - /* Create new fanotify device */ - if ((fanotify_fd = fanotify_init (FAN_CLOEXEC, - O_RDONLY | O_CLOEXEC | O_LARGEFILE)) < 0) - { - fprintf (stderr, - "Couldn't setup new fanotify device: %s\n", - strerror (errno)); - return -1; + /* Create new fanotify device */ + fdno = fanotify_init(FAN_CLOEXEC, O_RDONLY | O_CLOEXEC | O_LARGEFILE); + if (fdno < 0) { + fprintf(stderr, "Couldn't setup new fanotify device: %s\n", + strerror(errno)); + goto exit; } - /* Allocate array of monitor setups */ - n_monitors = argc - 1; - monitors = malloc (n_monitors * sizeof (monitored_t)); - - /* Loop all input directories, setting up marks */ - for (i = 0; i < n_monitors; ++i) - { - monitors[i].path = strdup (argv[i + 1]); - /* Add new fanotify mark */ - if (fanotify_mark (fanotify_fd, - FAN_MARK_ADD, - event_mask, - AT_FDCWD, - monitors[i].path) < 0) - { - fprintf (stderr, - "Couldn't add monitor in directory '%s': '%s'\n", - monitors[i].path, - strerror (errno)); - return -1; - } + /* Allocate array of monitor setups */ + n_monitors = argc - 1; + monitors = malloc(n_monitors * sizeof(monitored_t)); + + /* Loop all input directories, setting up marks */ + for (int i = 0; i < n_monitors; ++i) { + char * path = strdup(argv[i+1]); + monitors[i].path = path; + /* Add new fanotify mark */ + rc = fanotify_mark(fdno, FAN_MARK_ADD, event_mask, AT_FDCWD, path); + if (rc < 0) { + fprintf(stderr, "Couldn't add monitor in directory '%s': '%s'\n", + path, strerror(errno)); + close(fdno); + fdno = -1; + goto exit; + } - printf ("Started monitoring directory '%s'...\n", - monitors[i].path); + printf("Started monitoring directory '%s'...\n", path); } - return fanotify_fd; +exit: + return fdno; } -static void -shutdown_signals (int signal_fd) +static void shutdown_signals(int signal_fd) { - close (signal_fd); + close(signal_fd); } -static int -initialize_signals (void) +static int initialize_signals(void) { - int signal_fd; - sigset_t sigmask; + int signal_fd; + sigset_t sigmask; - /* We want to handle SIGINT and SIGTERM in the signal_fd, so we block them. */ - sigemptyset (&sigmask); - sigaddset (&sigmask, SIGINT); - sigaddset (&sigmask, SIGTERM); - - if (sigprocmask (SIG_BLOCK, &sigmask, NULL) < 0) - { - fprintf (stderr, - "Couldn't block signals: '%s'\n", - strerror (errno)); - return -1; + /* Handle SIGINT and SIGTERM in the signal_fd, so we block them. */ + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGINT); + sigaddset(&sigmask, SIGTERM); + + if (sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0) { + fprintf(stderr, "Couldn't block signals: '%s'\n", strerror(errno)); + return -1; } - /* Get new FD to read signals from it */ - if ((signal_fd = signalfd (-1, &sigmask, 0)) < 0) - { - fprintf (stderr, - "Couldn't setup signal FD: '%s'\n", - strerror (errno)); - return -1; + /* Get new FD to read signals from */ + if ((signal_fd = signalfd(-1, &sigmask, 0)) < 0) { + fprintf(stderr, "Couldn't setup signal FD: '%s'\n", strerror(errno)); + return -1; } - return signal_fd; + return signal_fd; } -int -main (int argc, - const char **argv) +int main(int argc, const char **argv) { - int signal_fd; - int fanotify_fd; - struct pollfd fds[FD_POLL_MAX]; - - /* Input arguments... */ - if (argc < 2) - { - fprintf (stderr, "Usage: %s directory1 [directory2 ...]\n", argv[0]); - exit (EXIT_FAILURE); + int signal_fd = -1; + int fanotify_fd = -1; + struct pollfd fds[FD_POLL_MAX]; + int ec = EXIT_FAILURE; /* assume failure */ + + /* Input arguments... */ + if (argc < 2) { + fprintf(stderr, "Usage: %s directory1 [directory2 ...]\n", argv[0]); + goto exit; } - /* Initialize signals FD */ - if ((signal_fd = initialize_signals ()) < 0) - { - fprintf (stderr, "Couldn't initialize signals\n"); - exit (EXIT_FAILURE); + /* Initialize signals FD */ + if ((signal_fd = initialize_signals()) < 0) { + fprintf(stderr, "Couldn't initialize signals\n"); + goto exit; } - /* Initialize fanotify FD and the marks */ - if ((fanotify_fd = initialize_fanotify (argc, argv)) < 0) - { - fprintf (stderr, "Couldn't initialize fanotify\n"); - exit (EXIT_FAILURE); + /* Initialize fanotify FD and the marks */ + if ((fanotify_fd = initialize_fanotify(argc, argv)) < 0) { + fprintf(stderr, "Couldn't initialize fanotify\n"); + goto exit; } - /* Setup polling */ - fds[FD_POLL_SIGNAL].fd = signal_fd; - fds[FD_POLL_SIGNAL].events = POLLIN; - fds[FD_POLL_FANOTIFY].fd = fanotify_fd; - fds[FD_POLL_FANOTIFY].events = POLLIN; - - /* Now loop */ - for (;;) - { - /* Block until there is something to be read */ - if (poll (fds, FD_POLL_MAX, -1) < 0) - { - fprintf (stderr, - "Couldn't poll(): '%s'\n", - strerror (errno)); - exit (EXIT_FAILURE); - } - - /* Signal received? */ - if (fds[FD_POLL_SIGNAL].revents & POLLIN) - { - struct signalfd_siginfo fdsi; - - if (read (fds[FD_POLL_SIGNAL].fd, - &fdsi, - sizeof (fdsi)) != sizeof (fdsi)) - { - fprintf (stderr, - "Couldn't read signal, wrong size read\n"); - exit (EXIT_FAILURE); - } - - /* Break loop if we got the expected signal */ - if (fdsi.ssi_signo == SIGINT || - fdsi.ssi_signo == SIGTERM) - { - break; - } - - fprintf (stderr, - "Received unexpected signal\n"); - } - - /* fanotify event received? */ - if (fds[FD_POLL_FANOTIFY].revents & POLLIN) - { - char buffer[FANOTIFY_BUFFER_SIZE]; - ssize_t length; - - /* Read from the FD. It will read all events available up to - * the given buffer size. */ - if ((length = read (fds[FD_POLL_FANOTIFY].fd, - buffer, - FANOTIFY_BUFFER_SIZE)) > 0) - { - struct fanotify_event_metadata *metadata; - - metadata = (struct fanotify_event_metadata *)buffer; - while (FAN_EVENT_OK (metadata, length)) - { - event_process (metadata); - if (metadata->fd > 0) - close (metadata->fd); - metadata = FAN_EVENT_NEXT (metadata, length); - } - } - } + /* Setup polling */ + fds[FD_POLL_SIGNAL].fd = signal_fd; + fds[FD_POLL_SIGNAL].events = POLLIN; + fds[FD_POLL_FANOTIFY].fd = fanotify_fd; + fds[FD_POLL_FANOTIFY].events = POLLIN; + + /* Now loop */ + for (;;) { + /* Block until there is something to be read */ + if (poll(fds, FD_POLL_MAX, -1) < 0) { + fprintf(stderr, "Couldn't poll(): '%s'\n", strerror(errno)); + goto exit; + } + + /* Signal received? */ + if (fds[FD_POLL_SIGNAL].revents & POLLIN) { + int fdno = fds[FD_POLL_SIGNAL].fd; + struct signalfd_siginfo fdsi; + + if (read(fdno, &fdsi, sizeof(fdsi)) != sizeof(fdsi)) { + fprintf(stderr, "Couldn't read signal, wrong size read\n"); + goto exit; + } + + /* Break loop if we got the expected signal */ + if (fdsi.ssi_signo == SIGINT || fdsi.ssi_signo == SIGTERM) + break; + + fprintf(stderr, "Received unexpected signal\n"); + } + + /* fanotify event received? */ + if (fds[FD_POLL_FANOTIFY].revents & POLLIN) { + int fdno = fds[FD_POLL_FANOTIFY].fd; + char b[BUFSIZ]; + size_t nb = sizeof(b); + ssize_t length; + + /* Read from the FD. It will read all events available up to + * the given buffer size. */ + if ((length = read(fdno, b, nb)) > 0) { + struct fanotify_event_metadata *metadata; + + metadata = (struct fanotify_event_metadata *) b; + while (FAN_EVENT_OK(metadata, length)) { + event_process(metadata); + if (metadata->fd > 0) + close(metadata->fd); + metadata = FAN_EVENT_NEXT(metadata, length); + } + } + } } + ec = EXIT_SUCCESS; - /* Clean exit */ - shutdown_fanotify (fanotify_fd); - shutdown_signals (signal_fd); - - printf ("Exiting fanotify example...\n"); - - return EXIT_SUCCESS; +exit: + if (fanotify_fd >= 0) + shutdown_fanotify(fanotify_fd); + if (signal_fd >= 0) + shutdown_signals(signal_fd); + return ec; } @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org