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

Reply via email to