/* Written by Holger Veit, released into the public domain */

#include <unistd.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

char* FN = "mmaptest.tmp";

int main(void)
{
	int fd, i, rc;
	char buf[10001];
	char *p;

	/* create a file */
	if ((fd=open(FN,O_RDWR|O_CREAT,0666)) < 0) {
		perror("Create file");
		exit(1);
	}

	/* fill it with lines of "AAAAAbbbbCCCCCdddd" */
	buf[0] = 0;
	for (i=0; i<10000; i+=20)
		strcat(buf+i,"AAAAAbbbbCCCCCdddd\r\n");

	if (write(fd,buf,10001) != 10001) {
		perror("Write file");
		exit(1);
	}

	/* close the file */
	close(fd);

	/* now open the file for reading and try a map write */
	if ((fd=open(FN,O_RDONLY)) < 0) {
		perror("Open test1");
		exit(1);
	}

#ifdef NOTYET
	p = mmap(0, 5000, PROT_WRITE, MAP_SHARED, fd, 0);
	if (p==MAP_FAILED) {
		printf("Test 0 ok\n");
	} else {
		printf("Test 0 FAILED: allowed an attempt to map a R/O file as R/W\n");
		exit(1);
	}
#endif

	/* try to use MAP_FIXED (unsupported) */
	p = mmap((void*)0x1000000, 5000, PROT_READ, MAP_FIXED|MAP_SHARED, fd, 0);
	if (p == MAP_FAILED) {
		printf("Test 1 ok\n");
	} else {
		printf("Test 1 FAILED: allowed the unsupported MAP_FIXED flag\n");
		exit(1);
	}

	/* ok, then try to read */
	p = mmap(0, 5000, PROT_READ, MAP_SHARED, fd, 0);
	if (p != MAP_FAILED) {
		printf("Test 2 ok, addr=%p\n",p);
	} else {
		perror("mmaptest: Error");
		printf("Test 2 FAILED: didn't allow to map R/O file, errno=%d\n",errno);
		exit(1);
	}

	/* check some data */
	/* at Offset 2021, there should be a "AAAAbbbbC" */
	if (strncmp(p+2021, "AAAAbbbbC", 9) == 0) {
		printf("Test 3 ok\n");
	} else {
		printf("Test 3 FAILED: expected was \"AAAAbbbbC\", found was \"");
		for (i=0; i<9; i++) putchar(*(p+2021+i));
		printf("\"\n");
		exit(1);
	}

	/* close the file */
	close(fd);

	/* unmap the region */
	rc = munmap(p,5000);
	if (rc != -1) {
		printf("Test 4 ok\n");
	} else {
		printf("Test 4 FAILED: cannot unmap the region\n");
		exit(1);
	}

	/* look whether you can unmap a region which is already unmapped */
	rc = munmap(p,5000);
	if (rc == -1) {
		printf("Test 5 ok\n");
	} else {
		printf("Test 5 FAILED: apparently can unmap an already unmapped region\n");
		exit(1);
	}

	exit(0);
}
