#include <unistd.h>		// sysconf
#include <stdio.h>		// printf
#include <stdlib.h>		// exit
#include <fcntl.h>		// O_RDWR
#include <sys/mman.h>	// mmap
#include <string.h>		// strlen
#include <errno.h>		// errno

#define eprintf(args...) fprintf(stderr, ##args)

const char *DEVICE_PATH = "/dev/my_shmem";

int parse_argument(int argc, char *argv[], size_t *parsed_arg) {
	if (argc != 2) {
		eprintf(
			"Usage: %s <decimal: number of pages to write>\n", argv[0]);
		return 1;
	}

	*parsed_arg = strtol(argv[1], NULL, 10);
	if (errno)
		return 1;
	return 0;
}

int main(int argc, char *argv[])
{
	// Set write & alloc amount
	size_t page_count;
	if (parse_argument(argc, argv, &page_count))
		exit(EXIT_FAILURE);

	const long PAGE_SIZE = sysconf(_SC_PAGESIZE);
	if (PAGE_SIZE == -1) {
		eprintf("Error retrieving page size: %d.\n", errno);
		exit(EXIT_FAILURE);
	}

	const size_t WRITE_AMNT = PAGE_SIZE * page_count;

	// open device file w/ RW perms
	FILE *fp = fopen(DEVICE_PATH, "r+");
	if (!fp) {
		eprintf("Error opening device %s: %d.\n", DEVICE_PATH, errno);
		exit(EXIT_FAILURE);
	}
	int fd = fileno(fp);
	if (fd == -1) {
		eprintf("Error retrieving file descriptor: %d.\n", errno);
		exit(EXIT_FAILURE);
	}

	// mmap device
	void *buf = mmap(NULL, WRITE_AMNT, PROT_READ | PROT_WRITE,
		MAP_SHARED, fd, 0);
	if (!buf) {
		eprintf("Error mmap-ing: %d.\n", errno);
		exit(EXIT_FAILURE);
	}

	// Write to mmap-ed device
	char to_write[4] = {0xca, 0xfe, 0xbe, 0xef};
	for (size_t byte_offset = 0; byte_offset < WRITE_AMNT; byte_offset += 4)
		memcpy(buf, to_write, 4);

	// Unmap device
	munmap(buf, WRITE_AMNT);

	// Close device
	fclose(fp);

	printf("Finished!\n");
	exit(EXIT_SUCCESS);
}
