/*
	FileGen.c	Test file generator.

	First Written : 27/08/1999	by M.A.Smith	V1.0

	Updates :	31/08/1999	by M.A.Smith	V1.1
					Bug fixed in selecting 'random contents' option 
					from the command line.

		(c) 1999 dataIP		http://www.dataIP.co.uk/
*/

#include <stdio.h>
#include <stdlib.h>

#define FG_SEQUENTIAL	0		/* Flags to define if required contents */
#define FG_RANDOM	1		/* is 'random' or in a sequence 0..255  */

#define BUFFER_SIZE	512		/* NOTE : If this is not a multiple of 256,  */
					/* the sequential fill option will result    */
					/* in odd 'steps' in the file contents.      */


static char Progress[] = 
	{ '|', '/', '-', '\\' };	/* Used to generate a 'progress' display */

/* ---------------------------------------------------------------------------- */
/* Fill the buffer with sequential bytes starting at 0 (obviously(?) restarting */
/* at 0 after 255). */

static void SequentialFill(unsigned char *Buffer, unsigned int Length)
	{
	unsigned char Index = 0;
	while (Length-- > 0)
		{
		*Buffer = Index++;
		Buffer++;
		}
	}

/* ---------------------------------------------------------------------------- */
/* Fill the buffer with random bytes.	*/

static void RandomFill(unsigned char *Buffer, unsigned int Length)
	{
	while (Length-- > 0)
		{
		*Buffer = rand();
		Buffer++;
		}
	}

/* ---------------------------------------------------------------------------- */
/* Create a binary file of the given size.                                      */
/* If Type is zero, a file with sequential contents is created (starting at 0). */
/* else, the file has random contents.                                          */

/* If the file could not be created, MF_NOCREATE is returned.
   If an error occured  during writing MF_NOSPACE is returned, 
   else 0 if all is okay.     */
#define MF_NOSPACE	(-2)
#define MF_NOCREATE	(-1)

static int MakeFile(char *Filename, unsigned long FileSize, int Type)
	{
	unsigned char Buffer[BUFFER_SIZE];
	FILE *Handle;
	int Result = 0;

	/* Start with sequential contents... may get overwritten later */
	SequentialFill(Buffer, BUFFER_SIZE);

	/* Create file */
	if ( (Handle = fopen(Filename, "wb")) != NULL)
		{
		/* If it was okay... */
		unsigned char ProgressIndex = 0;

		/* Add a blank to make space for progress indication */
		printf(" ");

		while ( (FileSize > 0) && (Result == 0) )
			{
			/* If random contents are required, then replace it every */
			/* pass, otherwise it won't be very random! */
			if (Type)
				{
				RandomFill(Buffer, BUFFER_SIZE);
				}

			/* Write buffer */
			if (FileSize >= BUFFER_SIZE)
				{
				if (fwrite(Buffer, 1, BUFFER_SIZE, Handle) != BUFFER_SIZE)
					Result = MF_NOSPACE;

				/* Calculate the number of bytes left to do */
				FileSize = FileSize - BUFFER_SIZE;
				}
			else
				{
				if (fwrite(Buffer, 1, (int)FileSize, Handle) != (int)FileSize)
					Result = MF_NOSPACE;

				/* No bytes left to do */
				FileSize = 0;
				}


			/* Remove previous, and display new progress indicator */
			printf("\b%c", Progress[ProgressIndex]);
			ProgressIndex = ++ProgressIndex % 4;
			}

		/* Remove last progress indication */
		printf("\b");

		fclose(Handle);
		return (Result);
		}
	else
		{
		return (MF_NOCREATE);
		}		
	}


/* ---------------------------------------------------------------------------- */

static void Help(void)
	{
	puts("Usage:-");
	puts("   FileGen Name Size [R|S]\n");
	puts("   Name  The required output filename.");
	puts("   Size  The size in bytes of the generated file.");
	puts("   R     Use randomly generated file contents.");
	puts("   S     Use sequential file contents (bytes 00,01..FE,FF repeated).");
	puts("\n       (c)1999 dataIP             This program is freeware");
	puts("   http://www.dataIP.co.uk/       distribute as required.\n");
	}

/* ---------------------------------------------------------------------------- */

int main(int argc, char **argv)
	{
	int Result;

	if ( (argc == 3) || (argc == 4) )
		{
		unsigned long Size;
		int Type;
		
		printf("FileGen V1.1\n");
		sscanf(argv[2], "%lu", &Size);
		Type = (toupper(*argv[3]) == (int)'R' ? FG_RANDOM : FG_SEQUENTIAL);

		printf("  Generating file \"%s\"\n   using %lu bytes and %s contents...", argv[1], Size, (Type == FG_RANDOM ? "random" : "sequential"));
		Result = MakeFile(argv[1], Size, Type);

		switch (Result)
			{
			case MF_NOSPACE:
				puts("\nFAILED : Out of space?");
				break;
			case MF_NOCREATE:
				puts("\nFAILED : Could not create file.");
				break;
			default:
				puts(" complete.");
			}

		}
	else
		{
		Help();
		}

	return (0);
	}

/* ---------------------------------------------------------------------------- */
