#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <err.h>

#ifdef RCSID
RCSID("$Id: mmap-and-read.c,v 1.4 1998/12/05 22:45:50 assar Exp $");
#endif

#ifndef MAP_FAILED
#define MAP_FAILED ((void *)-1)
#endif

static char *
generate_random_file (const char *filename,
		      unsigned npages,
		      unsigned pagesize)
{
    int fd;
    char *buf, *fbuf;
    int i;
    int prot;
    int flags;
    size_t sz = npages * pagesize;

    buf = malloc (sz);
    if (buf == NULL)
	err (1, "malloc %u", sz);

    for (i = 0; i < npages; ++i)
	memset (buf + pagesize * i, '0' + i, pagesize);

    fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
    if (fd < 0)
	err (1, "open %s", filename);

    if (ftruncate (fd, sz) < 0)
	err (1, "ftruncate");

    prot = PROT_READ | PROT_WRITE;
    flags = MAP_SHARED;

    fbuf = mmap (0, sz, prot, flags, fd, 0);
    if (fbuf == MAP_FAILED)
	err (1, "mmap");

    if(write(fd, "hej\n", 4) != 4)
	err(1, "write");

    memcpy (fbuf, buf, sz);

#if 0
    if (msync (fbuf, sz, MS_SYNC))
	err(1, "msync");
#endif

    if (munmap (fbuf, sz) != 0)
	err (1, "munmap");

    if (close (fd))
	err (1, "close");
    return buf;
}

static char *
read_file (int fd, size_t sz)
{
    char *buf;

    buf = malloc (sz);
    if (buf == NULL)
	err (1, "malloc %u", sz);
    if (read (fd, buf, sz) != sz)
	err (1, "read");
    return buf;
}

int
main (int argc, char **argv)
{
    const char *file = "foo";
    const size_t sz  = 4 * getpagesize();

    char *buf;
    char *malloc_buf;
    int fd;
    int ret;

    srand (time(NULL));

    buf = generate_random_file (file, 4, getpagesize());

    fd = open (file, O_RDONLY, 0);
    if (fd < 0)
	err (1, "open %s", file);

    malloc_buf = read_file (fd, sz);
    close (fd);
    ret = memcmp (buf, malloc_buf, sz);
    free (buf);
    return ret != 0;
}
