#define _GNU_SOURCE
#define __USE_GNU

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <asm/page.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#ifndef PAGE_SIZE
#define PAGE_SIZE getpagesize()
#endif

#define WRITE_LEN 2147483648UL

void *buf = NULL;
int opt_r = 0;
int opt_w = 0;
int opt_d = 0;
char *filename = NULL;
unsigned long f_size = WRITE_LEN;

void parse_args(int argc, char **argv)
{
	int opt;

	while ((opt = getopt(argc, argv, "rwds:f:")) != EOF) {
		switch (opt) {
		case 'r':
			opt_r++;
			break;
		case 'w':
			opt_w++;
			break;
		case 'd':
			opt_d++;
			break;
		case 'f':
			filename = optarg;
			break;
		case 's':
			f_size = atoi(optarg);
			printf("%lu,", f_size);
		}
	}

	if ((opt_r && opt_w) || !filename) {
		fprintf(stderr, "bad parameter\n");
		exit(1);
	}
}

int main(int argc, char *argv[])
{
	int fd, num, ret;
	int count = 0;
	int flags = O_RDWR | O_LARGEFILE;

	parse_args(argc, argv);

	if (opt_d)
		flags |= O_DIRECT;
	if (opt_w)
		flags |= O_CREAT;
	
	if ((fd = open(filename, flags, 0600)) < 0) {
		perror("open fail");
		return 1;
	}

	ret = posix_memalign(&buf, PAGE_SIZE, 4096);
        if (ret < 0) {
		perror("posix_memalign");
                return 1;
        }
	memset(buf, 0xaa, 4096);

	if (opt_r) {
		while ((num = read(fd, buf, 4096))) {
			if (num <= 0) {
				printf("num:%d\n", num);
				perror("read");
				return 1;
			}
			count += num;
		}
	}	

	if (opt_w) {
		while ((count += write(fd, buf, 4096)) < f_size) {
			;
		}
	}

	close(fd);
	printf("%d\n", count);
	return 0;
}
