/* By Scott Anderson, Spring 2005
 *
 * Edited to conform to Linux coding standards
 * by Mark A. Sheldon, Spring 2008
 */

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>		/* for exit() */
#include <sys/types.h>		/* for open() */
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>		/* for strcpy */

#define BLOCKSIZE 4012

struct datablock {
	int pageno;
	char data[BLOCKSIZE-4];
};

int main( int argc, char* argv[] )
{
	int file_size;
	int dbf;
	char buf[1];		/* Fill up the file with this byte */
	int prev_num_bytes=0;
	int prev_num_blocks=0;
	int prev_num_disk_blocks=0;
	int disk_blksize;
	struct stat statbuf;

	buf[0] = 'A';

	if( sizeof(struct datablock) != BLOCKSIZE ) {
		fprintf(stderr,"a datablock is %d not %d\n",
			sizeof(struct datablock), BLOCKSIZE );
		exit(1);
	}
	if( argc < 3 ) {
		printf("Usage: %s dbfile size_in_blocks\n", argv[0]);
		exit(1);
	}
	file_size = atoi(argv[2]);
	dbf = open(argv[1], O_RDWR | O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP );
	if ( -1 == dbf ) {
		perror("Couldn't open file");
		exit(2);
	}
	if ( !fstat(dbf,&statbuf) ) perror("before main loop");
	printf("blocksize for filesystem I/O: %d\n", (int) statbuf.st_blksize);
	disk_blksize = statbuf.st_blksize;

	for (;;) {
		int size = write(dbf, buf, 1);
		if( 1 != size ) {
			fprintf(stderr, "write failed at byte %d\n",
				prev_num_bytes);
			perror("after write");
		}
		if ( 0 != fstat(dbf, &statbuf) ) perror("after fstat");
		if ( prev_num_bytes + 1 != statbuf.st_size ) {
			printf("Disagrees on file size:  prev=%d, stat=%d\n",
			       prev_num_bytes + 1, (int) statbuf.st_size);
			break;
		}
		if ( prev_num_blocks != statbuf.st_blocks ) {
			printf("%d bytes => %d legacy blocks => %d ",
				prev_num_bytes, prev_num_blocks,
			       prev_num_disk_blocks);
			printf("disk blocks\n");
			printf("%d bytes => %d legacy blocks ",
			       (int) statbuf.st_size,
			       (int) statbuf.st_blocks);
			printf("=> %d disk blocks %s\n",
			       (int) statbuf.st_blocks * 512 / disk_blksize,
			       prev_num_disk_blocks + 1
			       != statbuf.st_blocks * 512 / disk_blksize ?
			       " ***********" :
			       "");
		}
		// preserve old values
		prev_num_bytes = statbuf.st_size;
		prev_num_blocks = statbuf.st_blocks;
		prev_num_disk_blocks = statbuf.st_blocks * 512 / disk_blksize;
		// consider quitting
		if ( prev_num_disk_blocks >= file_size ) break;
	}
	close(dbf);
	return 0;
}
