/* SPDX-License-Identifier: MIT */
/*
 * Description: test sharing a ring across a fork
 */
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include "liburing.h"


struct forktestmem
{
	struct io_uring ring;
	pthread_barrier_t barrier;
	pthread_barrierattr_t barrierattr;
};

static int open_tempfile(const char *dir, const char *fname)
{
	int fd;
	char buf[32];

	snprintf(buf, sizeof(buf), "%s/%s",
		 dir, fname);
	fd = open(buf, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
	if (fd < 0) {
		perror("open");
		exit(1);
	}

	return fd;
}

static int submit_write(struct io_uring *ring, int fd, const char *str,
			int wait)
{
	struct io_uring_sqe *sqe;
	struct iovec iovec;
	int ret;

	sqe = io_uring_get_sqe(ring);
	if (!sqe) {
		fprintf(stderr, "could not get sqe\n");
		return 1;
	}

	iovec.iov_base = (char *) str;
	iovec.iov_len = strlen(str);
	io_uring_prep_writev(sqe, fd, &iovec, 1, 0);
	ret = io_uring_submit_and_wait(ring, wait);
	if (ret < 0) {
		fprintf(stderr, "submit failed: %s\n", strerror(-ret));
		return 1;
	}

	return 0;
}

static int wait_cqe(struct io_uring *ring, const char *stage)
{
	struct io_uring_cqe *cqe;
	int ret;

	ret = io_uring_wait_cqe(ring, &cqe);
	if (ret) {
		fprintf(stderr, "%s wait_cqe failed %d\n", stage, ret);
		return 1;
	}
	if (cqe->res < 0) {
		fprintf(stderr, "%s cqe failed %d\n", stage, cqe->res);
		return 1;
	}

	io_uring_cqe_seen(ring, cqe);
	return 0;
}

static int verify_file(const char *tmpdir, const char *fname, const char* expect)
{
	int fd;
	char buf[512];
	int err = 0;

	memset(buf, 0, sizeof(buf));

	fd = open_tempfile(tmpdir, fname);
	if (fd < 0)
		return 1;

	if (read(fd, buf, sizeof(buf) - 1) < 0)
		return 1;

	if (strcmp(buf, expect) != 0) {
		fprintf(stderr, "content mismatch for %s\n"
			"got:\n%s\n"
			"expected:\n%s\n",
			fname, buf, expect);
		err = 1;
	}

	close(fd);
	return err;
}

static void cleanup(const char *tmpdir)
{
	char buf[32];

	/* don't check errors, called during partial runs */

	snprintf(buf, sizeof(buf), "%s/%s", tmpdir, "shared");
	unlink(buf);

	snprintf(buf, sizeof(buf), "%s/%s", tmpdir, "parent1");
	unlink(buf);

	snprintf(buf, sizeof(buf), "%s/%s", tmpdir, "parent2");
	unlink(buf);

	snprintf(buf, sizeof(buf), "%s/%s", tmpdir, "child");
	unlink(buf);

	rmdir(tmpdir);
}

int main(int argc, char *argv[])
{
	struct forktestmem *shmem;
	char tmpdir[] = "forktmpXXXXXX";
	int shared_fd;
	int ret;
	pid_t p;

	if (argc > 1)
		return 0;

	shmem = mmap(0, sizeof(struct forktestmem), PROT_READ|PROT_WRITE,
		   MAP_SHARED | MAP_ANONYMOUS, 0, 0);
	if (!shmem) {
		fprintf(stderr, "mmap failed\n");
		exit(1);
	}

	pthread_barrierattr_init(&shmem->barrierattr);
	pthread_barrierattr_setpshared(&shmem->barrierattr, 1);
	pthread_barrier_init(&shmem->barrier, &shmem->barrierattr, 2);

	ret = io_uring_queue_init(10, &shmem->ring, 0);
	if (ret < 0) {
		fprintf(stderr, "queue init failed\n");
		exit(1);
	}

	if (mkdtemp(tmpdir) == NULL) {
		fprintf(stderr, "temp directory creation failed\n");
		exit(1);
	}

	shared_fd = open_tempfile(tmpdir, "shared");

	/*
	 * First do a write before the fork, to test whether child can
	 * reap that
	 */
	if (submit_write(&shmem->ring, shared_fd, "before fork: write shared fd\n", 0))
		goto errcleanup;

	p = fork();
	switch (p) {
	case -1:
		fprintf(stderr, "fork failed\n");
		goto errcleanup;

	default: {
		/* parent */
		int parent_fd1;
		int parent_fd2;
		int wstatus;

		/* wait till fork is started up */
		pthread_barrier_wait(&shmem->barrier);

		parent_fd1 = open_tempfile(tmpdir, "parent1");
		parent_fd2 = open_tempfile(tmpdir, "parent2");

		/* do a parent write to the shared fd */
		if (submit_write(&shmem->ring, shared_fd, "parent: write shared fd\n", 0))
			goto errcleanup;

		/* do a parent write to an fd where same numbered fd exists in child */
		if (submit_write(&shmem->ring, parent_fd1, "parent: write parent fd 1\n", 0))
			goto errcleanup;

		/* do a parent write to an fd where no same numbered fd exists in child */
		if (submit_write(&shmem->ring, parent_fd2, "parent: write parent fd 2\n", 0))
			goto errcleanup;

		/* wait to switch read/writ roles with child */
		pthread_barrier_wait(&shmem->barrier);

		/* now wait for child to exit, to ensure we still can read completion */
		waitpid(p, &wstatus, 0);
		if (WEXITSTATUS(wstatus) != 0) {
			fprintf(stderr, "child failed\n");
			goto errcleanup;
		}

		if (wait_cqe(&shmem->ring, "p cqe 1"))
			goto errcleanup;

		if (wait_cqe(&shmem->ring, "p cqe 2"))
			goto errcleanup;

		/* check that IO can still be submitted after child exited */
		if (submit_write(&shmem->ring, shared_fd, "parent: write shared fd after child exit\n", 0))
			goto errcleanup;

		if (wait_cqe(&shmem->ring, "p cqe 3"))
			goto errcleanup;

		break;
	}
	case 0: {
		/* child */
		int child_fd;

		/* wait till fork is started up */
		pthread_barrier_wait(&shmem->barrier);

		child_fd = open_tempfile(tmpdir, "child");

		if (wait_cqe(&shmem->ring, "c cqe shared"))
			exit(1);

		if (wait_cqe(&shmem->ring, "c cqe parent 1"))
			exit(1);

		if (wait_cqe(&shmem->ring, "c cqe parent 2"))
			exit(1);

		if (wait_cqe(&shmem->ring, "c cqe parent 3"))
			exit(1);

		/* wait to switch read/writ roles with parent */
		pthread_barrier_wait(&shmem->barrier);

		if (submit_write(&shmem->ring, child_fd, "child: write child fd\n", 0))
			exit(1);

		/* ensure both writes have finished before child exits */
		if (submit_write(&shmem->ring, shared_fd, "child: write shared fd\n", 2))
			exit(1);

		exit(0);
	}
	}

	if (verify_file(tmpdir, "shared",
			 "before fork: write shared fd\n"
			 "parent: write shared fd\n"
			 "child: write shared fd\n"
			 "parent: write shared fd after child exit\n") ||
	    verify_file(tmpdir, "parent1", "parent: write parent fd 1\n") ||
	    verify_file(tmpdir, "parent2", "parent: write parent fd 2\n") ||
	    verify_file(tmpdir, "child", "child: write child fd\n"))
		goto errcleanup;

	cleanup(tmpdir);
	exit(0);

errcleanup:
	cleanup(tmpdir);
	exit(1);
}
