#include <sys/mman.h>
#include <sys/syscall.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

sig_atomic_t gotsigsys;

void
sigsys_handler(int sig)
{

	gotsigsys = 1;
}

int
main()
{
	int pipefds[2];
	int wfd, rfd;

	char p[] = "V";
	char readchar;
	int r;

	if (pipe(pipefds) == -1)
		exit(1);

	rfd = pipefds[0];
	wfd = pipefds[1];

	if (write(wfd, p, 1) != 1)
		exit(1);

	if (read(rfd, &readchar, 1) != 1)
		exit(1);

	if (readchar != p[0])
		exit(1);

	if (syscall(SYS_write, wfd, p, 1) != 1)
		exit(1);

	if (read(rfd, &readchar, 1) != 1)
		exit(1);

	if (readchar != p[0])
		exit(1);

	signal(SIGSYS, sigsys_handler);

	/* check for bug in arm64 32-bit compat code */
	gotsigsys = 0;
	r = __syscall((quad_t)SYS_write << 32, wfd, p, 1);

	if (!gotsigsys)
		exit(1);
	gotsigsys = 0;
	r = __syscall((quad_t)SYS_write, wfd, p, 1);

	if (gotsigsys)
		exit(1);

	if (r != 1)
		exit(1);

	if (read(rfd, &readchar, 1) != 1)
		exit(1);

	if (readchar != p[0])
		exit(1);

	void *addr;

	/* xxx would be better to map a real file with an offset to make sure off_t is endian clean */
	addr = mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);

	if (gotsigsys)
		exit(1);

	if (addr == NULL)
		exit(1);

	if (sizeof(void *) <= sizeof(int)) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
		addr = (void *)syscall(SYS_mmap, NULL, 8192, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
#pragma clang diagnostic pop

		if (addr == NULL)
			exit(1);
	}

	addr = (void *)__syscall(SYS_mmap, NULL, 8192, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);

	if (gotsigsys)
		exit(1);

	if (addr == NULL)
		exit(1);

	return 0;
}
