/*
 * Author:  Andreas Henriksson <andreas@fjortis.info>.
 *
 * Description: move a file from within a basedir to new location.
 *
 * Build:   gcc movebasedir.c -DFROMBASEDIR=\"/tmp\" \
 *             -DTOBASEDIR=\"/tmp/quux/\"
 *          gcc movebasedir.c -DFROMBASEDIR=\"/tmp\" -DNOTOBASE
 *
 * Usage:   ./a.out <from> <to>
 *
 * Example: ./a.out foobar1 /tmp/quux/
 *          ./a.out foobar1 quux
 *
 * Written for Neon at Reelab (reelab.se), 2005-07-14.
 */

#include <stdio.h>
#include <limits.h>

// int rename(const char *oldpath, const char *newpath);

#ifndef FROMBASEDIR
#	error "Basepath for source 'FROMBASEDIR' not defined!"
#endif

#if !defined(NOTOBASE) && !defined(TOBASEDIR)
#	error "Basepath for destination 'TOBASEDIR' not defined!"
#endif

int main(int argc, char **argv)
{
	char *infrompath, *intopath;
	char frompath[PATH_MAX], topath[PATH_MAX];

	if (argc < 3) {
		fprintf(stderr, "Usage: %s <oldpath> <newpath>\n", argv[0]);
		exit(1);
	}
	
	infrompath = argv[1];
	intopath = argv[2];
	
	if (!realpath(infrompath, frompath)) {
		perror("frompath");
		exit(1);
	}

	if (realpath(intopath, topath)) {
		fprintf(stderr, "Error: topath already exists!\n");
		exit(1);
	}

	strcpy(intopath, topath); /* FIXME: validate topath? TOBASEDIR? */
	

	if (strncmp(frompath, FROMBASEDIR, strlen(FROMBASEDIR))) {
		fprintf(stderr, "Error: frompath outside of FROMBASEDIR.\n");
		exit(2);
	}

#ifndef NOTOBASE
	if (strncmp(topath, TOBASEDIR, strlen(TOBASEDIR))) {
		fprintf(stderr, "Error: topath outside of TOBASEDIR.\n");
		exit(2);
	}
#endif
	
	if (setuid(0)) {
		fprintf(stderr, "Warning: failed to setuid(0).\n");
	}

	if (rename(frompath, topath)) {
		perror("rename");
		exit(3);
	}

	return 0;
}
