/*
 * Copyright (c) 2014 SUSE.  All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Further, this software is distributed without any warranty that it is
 * free of the rightful claim of any third person regarding infringement
 * or the like.  Any license provided herein, whether implied or
 * otherwise, applies only to this software file.  Patent licenses, if
 * any, provided herein do not apply to combinations of this program with
 * other software, or any other product whatsoever.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Started by Jan Kara <jack@suse.cz>
 *
 * DESCRIPTION
 *     Check that fanotify properly merges ignore mask of an inode and
 *     mountpoint.
 */
#include "config.h"

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/syscall.h>
#include "test.h"
#include "linux_syscall_numbers.h"
#include "fanotify.h"
#include "safe_macros.h"

char *TCID = "fanotify06";

#if defined(HAVE_SYS_FANOTIFY_H)
#include <sys/fanotify.h>

#define EVENT_MAX 1024
/* size of the event structure, not counting name */
#define EVENT_SIZE  (sizeof (struct fanotify_event_metadata))
/* reasonable guess as to size of 1024 events */
#define EVENT_BUF_LEN        (EVENT_MAX * EVENT_SIZE)

static void setup(void);
static void cleanup(void);

unsigned int fanotify_prio[] = {
	FAN_CLASS_PRE_CONTENT,
	FAN_CLASS_CONTENT,
	FAN_CLASS_NOTIF
};
#define FANOTIFY_PRIORITIES ARRAY_SIZE(fanotify_prio)

#define GROUPS_PER_PRIO 3

int TST_TOTAL = GROUPS_PER_PRIO * FANOTIFY_PRIORITIES;

#define BUF_SIZE 256
static char fname[BUF_SIZE];
static int fd;
static int fd_notify[FANOTIFY_PRIORITIES][GROUPS_PER_PRIO];

static char event_buf[EVENT_BUF_LEN];

static void create_fanotify_groups(void)
{
	unsigned int p, i;
	int ret;

	for (p = 0; p < FANOTIFY_PRIORITIES; p++) {
		for (i = 0; i < GROUPS_PER_PRIO; i++) {
			fd_notify[p][i] = fanotify_init(fanotify_prio[p] |
							FAN_NONBLOCK,
							O_RDONLY);
			if (fd_notify[p][i] < 0) {
				if (errno == ENOSYS) {
					tst_brkm(TCONF, cleanup,
						 "fanotify is not configured in"
						 " this kernel.");
				} else {
					tst_brkm(TBROK | TERRNO, cleanup,
						 "fanotify_init failed");
				}
			}
			/* Add mount mark for each group */
			ret = fanotify_mark(fd_notify[p][i],
					    FAN_MARK_ADD | FAN_MARK_MOUNT,
					    FAN_MODIFY,
					    AT_FDCWD, ".");
			if (ret < 0) {
				tst_brkm(TBROK | TERRNO, cleanup,
					 "fanotify_mark(%d, FAN_MARK_ADD | "
					 "FAN_MARK_MOUNT, FAN_MODIFY, AT_FDCWD,"
					 " '.') failed", fd_notify[p][i]);
			}
			/* Add ignore mark for groups with higher priority */
			if (p == 0)
				continue;
			ret = fanotify_mark(fd_notify[p][i],
					    FAN_MARK_ADD |
					    FAN_MARK_IGNORED_MASK |
					    FAN_MARK_IGNORED_SURV_MODIFY,
					    FAN_MODIFY, AT_FDCWD, fname);
			if (ret < 0) {
				tst_brkm(TBROK | TERRNO, cleanup,
					 "fanotify_mark(%d, FAN_MARK_ADD | "
					 "FAN_MARK_IGNORED_MASK | "
					 "FAN_MARK_IGNORED_SURV_MODIFY, "
					 "FAN_MODIFY, AT_FDCWD, %s) failed",
					 fd_notify[p][i], fname);
			}
		}
	}
}

static void cleanup_fanotify_groups(void)
{
	unsigned int i, p;

	for (p = 0; p < FANOTIFY_PRIORITIES; p++) {
		for (i = 0; i < GROUPS_PER_PRIO; i++) {
			if (fd_notify[p][i] && fd_notify[p][i] != -1) {
				if (close(fd_notify[p][i]) == -1)
					tst_resm(TWARN, "close(%d) failed",
						 fd_notify[p][i]);
				fd_notify[p][i] = 0;
			}
		}
	}
}

static void verify_event(int group, struct fanotify_event_metadata *event)
{
	if (event->mask != FAN_MODIFY) {
		tst_resm(TFAIL, "group %d get event: mask %llx (expected %llx) "
			 "pid=%u fd=%u", group, (unsigned long long)event->mask,
			 (unsigned long long)FAN_MODIFY,
			 (unsigned)event->pid, event->fd);
	} else if (event->pid != getpid()) {
		tst_resm(TFAIL, "group %d get event: mask %llx pid=%u "
			 "(expected %u) fd=%u", group,
			 (unsigned long long)event->mask, (unsigned)event->pid,
			 (unsigned)getpid(), event->fd);
	} else {
		tst_resm(TPASS, "group %d get event: mask %llx pid=%u fd=%u",
			 group, (unsigned long long)event->mask,
			 (unsigned)event->pid, event->fd);
	}
}

int main(int ac, char **av)
{
	int lc;
	const char *msg;

	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);

	setup();

	for (lc = 0; TEST_LOOPING(lc); lc++) {
		int ret;
		unsigned int p, i;
		struct fanotify_event_metadata *event;

		create_fanotify_groups();

		/*
		 * generate sequence of events
		 */
		fd = SAFE_OPEN(cleanup, fname, O_RDWR);
		SAFE_WRITE(cleanup, 1, fd, fname, strlen(fname));
		SAFE_CLOSE(cleanup, fd);

		/* First verify all groups without ignore mask got the event */
		for (i = 0; i < GROUPS_PER_PRIO; i++) {
			ret = read(fd_notify[0][i], event_buf, EVENT_BUF_LEN);
			if (ret < 0) {
				if (errno == EAGAIN) {
					tst_resm(TFAIL, "group %d did not get "
						 "event", i);
				}
				tst_brkm(TBROK | TERRNO, cleanup,
					 "reading fanotify events failed");
			}
			if (ret < (int)FAN_EVENT_METADATA_LEN) {
				tst_brkm(TBROK, cleanup,
					 "short read when reading fanotify "
					 "events (%d < %d)", ret,
					 (int)EVENT_BUF_LEN);
			}
			event = (struct fanotify_event_metadata *)event_buf;
			if (ret > (int)event->event_len) {
				tst_resm(TFAIL, "group %d got more than one "
					 "event (%d > %d)", i, ret,
					 event->event_len);
			} else
				verify_event(i, event);
			close(event->fd);
		}
		for (p = 1; p < FANOTIFY_PRIORITIES; p++) {
			for (i = 0; i < GROUPS_PER_PRIO; i++) {
				ret = read(fd_notify[p][i], event_buf, EVENT_BUF_LEN);
				if (ret > 0) {
					tst_resm(TFAIL, "group %d got event",
						 p*GROUPS_PER_PRIO + i);
				} else if (ret == 0) {
					tst_brkm(TBROK, cleanup, "zero length "
						 "read from fanotify fd");
				} else if (errno != EAGAIN) {
					tst_brkm(TBROK | TERRNO, cleanup,
						 "reading fanotify events failed");
				} else {
					tst_resm(TPASS, "group %d got no event",
						 p*GROUPS_PER_PRIO + i);
				}
			}
		}
		cleanup_fanotify_groups();
	}

	cleanup();
	tst_exit();
}

static void setup(void)
{
	tst_sig(NOFORK, DEF_HANDLER, cleanup);

	TEST_PAUSE;

	tst_tmpdir();

	sprintf(fname, "tfile_%d", getpid());
	fd = SAFE_OPEN(cleanup, fname, O_RDWR | O_CREAT, 0700);
	SAFE_WRITE(cleanup, 1, fd, fname, 1);

	/* close the file we have open */
	SAFE_CLOSE(cleanup, fd);
}

static void cleanup(void)
{
	cleanup_fanotify_groups();
	tst_rmdir();
}

#else

int main(void)
{
	tst_brkm(TCONF, NULL, "system doesn't have required fanotify support");
}

#endif
