/* Copyright 2005 George Peter Staplin */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>

/* This is used to touch all of the pages.
 */
void reverse_bytes (unsigned char *buf, int len) {
 unsigned char *head = buf;
 unsigned char *tail = (buf + (len - 1));
 int i;

 for (i = 0; i < (len / 2); ++i) {
  *head = *tail;
  head++;
  tail--;
 }
}

int test_a (void) {
 unsigned char *buf;
 int fd;
 struct stat sb;
 int i;
 
 if (!(fd = open ("bigfile", O_RDONLY, 0666))) {
  perror ("open");
  return EXIT_FAILURE;
 }

 if (fstat (fd, &sb)) {
  perror ("fstat");
  return EXIT_FAILURE;
 }

 if (NULL == (buf = malloc (sb.st_size))) {
  perror ("malloc");
  return EXIT_FAILURE;
 };

 if (sb.st_size != read (fd, buf, sb.st_size)) {
  fprintf (stderr, "failed to read entire file\n");
  return EXIT_FAILURE;
 }

 reverse_bytes (buf, sb.st_size);

 printf ("completed test_a with result: size %d\n", sb.st_size);

 return EXIT_SUCCESS;
}

int test_b (void) {
 unsigned char *buf;
 struct stat sb;
 int fd;
 int i;
 
 if (!(fd = open ("bigfile", O_RDONLY, 0666))) {
  perror ("open");
  return EXIT_FAILURE;
 }

 if (fstat (fd, &sb)) {
  perror ("fstat");
  return EXIT_FAILURE;
 }

 buf = mmap (0, sb.st_size, (PROT_READ | PROT_WRITE), MAP_FILE, fd, 0);

 if (MAP_FAILED == buf) {
  perror ("mmap");
  return EXIT_FAILURE;
 }

 reverse_bytes (buf, sb.st_size);

 printf ("completed test_b with result: size %d\n", sb.st_size);

 return EXIT_SUCCESS;
}

int main (int argc, char *argv[]) { 

 if (1 == argc) {
  return test_a ();
 }

 return test_b ();
}
