/*
 * Copyright (C) 2014 Karel Zak <kzak@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 */

/**
 * SECTION: monitor
 * @title: Monitor
 * @short_description: interface to monitor mount tables
 *
 * For example monitor VFS (/proc/self/mountinfo) for changes:
 *
 * <informalexample>
 *   <programlisting>
 * const char *filename;
 * struct libmount_monitor *mn = mnt_new_monitor();
 *
 * mnt_monitor_enable_kernel(mn, TRUE));
 *
 * printf("waiting for changes...\n");
 * while (mnt_monitor_wait(mn, -1) > 0) {
 *    while (mnt_monitor_next_change(mn, &filename, NULL) == 0)
 *       printf(" %s: change detected\n", filename);
 * }
 * mnt_unref_monitor(mn);
 *   </programlisting>
 * </informalexample>
 *
 */

#include "fileutils.h"
#include "mountP.h"
#include "pathnames.h"

#include <sys/inotify.h>
#include <sys/epoll.h>


struct monitor_opers;

struct monitor_entry {
	int			fd;		/* private entry file descriptor */
	char			*path;		/* path to the monitored file */
	int			type;		/* MNT_MONITOR_TYPE_* */
	uint32_t		events;		/* wanted epoll events */

	const struct monitor_opers *opers;

	unsigned int		enable : 1,
				changed : 1;

	struct list_head	ents;
};

struct libmnt_monitor {
	int			refcount;
	int			fd;		/* public monitor file descriptor */

	struct list_head	ents;
};

struct monitor_opers {
	int (*op_get_fd)(struct libmnt_monitor *, struct monitor_entry *);
	int (*op_close_fd)(struct libmnt_monitor *, struct monitor_entry *);
	int (*op_event_verify)(struct libmnt_monitor *, struct monitor_entry *);
};

static int monitor_modify_epoll(struct libmnt_monitor *mn,
				struct monitor_entry *me, int enable);

/**
 * mnt_new_monitor:
 *
 * The initial refcount is 1, and needs to be decremented to
 * release the resources of the filesystem.
 *
 * Returns: newly allocated struct libmnt_monitor.
 */
struct libmnt_monitor *mnt_new_monitor(void)
{
	struct libmnt_monitor *mn = calloc(1, sizeof(*mn));
	if (!mn)
		return NULL;

	mn->refcount = 1;
	mn->fd = -1;
	INIT_LIST_HEAD(&mn->ents);

	DBG(MONITOR, ul_debugobj(mn, "alloc"));
	return mn;
}

/**
 * mnt_ref_monitor:
 * @mn: monitor pointer
 *
 * Increments reference counter.
 */
void mnt_ref_monitor(struct libmnt_monitor *mn)
{
	if (mn)
		mn->refcount++;
}

static void free_monitor_entry(struct monitor_entry *me)
{
	if (!me)
		return;
	list_del(&me->ents);
	if (me->fd >= 0)
		close(me->fd);
	free(me->path);
	free(me);
}

/**
 * mnt_unref_monitor:
 * @mn: monitor pointer
 *
 * Decrements the reference counter, on zero the @mn is automatically
 * deallocated.
 */
void mnt_unref_monitor(struct libmnt_monitor *mn)
{
	if (!mn)
		return;

	mn->refcount--;
	if (mn->refcount <= 0) {
		mnt_monitor_close_fd(mn);	/* destroys all file descriptors */

		while (!list_empty(&mn->ents)) {
			struct monitor_entry *me = list_entry(mn->ents.next,
						  struct monitor_entry, ents);
			free_monitor_entry(me);
		}

		free(mn);
	}
}

static struct monitor_entry *monitor_new_entry(struct libmnt_monitor *mn)
{
	struct monitor_entry *me;

	assert(mn);

	me = calloc(1, sizeof(*me));
	if (!me)
		return NULL;
        INIT_LIST_HEAD(&me->ents);
	list_add_tail(&me->ents, &mn->ents);

	me->fd = -1;

	return me;
}

static int monitor_next_entry(struct libmnt_monitor *mn,
			      struct libmnt_iter *itr,
			      struct monitor_entry **me)
{
	int rc = 1;

	assert(mn);
	assert(itr);
	assert(me);

	*me = NULL;

	if (!itr->head)
		MNT_ITER_INIT(itr, &mn->ents);
	if (itr->p != itr->head) {
		MNT_ITER_ITERATE(itr, *me, struct monitor_entry, ents);
		rc = 0;
	}

	return rc;
}

/* returns entry by type */
static struct monitor_entry *monitor_get_entry(struct libmnt_monitor *mn, int type)
{
	struct libmnt_iter itr;
	struct monitor_entry *me;

	mnt_reset_iter(&itr, MNT_ITER_FORWARD);
	while (monitor_next_entry(mn, &itr, &me) == 0) {
		if (me->type == type)
			return me;
	}
	return NULL;
}


/*
 * Userspace monitor
 */

static int userspace_monitor_close_fd(struct libmnt_monitor *mn __attribute__((__unused__)),
				    struct monitor_entry *me)
{
	assert(me);

	if (me->fd >= 0)
		close(me->fd);
	me->fd = -1;
	return 0;
}

static int userspace_add_watch(struct monitor_entry *me, int *final, int *fd)
{
	char *filename = NULL;
	int wd, rc = -EINVAL;

	assert(me);
	assert(me->path);

	/*
	 * libmount uses rename(2) to atomically update utab, monitor
	 * rename changes is too tricky. It seems better to monitor utab
	 * lockfile close.
	 */
	if (asprintf(&filename, "%s.lock", me->path) <= 0) {
		rc = -errno;
		goto done;
	}

	/* try lock file if already exists */
	errno = 0;
	wd = inotify_add_watch(me->fd, filename, IN_CLOSE_NOWRITE);
	if (wd >= 0) {
		DBG(MONITOR, ul_debug(" added inotify watch for %s [fd=%d]", filename, wd));
		rc = 0;
		if (final)
			*final = 1;
		if (fd)
			*fd = wd;
		goto done;
	} else if (errno != ENOENT) {
		rc = -errno;
		goto done;
	}

	while (strchr(filename, '/')) {
		stripoff_last_component(filename);
		if (!*filename)
			break;

		/* try directory where is the lock file */
		errno = 0;
		wd = inotify_add_watch(me->fd, filename, IN_CREATE|IN_ISDIR);
		if (wd >= 0) {
			DBG(MONITOR, ul_debug(" added inotify watch for %s [fd=%d]", filename, wd));
			rc = 0;
			if (fd)
				*fd = wd;
			break;
		} else if (errno != ENOENT) {
			rc = -errno;
			break;
		}
	}
done:
	free(filename);
	return rc;
}

static int userspace_monitor_get_fd(struct libmnt_monitor *mn,
				    struct monitor_entry *me)
{
	int rc;

	if (!me || me->enable == 0)	/* not-initialized or disabled */
		return -EINVAL;
	if (me->fd >= 0)
		return me->fd;		/* already initialized */

	assert(me->path);
	DBG(MONITOR, ul_debugobj(mn, " open userspace monitor for %s", me->path));

	me->fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
	if (me->fd < 0)
		goto err;

	if (userspace_add_watch(me, NULL, NULL) < 0)
		goto err;

	return me->fd;
err:
	rc = -errno;
	if (me->fd >= 0)
		close(me->fd);
	me->fd = -1;
	DBG(MONITOR, ul_debugobj(mn, "failed to create userspace monitor [rc=%d]", rc));
	return rc;
}

/*
 * verify and drain inotify buffer
 */
static int userspace_event_verify(struct libmnt_monitor *mn,
					struct monitor_entry *me)
{
	char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
	int status = 0;

	if (!me || me->fd < 0)
		return 0;

	DBG(MONITOR, ul_debugobj(mn, "drain and verify userspace monitor inotify"));

	/* the me->fd is non-blocking */
	do {
		ssize_t len;
		char *p;
		const struct inotify_event *e;

		len = read(me->fd, buf, sizeof(buf));
		if (len < 0)
			break;

		for (p = buf; p < buf + len;
		     p += sizeof(struct inotify_event) + e->len) {

			int fd = -1;

			e = (const struct inotify_event *) p;
			DBG(MONITOR, ul_debugobj(mn, " inotify event 0x%x [%s]\n", e->mask, e->len ? e->name : ""));

			if (e->mask & IN_CLOSE_NOWRITE)
				status = 1;
			else {
				/* event on lock file */
				userspace_add_watch(me, &status, &fd);

				if (fd != e->wd) {
					DBG(MONITOR, ul_debugobj(mn, " removing watch [fd=%d]", e->wd));
					inotify_rm_watch(me->fd, e->wd);
				}
			}
		}
	} while (1);

	DBG(MONITOR, ul_debugobj(mn, "%s", status == 1 ? " success" : " nothing"));
	return status;
}

/*
 * userspace monitor operations
 */
static const struct monitor_opers userspace_opers = {
	.op_get_fd		= userspace_monitor_get_fd,
	.op_close_fd		= userspace_monitor_close_fd,
	.op_event_verify	= userspace_event_verify
};

/**
 * mnt_monitor_enable_userspace:
 * @mn: monitor
 * @enable: 0 or 1
 * @filename: overwrites default
 *
 * Enables or disables userspace monitoring. If the userspace monitor does not
 * exist and enable=1 then allocates new resources necessary for the monitor.
 *
 * If the top-level monitor has been already created (by mnt_monitor_get_fd()
 * or mnt_monitor_wait()) then it's updated according to @enable.
 *
 * The @filename is used only the first time when you enable the monitor. It's
 * impossible to have more than one userspace monitor. The recommended is to
 * use NULL as filename.
 *
 * The userspace monitor is unsupported for systems with classic regular
 * /etc/mtab file.
 *
 * Return: 0 on success and <0 on error
 */
int mnt_monitor_enable_userspace(struct libmnt_monitor *mn, int enable, const char *filename)
{
	struct monitor_entry *me;
	int rc = 0;

	if (!mn)
		return -EINVAL;

	me = monitor_get_entry(mn, MNT_MONITOR_TYPE_USERSPACE);
	if (me) {
		rc = monitor_modify_epoll(mn, me, enable);
		if (!enable)
			userspace_monitor_close_fd(mn, me);
		return rc;
	}
	if (!enable)
		return 0;

	DBG(MONITOR, ul_debugobj(mn, "allocate new userspace monitor"));

	if (!filename)
		filename = mnt_get_utab_path();		/* /run/mount/utab */
	if (!filename) {
		DBG(MONITOR, ul_debugobj(mn, "failed to get userspace mount table path"));
		return -EINVAL;
	}

	me = monitor_new_entry(mn);
	if (!me)
		goto err;

	me->type = MNT_MONITOR_TYPE_USERSPACE;
	me->opers = &userspace_opers;
	me->events = EPOLLIN;
	me->path = strdup(filename);
	if (!me->path)
		goto err;

	return monitor_modify_epoll(mn, me, TRUE);
err:
	rc = -errno;
	free_monitor_entry(me);
	DBG(MONITOR, ul_debugobj(mn, "failed to allocate userspace monitor [rc=%d]", rc));
	return rc;
}


/*
 * Kernel monitor
 */

static int kernel_monitor_close_fd(struct libmnt_monitor *mn __attribute__((__unused__)),
				   struct monitor_entry *me)
{
	assert(me);

	if (me->fd >= 0)
		close(me->fd);
	me->fd = -1;
	return 0;
}

static int kernel_monitor_get_fd(struct libmnt_monitor *mn,
				 struct monitor_entry *me)
{
	int rc;

	if (!me || me->enable == 0)	/* not-initialized or disabled */
		return -EINVAL;
	if (me->fd >= 0)
		return me->fd;		/* already initialized */

	assert(me->path);
	DBG(MONITOR, ul_debugobj(mn, " open kernel monitor for %s", me->path));

	me->fd = open(me->path, O_RDONLY|O_CLOEXEC);
	if (me->fd < 0)
		goto err;

	return me->fd;
err:
	rc = -errno;
	DBG(MONITOR, ul_debugobj(mn, "failed to create kernel  monitor [rc=%d]", rc));
	return rc;
}

/*
 * kernel monitor operations
 */
static const struct monitor_opers kernel_opers = {
	.op_get_fd		= kernel_monitor_get_fd,
	.op_close_fd		= kernel_monitor_close_fd,
};

/**
 * mnt_monitor_enable_kernel:
 * @mn: monitor
 * @enable: 0 or 1
 *
 * Enables or disables kernel VFS monitoring. If the monitor does not exist and
 * enable=1 then allocates new resources necessary for the monitor.
 *
 * If the top-level monitor has been already created (by mnt_monitor_get_fd()
 * or mnt_monitor_wait()) then it's updated according to @enable.
 *
 * Return: 0 on success and <0 on error
 */
int mnt_monitor_enable_kernel(struct libmnt_monitor *mn, int enable)
{
	struct monitor_entry *me;
	int rc = 0;

	if (!mn)
		return -EINVAL;

	me = monitor_get_entry(mn, MNT_MONITOR_TYPE_KERNEL);
	if (me) {
		rc = monitor_modify_epoll(mn, me, enable);
		if (!enable)
			kernel_monitor_close_fd(mn, me);
		return rc;
	}
	if (!enable)
		return 0;

	DBG(MONITOR, ul_debugobj(mn, "allocate new kernel monitor"));

	/* create a new entry */
	me = monitor_new_entry(mn);
	if (!me)
		goto err;

	/* If you want to use epoll FD in another epoll then top level
	 * epoll_wait() will drain all events from low-level FD if the
	 * low-level FD is not added with EPOLLIN. It means without EPOLLIN it
	 * it's impossible to detect which low-level FD has been active.
	 *
	 * Unfortunately, use EPOLLIN for mountinfo is tricky because in this
	 * case kernel returns events all time (we don't read from the FD).
	 * The solution is to use also edge-triggered (EPOLLET) flag, then
	 * kernel generate events on mountinfo changes only. The disadvantage is
	 * that we have to drain initial event generated by EPOLLIN after
	 * epoll_ctl(ADD). See monitor_modify_epoll().
	 */
	me->events = EPOLLIN | EPOLLET;

	me->type = MNT_MONITOR_TYPE_KERNEL;
	me->opers = &kernel_opers;
	me->path = strdup(_PATH_PROC_MOUNTINFO);
	if (!me->path)
		goto err;

	return monitor_modify_epoll(mn, me, TRUE);
err:
	rc = -errno;
	free_monitor_entry(me);
	DBG(MONITOR, ul_debugobj(mn, "failed to allocate kernel monitor [rc=%d]", rc));
	return rc;
}

/*
 * Add/Remove monitor entry to/from monitor epoll.
 */
static int monitor_modify_epoll(struct libmnt_monitor *mn,
				struct monitor_entry *me, int enable)
{
	assert(mn);
	assert(me);

	me->enable = enable ? 1 : 0;
	me->changed = 0;

	if (mn->fd < 0)
		return 0;	/* no epoll, ignore request */

	if (enable) {
		struct epoll_event ev = { .events = me->events };
		int fd = me->opers->op_get_fd(mn, me);

		if (fd < 0)
			goto err;

		DBG(MONITOR, ul_debugobj(mn, " add fd=%d (for %s)", fd, me->path));

		ev.data.ptr = (void *) me;

		if (epoll_ctl(mn->fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
			if (errno != EEXIST)
				goto err;
		}
		if (me->events & (EPOLLIN | EPOLLET)) {
			/* Drain initial events generated for /proc/self/mountinfo */
			struct epoll_event events[1];
			while (epoll_wait(mn->fd, events, 1, 0) > 0);
		}
	} else if (me->fd) {
		DBG(MONITOR, ul_debugobj(mn, " remove fd=%d (for %s)", me->fd, me->path));
		if (epoll_ctl(mn->fd, EPOLL_CTL_DEL, me->fd, NULL) < 0) {
			if (errno != ENOENT)
				goto err;
		}
	}

	return 0;
err:
	return -errno;
}

/**
 * mnt_monitor_close_fd:
 * @mn: monitor
 *
 * Close monitor file descriptor. This is usually unnecessary, because
 * mnt_unref_monitor() cleanups all.
 *
 * The function is necessary only if you want to reset monitor setting. The
 * next mnt_monitor_get_fd() or mnt_monitor_wait() will use newly initialized
 * monitor.  This restart is unnecessary for mnt_monitor_enable_*() functions.
 *
 * Returns: 0 on success, <0 on error.
 */
int mnt_monitor_close_fd(struct libmnt_monitor *mn)
{
	struct libmnt_iter itr;
	struct monitor_entry *me;

	if (!mn)
		return -EINVAL;

	mnt_reset_iter(&itr, MNT_ITER_FORWARD);

	/* disable all monitor entries */
	while (monitor_next_entry(mn, &itr, &me) == 0) {

		/* remove entry from epoll */
		if (mn->fd >= 0)
			monitor_modify_epoll(mn, me, FALSE);

		/* close entry FD */
		me->opers->op_close_fd(mn, me);
	}

	if (mn->fd >= 0) {
		DBG(MONITOR, ul_debugobj(mn, "closing top-level monitor fd"));
		close(mn->fd);
	}
	mn->fd = -1;
	return 0;
}

/**
 * mnt_monitor_get_fd:
 * @mn: monitor
 *
 * The file descriptor is associated with all monitored files and it's usable
 * for example for epoll. You have to call mnt_monitor_event_cleanup() or
 * mnt_monitor_next_change() after each event.
 *
 * Returns: >=0 (fd) on success, <0 on error
 */
int mnt_monitor_get_fd(struct libmnt_monitor *mn)
{
	struct libmnt_iter itr;
	struct monitor_entry *me;
	int rc = 0;

	if (!mn)
		return -EINVAL;
	if (mn->fd >= 0)
		return mn->fd;

	DBG(MONITOR, ul_debugobj(mn, "create top-level monitor fd"));
	mn->fd = epoll_create1(EPOLL_CLOEXEC);
	if (mn->fd < 0)
		return -errno;

	mnt_reset_iter(&itr, MNT_ITER_FORWARD);

	DBG(MONITOR, ul_debugobj(mn, "adding monitor entries to epoll (fd=%d)", mn->fd));
	while (monitor_next_entry(mn, &itr, &me) == 0) {
		if (!me->enable)
			continue;
		rc = monitor_modify_epoll(mn, me, TRUE);
		if (rc)
			goto err;
	}

	DBG(MONITOR, ul_debugobj(mn, "successfully created monitor"));
	return mn->fd;
err:
	rc = errno ? -errno : -EINVAL;
	close(mn->fd);
	mn->fd = -1;
	DBG(MONITOR, ul_debugobj(mn, "failed to create monitor [rc=%d]", rc));
	return rc;
}

/**
 * mnt_monitor_wait:
 * @mn: monitor
 * @timeout: number of milliseconds, -1 block indefinitely, 0 return immediately
 *
 * Waits for the next change, after the event it's recommended to use
 * mnt_monitor_next_change() to get more details about the change and to
 * avoid false positive events.
 *
 * Returns: 1 success (something changed), 0 timeout, <0 error.
 */
int mnt_monitor_wait(struct libmnt_monitor *mn, int timeout)
{
	int rc;
	struct monitor_entry *me;
	struct epoll_event events[1];

	if (!mn)
		return -EINVAL;

	if (mn->fd < 0) {
		rc = mnt_monitor_get_fd(mn);
		if (rc < 0)
			return rc;
	}

	do {
		DBG(MONITOR, ul_debugobj(mn, "calling epoll_wait(), timeout=%d", timeout));
		rc = epoll_wait(mn->fd, events, 1, timeout);
		if (rc < 0)
			return -errno;		/* error */
		if (rc == 0)
			return 0;		/* timeout */

		me = (struct monitor_entry *) events[0].data.ptr;
		if (!me)
			return -EINVAL;

		if (me->opers->op_event_verify == NULL ||
		    me->opers->op_event_verify(mn, me) == 1) {
			me->changed = 1;
			break;
		}
	} while (1);

	return 1;			/* success */
}


static struct monitor_entry *get_changed(struct libmnt_monitor *mn)
{
	struct libmnt_iter itr;
	struct monitor_entry *me;

	mnt_reset_iter(&itr, MNT_ITER_FORWARD);
	while (monitor_next_entry(mn, &itr, &me) == 0) {
		if (me->changed)
			return me;
	}
	return NULL;
}

/**
 * mnt_monitor_next_change:
 * @mn: monitor
 * @filename: returns changed file (optional argument)
 * @type: returns MNT_MONITOR_TYPE_* (optional argument)
 *
 * The function does not wait and it's designed to provide details about changes.
 * It's always recommended to use this function to avoid false positives.
 *
 * Returns: 0 on success, 1 no change, <0 on error
 */
int mnt_monitor_next_change(struct libmnt_monitor *mn,
			     const char **filename,
			     int *type)
{
	int rc;
	struct monitor_entry *me;

	if (!mn || mn->fd < 0)
		return -EINVAL;

	/*
	 * if we previously called epoll_wait() (e.g. mnt_monitor_wait()) then
	 * info about unread change is already stored in monitor_entry.
	 *
	 * If we get nothing, then ask kernel.
	 */
	me = get_changed(mn);
	while (!me) {
		struct epoll_event events[1];

		DBG(MONITOR, ul_debugobj(mn, "asking for next changed"));

		rc = epoll_wait(mn->fd, events, 1, 0);	/* no timeout! */
		if (rc < 0) {
			DBG(MONITOR, ul_debugobj(mn, " *** error"));
			return -errno;
		}
		if (rc == 0) {
			DBG(MONITOR, ul_debugobj(mn, " *** nothing"));
			return 1;
		}

		me = (struct monitor_entry *) events[0].data.ptr;
		if (!me)
			return -EINVAL;

		if (me->opers->op_event_verify != NULL &&
		    me->opers->op_event_verify(mn, me) != 1)
			me = NULL;
	}

	me->changed = 0;

	if (filename)
		*filename = me->path;
	if (type)
		*type = me->type;

	DBG(MONITOR, ul_debugobj(mn, " *** success [changed: %s]", me->path));
	return 0;				/* success */
}

/**
 * mnt_monitor_event_cleanup:
 * @mn: monitor
 *
 * This function cleanups (drain) internal buffers. It's necessary to call
 * this function after event if you do not call mnt_monitor_next_change().
 *
 * Returns: 0 on success, <0 on error
 */
int mnt_monitor_event_cleanup(struct libmnt_monitor *mn)
{
	int rc;

	if (!mn || mn->fd < 0)
		return -EINVAL;

	while ((rc = mnt_monitor_next_change(mn, NULL, NULL)) == 0);
	return rc < 0 ? rc : 0;
}

#ifdef TEST_PROGRAM

static struct libmnt_monitor *create_test_monitor(int argc, char *argv[])
{
	struct libmnt_monitor *mn;
	int i;

	mn = mnt_new_monitor();
	if (!mn) {
		warn("failed to allocate monitor");
		goto err;
	}

	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "userspace") == 0) {
			if (mnt_monitor_enable_userspace(mn, TRUE, NULL)) {
				warn("failed to initialize userspace monitor");
				goto err;
			}

		} else if (strcmp(argv[i], "kernel") == 0) {
			if (mnt_monitor_enable_kernel(mn, TRUE)) {
				warn("failed to initialize kernel monitor");
				goto err;
			}
		}
	}
	if (i == 1) {
		warnx("No monitor type specified");
		goto err;
	}

	return mn;
err:
	mnt_unref_monitor(mn);
	return NULL;
}

/*
 * create a monitor and add the monitor fd to epoll
 */
static int __test_epoll(struct libmnt_test *ts, int argc, char *argv[], int cleanup)
{
	int fd, efd = -1, rc = -1;
	struct epoll_event ev;
	struct libmnt_monitor *mn = create_test_monitor(argc, argv);

	if (!mn)
		return -1;

	fd = mnt_monitor_get_fd(mn);
	if (fd < 0) {
		warn("failed to initialize monitor fd");
		goto done;
	}

	efd = epoll_create1(EPOLL_CLOEXEC);
	if (efd < 0) {
		warn("failed to create epoll");
		goto done;
	}

	ev.events = EPOLLIN;
	ev.data.fd = fd;

	rc = epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev);
	if (rc < 0) {
		warn("failed to add fd to epoll");
		goto done;
	}

	printf("waiting for changes...\n");
	do {
		const char *filename = NULL;
		struct epoll_event events[1];
		int n = epoll_wait(efd, events, 1, -1);

		if (n < 0) {
			rc = -errno;
			warn("polling error");
			goto done;
		}
		if (n == 0 || events[0].data.fd != fd)
			continue;

		printf(" top-level FD active\n");
		if (cleanup)
			mnt_monitor_event_cleanup(mn);
		else {
			while (mnt_monitor_next_change(mn, &filename, NULL) == 0)
				printf("  %s: change detected\n", filename);
		}
	} while (1);

	rc = 0;
done:
	if (efd >= 0)
		close(efd);
	mnt_unref_monitor(mn);
	return rc;
}

/*
 * create a monitor and add the monitor fd to epoll
 */
static int test_epoll(struct libmnt_test *ts, int argc, char *argv[])
{
	return __test_epoll(ts, argc, argv, 0);
}

static int test_epoll_cleanup(struct libmnt_test *ts, int argc, char *argv[])
{
	return __test_epoll(ts, argc, argv, 1);
}

/*
 * create a monitor and wait for a change
 */
static int test_wait(struct libmnt_test *ts, int argc, char *argv[])
{
	const char *filename;
	struct libmnt_monitor *mn = create_test_monitor(argc, argv);

	if (!mn)
		return -1;

	printf("waiting for changes...\n");
	while (mnt_monitor_wait(mn, -1) > 0) {
		printf("notification detected\n");

		while (mnt_monitor_next_change(mn, &filename, NULL) == 0)
			printf(" %s: change detected\n", filename);

	}
	mnt_unref_monitor(mn);
	return 0;
}

int main(int argc, char *argv[])
{
	struct libmnt_test tss[] = {
		{ "--epoll", test_epoll, "<userspace kernel ...>  monitor in epoll" },
		{ "--epoll-clean", test_epoll_cleanup, "<userspace kernel ...>  monitor in epoll and clean events" },
		{ "--wait",  test_wait,  "<userspace kernel ...>  monitor wait function" },
		{ NULL }
	};

	return mnt_run_test(tss, argc, argv);
}

#endif /* TEST_PROGRAM */
