/*
 * Based originally on the ubiupdatevol utility
 * Copyright (c) International Business Machines Corp., 2006
 * Copyright (c) Google, Inc, 2014
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * A utility to replicate/copy UBI volumes.
 *
 * Authors: Frank Haverkamp
 *          Joshua W. Boyer
 *          Artem Bityutskiy
 *          Peter van Vugt
 */

#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <libubi.h>
#include "common.h"

#define PROGRAM_VERSION "1.0"
#define PROGRAM_NAME    "ubicpvol"

struct args {
	const char *destNode;
	const char *srcNode;
};

static struct args args;

static const char *doc = PROGRAM_NAME " version " PROGRAM_VERSION
			 " - a tool to replicate/copy UBI volumes.\n";

static const char *optionsstr =
"Options:\n"
"-h, --help                 print help message\n"
"-V, --version              print program version\n";

static const char *usage =
"Usage: " PROGRAM_NAME " [OPTIONS] <UBI source volume node> <UBI destination volume node>\n\n"
"Example: " PROGRAM_NAME " /dev/ubi0_1 /dev/ubi0_2 - copy UBI volume \"/dev/ubi0_1\" to \"/dev/ubi0_2\"\n";

static const char *notes =
"Note that both volumes must have the same LEB size and the data in the source\n"
"volume must fit into the destination volume.\n";

struct option long_options[] = {
	{ .name = "help",     .has_arg = 0, .flag = NULL, .val = 'h' },
	{ .name = "version",  .has_arg = 0, .flag = NULL, .val = 'V' },
	{ NULL, 0, NULL, 0}
};

static int parse_opt(int argc, char * const argv[])
{
	while (1) {
		int key;

		key = getopt_long(argc, argv, "h?V", long_options, NULL);
		if (key == -1)
			break;

		switch (key) {
		case 'h':
		case '?':
			fprintf(stderr, "%s\n", doc);
			fprintf(stderr, "%s\n", usage);
			fprintf(stderr, "%s\n", optionsstr);
			fprintf(stderr, "%s\n", notes);
			exit(EXIT_SUCCESS);

		case 'V':
			fprintf(stderr, "%s\n", PROGRAM_VERSION);
			exit(EXIT_SUCCESS);

		case ':':
			return errmsg("parameter is missing");

		default:
			fprintf(stderr, "Use -h for help\n");
			return -1;
		}
	}

	if (optind != argc - 2)
		return errmsg("specify source and destination UBI device names as first 2 "
			      "parameters (use -h for help)");

	args.srcNode  = argv[optind];
	args.destNode = argv[optind + 1];

	return 0;
}

static int ubi_write(int fd, const void *buf, int len)
{
	int ret;

	while (len) {
		ret = write(fd, buf, len);
		if (ret <= 0) {
			if (errno == EINTR) {
				warnmsg("do not interrupt me!");
				continue;
			}
			return errmsg("error %d: cannot write %d bytes to volume \"%s\"",
					  errno, len, args.destNode);
		}

		len -= ret;
		buf += ret;
	}

	return 0;
}

static int copy_volume(libubi_t libubi, struct ubi_vol_info *src_vol_info, struct ubi_vol_info *dest_vol_info)
{
	int err, dest_fd, src_fd;
	long long bytes;
	char *buf;
	int ret = -1;

	if (src_vol_info->leb_size != dest_vol_info->leb_size) {
		return errmsg("source and destination volumes have different LEB sizes");
	} else if (src_vol_info->data_bytes > dest_vol_info->rsvd_bytes) {
		return errmsg("source volume \"%s\" too large for destination volume \"%s\" (%lld > %lld)", args.srcNode, args.destNode, src_vol_info->data_bytes, dest_vol_info->rsvd_bytes);
	}

	buf = malloc(dest_vol_info->leb_size);
	if (!buf)
		return errmsg("cannot allocate %d bytes of memory", dest_vol_info->leb_size);

	bytes = src_vol_info->data_bytes;

	src_fd = open(args.srcNode, O_RDONLY);
	if (src_fd == -1) {
		errmsg("cannot open source UBI volume \"%s\"", args.srcNode);
		goto out_free;
	}

	dest_fd = open(args.destNode, O_RDWR);
	if (dest_fd == -1) {
		errmsg("cannot open destination UBI volume \"%s\"", args.destNode);
		goto out_close1;
	}

	err = ubi_update_start(libubi, dest_fd, bytes);
	if (err) {
		errmsg("cannot start volume \"%s\" update", args.destNode);
		goto out_close;
	}

	while (bytes) {
		int ret, to_copy = dest_vol_info->leb_size;

		if (to_copy > bytes)
			to_copy = bytes;

		ret = read(src_fd, buf, to_copy);
		if (ret <= 0) {
			if (errno == EINTR) {
				warnmsg("do not interrupt me!");
				continue;
			} else {
				errmsg("cannot read %d bytes from \"%s\"",
						to_copy, args.srcNode);
				goto out_close;
			}
		}

		err = ubi_write(dest_fd, buf, ret);
		if (err)
		{
			errmsg("cannot write %d bytes to \"%s\"", ret, args.destNode);
			goto out_close;
		}
		bytes -= ret;

		fprintf(stdout, "\r" PROGRAM_NAME ": copied %lli%%", (100 - (100 * bytes / src_vol_info->data_bytes)));
		fflush(stdout);
	}
	fprintf(stdout, "\r" PROGRAM_NAME ": finished copying ubi%d:%s to ubi%d:%s\n", src_vol_info->dev_num, src_vol_info->name, dest_vol_info->dev_num, dest_vol_info->name);
	ret = 0;

out_close:
	close(dest_fd);
out_close1:
	close(src_fd);
out_free:
	free(buf);
	return ret;
}

int main(int argc, char * const argv[])
{
	int err;
	libubi_t libubi;
	struct ubi_vol_info src_vol_info, dest_vol_info;
	int ret = -1;

	err = parse_opt(argc, argv);
	if (err)
		return -1;

	libubi = libubi_open();
	if (!libubi) {
		if (errno == 0)
			return errmsg("UBI is not present in the system");
		else
			return errmsg("cannot open libubi");
	}

	err = ubi_probe_node(libubi, args.srcNode);
	if (err == 1) {
		errmsg("Source node \"%s\" is a UBI device node, not a UBI volume node",
		       args.srcNode);
		goto out_libubi;
	} else if (err < 0) {
		if (errno == ENODEV)
			errmsg("Source node \"%s\" is not a UBI volume node", args.srcNode);
		else
			errmsg("error while probing source node \"%s\"", args.srcNode);
		goto out_libubi;
	}

	err = ubi_probe_node(libubi, args.destNode);
	if (err == 1) {
		errmsg("Destination node \"%s\" is a UBI device node, not a UBI volume node",
		       args.destNode);
		goto out_libubi;
	} else if (err < 0) {
		if (errno == ENODEV)
			errmsg("Destination node \"%s\" is not a UBI volume node", args.destNode);
		else
			errmsg("error while probing destination node \"%s\"", args.destNode);
		goto out_libubi;
	}

	err = ubi_get_vol_info(libubi, args.srcNode, &src_vol_info);
	if (err) {
		errmsg("cannot get information about source UBI volume \"%s\"",
			   args.srcNode);
		goto out_libubi;
	}

	err = ubi_get_vol_info(libubi, args.destNode, &dest_vol_info);
	if (err) {
		errmsg("cannot get information about destination UBI volume \"%s\"",
			   args.destNode);
		goto out_libubi;
	}

	if ((src_vol_info.dev_num == dest_vol_info.dev_num) && (src_vol_info.vol_id == dest_vol_info.vol_id)) {
		errmsg("Source and destination nodes \"%s\" and  \"%s\" point to same volume", args.srcNode, args.destNode);
		goto out_libubi;
	}

	err = copy_volume(libubi, &src_vol_info, &dest_vol_info);
	if (err)
	{
		errmsg("copy failed, err=%d", args.srcNode, args.destNode, err);
		goto out_libubi;
	}

	ret = 0;

out_libubi:
	libubi_close(libubi);
	return ret;
}
