/*
 * random_exercise.c --- Test program which exercises an ext2
 * 	filesystem.  It creates a lot of random files in the current
 * 	directory, while holding some files open while they are being
 * 	deleted.  This exercises the orphan list code, as well as
 * 	creating lots of fodder for the ext3 journal.
 *
 * Copyright (C) 2000 Theodore Ts'o.
 *
 * %Begin-Header%
 * This file may be redistributed under the terms of the GNU Public
 * License.
 * %End-Header%
 */

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

#define MAXFDS	128

struct state {
	char	name[16];
	int	state;
	int	isdir;
};

#define STATE_CLEAR	0
#define STATE_CREATED	1
#define STATE_DELETED	2

struct state state_array[MAXFDS];

#define DATA_SIZE 65536

char data_buffer[DATA_SIZE];

void clear_state_array()
{
	int	i;

	for (i = 0; i < MAXFDS; i++)
		state_array[i].state = STATE_CLEAR;
}

int get_random_fd()
{
	int	fd;

	while (1) {
		fd = ((int) random()) % MAXFDS;
		if (fd > 2)
			return fd;
	}
}

unsigned int get_inode_num(int fd)
{
	struct stat st;

	if (fstat(fd, &st) < 0) {
		perror("fstat");
		return 0;
	}
	return st.st_ino;
}


void create_random_file()
{
	char template[16] = "EX.XXXXXX";
	int	fd;
	int	isdir = 0;
	int	size;

	mktemp(template);
	isdir = random() & 1;
	if (isdir) {
		if (mkdir(template, 0700) < 0)
			return;
		fd = open(template, O_RDONLY, 0600);
		printf("Created temp directory %s, fd = %d\n",
		       template, fd);
	} else {
		size = random() & (DATA_SIZE-1);
		fd = open(template, O_CREAT|O_RDWR, 0600);
		write(fd, data_buffer, size);
		printf("Created temp file %s, fd = %d, size=%d\n",
		       template, fd, size);
	}
	state_array[fd].isdir = isdir;
	if (fd < 0)
		return;
	state_array[fd].isdir = isdir;
	state_array[fd].state = STATE_CREATED;
	strcpy(state_array[fd].name, template);
}

void truncate_file(int fd)
{
	int	size;

	size = random() & (DATA_SIZE-1);

	if (state_array[fd].isdir)
		return;

	ftruncate(fd, size);
	printf("Truncating temp file %s, fd = %d, ino=%u, size=%d\n",
	       state_array[fd].name, fd, get_inode_num(fd), size);
}


void unlink_file(int fd)
{
	char *filename = state_array[fd].name;

	printf("Deleting %s, fd = %d, ino = %u\n", filename, fd,
	       get_inode_num(fd));

	if (state_array[fd].isdir)
		rmdir(filename);
	else
		unlink(filename);
	state_array[fd].state = STATE_DELETED;
}

void close_file(int fd)
{
	char *filename = state_array[fd].name;

	printf("Closing %s, fd = %d, ino = %u\n", filename, fd,
	       get_inode_num(fd));

	close(fd);
	state_array[fd].state = STATE_CLEAR;
}


main(int argc, char **argv)
{
	int	i, fd;

	memset(data_buffer, 0, sizeof(data_buffer));
	sprintf(data_buffer, "This is a test file created by the "
		"random_exerciser program\n");

	for (i=0; i < 100000; i++) {
		fd = get_random_fd();
		switch (state_array[fd].state) {
		case STATE_CLEAR:
			create_random_file();
			break;
		case STATE_CREATED:
			if ((state_array[fd].isdir == 0) &&
			    (random() & 2))
				truncate_file(fd);
			else
				unlink_file(fd);
			break;
		case STATE_DELETED:
			close_file(fd);
			break;
		}
	}
}


