/*
 * e2undo.c - Replay an undo log onto an ext2/3/4 filesystem
 *
 * Copyright IBM Corporation, 2007
 * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 *
 * %Begin-Header%
 * This file may be redistributed under the terms of the GNU Public
 * License.
 * %End-Header%
 */

#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <fcntl.h>
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include "ext2fs/tdb.h"
#include "ext2fs/ext2fs.h"
#include "nls-enable.h"

static unsigned char mtime_key[] = "filesystem MTIME";
static unsigned char uuid_key[] = "filesystem UUID";
static unsigned char blksize_key[] = "filesystem BLKSIZE";

static char *prg_name;

static void usage(void)
{
	fprintf(stderr,
		_("Usage: %s <transaction file> <filesystem>\n"), prg_name);
	exit(1);
}

static int check_filesystem(TDB_CONTEXT *tdb, io_channel channel)
{
	__u32   s_mtime;
	__u8    s_uuid[16];
	errcode_t retval;
	TDB_DATA tdb_key, tdb_data;
	struct ext2_super_block super;

	io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
	retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
	if (retval) {
		com_err(prg_name, retval,
			"%s", _("Failed to read the file system data \n"));
		return retval;
	}

	tdb_key.dptr = mtime_key;
	tdb_key.dsize = sizeof(mtime_key);
	tdb_data = tdb_fetch(tdb, tdb_key);
	if (!tdb_data.dptr) {
		retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
		com_err(prg_name, retval,
			_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
		return retval;
	}

	s_mtime = *(__u32 *)tdb_data.dptr;
	if (super.s_mtime != s_mtime) {

		com_err(prg_name, 0,
			_("The file system Mount time didn't match %u\n"),
			s_mtime);

		return  -1;
	}


	tdb_key.dptr = uuid_key;
	tdb_key.dsize = sizeof(uuid_key);
	tdb_data = tdb_fetch(tdb, tdb_key);
	if (!tdb_data.dptr) {
		retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
		com_err(prg_name, retval,
			_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
		return retval;
	}
	memcpy(s_uuid, tdb_data.dptr, sizeof(s_uuid));
	if (memcmp(s_uuid, super.s_uuid, sizeof(s_uuid))) {
		com_err(prg_name, 0, "%s",
			_("The file system UUID didn't match \n"));
		return -1;
	}

	return 0;
}

static int set_blk_size(TDB_CONTEXT *tdb, io_channel channel)
{
	int block_size;
	errcode_t retval;
	TDB_DATA tdb_key, tdb_data;

	tdb_key.dptr = blksize_key;
	tdb_key.dsize = sizeof(blksize_key);
	tdb_data = tdb_fetch(tdb, tdb_key);
	if (!tdb_data.dptr) {
		retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
		com_err(prg_name, retval,
			_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
		return retval;
	}

	block_size = *(int *)tdb_data.dptr;
#ifdef DEBUG
	printf("Block size %d\n", block_size);
#endif
	io_channel_set_blksize(channel, block_size);

	return 0;
}

int main(int argc, char *argv[])
{
	int c,force = 0;
	TDB_CONTEXT *tdb;
	TDB_DATA key, data;
	io_channel channel;
	errcode_t retval;
	int  mount_flags;
	blk64_t  blk_num;
	char *device_name, *tdb_file;
	io_manager manager = unix_io_manager;

#ifdef ENABLE_NLS
	setlocale(LC_MESSAGES, "");
	setlocale(LC_CTYPE, "");
	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
	textdomain(NLS_CAT_NAME);
	set_com_err_gettext(gettext);
#endif
	add_error_table(&et_ext2_error_table);

	prg_name = argv[0];
	while((c = getopt(argc, argv, "f")) != EOF) {
		switch (c) {
			case 'f':
				force = 1;
				break;
			default:
				usage();
		}
	}

	if (argc != optind + 2)
		usage();

	tdb_file = argv[optind];
	device_name = argv[optind+1];

	tdb = tdb_open(tdb_file, 0, 0, O_RDONLY, 0600);

	if (!tdb) {
		com_err(prg_name, errno,
				_("Failed tdb_open %s\n"), tdb_file);
		exit(1);
	}

	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
	if (retval) {
		com_err(prg_name, retval, _("Error while determining whether "
				"%s is mounted.\n"), device_name);
		exit(1);
	}

	if (mount_flags & EXT2_MF_MOUNTED) {
		com_err(prg_name, retval, "%s", _("e2undo should only be run "
						"on unmounted file system\n"));
		exit(1);
	}

	retval = manager->open(device_name,
				IO_FLAG_EXCLUSIVE | IO_FLAG_RW,  &channel);
	if (retval) {
		com_err(prg_name, retval,
				_("Failed to open %s\n"), device_name);
		exit(1);
	}

	if (!force && check_filesystem(tdb, channel)) {
		exit(1);
	}

	if (set_blk_size(tdb, channel)) {
		exit(1);
	}

	for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key)) {
		if (!strcmp((char *) key.dptr, (char *) mtime_key) ||
		    !strcmp((char *) key.dptr, (char *) uuid_key) ||
		    !strcmp((char *) key.dptr, (char *) blksize_key)) {
			continue;
		}

		data = tdb_fetch(tdb, key);
		if (!data.dptr) {
			com_err(prg_name, 0,
				_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
			exit(1);
		}
		blk_num = *(blk64_t *)key.dptr;
		printf(_("Replayed transaction of size %zd at location %llu\n"),
							data.dsize, blk_num);
		retval = io_channel_write_blk64(channel, blk_num,
						-data.dsize, data.dptr);
		if (retval == -1) {
			com_err(prg_name, retval,
					_("Failed write %s\n"),
					strerror(errno));
			exit(1);
		}
	}
	io_channel_close(channel);
	tdb_close(tdb);

	return 0;
}
