8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek/*
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek Copyright (C) 2016 Red Hat
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek This program is free software; you can redistribute it and/or modify
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek it under the terms of the GNU General Public License as published by
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek the Free Software Foundation; either version 3 of the License, or
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek (at your option) any later version.
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek This program is distributed in the hope that it will be useful,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek GNU General Public License for more details.
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek You should have received a copy of the GNU General Public License
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek along with this program. If not, see <http://www.gnu.org/licenses/>.
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek*/
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#include <talloc.h>
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#include <errno.h>
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#include <libgen.h>
0f058b3156f584b21cffb0c9725e8082fbee47d0Lukas Slebodnik#include <limits.h>
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#include <sys/inotify.h>
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#include <sys/time.h>
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#include "util/inotify.h"
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#include "util/util.h"
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek/* For parent directories, we want to know if a file was moved there or
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * created there
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#define PARENT_DIR_MASK (IN_CREATE | IN_MOVED_TO)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek/* This structure is recreated if we need to rewatch the file and/or
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * directory
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstruct snotify_watch_ctx {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek int inotify_fd; /* The inotify_fd */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct tevent_fd *tfd; /* Activity on the fd */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_ctx *snctx; /* Pointer up to the main snotify struct */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* In case we're also watching the parent directory, otherwise -1.
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * We keep the variable here and not in snctx so that we're able
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * to catch even changes to the parent directory
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek int dir_wd;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* The file watch */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek int file_wd;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek};
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek/* This is what we call when an event we're interested in arrives */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstruct snotify_cb_ctx {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snotify_cb_fn fn;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *fn_name;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint32_t mask;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek void *pvt;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek};
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek/* One instance of a callback. We hoard the inotify notifications
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * until timer fires in caught_flags
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstruct snotify_dispatcher {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct tevent_timer *te;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint32_t caught_flags;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek};
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstruct snotify_ctx {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct tevent_context *ev;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* The full path of the file we're watching,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * its file and directory components */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *filename;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *dir_name;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *base_name;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* Private pointer passed to the callback */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_cb_ctx cb;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* A singleton callback dispatcher */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_dispatcher *disp;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* Internal snotify flags */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint16_t snotify_flags;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* The caller might decide to batch the updates and receive
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * them all together with a delay
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct timeval delay;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* We keep the structure that actually does the work
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * separately to be able to reinitialize it when the
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz * file is recreated or moved to the directory
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_watch_ctx *wctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek};
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstruct flg2str {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint32_t flg;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *str;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek} flg_table[] = {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000001, "IN_ACCESS" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000002, "IN_MODIFY" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000004, "IN_ATTRIB" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000008, "IN_CLOSE_WRITE" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000010, "IN_CLOSE_NOWRITE" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000020, "IN_OPEN" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000040, "IN_MOVED_FROM" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000080, "IN_MOVED_TO" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000100, "IN_CREATE" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000200, "IN_DELETE" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000400, "IN_DELETE_SELF" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00000800, "IN_MOVE_SELF" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00002000, "IN_UNMOUNT" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00004000, "IN_Q_OVERFLOW" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x00008000, "IN_IGNORED" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x01000000, "IN_ONLYDIR" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x02000000, "IN_DONT_FOLLOW" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x04000000, "IN_EXCL_UNLINK" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x20000000, "IN_MASK_ADD" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x40000000, "IN_ISDIR" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0x80000000, "IN_ONESHOT" },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek { 0, NULL },
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek};
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#if 0
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic void debug_flags(uint32_t flags, const char *file)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek char msgbuf[1024];
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek size_t total = 0;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (!DEBUG_IS_SET(SSSDBG_TRACE_LIBS)) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek for (int i = 0; flg_table[i].flg != 0; i++) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (flags & flg_table[i].flg) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek total += snprintf(msgbuf+total,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek sizeof(msgbuf)-total,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "%s ", flg_table[i].str);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (total == 0) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snprintf(msgbuf, sizeof(msgbuf), "NONE\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "Inotify event: %s on %s\n", msgbuf, file);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek#endif
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic void snotify_process_callbacks(struct tevent_context *ev,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct tevent_timer *te,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct timeval t,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek void *ptr)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_ctx *snctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx = talloc_get_type(ptr, struct snotify_ctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Bad pointer\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->cb.fn(snctx->filename,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->disp->caught_flags,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->cb.pvt);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek talloc_zfree(snctx->disp);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic struct snotify_dispatcher *create_dispatcher(struct snotify_ctx *snctx)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_dispatcher *disp;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct timeval tv;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek disp = talloc_zero(snctx, struct snotify_dispatcher);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (disp == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return NULL;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek gettimeofday(&tv, NULL);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek tv.tv_sec += snctx->delay.tv_sec;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek tv.tv_usec += snctx->delay.tv_usec;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Running a timer with delay %ld.%ld\n",
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek (unsigned long) snctx->delay.tv_sec,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek (unsigned long) snctx->delay.tv_usec);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek disp->te = tevent_add_timer(snctx->ev, disp, tv,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snotify_process_callbacks,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (disp->te == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Unable to queue file update!\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek talloc_free(disp);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return NULL;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return disp;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic struct snotify_dispatcher *get_dispatcher(struct snotify_ctx *snctx)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx->disp != NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "Reusing existing dispatcher\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return snctx->disp;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return create_dispatcher(snctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic errno_t dispatch_event(struct snotify_ctx *snctx,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint32_t ev_flags)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_dispatcher *disp;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if ((snctx->cb.mask & ev_flags) == 0) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EOK;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek disp = get_dispatcher(snctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (disp == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return ENOMEM;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek disp->caught_flags |= ev_flags;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Dispatched an event with combined flags 0x%X\n",
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek disp->caught_flags);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->disp = disp;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EOK;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic errno_t process_dir_event(struct snotify_ctx *snctx,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const struct inotify_event *in_event)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek errno_t ret;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_ALL, "inotify name: %s\n", in_event->name);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (in_event->len == 0 \
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek || strcmp(in_event->name, snctx->base_name) != 0) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, "Not interested in %s\n", in_event->name);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EOK;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "received notification for watched file [%s] under %s\n",
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek in_event->name, snctx->dir_name);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* file the event for the file to see if the caller is interested in it */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = dispatch_event(snctx, in_event->mask);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (ret == EOK) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* Tells the outer loop to re-initialize flags once the loop is finished.
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * However, finish reading all the events first to make sure we don't
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * miss any
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EAGAIN;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return ret;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic errno_t process_file_event(struct snotify_ctx *snctx,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const struct inotify_event *in_event)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (in_event->mask & IN_IGNORED) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Will reopen moved or deleted file %s\n", snctx->filename);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* Notify caller of the event, don't quit */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EAGAIN;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "received notification for watched file %s\n", snctx->filename);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return dispatch_event(snctx, in_event->mask);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic errno_t snotify_rewatch(struct snotify_ctx *snctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic void snotify_internal_cb(struct tevent_context *ev,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct tevent_fd *fde,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint16_t flags,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek void *data)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek char ev_buf[sizeof(struct inotify_event) + PATH_MAX];
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *ptr;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const struct inotify_event *in_event;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_ctx *snctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ssize_t len;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek errno_t ret;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek bool rewatch;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx = talloc_get_type(data, struct snotify_ctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Bad pointer\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek while (1) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek len = read(snctx->wctx->inotify_fd, ev_buf, sizeof(ev_buf));
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (len == -1) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = errno;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (ret != EAGAIN) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Cannot read inotify_event [%d]: %s\n",
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret, strerror(ret));
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek } else {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "All inotify events processed\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if ((size_t) len < sizeof(struct inotify_event)) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* Did not even read the required amount of data, move on.. */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek continue;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek for (ptr = ev_buf;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ptr < ev_buf + len;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ptr += sizeof(struct inotify_event) + in_event->len) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek in_event = (const struct inotify_event *) ptr;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek //debug_flags(in_event->mask, in_event->name);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx->wctx->dir_wd == in_event->wd) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = process_dir_event(snctx, in_event);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (ret == EAGAIN) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek rewatch = true;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* Continue with the loop and read all the events from
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * this descriptor first, then rewatch when done
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek } else if (ret != EOK) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Failed to process inotify event\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek continue;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek } else if (snctx->wctx->file_wd == in_event->wd) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = process_file_event(snctx, in_event);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (ret != EOK) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Failed to process inotify event\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek continue;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek } else {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
346d6d8bf5fdb446921d754c07c8a7d913a048d5René Genz "Unknown watch %d\n", in_event->wd);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = EOK;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (rewatch) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = snotify_rewatch(snctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (ret != EOK) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Failed to re-set watch");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic int watch_ctx_destructor(void *memptr)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_watch_ctx *wctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx = talloc_get_type(memptr, struct snotify_watch_ctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (wctx == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Bad pointer\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return 1;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* We don't need to close the watches explicitly. man 7 inotify says:
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * When all file descriptors referring to an inotify instance
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * have been closed (using close(2)), the underlying object
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * and its resources are freed for reuse by the kernel; all
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * associated watches are automatically freed.
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (wctx->inotify_fd != -1) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Closing inotify fd %d\n", wctx->inotify_fd);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek close(wctx->inotify_fd);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return 0;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic errno_t copy_filenames(struct snotify_ctx *snctx,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *filename)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek char *p;
c53997720b231ad61af435a3124c7ecd731fc99bLukas Slebodnik char fcopy[PATH_MAX + 1];
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
c53997720b231ad61af435a3124c7ecd731fc99bLukas Slebodnik strncpy(fcopy, filename, sizeof(fcopy) - 1);
c53997720b231ad61af435a3124c7ecd731fc99bLukas Slebodnik fcopy[PATH_MAX] = '\0';
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek p = dirname(fcopy);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (p == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EIO;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->dir_name = talloc_strdup(snctx, p);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx->dir_name == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return ENOMEM;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
c53997720b231ad61af435a3124c7ecd731fc99bLukas Slebodnik strncpy(fcopy, filename, sizeof(fcopy) - 1);
c53997720b231ad61af435a3124c7ecd731fc99bLukas Slebodnik fcopy[PATH_MAX] = '\0';
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek p = basename(fcopy);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (p == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EIO;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->base_name = talloc_strdup(snctx, p);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx->base_name == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return ENOMEM;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->filename = talloc_strdup(snctx, filename);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx->filename == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return ENOMEM;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EOK;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic struct snotify_watch_ctx *snotify_watch(struct snotify_ctx *snctx,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint32_t mask)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_watch_ctx *wctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek errno_t ret;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx = talloc_zero(snctx, struct snotify_watch_ctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (wctx == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return NULL;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx->inotify_fd = -1;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx->dir_wd = -1;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx->file_wd = -1;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx->snctx = snctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek talloc_set_destructor((TALLOC_CTX *)wctx, watch_ctx_destructor);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx->inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (wctx->inotify_fd == -1) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = errno;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "inotify_init1 failed: %d: %s\n", ret, strerror(ret));
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek goto fail;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "Opened inotify fd %d\n", wctx->inotify_fd);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx->tfd = tevent_add_fd(snctx->ev, wctx, wctx->inotify_fd,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek TEVENT_FD_READ, snotify_internal_cb,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (wctx->tfd == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Cannot add tevent fd watch for %s\n",
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->filename);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek goto fail;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx->file_wd = inotify_add_watch(wctx->inotify_fd, snctx->filename, mask);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (wctx->file_wd == -1) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = errno;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (ret != ENOENT || (!(snctx->snotify_flags & SNOTIFY_WATCH_DIR))) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "inotify_add_watch failed [%d]: %s\n",
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret, strerror(ret));
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek goto fail;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "Opened file watch %d\n", wctx->file_wd);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx->snotify_flags & SNOTIFY_WATCH_DIR) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek /* Create a watch for the parent directory. This is useful for cases
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * where we start watching a file before it's created, but still want
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek * a notification when the file is moved in
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek */
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek wctx->dir_wd = inotify_add_watch(wctx->inotify_fd,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->dir_name, PARENT_DIR_MASK);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (wctx->dir_wd == -1) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = errno;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "inotify_add_watch failed [%d]: %s\n",
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret, strerror(ret));
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek goto fail;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Opened directory watch %d\n", wctx->dir_wd);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return wctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekfail:
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek talloc_free(wctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return NULL;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstatic errno_t snotify_rewatch(struct snotify_ctx *snctx)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek talloc_free(snctx->wctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->wctx = snotify_watch(snctx, snctx->cb.mask);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx->wctx == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return ENOMEM;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, "Recreated watch\n");
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return EOK;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozekstruct snotify_ctx *_snotify_create(TALLOC_CTX *mem_ctx,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct tevent_context *ev,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint16_t snotify_flags,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *filename,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct timeval *delay,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek uint32_t mask,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snotify_cb_fn fn,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek const char *fn_name,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek void *pvt)
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek{
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek errno_t ret;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek struct snotify_ctx *snctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx = talloc_zero(mem_ctx, struct snotify_ctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return NULL;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->ev = ev;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->snotify_flags = snotify_flags;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (delay) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->delay.tv_sec = delay->tv_sec;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->delay.tv_usec = delay->tv_usec;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->cb.fn = fn;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->cb.fn_name = fn_name;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->cb.mask = mask;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->cb.pvt = pvt;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek ret = copy_filenames(snctx, filename);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (ret != EOK) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek talloc_free(snctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return NULL;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->wctx = snotify_watch(snctx, mask);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek if (snctx->wctx == NULL) {
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek talloc_free(snctx);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return NULL;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek }
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "Added a watch for %s with inotify flags 0x%X "
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "internal flags 0x%X "
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek "using function %s after delay %ld.%ld\n",
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snctx->filename,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek mask,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek snotify_flags,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek fn_name,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek (unsigned long) snctx->delay.tv_sec,
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek (unsigned long) snctx->delay.tv_usec);
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek return snctx;
8cfb42e1985550e99585d311f68087d414932806Jakub Hrozek}