#!/bin/bash
###SHELLPACK preamble sparsetruncate 0

###SHELLPACK parseargBegin
###SHELLPACK parseargEnd

###SHELLPACK self_extract sparsetruncate.c 

mkdir $SHELLPACK_SOURCES/sparsetruncate-${VERSION}-installed
gcc -Wall -lpthread $SHELLPACK_TEMP/sparsetruncate.c -o $SHELLPACK_SOURCES/sparsetruncate-${VERSION}-installed/sparsetruncate || \
	die Failed to build sparsetruncate

echo sparsetruncate installed successfully
exit $SHELLPACK_SUCCESS

==== BEGIN sparsetruncate.c ====
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/stat.h>

unsigned long time_diff(struct timeval *start, struct timeval *end)
{
	return ((unsigned long long)(end->tv_sec - start->tv_sec)) * 1000000 +
		end->tv_usec - start->tv_usec;
}

void write_file(int fd, loff_t size)
{
	char buf[16];
	int i;

	if (ftruncate(fd, size) < 0) {
		perror("ftruncate");
		exit(1);
	}
	for (i = 0; i < (size + 4095) / 4096; i++)
		if (pread(fd, buf, sizeof(buf), i*4096) < 0) {
			perror("pread");
			exit(1);
		}
}

int main(int argc, char **argv)
{
	int dirs, files;
	loff_t fsize;
	int i, j, fd, initonly;
	char namebuf[256];

	if (argc != 6) {
		fprintf(stderr, "Usage: <dir> <dirs> <files> <fsize> <initonly>\n");
		exit(1);
	}

	dirs = strtol(argv[2], NULL, 10);
	files = strtol(argv[3], NULL, 10);
	fsize = strtol(argv[4], NULL, 10);
	initonly = strtol(argv[5], NULL, 10);

	if (chdir(argv[1]) < 0) {
		perror("chdir");
		exit(1);
	}

	if (initonly) {
		for (i = 0; i < dirs; i++) {
			sprintf(namebuf, "dir%d", i);
			printf("o %s/%s\n", argv[1], namebuf);
			if (mkdir(namebuf, 0755) < 0) {
				perror("mkdir");
				exit(1);
			}
			for (j = 0; j < files; j++) {
				sprintf(namebuf, "dir%d/file%d", i, j);
				fd = open(namebuf, O_RDWR | O_CREAT, 0644);
				if (fd < 0) {
					perror("open");
					exit(1);
				}
				write_file(fd, fsize);
				close(fd);
			}
		}

		exit(0);
	}

	for (i = 0; i < dirs; i++) {
		struct timeval start, end;

		for (j = 0; j < files; j++) {
			sprintf(namebuf, "dir%d/file%d", i, j);
			gettimeofday(&start, NULL);
			if (unlink(namebuf) < 0) {
				perror("unlink");
				exit(1);
			}
			gettimeofday(&end, NULL);
			printf("%lu\n", time_diff(&start, &end));
		}
		sprintf(namebuf, "dir%d", i);
		if (rmdir(namebuf) < 0) {
			perror("rmdir");
			exit(1);
		}
	}


	return 0;
}
==== END sparsetruncate.c ====
