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