sd_event_add_inotify - Man Page

Add an "inotify" file system inode event source to an event loop

Synopsis

#include <systemd/sd-event​.h>
typedef struct sd_event_source sd_event_source;

typedef int (*sd_event_inotify_handler_t)(sd_event_source *s, const struct inotify_event *event, void *userdata);

int sd_event_add_inotify(sd_event *event, sd_event_source **source, const char *path, uint32_t mask, sd_event_inotify_handler_t handler, void *userdata);

int sd_event_add_inotify_fd(sd_event *event, sd_event_source **source, int fd, uint32_t mask, sd_event_inotify_handler_t handler, void *userdata);

int sd_event_source_get_inotify_mask(sd_event_source *source, uint32_t *ret);

int sd_event_source_get_inotify_path(sd_event_source *source, const char **ret);

Description

sd_event_add_inotify() adds a new inotify(7) file system inode event source to an event loop​. The event loop object is specified in the event parameter, the event source object is returned in the source parameter​. The path parameter specifies the path of the file system inode to watch​. The mask parameter specifies which types of inode events to watch specifically​. It must contain an OR-ed combination of IN_ACCESS, IN_ATTRIB, IN_CLOSE_WRITE, ​... flags​. See inotify(7) for further information​.

The handler must reference a function to call when the inode changes or NULL​. The handler function will be passed the userdata pointer, which may be chosen freely by the caller​. The handler also receives a pointer to a struct inotify_event structure containing information about the inode event​. The handler may return negative to signal an error (see below), other return values are ignored​. If handler is NULL, a default handler that calls sd_event_exit(3) will be used​.

sd_event_add_inotify_fd() is identical to sd_event_add_inotify(), except that it takes a file descriptor to an inode (possibly an O_PATH one, but any other will do too) instead of a path in the file system​.

If multiple event sources are installed for the same inode the backing inotify watch descriptor is automatically shared​. The mask parameter may contain any flag defined by the inotify API, with the exception of IN_MASK_ADD​.

The handler is enabled continuously (SD_EVENT_ON), but this may be changed with sd_event_source_set_enabled(3)​. Alternatively, the IN_ONESHOT mask flag may be used to request SD_EVENT_ONESHOT mode​. If the handler function returns a negative error code, it will be disabled after the invocation, even if the SD_EVENT_ON mode was requested before​.

As a special limitation the priority of inotify event sources may only be altered (see sd_event_source_set_priority(3)) in the time between creation of the event source object with sd_event_add_inotify() and the beginning of the next event loop iteration​. Attempts of changing the priority any later will be refused​. Consider freeing and allocating a new inotify event source to change the priority at that point​.

To destroy an event source object use sd_event_source_unref(3), but note that the event source is only removed from the event loop when all references to the event source are dropped​. To make sure an event source does not fire anymore, even when there's still a reference to it kept, consider disabling it with sd_event_source_set_enabled(3)​.

If the second parameter of sd_event_add_inotify() is passed as NULL no reference to the event source object is returned​. In this case, the event source is considered "floating", and will be destroyed implicitly when the event loop itself is destroyed​.

If the handler parameter to sd_event_add_inotify() is NULL, and the event source fires, this will be considered a request to exit the event loop​. In this case, the userdata parameter, cast to an integer, is passed as the exit code parameter to sd_event_exit(3)​.

sd_event_source_get_inotify_mask() retrieves the configured inotify watch mask of an event source created previously with sd_event_add_inotify()​. It takes the event source object as the source parameter and a pointer to a uint32_t variable to return the mask in​.

sd_event_source_get_inotify_path() retrieves the target path of the configured inotify watch of an event source created previously with sd_event_add_inotify()​. It takes the event source object as the source parameter and a pointer to a const char ** variable to return the path in​. The caller must not free the returned path​.

Return Value

On success, these functions return 0 or a positive integer​. On failure, they return a negative errno-style error code​.

Errors

Returned errors may indicate the following problems:

-ENOMEM

Not enough memory to allocate an object​.

-EINVAL

An invalid argument has been passed​. This includes specifying a mask with IN_MASK_ADD set​.

-ESTALE

Returned by sd_event_source_add_inotify() or sd_event_source_add_inotify_fd() when the event loop is already terminated​. Returned by sd_event_source_get_inotify_path() when no active inode data is assigned to the event source, e​.g​. when the event source is disabled​.

-ECHILD

The event loop has been created in a different process, library or module instance​.

-EDOM

The passed event source is not an inotify process event source​.

-EBADF

The passed file descriptor is not valid​.

-ENOSYS

sd_event_add_inotify_fd() or sd_event_source_get_inotify_path() was called without /proc/ mounted​.

Examples

Example ​1. ​A simple program that uses inotify to monitor one or two directories

/* SPDX-License-Identifier: MIT-0 */

#include <stdio​.h>
#include <string​.h>
#include <sys/inotify​.h>

#include <systemd/sd-event​.h>

#define _cleanup_(f) __attribute__((cleanup(f)))

static int inotify_handler(sd_event_source *source,
                           const struct inotify_event *event,
                           void *userdata) {

  const char *desc = NULL;

  sd_event_source_get_description(source, &desc);

  if (event->mask & IN_Q_OVERFLOW)
    printf("inotify-handler <%s>: overflow\n", desc);
  else if (event->mask & IN_CREATE)
    printf("inotify-handler <%s>: create on %s\n", desc, event->name);
  else if (event->mask & IN_DELETE)
    printf("inotify-handler <%s>: delete on %s\n", desc, event->name);
  else if (event->mask & IN_MOVED_TO)
    printf("inotify-handler <%s>: moved-to on %s\n", desc, event->name);

  /* Terminate the program if an "exit" file appears */
  if ((event->mask & (IN_CREATE|IN_MOVED_TO)) &&
      strcmp(event->name, "exit") == 0)
    sd_event_exit(sd_event_source_get_event(source), 0);

  return 1;
}

int main(int argc, char **argv) {
  _cleanup_(sd_event_unrefp) sd_event *event = NULL;
  _cleanup_(sd_event_source_unrefp) sd_event_source *source1 = NULL, *source2 = NULL;

  const char *path1 = argc > 1 ? argv[1] : "/tmp";
  const char *path2 = argc > 2 ? argv[2] : NULL;

  /* Note: failure handling is omitted for brevity */

  sd_event_default(&event);

  sd_event_add_inotify(event, &source1, path1,
                       IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_TO,
                       inotify_handler, NULL);
  if (path2)
    sd_event_add_inotify(event, &source2, path2,
                         IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVED_TO,
                         inotify_handler, NULL);

  sd_event_loop(event);

  return 0;
}

Notes

Functions described here are available as a shared library, which can be compiled against and linked to with the libsystemd ​pkg-config(1) file​.

All functions listed here are thread-agnostic and only a single thread may operate on a given object at any given time​. Different threads may access the same object at different times​. Multiple independent objects may be used from different threads in parallel​.

The code described here uses getenv(3), which is declared to be not multi-thread-safe​. This means that the code calling the functions described here must not call setenv(3) from a parallel thread​. It is recommended to only do calls to setenv() from an early phase of the program when no other threads have been started​.

History

sd_event_inotify_handler_t(), sd_event_add_inotify(), and sd_event_source_get_inotify_mask() were added in version 239​.

sd_event_add_inotify_fd() was added in version 250​.

sd_event_source_get_inotify_path() was added in version 256​.

See Also

systemd(1), sd-event(3), sd_event_new(3), sd_event_now(3), sd_event_add_io(3), sd_event_add_time(3), sd_event_add_signal(3), sd_event_add_defer(3), sd_event_add_child(3), sd_event_source_set_enabled(3), sd_event_source_set_priority(3), sd_event_source_set_userdata(3), sd_event_source_set_description(3), sd_event_source_set_floating(3), waitid(2)

Referenced By

sd-event(3), sd_event_add_child(3), sd_event_add_defer(3), sd_event_add_io(3), sd_event_add_memory_pressure(3), sd_event_add_signal(3), sd_event_add_time(3), sd_event_exit(3), sd_event_new(3), sd_event_run(3), sd_event_set_exit_on_idle(3), sd_event_set_watchdog(3), sd_event_source_get_event(3), sd_event_source_get_pending(3), sd_event_source_set_description(3), sd_event_source_set_destroy_callback(3), sd_event_source_set_enabled(3), sd_event_source_set_exit_on_failure(3), sd_event_source_set_floating(3), sd_event_source_set_prepare(3), sd_event_source_set_priority(3), sd_event_source_set_ratelimit(3), sd_event_source_set_userdata(3), sd_event_source_unref(3), sd_event_wait(3), systemd.directives(7), systemd.index(7).

The man pages sd_event_add_inotify_fd(3), sd_event_inotify_handler_t(3), sd_event_source_get_inotify_mask(3) and sd_event_source_get_inotify_path(3) are aliases of sd_event_add_inotify(3).

systemd 262~rc2