Project import generated by Copybara.

NOKEYCHECK=True
GitOrigin-RevId: e0fbe4e4cb0867f725b6306c609c6eb3bd4e8385
diff --git a/mtd-utils.patches/mtd-utils-00.patch b/mtd-utils.patches/mtd-utils-00.patch
new file mode 100644
index 0000000..a62434a
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-00.patch
@@ -0,0 +1,129 @@
+diff -aruN a/nandtest.c b/nandtest.c
+--- a/nandtest.c	2011-10-17 11:17:50.972096998 -0700
++++ b/nandtest.c	2011-10-17 11:16:59.116096996 -0700
+@@ -1,3 +1,5 @@
++#define PROGRAM_NAME "nandtest"
++
+ #define _GNU_SOURCE
+ #include <ctype.h>
+ #include <errno.h>
+@@ -17,14 +19,15 @@
+ 
+ void usage(void)
+ {
+-	fprintf(stderr, "usage: nandtest [OPTIONS] <device>\n\n"
+-		"  -h, --help		Display this help output\n"
+-		"  -m, --markbad	Mark blocks bad if they appear so\n"
+-		"  -s, --seed		Supply random seed\n"
+-		"  -p, --passes		Number of passes\n"
+-		"  -o, --offset		Start offset on flash\n"
+-		"  -l, --length		Length of flash to test\n"
+-		"  -k, --keep		Restore existing contents after test\n");
++	fprintf(stderr, "usage: %s [OPTIONS] <device>\n\n"
++		"  -h, --help           Display this help output\n"
++		"  -m, --markbad        Mark blocks bad if they appear so\n"
++		"  -s, --seed           Supply random seed\n"
++		"  -p, --passes         Number of passes\n"
++		"  -o, --offset         Start offset on flash\n"
++		"  -l, --length         Length of flash to test\n"
++		"  -k, --keep           Restore existing contents after test\n",
++		PROGRAM_NAME);
+ 	exit(1);
+ }
+ 
+@@ -70,23 +73,23 @@
+ 	}
+ 	if (len < meminfo.erasesize) {
+ 		printf("\n");
+-		fprintf(stderr, "Short write (%d bytes)\n", len);
++		fprintf(stderr, "Short write (%zd bytes)\n", len);
+ 		exit(1);
+ 	}
+ 
+ 	printf("\r%08x: reading...", (unsigned)ofs);
+ 	fflush(stdout);
+-	
++
+ 	len = pread(fd, rbuf, meminfo.erasesize, ofs);
+ 	if (len < meminfo.erasesize) {
+ 		printf("\n");
+ 		if (len)
+-			fprintf(stderr, "Short read (%d bytes)\n", len);
++			fprintf(stderr, "Short read (%zd bytes)\n", len);
+ 		else
+ 			perror("read");
+ 		exit(1);
+ 	}
+-		
++
+ 	if (ioctl(fd, ECCGETSTATS, &newstats)) {
+ 		printf("\n");
+ 		perror("ECCGETSTATS");
+@@ -95,7 +98,9 @@
+ 	}
+ 
+ 	if (newstats.corrected > oldstats.corrected) {
+-		printf("\nECC corrected at %08x\n", (unsigned) ofs);
++		printf("\n %d bit(s) ECC corrected at %08x\n",
++				newstats.corrected - oldstats.corrected,
++				(unsigned) ofs);
+ 		oldstats.corrected = newstats.corrected;
+ 	}
+ 	if (newstats.failed > oldstats.failed) {
+@@ -181,7 +186,7 @@
+ 		case 'l':
+ 			length = strtol(optarg, NULL, 0);
+ 			break;
+-			
++
+ 		}
+ 	}
+ 	if (argc - optind != 1)
+@@ -192,7 +197,7 @@
+ 		perror("open");
+ 		exit(1);
+ 	}
+-	
++
+ 	if (ioctl(fd, MEMGETINFO, &meminfo)) {
+ 		perror("MEMGETINFO");
+ 		close(fd);
+@@ -203,20 +208,20 @@
+ 		length = meminfo.size;
+ 
+ 	if (offset % meminfo.erasesize) {
+-		fprintf(stderr, "Offset %x not multiple of erase size %x\n", 
++		fprintf(stderr, "Offset %x not multiple of erase size %x\n",
+ 			offset, meminfo.erasesize);
+ 		exit(1);
+ 	}
+ 	if (length % meminfo.erasesize) {
+-		fprintf(stderr, "Length %x not multiple of erase size %x\n", 
++		fprintf(stderr, "Length %x not multiple of erase size %x\n",
+ 			length, meminfo.erasesize);
+ 		exit(1);
+ 	}
+ 	if (length + offset > meminfo.size) {
+-		fprintf(stderr, "Length %x + offset %x exceeds device size %x\n", 
++		fprintf(stderr, "Length %x + offset %x exceeds device size %x\n",
+ 			length, offset, meminfo.size);
+ 		exit(1);
+-	}		
++	}
+ 
+ 	wbuf = malloc(meminfo.erasesize * 3);
+ 	if (!wbuf) {
+@@ -259,11 +264,11 @@
+ 				printf("\r%08x: reading... ", (unsigned)test_ofs);
+ 				fflush(stdout);
+ 
+-				len = pread(fd, rbuf, meminfo.erasesize, test_ofs);
++				len = pread(fd, kbuf, meminfo.erasesize, test_ofs);
+ 				if (len < meminfo.erasesize) {
+ 					printf("\n");
+ 					if (len)
+-						fprintf(stderr, "Short read (%d bytes)\n", len);
++						fprintf(stderr, "Short read (%zd bytes)\n", len);
+ 					else
+ 						perror("read");
+ 					exit(1);
diff --git a/mtd-utils.patches/mtd-utils-50.patch b/mtd-utils.patches/mtd-utils-50.patch
new file mode 100644
index 0000000..2686389
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-50.patch
@@ -0,0 +1,16 @@
+diff -aruN a/Makefile b/Makefile
+--- a/Makefile	2010-01-15 09:12:24.000000000 -0800
++++ b/Makefile	2010-09-08 16:03:05.000000000 -0700
+@@ -1,6 +1,12 @@
+ 
+ # -*- sh -*-
+ 
++PREFIX=/usr
++EXEC_PREFIX=$(PREFIX)
++SBINDIR=$(EXEC_PREFIX)/sbin
++MANDIR=$(PREFIX)/man
++INCLUDEDIR=$(PREFIX)/include
++
+ CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
+ 
+ ifeq ($(WITHOUT_XATTR), 1)
diff --git a/mtd-utils.patches/mtd-utils-51.patch b/mtd-utils.patches/mtd-utils-51.patch
new file mode 100644
index 0000000..df60c76
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-51.patch
@@ -0,0 +1,19 @@
+diff -aruN a/mkfs.ubifs/Makefile b/mkfs.ubifs/Makefile
+--- a/mkfs.ubifs/Makefile	2010-01-15 09:12:24.000000000 -0800
++++ b/mkfs.ubifs/Makefile	2010-09-12 14:23:23.000000000 -0700
+@@ -1,13 +1,13 @@
+ 
+ CPPFLAGS += -I../include -I../ubi-utils/include
+-CPPFLAGS += $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
++CPPFLAGS += $(ZLIBCPPFLAGS) $(LZOCPPFLAGS) $(UUIDCPPFLAGS)
+ 
+ ALL_SOURCES=*.[ch] hashtable/*.[ch]
+ 
+ TARGETS = mkfs.ubifs
+ 
+ LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
+-LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
++LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS) $(UUIDLDFLAGS)
+ 
+ include ../common.mk
+ 
diff --git a/mtd-utils.patches/mtd-utils-52.patch b/mtd-utils.patches/mtd-utils-52.patch
new file mode 100644
index 0000000..f34c686
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-52.patch
@@ -0,0 +1,12 @@
+diff -aruN a/ubi-utils/Makefile b/ubi-utils/Makefile
+--- a/ubi-utils/Makefile	2010-01-15 09:12:24.000000000 -0800
++++ b/ubi-utils/Makefile	2011-08-02 13:55:18.420060547 -0700
+@@ -4,8 +4,6 @@
+ 
+ KERNELHDR := ../include
+ 
+-SUBDIRS = old-utils
+-
+ # CFLAGS += -Werror
+ CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
+ 
diff --git a/mtd-utils.patches/mtd-utils-53.patch b/mtd-utils.patches/mtd-utils-53.patch
new file mode 100644
index 0000000..3703fea
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-53.patch
@@ -0,0 +1,91 @@
+diff -aruN a/nanddump.c b/nanddump.c
+--- a/nanddump.c	2011-11-02 21:48:36.159532935 -0700
++++ b/nanddump.c	2011-11-04 12:20:36.000000000 -0700
+@@ -54,6 +54,7 @@
+ "-p         --prettyprint        Print nice (hexdump)\n"
+ "-q         --quiet              Don't display progress and status messages\n"
+ "-s addr    --startaddress=addr  Start address\n"
++"-e         --omitempty          Omit empty pages\n"
+ 	);
+ 	exit(EXIT_SUCCESS);
+ }
+@@ -83,6 +84,7 @@
+ static const char	*dumpfile;		// dump file name
+ static bool		omitbad = false;
+ static bool		quiet = false;		// suppress diagnostic output
++static bool		omitempty = false;      // don't output empty pages
+ 
+ static void process_options (int argc, char * const argv[])
+ {
+@@ -90,7 +92,7 @@
+ 
+ 	for (;;) {
+ 		int option_index = 0;
+-		static const char *short_options = "bs:f:il:opqn";
++		static const char *short_options = "bs:f:il:opqne";
+ 		static const struct option long_options[] = {
+ 			{"help", no_argument, 0, 0},
+ 			{"version", no_argument, 0, 0},
+@@ -103,6 +105,7 @@
+ 			{"length", required_argument, 0, 'l'},
+ 			{"noecc", no_argument, 0, 'n'},
+ 			{"quiet", no_argument, 0, 'q'},
++			{"omitempty", no_argument, 0, 'e'},
+ 			{0, 0, 0, 0},
+ 		};
+ 
+@@ -153,6 +156,9 @@
+ 			case 'n':
+ 				noecc = true;
+ 				break;
++			case 'e':
++				omitempty = true;
++				break;
+ 			case '?':
+ 				error++;
+ 				break;
+@@ -192,6 +198,7 @@
+ 	struct nand_oobinfo old_oobinfo;
+ 	struct mtd_ecc_stats stat1, stat2;
+ 	bool eccstats = false;
++	bool isempty;
+ 
+ 	process_options(argc, argv);
+ 
+@@ -329,6 +336,23 @@
+ 			stat1 = stat2;
+ 		}
+ 
++		if (omitempty) {
++			isempty = true;
++			for (i = 0; i < bs; i++) {
++				if (readbuf[i] != 0xff) {
++					isempty = false;
++					break;
++				}
++			}
++
++			if (isempty) {
++				if (!quiet)
++					fprintf(stderr, "Skipping empty page at offset 0x%08lx\n", ofs);
++
++				continue;
++        	}
++        }
++
+ 		/* Write out page data */
+ 		if (pretty_print) {
+ 			for (i = 0; i < bs; i += 16) {
+diff -aruN a/nandwrite.c b/nandwrite.c
+--- a/nandwrite.c	2011-11-02 21:48:36.159532935 -0700
++++ b/nandwrite.c	2011-11-03 15:54:26.949570997 -0700
+@@ -486,6 +486,9 @@
+ 
+ 				if (baderaseblock) {
+ 					mtdoffset = blockstart + meminfo.erasesize;
++					if (mtdoffset >= meminfo.size) {
++						goto closeall;
++					}
+ 				}
+ 				offs +=  meminfo.erasesize / blockalign ;
+ 			} while ( offs < blockstart + meminfo.erasesize );
diff --git a/mtd-utils.patches/mtd-utils-54.patch b/mtd-utils.patches/mtd-utils-54.patch
new file mode 100644
index 0000000..2bd685c
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-54.patch
@@ -0,0 +1,111 @@
+diff -aruN a/nandtest.c b/nandtest.c
+--- a/nandtest.c	2011-11-16 11:20:33.715549264 -0800
++++ b/nandtest.c	2011-11-16 11:20:46.135549260 -0800
+@@ -4,6 +4,7 @@
+ #include <ctype.h>
+ #include <errno.h>
+ #include <fcntl.h>
++#include <stdbool.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -37,6 +38,9 @@
+ int markbad=0;
+ int seed;
+ 
++/*
++ * Erase and write block by block, checking for errors
++ */
+ int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf)
+ {
+ 	struct erase_info_user er;
+@@ -126,6 +130,71 @@
+ 	return 0;
+ }
+ 
++/*
++ * Restore page by page, skipping empty writes (writing all 0xff can result in non-0xff
++ * OOB bytes in empty blocks, which will be a problem for the fs after the test is complete).
++ */
++int erase_and_restore(loff_t ofs, unsigned char *data)
++{
++    struct erase_info_user er;
++    ssize_t len;
++    int page;
++    int page_count = (meminfo.erasesize/meminfo.writesize);
++    int i;
++    bool isempty;
++    unsigned char *data_page = data;
++
++    printf("\r%08x: erasing... ", (unsigned)ofs);
++    fflush(stdout);
++
++    er.start = ofs;
++    er.length = meminfo.erasesize;
++
++    /* Erase the whole block */
++    if (ioctl(fd, MEMERASE, &er)) {
++        perror("MEMERASE");
++        if (markbad) {
++            printf("Mark block bad at %08lx\n", (long)ofs);
++            ioctl(fd, MEMSETBADBLOCK, &ofs);
++	}
++	return 1;
++    }
++
++    printf("\r%08x: writing...", (unsigned)ofs);
++    fflush(stdout);
++
++    /* Write back page by page */
++    for (page = 0; page < page_count; page++, data_page += meminfo.writesize, ofs += meminfo.writesize) {        
++        isempty = true;
++        for (i = 0; i < meminfo.writesize; i++) {
++            if (data_page[i] != 0xff) {
++                isempty = false;
++                break;
++            }
++        }
++
++        if (isempty == false) {
++            len = pwrite(fd, data_page, meminfo.writesize, ofs);
++
++            if (len < 0) {
++                printf("\n");
++                perror("write");
++                if (markbad) {
++                    printf("Mark block bad at %08lx\n", (long)ofs);
++                    ioctl(fd, MEMSETBADBLOCK, &ofs);
++                }
++                return 1;
++            }
++            if (len < meminfo.writesize) {
++                printf("\n");
++                fprintf(stderr, "Short write (%zd bytes)\n", len);
++                exit(1);
++            }
++        }
++    }
++
++    return 0;
++}
+ 
+ /*
+  * Main program
+@@ -226,7 +295,7 @@
+ 	wbuf = malloc(meminfo.erasesize * 3);
+ 	if (!wbuf) {
+ 		fprintf(stderr, "Could not allocate %d bytes for buffer\n",
+-			meminfo.erasesize * 2);
++			meminfo.erasesize * 3);
+ 		exit(1);
+ 	}
+ 	rbuf = wbuf + meminfo.erasesize;
+@@ -277,7 +346,7 @@
+ 			if (erase_and_write(test_ofs, wbuf, rbuf))
+ 				continue;
+ 			if (keep_contents)
+-				erase_and_write(test_ofs, kbuf, rbuf);
++				erase_and_restore(test_ofs, kbuf);
+ 		}
+ 		printf("\nFinished pass %d successfully\n", pass+1);
+ 	}
diff --git a/mtd-utils.patches/mtd-utils-55.patch b/mtd-utils.patches/mtd-utils-55.patch
new file mode 100644
index 0000000..77a7a30
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-55.patch
@@ -0,0 +1,323 @@
+diff -Naur a/ubi-utils/Makefile b/ubi-utils/Makefile
+--- a/ubi-utils/Makefile	2014-12-19 15:27:10.990583444 -0800
++++ b/ubi-utils/Makefile	2014-12-19 14:52:57.462133419 -0800
+@@ -8,7 +8,7 @@
+ CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
+ 
+ LIBS = libubi libmtd libubigen libiniparser libscan
+-TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
++TARGETS = ubicpvol ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
+           ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol
+ 
+ VPATH = src
+diff -Naur a/ubi-utils/src/ubicpvol.c b/ubi-utils/src/ubicpvol.c
+--- a/ubi-utils/src/ubicpvol.c	1969-12-31 16:00:00.000000000 -0800
++++ b/ubi-utils/src/ubicpvol.c	2014-12-19 15:24:59.765776184 -0800
+@@ -0,0 +1,291 @@
++/*
++ * 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;
++}
+diff -Naur a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c
+--- a/ubi-utils/src/ubiupdatevol.c	2010-01-15 09:12:24.000000000 -0800
++++ b/ubi-utils/src/ubiupdatevol.c	2014-12-19 15:12:23.549163250 -0800
+@@ -283,10 +283,9 @@
+ 	libubi = libubi_open();
+ 	if (!libubi) {
+ 		if (errno == 0)
+-			errmsg("UBI is not present in the system");
++			return errmsg("UBI is not present in the system");
+ 		else
+-			sys_errmsg("cannot open libubi");
+-		goto out_libubi;
++			return errmsg("cannot open libubi");
+ 	}
+ 
+ 	err = ubi_probe_node(libubi, args.node);
diff --git a/mtd-utils.patches/mtd-utils-56.patch b/mtd-utils.patches/mtd-utils-56.patch
new file mode 100644
index 0000000..7d4a4e3
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-56.patch
@@ -0,0 +1,9 @@
+diff -Naur a/common.mk b/common.mk
+--- a/common.mk	2015-02-19 14:37:51.171316542 -0800
++++ b/common.mk	2015-02-19 14:31:21.235607345 -0800
+@@ -1,3 +1,5 @@
++.NOTPARALLEL:
++
+ CC := $(CROSS)gcc
+ AR := $(CROSS)ar
+ RANLIB := $(CROSS)ranlib
diff --git a/mtd-utils.patches/mtd-utils-57.patch b/mtd-utils.patches/mtd-utils-57.patch
new file mode 100644
index 0000000..02a2b2e
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-57.patch
@@ -0,0 +1,124 @@
+diff -Naur mtd-utils-1.3.1.pristine/nanddump.c mtd-utils-1.3.1.N/nanddump.c
+--- mtd-utils-1.3.1.pristine/nanddump.c	2015-08-24 17:31:43.707872733 -0700
++++ mtd-utils-1.3.1.N/nanddump.c	2015-08-24 17:52:22.608267037 -0700
+@@ -178,20 +178,14 @@
+ }
+ 
+ /*
+- * Buffers for reading data from flash
+- */
+-static unsigned char readbuf[4096];
+-static unsigned char oobbuf[128];
+-
+-/*
+  * Main program
+  */
+ int main(int argc, char * const argv[])
+ {
+ 	unsigned long ofs, end_addr = 0;
+ 	unsigned long long blockstart = 1;
+-	int ret, i, fd, ofd, bs, badblock = 0;
+-	struct mtd_oob_buf oob = {0, 16, oobbuf};
++	int ret, i, fd, ofd = 0, bs, badblock = 0;
++	struct mtd_oob_buf oob;
+ 	mtd_info_t meminfo;
+ 	char pretty_buf[80];
+ 	int oobinfochanged = 0 ;
+@@ -199,6 +193,7 @@
+ 	struct mtd_ecc_stats stat1, stat2;
+ 	bool eccstats = false;
+ 	bool isempty;
++	unsigned char *readbuf = NULL, *oobbuf = NULL;
+ 
+ 	process_options(argc, argv);
+ 
+@@ -215,18 +210,17 @@
+ 		exit (EXIT_FAILURE);
+ 	}
+ 
+-	/* Make sure device page sizes are valid */
+-	if (!(meminfo.oobsize == 128 && meminfo.writesize == 4096) &&
+-			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
+-			!(meminfo.oobsize == 32 && meminfo.writesize == 1024) &&
+-			!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
+-			!(meminfo.oobsize == 8 && meminfo.writesize == 256)) {
+-		fprintf(stderr, "Unknown flash (not normal NAND)\n");
+-		close(fd);
+-		exit(EXIT_FAILURE);
+-	}
+-	/* Read the real oob length */
++	/* Allocate buffers */
++	oobbuf = malloc(sizeof(oobbuf) * meminfo.oobsize);
++	readbuf = malloc(sizeof(readbuf) * meminfo.writesize);
++
++	if (oobbuf == NULL || readbuf == NULL)
++		goto closeall;
++
++	/* Fill in oob info */
++	oob.start = 0;
+ 	oob.length = meminfo.oobsize;
++	oob.ptr = oobbuf;
+ 
+ 	if (noecc)  {
+ 		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
+@@ -237,20 +231,17 @@
+ 			case ENOTTY:
+ 				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
+ 					perror ("MEMGETOOBSEL");
+-					close (fd);
+-					exit (EXIT_FAILURE);
++					goto closeall;
+ 				}
+ 				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
+ 					perror ("MEMSETOOBSEL");
+-					close (fd);
+-					exit (EXIT_FAILURE);
++					goto closeall;
+ 				}
+ 				oobinfochanged = 1;
+ 				break;
+ 			default:
+ 				perror ("MTDFILEMODE");
+-				close (fd);
+-				exit (EXIT_FAILURE);
++				goto closeall;
+ 			}
+ 		}
+ 	} else {
+@@ -274,8 +265,7 @@
+ 		ofd = STDOUT_FILENO;
+ 	} else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) {
+ 		perror (dumpfile);
+-		close(fd);
+-		exit(EXIT_FAILURE);
++		goto closeall;
+ 	}
+ 
+ 	/* Initialize start/end addresses and block size */
+@@ -420,14 +410,14 @@
+ 	if (oobinfochanged == 1) {
+ 		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
+ 			perror ("MEMSETOOBSEL");
+-			close(fd);
+-			close(ofd);
+-			return EXIT_FAILURE;
++			goto closeall;
+ 		}
+ 	}
+-	/* Close the output file and MTD device */
++	/* Close the output file and MTD device, free memory */
+ 	close(fd);
+ 	close(ofd);
++	free(oobbuf);
++	free(readbuf);
+ 
+ 	/* Exit happy */
+ 	return EXIT_SUCCESS;
+@@ -441,5 +431,7 @@
+ 	}
+ 	close(fd);
+ 	close(ofd);
++	free(oobbuf);
++	free(readbuf);
+ 	exit(EXIT_FAILURE);
+ }
diff --git a/mtd-utils.patches/mtd-utils-58.patch b/mtd-utils.patches/mtd-utils-58.patch
new file mode 100644
index 0000000..fe2f141
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-58.patch
@@ -0,0 +1,67 @@
+diff -Naur a/mkfs.ubifs/hashtable/hashtable_itr.c b/mkfs.ubifs/hashtable/hashtable_itr.c
+--- a/mkfs.ubifs/hashtable/hashtable_itr.c	2016-09-08 14:29:50.784056663 -0700
++++ b/mkfs.ubifs/hashtable/hashtable_itr.c	2016-09-08 16:09:35.255312282 -0700
+@@ -35,18 +35,6 @@
+ }
+ 
+ /*****************************************************************************/
+-/* key      - return the key of the (key,value) pair at the current position */
+-/* value    - return the value of the (key,value) pair at the current position */
+-
+-void *
+-hashtable_iterator_key(struct hashtable_itr *i)
+-{ return i->e->k; }
+-
+-void *
+-hashtable_iterator_value(struct hashtable_itr *i)
+-{ return i->e->v; }
+-
+-/*****************************************************************************/
+ /* advance - advance the iterator to the next element
+  *           returns zero if advanced to end of table */
+ 
+diff -Naur a/mkfs.ubifs/hashtable/hashtable_itr.h b/mkfs.ubifs/hashtable/hashtable_itr.h
+--- a/mkfs.ubifs/hashtable/hashtable_itr.h	2016-09-08 14:29:50.784056663 -0700
++++ b/mkfs.ubifs/hashtable/hashtable_itr.h	2016-09-08 16:09:35.255312282 -0700
+@@ -28,7 +28,7 @@
+ /* hashtable_iterator_key
+  * - return the value of the (key,value) pair at the current position */
+ 
+-extern inline void *
++static inline void *
+ hashtable_iterator_key(struct hashtable_itr *i)
+ {
+     return i->e->k;
+@@ -37,7 +37,7 @@
+ /*****************************************************************************/
+ /* value - return the value of the (key,value) pair at the current position */
+ 
+-extern inline void *
++static inline void *
+ hashtable_iterator_value(struct hashtable_itr *i)
+ {
+     return i->e->v;
+diff -Naur a/recv_image.c b/recv_image.c
+--- a/recv_image.c	2016-09-08 14:29:50.792056763 -0700
++++ b/recv_image.c	2016-09-08 16:09:35.263312383 -0700
+@@ -1,10 +1,10 @@
+ 
+ #define _XOPEN_SOURCE 500
++#define _BSD_SOURCE	/* struct ip_mreq */
+ 
+ #include <errno.h>
+ #include <error.h>
+ #include <stdio.h>
+-#define __USE_GNU
+ #include <netdb.h>
+ #include <stdlib.h>
+ #include <string.h>
+diff -Naur a/serve_image.c b/serve_image.c
+--- a/serve_image.c	2016-09-08 14:29:50.788056713 -0700
++++ b/serve_image.c	2016-09-08 16:09:35.259312333 -0700
+@@ -1,4 +1,4 @@
+-#define _POSIX_C_SOURCE 199309
++#define _POSIX_C_SOURCE 200112L
+ 
+ #include <time.h>
+ 
diff --git a/mtd-utils.patches/mtd-utils-59.patch b/mtd-utils.patches/mtd-utils-59.patch
new file mode 100644
index 0000000..7736e14
--- /dev/null
+++ b/mtd-utils.patches/mtd-utils-59.patch
@@ -0,0 +1,12 @@
+diff -aruN a/nandtest.c b/nandtest.c
+--- a/nandtest.c	2016-11-16 17:14:33.086196030 -0800
++++ b/nandtest.c	2016-11-16 17:16:03.575351493 -0800
+@@ -109,7 +109,7 @@
+ 	}
+ 	if (newstats.failed > oldstats.failed) {
+ 		printf("\nECC failed at %08x\n", (unsigned) ofs);
+-		oldstats.corrected = newstats.corrected;
++		oldstats.failed = newstats.failed;
+ 	}
+ 	if (len < meminfo.erasesize)
+ 		exit(1);
diff --git a/mtd-utils.tar.bz2 b/mtd-utils.tar.bz2
new file mode 100644
index 0000000..85f2173
--- /dev/null
+++ b/mtd-utils.tar.bz2
Binary files differ
diff --git a/mtd-utils.url b/mtd-utils.url
new file mode 100644
index 0000000..1c6ba0b
--- /dev/null
+++ b/mtd-utils.url
@@ -0,0 +1 @@
+ftp://ftp.linux-mtd.infradead.org/pub/mtd-utils/mtd-utils-1.3.1.tar.bz2
diff --git a/mtd-utils.version b/mtd-utils.version
new file mode 100644
index 0000000..3a3cd8c
--- /dev/null
+++ b/mtd-utils.version
@@ -0,0 +1 @@
+1.3.1