#!/bin/bash
P=sparsetruncate
DEFAULT_VERSION=0
. $SHELLPACK_INCLUDE/common.sh
TIME_CMD=`which time`
if [ "$TIME_CMD" = "" ]; then
        TIMEFORMAT="%2Uuser %2Ssystem %Relapsed %P%%CPU"
        TIME_CMD="time"
fi

# Basic argument parser
TASKSET_SERVER=
TASKSET_CLIENT=
SERVERSIDE_COMMAND=none
SERVERSIDE_NAME=`date +%Y%m%d-%H%M-%S`

while [ "$1" != "" ]; do
	case "$1" in
	-v)
		VERSION=$2
		shift 2
		;;
	--serverside-command)
		SERVERSIDE_COMMAND=$2
		shift 2
		;;
	--serverside-name)
		SERVERSIDE_NAME=$2
		shift 2
		;;
	*)
		echo Unrecognised option: $1
		shift
	esac
done
if [ "$TASKSET_SERVER" != "" ]; then
	echo TASKSET_SERVER: $TASKSET_SERVER
	echo TASKSET_CLIENT: $TASKSET_CLIENT
fi
if [ -z "$VERSION" ]; then
	VERSION=$DEFAULT_VERSION
fi

LINESTART=`grep -n "==== BEGIN sparsetruncate.c" $0 | tail -1 | awk -F : '{print $1}'`
LINEEND=`grep -n "==== END sparsetruncate.c" $0 | tail -1 | awk -F : '{print $1}'`
if [ "$LINEEND" = "" ]; then
	LINECOUNT=`wc -l $0 | awk '{print $1}'`
fi
if [ "$LINESTART" = "" ]; then
	die Failed to find start of file sparsetruncate.c
fi
echo Extracting $SHELLPACK_TEMP/sparsetruncate.c
sed -n $((LINESTART+1)),$((LINEEND-1))p $0 > $SHELLPACK_TEMP/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 ====
#### Description sparsetruncate
#### Details sparsetruncate 11
