#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

char *filename = "/tmp/test_mmap.dat";

int test_mmap( int fd, unsigned char *ptr, int offset )
{
  char buffer[16], before[16];
  int i;

  /* Fill buffer with some pseudo random bytes */
  for( i = 0; i < 4; i++ )
  {
    *(int*)(buffer + i*4) = random();
  }
  
  printf( "Offset: 0x%04X  ", offset );
  memcpy( before, ptr+offset, 16 );           /* Save current value */

  lseek( fd, offset, SEEK_SET );              /* Write() to file */
  write( fd, buffer, 16 );
  
  if( memcmp( before, buffer, 16 ) == 0  ||   /* Check mmap() changed */
      memcmp( ptr+offset, buffer, 16 ) != 0 )
  {
    printf( "Error\n" );
  }
  else
  {
    printf( "OK\n" );
  }
}

/* Make a 64K file to test */
void make_file()
{
  FILE *file = fopen( "/tmp/test_mmap.dat", "wb" );
  char buffer[256];
  int i;
  
  if( file == NULL )
  {
    perror( "Couldn't create test file" );
    exit(1);
  }
  
  memset( buffer, 0, sizeof(buffer) );
  for( i=0; i<256; i++ )
    fwrite( buffer, sizeof(buffer), 1, file );
    
  fclose( file );
}

int main()
{
  unsigned int offset = 0x12345678;
  int i, fd;
  unsigned char *ptr;
  
  make_file();
  
  fd = open( filename, O_RDWR );
  ptr = mmap( NULL, 65536, PROT_READ, MAP_SHARED, fd, 0 );

  for( i=0; i<64; i++ )    /* We go 64 times so each offset is modified more that once */
  {
    test_mmap( fd, ptr, offset & 0xFFFF );
    offset = (offset << 1) | (offset >> 31);  /* Rotate offset */
  }
}
