diff --git a/SOURCES/0001-Fix-Perl-directory-install-path.patch b/SOURCES/0001-Fix-Perl-directory-install-path.patch
new file mode 100644
index 0000000..0ca73e8
--- /dev/null
+++ b/SOURCES/0001-Fix-Perl-directory-install-path.patch
@@ -0,0 +1,25 @@
+From 1c6bd6e0085204425d7c687f2566cb9b13231e6e Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones@redhat.com>
+Date: Fri, 17 Feb 2017 15:58:04 +0000
+Subject: [PATCH 01/12] Fix Perl directory install path.
+
+---
+ perl/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/perl/Makefile.am b/perl/Makefile.am
+index a0ae863..144a1bc 100644
+--- a/perl/Makefile.am
++++ b/perl/Makefile.am
+@@ -43,7 +43,7 @@ $(TESTS): src_deps all
+ 
+ TESTS_ENVIRONMENT = ../run
+ 
+-INSTALLDIRS = site
++INSTALLDIRS = vendor
+ 
+ all: Makefile-pl src_deps
+ 	$(MAKE) -f Makefile-pl
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0001-generator-Fix-a-spelling-mistake-in-the-documentatio.patch b/SOURCES/0001-generator-Fix-a-spelling-mistake-in-the-documentatio.patch
deleted file mode 100644
index dc8ed8e..0000000
--- a/SOURCES/0001-generator-Fix-a-spelling-mistake-in-the-documentatio.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-diff -ur hivex-1.3.10.old/generator/generator.ml hivex-1.3.10/generator/generator.ml
---- hivex-1.3.10.old/generator/generator.ml	2014-03-26 14:56:27.000000000 +0000
-+++ hivex-1.3.10/generator/generator.ml	2014-11-17 11:53:46.469958904 +0000
-@@ -242,7 +242,7 @@
-     "\
- Return the length of the key (name) of a (key, value) pair as produced
- by C<hivex_value_key>. The length can legitimately be 0, so errno is 
--the necesary mechanism to check for errors.
-+the necessary mechanism to check for errors.
- 
- In the context of Windows Registries, a zero-length name means
- that this value is the default key for this node in the tree.
-diff -ur hivex-1.3.10.old/lib/hivex.pod hivex-1.3.10/lib/hivex.pod
---- hivex-1.3.10.old/lib/hivex.pod	2014-01-10 10:00:53.000000000 +0000
-+++ hivex-1.3.10/lib/hivex.pod	2014-11-17 11:53:49.288886768 +0000
-@@ -346,7 +346,7 @@
- 
- Return the length of the key (name) of a (key, value) pair as produced
- by C<hivex_value_key>. The length can legitimately be 0, so errno is 
--the necesary mechanism to check for errors.
-+the necessary mechanism to check for errors.
- 
- In the context of Windows Registries, a zero-length name means
- that this value is the default key for this node in the tree.
-diff -ur hivex-1.3.10.old/perl/lib/Win/Hivex.pm hivex-1.3.10/perl/lib/Win/Hivex.pm
---- hivex-1.3.10.old/perl/lib/Win/Hivex.pm	2014-01-10 10:00:53.000000000 +0000
-+++ hivex-1.3.10/perl/lib/Win/Hivex.pm	2014-11-17 11:53:49.337885514 +0000
-@@ -212,7 +212,7 @@
- 
- Return the length of the key (name) of a (key, value) pair as produced
- by C<value_key>. The length can legitimately be 0, so errno is 
--the necesary mechanism to check for errors.
-+the necessary mechanism to check for errors.
- 
- In the context of Windows Registries, a zero-length name means
- that this value is the default key for this node in the tree.
-diff -ur hivex-1.3.10.old/ruby/ext/hivex/_hivex.c hivex-1.3.10/ruby/ext/hivex/_hivex.c
---- hivex-1.3.10.old/ruby/ext/hivex/_hivex.c	2014-01-13 22:20:34.000000000 +0000
-+++ hivex-1.3.10/ruby/ext/hivex/_hivex.c	2014-11-17 11:53:50.808847877 +0000
-@@ -580,8 +580,8 @@
-  *
-  * Return the length of the key (name) of a (key, value)
-  * pair as produced by "h.value_key". The length can
-- * legitimately be 0, so errno is the necesary mechanism to
-- * check for errors.
-+ * legitimately be 0, so errno is the necessary mechanism
-+ * to check for errors.
-  * 
-  * In the context of Windows Registries, a zero-length name
-  * means that this value is the default key for this node
diff --git a/SOURCES/0001-handle-Refuse-to-open-files-8192-bytes-in-size.patch b/SOURCES/0001-handle-Refuse-to-open-files-8192-bytes-in-size.patch
deleted file mode 100644
index ac5dbf6..0000000
--- a/SOURCES/0001-handle-Refuse-to-open-files-8192-bytes-in-size.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 357f26fa64fd1d9ccac2331fe174a8ee9c607adb Mon Sep 17 00:00:00 2001
-From: "Richard W.M. Jones" <rjones@redhat.com>
-Date: Thu, 30 Oct 2014 13:50:39 +0000
-Subject: [PATCH 1/2] handle: Refuse to open files < 8192 bytes in size.
-
-These cannot be valid hives, since they don't contain a full header
-page and at least a single page of data (in other words they couldn't
-contain a root node).
-
-Thanks: Mahmoud Al-Qudsi
----
- lib/handle.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/lib/handle.c b/lib/handle.c
-index 62a8644..a3cbcf7 100644
---- a/lib/handle.c
-+++ b/lib/handle.c
-@@ -104,6 +104,13 @@ hivex_open (const char *filename, int flags)
- 
-   h->size = statbuf.st_size;
- 
-+  if (h->size < 0x2000) {
-+    SET_ERRNO (EINVAL,
-+               "%s: file is too small to be a Windows NT Registry hive file",
-+               filename);
-+    goto error;
-+  }
-+
-   if (!h->writable) {
-     h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
-     if (h->addr == MAP_FAILED)
--- 
-2.1.0
-
diff --git a/SOURCES/0001-lib-Don-t-leak-errno-from-_hivex_recode-function.patch b/SOURCES/0001-lib-Don-t-leak-errno-from-_hivex_recode-function.patch
deleted file mode 100644
index 24ece49..0000000
--- a/SOURCES/0001-lib-Don-t-leak-errno-from-_hivex_recode-function.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 4b3c3cd2b3d8d34601979feeb1390fddd442ab04 Mon Sep 17 00:00:00 2001
-From: "Richard W.M. Jones" <rjones@redhat.com>
-Date: Thu, 20 Nov 2014 21:37:19 +0000
-Subject: [PATCH] lib: Don't leak errno from _hivex_recode function.
-
-If iconv returns E2BIG, that's an internal indication for us, and not
-an error.  Don't leak the errno up to the user, as happened here:
-
-https://www.redhat.com/archives/libguestfs/2014-November/msg00140.html
-
-Thanks Nicolas Ecarnot.
----
- lib/utf16.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/lib/utf16.c b/lib/utf16.c
-index fe2c3bd..238f40a 100644
---- a/lib/utf16.c
-+++ b/lib/utf16.c
-@@ -58,6 +58,10 @@ _hivex_recode (const char *input_encoding, const char *input, size_t input_len,
-   if (r == (size_t) -1) {
-     if (errno == E2BIG) {
-       int err = errno;
-+      /* Reset errno here because we don't want to accidentally
-+       * return E2BIG to a library caller.
-+       */
-+      errno = 0;
-       size_t prev = outalloc;
-       /* Try again with a larger output buffer. */
-       free (out);
--- 
-2.1.0
-
diff --git a/SOURCES/0001-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch b/SOURCES/0001-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch
deleted file mode 100644
index 0344910..0000000
--- a/SOURCES/0001-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 38522d66673f341f8b12a82eb070fd1ffb8e55ec Mon Sep 17 00:00:00 2001
-From: "Richard W.M. Jones" <rjones@redhat.com>
-Date: Mon, 22 Sep 2014 15:08:44 +0100
-Subject: [PATCH 1/2] value: Set errno = 0 on non-error path in
- hivex_value_data_cell_offset (RHBZ#1145056).
-
-hivex_value_data_cell_offset may return 0 to indicate that the data is
-inline.  This is not an error return, but it was possible for errno to
-have a random (non-zero) value along this path.  Explicitly set errno
-= 0 on this path.
-
-Thanks: Wei Shi
-(cherry picked from commit 9763f96a1374486c7d00ea5c04b8048fe69e63f3)
----
- lib/value.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/lib/value.c b/lib/value.c
-index f222b41..aa80238 100644
---- a/lib/value.c
-+++ b/lib/value.c
-@@ -276,6 +276,7 @@ hivex_value_data_cell_offset (hive_h *h, hive_value_h value, size_t *len)
-     /* There is no other location for the value data. */
-     if (len)
-       *len = 0;
-+    errno = 0;
-     return 0;
-   } else {
-     if (len)
--- 
-2.0.4
-
diff --git a/SOURCES/0002-handle-Check-that-pages-do-not-extend-beyond-the-end.patch b/SOURCES/0002-handle-Check-that-pages-do-not-extend-beyond-the-end.patch
deleted file mode 100644
index 7977e16..0000000
--- a/SOURCES/0002-handle-Check-that-pages-do-not-extend-beyond-the-end.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 4bbdf555f88baeae0fa804a369a81a83908bd705 Mon Sep 17 00:00:00 2001
-From: "Richard W.M. Jones" <rjones@redhat.com>
-Date: Thu, 30 Oct 2014 14:02:25 +0000
-Subject: [PATCH 2/2] handle: Check that pages do not extend beyond the end of
- the file.
-
-Thanks: Mahmoud Al-Qudsi
----
- lib/handle.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/lib/handle.c b/lib/handle.c
-index a3cbcf7..3a8f09b 100644
---- a/lib/handle.c
-+++ b/lib/handle.c
-@@ -247,6 +247,13 @@ hivex_open (const char *filename, int flags)
-       goto error;
-     }
- 
-+    if (off + page_size > h->size) {
-+      SET_ERRNO (ENOTSUP,
-+                 "%s: page size %zu at 0x%zx extends beyond end of file, bad registry",
-+                 filename, page_size, off);
-+      goto error;
-+    }
-+
-     /* Read the blocks in this page. */
-     size_t blkoff;
-     struct ntreg_hbin_block *block;
--- 
-2.1.0
-
diff --git a/SOURCES/0002-hivexml-Tidy-up-error-handling-and-printing.patch b/SOURCES/0002-hivexml-Tidy-up-error-handling-and-printing.patch
deleted file mode 100644
index 0be6d03..0000000
--- a/SOURCES/0002-hivexml-Tidy-up-error-handling-and-printing.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-From c7e6dd0f09ca43c616bb2740ec748206bee6b14f Mon Sep 17 00:00:00 2001
-From: "Richard W.M. Jones" <rjones@redhat.com>
-Date: Mon, 22 Sep 2014 15:10:36 +0100
-Subject: [PATCH 2/2] hivexml: Tidy up error handling and printing.
-
-(cherry picked from commit 914d9b9a91babf0227989bc7ea00cf5e41ed7da4)
----
- xml/hivexml.c | 28 +++++++++++++---------------
- 1 file changed, 13 insertions(+), 15 deletions(-)
-
-diff --git a/xml/hivexml.c b/xml/hivexml.c
-index a4bc7eb..b496bb6 100644
---- a/xml/hivexml.c
-+++ b/xml/hivexml.c
-@@ -116,7 +116,7 @@ main (int argc, char *argv[])
- 
-   hive_h *h = hivex_open (argv[optind], open_flags);
-   if (h == NULL) {
--    perror (argv[optind]);
-+    fprintf (stderr, "hivex_open: %s: %m\n", argv[optind]);
-     exit (EXIT_FAILURE);
-   }
- 
-@@ -148,12 +148,12 @@ main (int argc, char *argv[])
-   }
- 
-   if (hivex_visit (h, &visitor, sizeof visitor, writer, visit_flags) == -1) {
--    perror (argv[optind]);
-+    fprintf (stderr, "hivex_visit: %s: %m\n", argv[optind]);
-     exit (EXIT_FAILURE);
-   }
- 
-   if (hivex_close (h) == -1) {
--    perror (argv[optind]);
-+    fprintf (stderr, "hivex_close: %s: %m\n", argv[optind]);
-     exit (EXIT_FAILURE);
-   }
- 
-@@ -217,12 +217,9 @@ node_byte_runs (hive_h *h, void *writer_v, hive_node_h node)
- {
-   xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
-   char buf[1+BYTE_RUN_BUF_LEN];
--  errno = 0;
-   size_t node_struct_length = hivex_node_struct_length (h, node);
--  if (errno) {
--    if (errno == EINVAL) {
--      fprintf (stderr, "node_byte_runs: Invoked on what does not seem to be a node (%zu).\n", node);
--    }
-+  if (node_struct_length == 0) {
-+    fprintf (stderr, "node_byte_runs: hivex_node_struct_length: %m\n");
-     return -1;
-   }
-   /* A node has one byte run. */
-@@ -301,17 +298,18 @@ value_byte_runs (hive_h *h, void *writer_v, hive_value_h value) {
-   xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
-   char buf[1+BYTE_RUN_BUF_LEN];
-   size_t value_data_cell_length;
--  errno = 0;
-   size_t value_data_structure_length = hivex_value_struct_length (h, value);
--  if (errno != 0) {
--    if (errno == EINVAL) {
--      fprintf (stderr, "value_byte_runs: Invoked on what does not seem to be a value (%zu).\n", value);
--    }
-+  if (value_data_structure_length == 0) {
-+    fprintf (stderr, "value_byte_runs: hivex_value_struct_length: %m\n");
-     return -1;
-   }
--  hive_value_h value_data_cell_offset = hivex_value_data_cell_offset (h, value, &value_data_cell_length);
--  if (errno != 0)
-+  errno = 0;
-+  hive_value_h value_data_cell_offset =
-+    hivex_value_data_cell_offset (h, value, &value_data_cell_length);
-+  if (value_data_cell_offset == 0 && errno != 0) {
-+    fprintf (stderr, "value_byte_runs: hivex_value_data_cell_offset: %m\n");
-     return -1;
-+  }
- 
-   XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs"));
-   memset (buf, 0, 1+BYTE_RUN_BUF_LEN);
--- 
-2.0.4
-
diff --git a/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch b/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch
new file mode 100644
index 0000000..32dd1b4
--- /dev/null
+++ b/SOURCES/0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch
@@ -0,0 +1,32 @@
+From 6a4dac0da1f318a1114363b274fcee76e73fcccf Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones@redhat.com>
+Date: Mon, 22 Sep 2014 15:08:44 +0100
+Subject: [PATCH 02/12] value: Set errno = 0 on non-error path in
+ hivex_value_data_cell_offset (RHBZ#1145056).
+
+hivex_value_data_cell_offset may return 0 to indicate that the data is
+inline.  This is not an error return, but it was possible for errno to
+have a random (non-zero) value along this path.  Explicitly set errno
+= 0 on this path.
+
+Thanks: Wei Shi
+(cherry picked from commit 9763f96a1374486c7d00ea5c04b8048fe69e63f3)
+---
+ lib/value.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/lib/value.c b/lib/value.c
+index f222b41..aa80238 100644
+--- a/lib/value.c
++++ b/lib/value.c
+@@ -276,6 +276,7 @@ hivex_value_data_cell_offset (hive_h *h, hive_value_h value, size_t *len)
+     /* There is no other location for the value data. */
+     if (len)
+       *len = 0;
++    errno = 0;
+     return 0;
+   } else {
+     if (len)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch b/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch
new file mode 100644
index 0000000..0942640
--- /dev/null
+++ b/SOURCES/0003-hivexml-Tidy-up-error-handling-and-printing.patch
@@ -0,0 +1,82 @@
+From 2cffe999c938a0bc67c3c6162ea4fc896af2dd22 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones@redhat.com>
+Date: Mon, 22 Sep 2014 15:10:36 +0100
+Subject: [PATCH 03/12] hivexml: Tidy up error handling and printing.
+
+(cherry picked from commit 914d9b9a91babf0227989bc7ea00cf5e41ed7da4)
+---
+ xml/hivexml.c | 28 +++++++++++++---------------
+ 1 file changed, 13 insertions(+), 15 deletions(-)
+
+diff --git a/xml/hivexml.c b/xml/hivexml.c
+index a4bc7eb..b496bb6 100644
+--- a/xml/hivexml.c
++++ b/xml/hivexml.c
+@@ -116,7 +116,7 @@ main (int argc, char *argv[])
+ 
+   hive_h *h = hivex_open (argv[optind], open_flags);
+   if (h == NULL) {
+-    perror (argv[optind]);
++    fprintf (stderr, "hivex_open: %s: %m\n", argv[optind]);
+     exit (EXIT_FAILURE);
+   }
+ 
+@@ -148,12 +148,12 @@ main (int argc, char *argv[])
+   }
+ 
+   if (hivex_visit (h, &visitor, sizeof visitor, writer, visit_flags) == -1) {
+-    perror (argv[optind]);
++    fprintf (stderr, "hivex_visit: %s: %m\n", argv[optind]);
+     exit (EXIT_FAILURE);
+   }
+ 
+   if (hivex_close (h) == -1) {
+-    perror (argv[optind]);
++    fprintf (stderr, "hivex_close: %s: %m\n", argv[optind]);
+     exit (EXIT_FAILURE);
+   }
+ 
+@@ -217,12 +217,9 @@ node_byte_runs (hive_h *h, void *writer_v, hive_node_h node)
+ {
+   xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+   char buf[1+BYTE_RUN_BUF_LEN];
+-  errno = 0;
+   size_t node_struct_length = hivex_node_struct_length (h, node);
+-  if (errno) {
+-    if (errno == EINVAL) {
+-      fprintf (stderr, "node_byte_runs: Invoked on what does not seem to be a node (%zu).\n", node);
+-    }
++  if (node_struct_length == 0) {
++    fprintf (stderr, "node_byte_runs: hivex_node_struct_length: %m\n");
+     return -1;
+   }
+   /* A node has one byte run. */
+@@ -301,17 +298,18 @@ value_byte_runs (hive_h *h, void *writer_v, hive_value_h value) {
+   xmlTextWriterPtr writer = (xmlTextWriterPtr) writer_v;
+   char buf[1+BYTE_RUN_BUF_LEN];
+   size_t value_data_cell_length;
+-  errno = 0;
+   size_t value_data_structure_length = hivex_value_struct_length (h, value);
+-  if (errno != 0) {
+-    if (errno == EINVAL) {
+-      fprintf (stderr, "value_byte_runs: Invoked on what does not seem to be a value (%zu).\n", value);
+-    }
++  if (value_data_structure_length == 0) {
++    fprintf (stderr, "value_byte_runs: hivex_value_struct_length: %m\n");
+     return -1;
+   }
+-  hive_value_h value_data_cell_offset = hivex_value_data_cell_offset (h, value, &value_data_cell_length);
+-  if (errno != 0)
++  errno = 0;
++  hive_value_h value_data_cell_offset =
++    hivex_value_data_cell_offset (h, value, &value_data_cell_length);
++  if (value_data_cell_offset == 0 && errno != 0) {
++    fprintf (stderr, "value_byte_runs: hivex_value_data_cell_offset: %m\n");
+     return -1;
++  }
+ 
+   XML_CHECK (xmlTextWriterStartElement, (writer, BAD_CAST "byte_runs"));
+   memset (buf, 0, 1+BYTE_RUN_BUF_LEN);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch b/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch
new file mode 100644
index 0000000..21a442e
--- /dev/null
+++ b/SOURCES/0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch
@@ -0,0 +1,35 @@
+From 1d90ea86a0ac6c5863597880b33a18755aff819c Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones@redhat.com>
+Date: Thu, 20 Nov 2014 21:37:19 +0000
+Subject: [PATCH 04/12] lib: Don't leak errno from _hivex_recode function.
+
+If iconv returns E2BIG, that's an internal indication for us, and not
+an error.  Don't leak the errno up to the user, as happened here:
+
+https://www.redhat.com/archives/libguestfs/2014-November/msg00140.html
+
+Thanks Nicolas Ecarnot.
+
+(cherry picked from commit 4b3c3cd2b3d8d34601979feeb1390fddd442ab04)
+---
+ lib/utf16.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/lib/utf16.c b/lib/utf16.c
+index f4299f2..3b54b01 100644
+--- a/lib/utf16.c
++++ b/lib/utf16.c
+@@ -59,6 +59,10 @@ _hivex_recode (const char *input_encoding, const char *input, size_t input_len,
+   if (r == (size_t) -1) {
+     if (errno == E2BIG) {
+       int err = errno;
++      /* Reset errno here because we don't want to accidentally
++       * return E2BIG to a library caller.
++       */
++      errno = 0;
+       size_t prev = outalloc;
+       /* Try again with a larger output buffer. */
+       free (out);
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch b/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch
new file mode 100644
index 0000000..b9e4483
--- /dev/null
+++ b/SOURCES/0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch
@@ -0,0 +1,36 @@
+From ebcb61e3d88d99b929b4d8ccaad837a871c102d8 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones@redhat.com>
+Date: Thu, 30 Oct 2014 13:50:39 +0000
+Subject: [PATCH 05/12] handle: Refuse to open files < 8192 bytes in size.
+
+These cannot be valid hives, since they don't contain a full header
+page and at least a single page of data (in other words they couldn't
+contain a root node).
+
+Thanks: Mahmoud Al-Qudsi
+(cherry picked from commit 357f26fa64fd1d9ccac2331fe174a8ee9c607adb)
+---
+ lib/handle.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/lib/handle.c b/lib/handle.c
+index 62a8644..a3cbcf7 100644
+--- a/lib/handle.c
++++ b/lib/handle.c
+@@ -104,6 +104,13 @@ hivex_open (const char *filename, int flags)
+ 
+   h->size = statbuf.st_size;
+ 
++  if (h->size < 0x2000) {
++    SET_ERRNO (EINVAL,
++               "%s: file is too small to be a Windows NT Registry hive file",
++               filename);
++    goto error;
++  }
++
+   if (!h->writable) {
+     h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
+     if (h->addr == MAP_FAILED)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch b/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch
new file mode 100644
index 0000000..8e4f674
--- /dev/null
+++ b/SOURCES/0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch
@@ -0,0 +1,33 @@
+From 5c718aab579d693ea3169ab4d29b5c3bc9105aa1 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones@redhat.com>
+Date: Thu, 30 Oct 2014 14:02:25 +0000
+Subject: [PATCH 06/12] handle: Check that pages do not extend beyond the end
+ of the file.
+
+Thanks: Mahmoud Al-Qudsi
+(cherry picked from commit 4bbdf555f88baeae0fa804a369a81a83908bd705)
+---
+ lib/handle.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/lib/handle.c b/lib/handle.c
+index a3cbcf7..3a8f09b 100644
+--- a/lib/handle.c
++++ b/lib/handle.c
+@@ -247,6 +247,13 @@ hivex_open (const char *filename, int flags)
+       goto error;
+     }
+ 
++    if (off + page_size > h->size) {
++      SET_ERRNO (ENOTSUP,
++                 "%s: page size %zu at 0x%zx extends beyond end of file, bad registry",
++                 filename, page_size, off);
++      goto error;
++    }
++
+     /* Read the blocks in this page. */
+     size_t blkoff;
+     struct ntreg_hbin_block *block;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch b/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch
new file mode 100644
index 0000000..161e615
--- /dev/null
+++ b/SOURCES/0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch
@@ -0,0 +1,27 @@
+From 026a1a2e01795defcfe5b638347671e09fcec2b6 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones@redhat.com>
+Date: Tue, 20 May 2014 10:48:40 +0100
+Subject: [PATCH 07/12] generator: Fix a spelling mistake in the documentation
+ (RHBZ#1099286).
+
+(cherry picked from commit cea8dbf029029a725768caa14ddc876f56bfd878)
+---
+ generator/generator.ml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/generator/generator.ml b/generator/generator.ml
+index 02aaf12..64c7681 100755
+--- a/generator/generator.ml
++++ b/generator/generator.ml
+@@ -242,7 +242,7 @@ default key.";
+     "\
+ Return the length of the key (name) of a (key, value) pair as produced
+ by C<hivex_value_key>. The length can legitimately be 0, so errno is 
+-the necesary mechanism to check for errors.
++the necessary mechanism to check for errors.
+ 
+ In the context of Windows Registries, a zero-length name means
+ that this value is the default key for this node in the tree.
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch b/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch
new file mode 100644
index 0000000..93c4e95
--- /dev/null
+++ b/SOURCES/0008-add-HIVEX_OPEN_UNSAFE-flag.patch
@@ -0,0 +1,70 @@
+From 691f5532ab4138093cdd8c661aba7519b0b1e2ad Mon Sep 17 00:00:00 2001
+From: Dawid Zamirski <dzamirski@datto.com>
+Date: Thu, 16 Feb 2017 18:17:22 -0500
+Subject: [PATCH 08/12] add HIVEX_OPEN_UNSAFE flag.
+
+This flag will be used to control behavior of libhivex API functions so
+that they tolerate corruption in hives by either using heuristic
+recovery from unexpected situations or simply ignore bad registry
+keys/values whenever possible.
+
+(cherry picked from commit 507f9328c67c701c32894249437551395bd8072c)
+---
+ generator/generator.ml | 8 ++++++++
+ lib/handle.c           | 1 +
+ lib/hivex-internal.h   | 1 +
+ 3 files changed, 10 insertions(+)
+
+diff --git a/generator/generator.ml b/generator/generator.ml
+index 64c7681..249a317 100755
+--- a/generator/generator.ml
++++ b/generator/generator.ml
+@@ -113,6 +113,7 @@ let open_flags = [
+   1, "VERBOSE", "Verbose messages";
+   2, "DEBUG", "Debug messages";
+   4, "WRITE", "Enable writes to the hive";
++  8, "UNSAFE", "Enable heuristics to allow read/write of corrupted hives";
+ ]
+ 
+ (* The API calls. *)
+@@ -145,6 +146,13 @@ Open the hive for writing.  If omitted, the hive is read-only.
+ 
+ See L<hivex(3)/WRITING TO HIVE FILES>.
+ 
++=item HIVEX_OPEN_UNSAFE
++
++Open the hive in unsafe mode that enables heuristics to handle corrupted hives.
++
++This may allow to read or write registry keys/values that appear intact in an
++otherwise corrupted hive. Use at your own risk.
++
+ =back";
+ 
+   "close", (RErrDispose, [AHive]),
+diff --git a/lib/handle.c b/lib/handle.c
+index 3a8f09b..dff2780 100644
+--- a/lib/handle.c
++++ b/lib/handle.c
+@@ -83,6 +83,7 @@ hivex_open (const char *filename, int flags)
+   DEBUG (2, "created handle %p", h);
+ 
+   h->writable = !!(flags & HIVEX_OPEN_WRITE);
++  h->unsafe = !!(flags & HIVEX_OPEN_UNSAFE);
+   h->filename = strdup (filename);
+   if (h->filename == NULL)
+     goto error;
+diff --git a/lib/hivex-internal.h b/lib/hivex-internal.h
+index bfd24c8..bbca215 100644
+--- a/lib/hivex-internal.h
++++ b/lib/hivex-internal.h
+@@ -30,6 +30,7 @@ struct hive_h {
+   size_t size;
+   int msglvl;                   /* 1 = verbose, 2 or 3 = debug */
+   int writable;
++  int unsafe;
+ 
+   /* Registry file, memory mapped if read-only, or malloc'd if writing. */
+   union {
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch b/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch
new file mode 100644
index 0000000..e20e700
--- /dev/null
+++ b/SOURCES/0009-lib-change-how-hbin-sections-are-read.patch
@@ -0,0 +1,94 @@
+From f80b9b31f99ccdc06887c23dab46a37fc4f4ce74 Mon Sep 17 00:00:00 2001
+From: Dawid Zamirski <dzamirski@datto.com>
+Date: Thu, 16 Feb 2017 18:17:23 -0500
+Subject: [PATCH 09/12] lib: change how hbin sections are read.
+
+Only when HIVEX_OPEN_UNSAFE flag is set:
+
+* hivex_open: when looping over hbin sections (aka pages), handle a
+  case where following hbin section may not begin at exactly at the end
+  of previous one. If this happens, scan the page section until next
+  one is found and validate it by checking declared offset with actual
+  one - if they match, all is good and we can safely move on.
+
+Rationale: there are registry hives there is some garbage data between
+hbin section but the hive is still perfectly usable as long as the
+offsets stated in hbin headers are correct.
+
+(cherry picked from commit 8d092a746dbd9e61ec85cf17449c201bc0719721)
+---
+ lib/handle.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 46 insertions(+), 5 deletions(-)
+
+diff --git a/lib/handle.c b/lib/handle.c
+index dff2780..8c64b6d 100644
+--- a/lib/handle.c
++++ b/lib/handle.c
+@@ -227,11 +227,42 @@ hivex_open (const char *filename, int flags)
+         page->magic[1] != 'b' ||
+         page->magic[2] != 'i' ||
+         page->magic[3] != 'n') {
+-      SET_ERRNO (ENOTSUP,
+-                 "%s: trailing garbage at end of file "
+-                 "(at 0x%zx, after %zu pages)",
+-                 filename, off, pages);
+-      goto error;
++
++      if (!h->unsafe) {
++        SET_ERRNO (ENOTSUP,
++                   "%s: trailing garbage at end of file "
++                   "(at 0x%zx, after %zu pages)",
++                   filename, off, pages);
++        goto error;
++      }
++
++      DEBUG (2,
++             "page not found at expected offset 0x%zx, "
++             "seeking until one is found or EOF is reached",
++             off);
++
++      int found = 0;
++      while (off < h->size) {
++        off += 0x1000;
++
++        if (off >= h->endpages)
++          break;
++
++        page = (struct ntreg_hbin_page *) ((char *) h->addr + off);
++        if (page->magic[0] == 'h' &&
++            page->magic[1] == 'b' &&
++            page->magic[2] == 'i' &&
++            page->magic[3] == 'n') {
++          DEBUG (2, "found next page by seeking at 0x%zx", off);
++          found = 1;
++          break;
++        }
++      }
++
++      if (!found) {
++        DEBUG (2, "page not found and end of pages section reached");
++        break;
++      }
+     }
+ 
+     size_t page_size = le32toh (page->page_size);
+@@ -255,6 +286,16 @@ hivex_open (const char *filename, int flags)
+       goto error;
+     }
+ 
++    size_t page_offset = le32toh(page->offset_first) + 0x1000;
++
++    if (page_offset != off) {
++      SET_ERRNO (ENOTSUP,
++                 "%s: declared page offset (0x%zx) does not match computed "
++                 "offset (0x%zx), bad registry",
++                 filename, page_offset, off);
++      goto error;
++    }
++
+     /* Read the blocks in this page. */
+     size_t blkoff;
+     struct ntreg_hbin_block *block;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch b/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch
new file mode 100644
index 0000000..c135032
--- /dev/null
+++ b/SOURCES/0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch
@@ -0,0 +1,137 @@
+From 8e187357f466c31a9e75ac4924b32bbf4823e73f Mon Sep 17 00:00:00 2001
+From: Dawid Zamirski <dzamirski@datto.com>
+Date: Thu, 16 Feb 2017 18:17:24 -0500
+Subject: [PATCH 10/12] lib: allow to walk registry with corrupted blocks
+
+Only when HIVEX_OPEN_UNSAFE flag is set.
+
+There are some corrupted registry files that have invalid hbin cells
+but are still readable. This patch makes the following changes:
+
+* hivex_open - do not abort with complete failure if we run across a
+  block with invalid size (unless it's the root block). Instead just
+  log the event, and move on. This will allow open hives that have
+  apparent invalid blocks but the ones of potential interest might be
+  perfectly accessible.
+* _hivex_get_children - similiarly, if the's invalid subkey, just skip
+  it instead of failing so one can continue to browse other valid
+  subkeys.
+
+The above is similar to the behavior to Windows regedit where one can
+load such corrupted hives with e.g. "reg load HKU\Corrupted" and
+browse/change it despite some keys might be missing.
+
+(cherry picked from commit 5345ec8f1df304dc93a6b1e4cbb40e7c1cf6f88d)
+---
+ lib/handle.c | 16 ++++++++++++----
+ lib/node.c   | 46 +++++++++++++++++++++++++++++++++++-----------
+ 2 files changed, 47 insertions(+), 15 deletions(-)
+
+diff --git a/lib/handle.c b/lib/handle.c
+index 8c64b6d..0d2b24b 100644
+--- a/lib/handle.c
++++ b/lib/handle.c
+@@ -313,10 +313,18 @@ hivex_open (const char *filename, int flags)
+       int used;
+       seg_len = block_len (h, blkoff, &used);
+       if (seg_len <= 4 || (seg_len & 3) != 0) {
+-        SET_ERRNO (ENOTSUP,
+-                   "%s: block size %" PRIu32 " at 0x%zx, bad registry",
+-                   filename, le32toh (block->seg_len), blkoff);
+-        goto error;
++        if (is_root || !h->unsafe) {
++          SET_ERRNO (ENOTSUP,
++                     "%s, the block at 0x%zx has invalid size %" PRIi32
++                     ", bad registry",
++                     filename, blkoff, le32toh (block->seg_len));
++          goto error;
++        } else {
++          DEBUG (2,
++                 "%s: block at 0x%zx has invalid size %" PRIi32 ", skipping",
++                 filename, blkoff, le32toh (block->seg_len));
++          break;
++        }
+       }
+ 
+       if (h->msglvl >= 2) {
+diff --git a/lib/node.c b/lib/node.c
+index 22d1861..a90c964 100644
+--- a/lib/node.c
++++ b/lib/node.c
+@@ -343,11 +343,18 @@ _hivex_get_children (hive_h *h, hive_node_h node,
+    */
+   size_t nr_children = _hivex_get_offset_list_length (&children);
+   if (nr_subkeys_in_nk != nr_children) {
+-    SET_ERRNO (ENOTSUP,
+-               "nr_subkeys_in_nk = %zu "
+-               "is not equal to number of children read %zu",
+-               nr_subkeys_in_nk, nr_children);
+-    goto error;
++    if (!h->unsafe) {
++      SET_ERRNO (ENOTSUP,
++                 "nr_subkeys_in_nk = %zu "
++                 "is not equal to number of childred read %zu",
++                 nr_subkeys_in_nk, nr_children);
++      goto error;
++    } else {
++      DEBUG (2,
++             "nr_subkeys_in_nk = %zu "
++             "is not equal to number of children read %zu",
++             nr_subkeys_in_nk, nr_children);
++    }
+   }
+ 
+  out:
+@@ -407,8 +414,14 @@ _get_children (hive_h *h, hive_node_h blkoff,
+     for (i = 0; i < nr_subkeys_in_lf; ++i) {
+       hive_node_h subkey = le32toh (lf->keys[i].offset);
+       subkey += 0x1000;
+-      if (check_child_is_nk_block (h, subkey, flags) == -1)
+-        return -1;
++      if (check_child_is_nk_block (h, subkey, flags) == -1) {
++        if (h->unsafe) {
++          DEBUG (2, "subkey at 0x%zx is not an NK block, skipping", subkey);
++          continue;
++        } else {
++          return -1;
++        }
++      }
+       if (_hivex_add_to_offset_list (children, subkey) == -1)
+         return -1;
+     }
+@@ -435,8 +448,14 @@ _get_children (hive_h *h, hive_node_h blkoff,
+     for (i = 0; i < nr_offsets; ++i) {
+       hive_node_h subkey = le32toh (ri->offset[i]);
+       subkey += 0x1000;
+-      if (check_child_is_nk_block (h, subkey, flags) == -1)
+-        return -1;
++      if (check_child_is_nk_block (h, subkey, flags) == -1) {
++        if (h->unsafe) {
++          DEBUG (2, "subkey at 0x%zx is not an NK block, skipping", subkey);
++          continue;
++        } else {
++          return -1;
++        }
++      }
+       if (_hivex_add_to_offset_list (children, subkey) == -1)
+         return -1;
+     }
+@@ -458,8 +477,13 @@ _get_children (hive_h *h, hive_node_h blkoff,
+       hive_node_h offset = le32toh (ri->offset[i]);
+       offset += 0x1000;
+       if (!IS_VALID_BLOCK (h, offset)) {
+-        SET_ERRNO (EFAULT, "ri-offset is not a valid block (0x%zx)", offset);
+-        return -1;
++        if (h->unsafe) {
++          DEBUG (2, "ri-offset is not a valid block (0x%zx), skipping", offset);
++          continue;
++        } else {
++          SET_ERRNO (EFAULT, "ri-offset is not a valid block (0x%zx)", offset);
++          return -1;
++        }
+       }
+ 
+       if (_get_children (h, offset, children, blocks, flags) == -1)
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch b/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch
new file mode 100644
index 0000000..37fde1d
--- /dev/null
+++ b/SOURCES/0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch
@@ -0,0 +1,95 @@
+From d4f5c255832391ba6132959d1ded57ce9286e7d6 Mon Sep 17 00:00:00 2001
+From: Dawid Zamirski <dzamirski@datto.com>
+Date: Thu, 16 Feb 2017 18:17:25 -0500
+Subject: [PATCH 11/12] hivexsh: add -u flag for HIVEX_OPEN_UNSAFE.
+
+and pass it to hivex_open. Additionally make hivex_value_value failures
+non-critical in this mode when iterating through node children/values.
+
+(cherry picked from commit 62c53cda651f34f18a2b55e91012c0448acb70f1)
+---
+ sh/hivexsh.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/sh/hivexsh.c b/sh/hivexsh.c
+index f578ccc..39ab9d0 100644
+--- a/sh/hivexsh.c
++++ b/sh/hivexsh.c
+@@ -67,6 +67,7 @@
+ 
+ static int quit = 0;
+ static int is_tty;
++static int unsafe = 0;
+ static hive_h *h = NULL;
+ static char *prompt_string = NULL; /* Normal prompt string. */
+ static char *loaded = NULL;     /* Basename of loaded file, if any. */
+@@ -97,7 +98,7 @@ static int cmd_setval (char *args);
+ static void
+ usage (void)
+ {
+-  fprintf (stderr, "hivexsh [-dfw] [hivefile]\n");
++  fprintf (stderr, "hivexsh [-dfwu] [hivefile]\n");
+   exit (EXIT_FAILURE);
+ }
+ 
+@@ -115,7 +116,7 @@ main (int argc, char *argv[])
+ 
+   set_prompt_string ();
+ 
+-  while ((c = getopt (argc, argv, "df:w")) != EOF) {
++  while ((c = getopt (argc, argv, "df:wu")) != EOF) {
+     switch (c) {
+     case 'd':
+       open_flags |= HIVEX_OPEN_DEBUG;
+@@ -126,6 +127,10 @@ main (int argc, char *argv[])
+     case 'w':
+       open_flags |= HIVEX_OPEN_WRITE;
+       break;
++    case 'u':
++      open_flags |= HIVEX_OPEN_UNSAFE;
++      unsafe = 1;
++      break;
+     default:
+       usage ();
+     }
+@@ -771,6 +776,7 @@ cmd_lsval (char *key)
+ 
+       hive_type t;
+       size_t len;
++
+       if (hivex_value_type (h, values[i], &t, &len) == -1)
+         goto error;
+ 
+@@ -779,8 +785,12 @@ cmd_lsval (char *key)
+       case hive_t_expand_string:
+       case hive_t_link: {
+         char *str = hivex_value_string (h, values[i]);
+-        if (!str)
+-          goto error;
++        if (!str) {
++          if (unsafe)
++            continue;
++          else
++            goto error;
++        }
+ 
+         if (t != hive_t_string)
+           printf ("str(%d):", t);
+@@ -813,8 +823,12 @@ cmd_lsval (char *key)
+       default: {
+         unsigned char *data =
+           (unsigned char *) hivex_value_value (h, values[i], &t, &len);
+-        if (!data)
+-          goto error;
++        if (!data) {
++          if (unsafe)
++            continue;
++          else
++            goto error;
++        }
+ 
+         printf ("hex(%d):", t);
+         size_t j;
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch b/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch
new file mode 100644
index 0000000..53a5aff
--- /dev/null
+++ b/SOURCES/0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch
@@ -0,0 +1,168 @@
+From 362d5cd9b6527e4f9d3a3729afbe7cd90486c39d Mon Sep 17 00:00:00 2001
+From: Dawid Zamirski <dzamirski@datto.com>
+Date: Thu, 16 Feb 2017 18:17:26 -0500
+Subject: [PATCH 12/12] hivexregedit: allow to pass HIVEX_OPEN_UNSAFE
+
+via new --unsafe flag. Also make --export catpure, log and skip over
+errors when reading subkeys/values so that export in unsafe mode does
+not abort at first sign of error.
+
+(cherry picked from commit 2610b1e089fa84d294f9925342929e3d7408c35b)
+---
+ perl/lib/Win/Hivex/Regedit.pm | 59 ++++++++++++++++++++++++++++++++++++++-----
+ regedit/hivexregedit          | 20 ++++++++++++---
+ 2 files changed, 70 insertions(+), 9 deletions(-)
+
+diff --git a/perl/lib/Win/Hivex/Regedit.pm b/perl/lib/Win/Hivex/Regedit.pm
+index 8914f9e..355699e 100644
+--- a/perl/lib/Win/Hivex/Regedit.pm
++++ b/perl/lib/Win/Hivex/Regedit.pm
+@@ -67,7 +67,7 @@ package Win::Hivex::Regedit;
+ use strict;
+ use warnings;
+ 
+-use Carp qw(croak confess);
++use Carp qw(croak carp confess);
+ use Encode qw(encode decode);
+ 
+ require Exporter;
+@@ -528,19 +528,51 @@ sub reg_export_node
+     print $fh "]\n";
+ 
+     my $unsafe_printable_strings = $params{unsafe_printable_strings};
++    my $unsafe = $params{unsafe};
++
++    my @values;
++    my @safe_values;
+ 
+     # Get the values.
+-    my @values = $h->node_values ($node);
++    if ($unsafe) {
++        my $have_vals = 0;
++        eval {
++            @values = $h->node_values ($node);
++            $have_vals = 1;
++        };
++
++        if (!$have_vals) {
++            carp "Failed to read node values at $path";
++        }
++    } else {
++        @values = $h->node_values ($node);
++    }
+ 
+     foreach (@values) {
+         use bytes;
+ 
+         my $key = $h->value_key ($_);
+-        my ($type, $data) = $h->value_value ($_);
+-        $_ = { key => $key, type => $type, data => $data }
++        my ($type, $data);
++
++        if ($unsafe) {
++            my $val_ok = 0;
++            eval {
++                ($type, $data) = $h->value_value ($_);
++                $val_ok = 1;
++            };
++
++            if (!$val_ok) {
++                carp "skipping unreadable value of key: $key in $path";
++                next;
++            }
++        } else {
++            ($type, $data) = $h->value_value ($_);
++        }
++
++        push @safe_values, { key => $key, type => $type, data => $data };
+     }
+ 
+-    @values = sort { $a->{key} cmp $b->{key} } @values;
++    @values = sort { $a->{key} cmp $b->{key} } @safe_values;
+ 
+     # Print the values.
+     foreach (@values) {
+@@ -573,7 +605,22 @@ sub reg_export_node
+     }
+     print $fh "\n";
+ 
+-    my @children = $h->node_children ($node);
++    my @children;
++
++    if ($unsafe) {
++        my $have_children = 0;
++        eval {
++            @children = $h->node_children ($node);
++            $have_children = 1;
++        };
++
++        if (!$have_children) {
++            carp "Could not get children of $path";
++        }
++    } else {
++        @children = $h->node_children ($node);
++    }
++
+     @children = sort { $h->node_name ($a) cmp $h->node_name ($b) } @children;
+     reg_export_node ($h, $_, $fh, @_) foreach @children;
+ }
+diff --git a/regedit/hivexregedit b/regedit/hivexregedit
+index 0e534de..aa0ee6e 100755
+--- a/regedit/hivexregedit
++++ b/regedit/hivexregedit
+@@ -252,6 +252,17 @@ into another program or stored in another hive.
+ 
+ =cut
+ 
++my $unsafe;
++
++=item B<--unsafe>
++
++Use heuristics to tolerate certain levels of corruption within hives.
++
++This is unsafe but may allow to export/merge valid keys/values in an
++othewise corrupted hive.
++
++=cut
++
+ GetOptions ("help|?" => \$help,
+             "debug" => \$debug,
+             "merge|import" => \$merge,
+@@ -259,6 +270,7 @@ GetOptions ("help|?" => \$help,
+             "prefix=s" => \$prefix,
+             "encoding=s" => \$encoding,
+             "unsafe-printable-strings" => \$unsafe_printable_strings,
++            "unsafe" => \$unsafe,
+     ) or pod2usage (2);
+ pod2usage (1) if $help;
+ 
+@@ -281,7 +293,8 @@ if ($merge) {                   # --merge (reg_import)
+ 
+     my $hivefile = shift @ARGV;
+ 
+-    my $h = Win::Hivex->open ($hivefile, write => 1, debug => $debug);
++    my $h = Win::Hivex->open ($hivefile, write => 1, debug => $debug,
++                              unsafe => $unsafe);
+ 
+     # Read from stdin unless other files have been specified.
+     unshift (@ARGV, '-') unless @ARGV;
+@@ -312,13 +325,14 @@ if ($merge) {                   # --merge (reg_import)
+     my $hivefile = shift @ARGV;
+     my $key = shift @ARGV;
+ 
+-    my $h = Win::Hivex->open ($hivefile, debug => $debug);
++    my $h = Win::Hivex->open ($hivefile, debug => $debug, unsafe => $unsafe);
+ 
+     print "Windows Registry Editor Version 5.00\n\n";
+ 
+     reg_export ($h, $key, \*STDOUT,
+                 prefix => $prefix,
+-                unsafe_printable_strings => $unsafe_printable_strings);
++                unsafe_printable_strings => $unsafe_printable_strings,
++                unsafe => $unsafe);
+ }
+ 
+ =head1 SEE ALSO
+-- 
+1.8.3.1
+
diff --git a/SOURCES/generated.patch b/SOURCES/generated.patch
new file mode 100644
index 0000000..b6ad060
--- /dev/null
+++ b/SOURCES/generated.patch
@@ -0,0 +1,272 @@
+Only in hivex-1.3.10/generator: .pod2text.data.version.2
+Only in hivex-1.3.10/generator: stamp-generator
+diff -ur hivex-1.3.10.old/lib/hivex.h hivex-1.3.10/lib/hivex.h
+--- hivex-1.3.10.old/lib/hivex.h	2014-01-10 10:00:53.000000000 +0000
++++ hivex-1.3.10/lib/hivex.h	2017-02-17 16:17:58.114476857 +0000
+@@ -3,7 +3,7 @@
+  *   generator/generator.ml
+  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+  *
+- * Copyright (C) 2009-2014 Red Hat Inc.
++ * Copyright (C) 2009-2017 Red Hat Inc.
+  * Derived from code by Petter Nordahl-Hagen under a compatible license:
+  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+  * Derived from code by Markus Stephany under a compatible license:
+@@ -111,6 +111,8 @@
+ #define HIVEX_OPEN_DEBUG      2
+   /* Enable writes to the hive */
+ #define HIVEX_OPEN_WRITE      4
++  /* Enable heuristics to allow read/write of corrupted hives */
++#define HIVEX_OPEN_UNSAFE     8
+ 
+ /* Array of (key, value) pairs passed to hivex_node_set_values. */
+ struct hive_set_value {
+diff -ur hivex-1.3.10.old/lib/hivex.pod hivex-1.3.10/lib/hivex.pod
+--- hivex-1.3.10.old/lib/hivex.pod	2014-01-10 10:00:53.000000000 +0000
++++ hivex-1.3.10/lib/hivex.pod	2017-02-17 16:17:58.137476198 +0000
+@@ -5,7 +5,7 @@
+    generator/generator.ml
+  ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+ 
+- Copyright (C) 2009-2014 Red Hat Inc.
++ Copyright (C) 2009-2017 Red Hat Inc.
+  Derived from code by Petter Nordahl-Hagen under a compatible license:
+    Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+  Derived from code by Markus Stephany under a compatible license:
+@@ -200,6 +200,13 @@
+ 
+ See L<hivex(3)/WRITING TO HIVE FILES>.
+ 
++=item HIVEX_OPEN_UNSAFE
++
++Open the hive in unsafe mode that enables heuristics to handle corrupted hives.
++
++This may allow to read or write registry keys/values that appear intact in an
++otherwise corrupted hive. Use at your own risk.
++
+ =back
+ 
+ Returns a new hive handle.
+@@ -346,7 +353,7 @@
+ 
+ Return the length of the key (name) of a (key, value) pair as produced
+ by C<hivex_value_key>. The length can legitimately be 0, so errno is 
+-the necesary mechanism to check for errors.
++the necessary mechanism to check for errors.
+ 
+ In the context of Windows Registries, a zero-length name means
+ that this value is the default key for this node in the tree.
+diff -ur hivex-1.3.10.old/lib/hivex.syms hivex-1.3.10/lib/hivex.syms
+--- hivex-1.3.10.old/lib/hivex.syms	2014-01-10 10:00:53.000000000 +0000
++++ hivex-1.3.10/lib/hivex.syms	2017-02-17 16:17:58.140476112 +0000
+@@ -3,7 +3,7 @@
+ #   generator/generator.ml
+ # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+ #
+-# Copyright (C) 2009-2014 Red Hat Inc.
++# Copyright (C) 2009-2017 Red Hat Inc.
+ # Derived from code by Petter Nordahl-Hagen under a compatible license:
+ #   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+ # Derived from code by Markus Stephany under a compatible license:
+diff -ur hivex-1.3.10.old/ocaml/hivex_c.c hivex-1.3.10/ocaml/hivex_c.c
+--- hivex-1.3.10.old/ocaml/hivex_c.c	2014-01-10 10:00:53.000000000 +0000
++++ hivex-1.3.10/ocaml/hivex_c.c	2017-02-17 16:17:58.161475510 +0000
+@@ -3,7 +3,7 @@
+  *   generator/generator.ml
+  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+  *
+- * Copyright (C) 2009-2014 Red Hat Inc.
++ * Copyright (C) 2009-2017 Red Hat Inc.
+  * Derived from code by Petter Nordahl-Hagen under a compatible license:
+  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+  * Derived from code by Markus Stephany under a compatible license:
+diff -ur hivex-1.3.10.old/ocaml/hivex.ml hivex-1.3.10/ocaml/hivex.ml
+--- hivex-1.3.10.old/ocaml/hivex.ml	2014-01-10 10:00:53.000000000 +0000
++++ hivex-1.3.10/ocaml/hivex.ml	2017-02-17 16:17:58.151475796 +0000
+@@ -3,7 +3,7 @@
+  *   generator/generator.ml
+  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+  *
+- * Copyright (C) 2009-2014 Red Hat Inc.
++ * Copyright (C) 2009-2017 Red Hat Inc.
+  * Derived from code by Petter Nordahl-Hagen under a compatible license:
+  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+  * Derived from code by Markus Stephany under a compatible license:
+@@ -56,6 +56,7 @@
+   | OPEN_VERBOSE (** Verbose messages *)
+   | OPEN_DEBUG (** Debug messages *)
+   | OPEN_WRITE (** Enable writes to the hive *)
++  | OPEN_UNSAFE (** Enable heuristics to allow read/write of corrupted hives *)
+ 
+ type set_value = {
+   key : string;
+diff -ur hivex-1.3.10.old/ocaml/hivex.mli hivex-1.3.10/ocaml/hivex.mli
+--- hivex-1.3.10.old/ocaml/hivex.mli	2014-01-10 10:00:53.000000000 +0000
++++ hivex-1.3.10/ocaml/hivex.mli	2017-02-17 16:17:58.147475911 +0000
+@@ -3,7 +3,7 @@
+  *   generator/generator.ml
+  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+  *
+- * Copyright (C) 2009-2014 Red Hat Inc.
++ * Copyright (C) 2009-2017 Red Hat Inc.
+  * Derived from code by Petter Nordahl-Hagen under a compatible license:
+  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+  * Derived from code by Markus Stephany under a compatible license:
+@@ -63,6 +63,7 @@
+   | OPEN_VERBOSE (** Verbose messages *)
+   | OPEN_DEBUG (** Debug messages *)
+   | OPEN_WRITE (** Enable writes to the hive *)
++  | OPEN_UNSAFE (** Enable heuristics to allow read/write of corrupted hives *)
+ (** Open flags for {!open_file} call. *)
+ 
+ type set_value = {
+diff -ur hivex-1.3.10.old/perl/Hivex.xs hivex-1.3.10/perl/Hivex.xs
+--- hivex-1.3.10.old/perl/Hivex.xs	2014-01-13 22:20:34.000000000 +0000
++++ hivex-1.3.10/perl/Hivex.xs	2017-02-17 16:17:58.172475194 +0000
+@@ -3,7 +3,7 @@
+  *   generator/generator.ml
+  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+  *
+- * Copyright (C) 2009-2014 Red Hat Inc.
++ * Copyright (C) 2009-2017 Red Hat Inc.
+  * Derived from code by Petter Nordahl-Hagen under a compatible license:
+  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+  * Derived from code by Markus Stephany under a compatible license:
+diff -ur hivex-1.3.10.old/perl/lib/Win/Hivex.pm hivex-1.3.10/perl/lib/Win/Hivex.pm
+--- hivex-1.3.10.old/perl/lib/Win/Hivex.pm	2014-01-10 10:00:53.000000000 +0000
++++ hivex-1.3.10/perl/lib/Win/Hivex.pm	2017-02-17 16:17:58.166475366 +0000
+@@ -3,7 +3,7 @@
+ #   generator/generator.ml
+ # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+ #
+-# Copyright (C) 2009-2014 Red Hat Inc.
++# Copyright (C) 2009-2017 Red Hat Inc.
+ # Derived from code by Petter Nordahl-Hagen under a compatible license:
+ #   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+ # Derived from code by Markus Stephany under a compatible license:
+@@ -66,7 +66,8 @@
+  $h = Win::Hivex->open ($filename,
+                         [verbose => 1,]
+                         [debug => 1,]
+-                        [write => 1,])
++                        [write => 1,]
++                        [unsafe => 1,])
+ 
+ Open a Windows Registry binary hive file.
+ 
+@@ -94,6 +95,8 @@
+   $flags += 2 if $flags{debug};
+   # Enable writes to the hive
+   $flags += 4 if $flags{write};
++  # Enable heuristics to allow read/write of corrupted hives
++  $flags += 8 if $flags{unsafe};
+ 
+   my $self = Win::Hivex::_open ($filename, $flags);
+   bless $self, $class;
+@@ -212,7 +215,7 @@
+ 
+ Return the length of the key (name) of a (key, value) pair as produced
+ by C<value_key>. The length can legitimately be 0, so errno is 
+-the necesary mechanism to check for errors.
++the necessary mechanism to check for errors.
+ 
+ In the context of Windows Registries, a zero-length name means
+ that this value is the default key for this node in the tree.
+@@ -388,7 +391,7 @@
+ 
+ =head1 COPYRIGHT
+ 
+-Copyright (C) 2009-2014 Red Hat Inc.
++Copyright (C) 2009-2017 Red Hat Inc.
+ 
+ =head1 LICENSE
+ 
+diff -ur hivex-1.3.10.old/python/hivex.py hivex-1.3.10/python/hivex.py
+--- hivex-1.3.10.old/python/hivex.py	2014-01-10 10:00:53.000000000 +0000
++++ hivex-1.3.10/python/hivex.py	2017-02-17 16:17:58.177475051 +0000
+@@ -3,7 +3,7 @@
+ #   generator/generator.ml
+ # ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+ #
+-# Copyright (C) 2009-2014 Red Hat Inc.
++# Copyright (C) 2009-2017 Red Hat Inc.
+ # Derived from code by Petter Nordahl-Hagen under a compatible license:
+ #   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+ # Derived from code by Markus Stephany under a compatible license:
+@@ -39,7 +39,7 @@
+ class Hivex(object):
+     """Instances of this class are hivex API handles."""
+ 
+-    def __init__ (self, filename, verbose = False, debug = False, write = False):
++    def __init__ (self, filename, verbose = False, debug = False, write = False, unsafe = False):
+         """Create a new hivex handle."""
+         flags = 0
+         # Verbose messages
+@@ -48,6 +48,8 @@
+         if debug: flags += 2
+         # Enable writes to the hive
+         if write: flags += 4
++        # Enable heuristics to allow read/write of corrupted hives
++        if unsafe: flags += 8
+         self._o = libhivexmod.open (filename, flags)
+ 
+     def __del__ (self):
+diff -ur hivex-1.3.10.old/python/hivex-py.c hivex-1.3.10/python/hivex-py.c
+--- hivex-1.3.10.old/python/hivex-py.c	2014-04-23 15:47:20.000000000 +0100
++++ hivex-1.3.10/python/hivex-py.c	2017-02-17 16:17:58.186474793 +0000
+@@ -3,7 +3,7 @@
+  *   generator/generator.ml
+  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+  *
+- * Copyright (C) 2009-2014 Red Hat Inc.
++ * Copyright (C) 2009-2017 Red Hat Inc.
+  * Derived from code by Petter Nordahl-Hagen under a compatible license:
+  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+  * Derived from code by Markus Stephany under a compatible license:
+diff -ur hivex-1.3.10.old/ruby/ext/hivex/_hivex.c hivex-1.3.10/ruby/ext/hivex/_hivex.c
+--- hivex-1.3.10.old/ruby/ext/hivex/_hivex.c	2014-01-13 22:20:34.000000000 +0000
++++ hivex-1.3.10/ruby/ext/hivex/_hivex.c	2017-02-17 16:17:59.440438835 +0000
+@@ -3,7 +3,7 @@
+  *   generator/generator.ml
+  * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+  *
+- * Copyright (C) 2009-2014 Red Hat Inc.
++ * Copyright (C) 2009-2017 Red Hat Inc.
+  * Derived from code by Petter Nordahl-Hagen under a compatible license:
+  *   Copyright (c) 1997-2007 Petter Nordahl-Hagen.
+  * Derived from code by Markus Stephany under a compatible license:
+@@ -121,6 +121,14 @@
+  * read-only.
+  * 
+  * See "WRITING TO HIVE FILES" in hivex(3).
++ * 
++ * HIVEX_OPEN_UNSAFE
++ * Open the hive in unsafe mode that enables heuristics
++ * to handle corrupted hives.
++ * 
++ * This may allow to read or write registry keys/values
++ * that appear intact in an otherwise corrupted hive.
++ * Use at your own risk.
+  *
+  *
+  * (For the C API documentation for this function, see
+@@ -137,6 +145,8 @@
+     flags += 2;
+   if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern ("write")))))
+     flags += 4;
++  if (RTEST (rb_hash_lookup (flagsv, ID2SYM (rb_intern ("unsafe")))))
++    flags += 8;
+ 
+   hive_h *r;
+ 
+@@ -580,8 +590,8 @@
+  *
+  * Return the length of the key (name) of a (key, value)
+  * pair as produced by "h.value_key". The length can
+- * legitimately be 0, so errno is the necesary mechanism to
+- * check for errors.
++ * legitimately be 0, so errno is the necessary mechanism
++ * to check for errors.
+  * 
+  * In the context of Windows Registries, a zero-length name
+  * means that this value is the default key for this node
diff --git a/SOURCES/hivex-1.3.8-dirs.patch b/SOURCES/hivex-1.3.8-dirs.patch
deleted file mode 100644
index 3f0f652..0000000
--- a/SOURCES/hivex-1.3.8-dirs.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -ur hivex-1.3.8.old/perl/Makefile.am hivex-1.3.8/perl/Makefile.am
---- hivex-1.3.8.old/perl/Makefile.am	2013-07-25 15:09:00.000000000 +0100
-+++ hivex-1.3.8/perl/Makefile.am	2013-07-25 23:14:10.952149773 +0100
-@@ -43,7 +43,7 @@
- 
- TESTS_ENVIRONMENT = ../run
- 
--INSTALLDIRS = site
-+INSTALLDIRS = vendor
- 
- all: Makefile-pl src_deps
- 	$(MAKE) -f Makefile-pl
diff --git a/SPECS/hivex.spec b/SPECS/hivex.spec
index 81e7343..24b555f 100644
--- a/SPECS/hivex.spec
+++ b/SPECS/hivex.spec
@@ -7,7 +7,7 @@
 
 Name:           hivex
 Version:        1.3.10
-Release:        5.7%{?dist}
+Release:        5.8%{?dist}
 Summary:        Read and write Windows Registry binary hive files
 
 License:        LGPLv2
@@ -15,22 +15,42 @@ URL:            http://libguestfs.org/
 
 Source0:        http://libguestfs.org/download/hivex/%{name}-%{version}.tar.gz
 
+# The RHEL 7 patches are stored in the upstream git repository,
+# in the branch called 'rhel-7.4', ie:
+# https://github.com/libguestfs/hivex/tree/rhel-7.4
+
 # Fix Perl directory install path.
-Patch0:         %{name}-1.3.8-dirs.patch
-BuildRequires:  autoconf, automake, libtool, gettext-devel
+Patch0001:      0001-Fix-Perl-directory-install-path.patch
 
-# Upstream patches to fix RHBZ#1145056
-Patch1:         0001-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch
-Patch2:         0002-hivexml-Tidy-up-error-handling-and-printing.patch
-Patch3:         0001-lib-Don-t-leak-errno-from-_hivex_recode-function.patch
+# Upstream patches to fix RHBZ#1145056.
+Patch0002:      0002-value-Set-errno-0-on-non-error-path-in-hivex_value_d.patch
+Patch0003:      0003-hivexml-Tidy-up-error-handling-and-printing.patch
+Patch0004:      0004-lib-Don-t-leak-errno-from-_hivex_recode-function.patch
 
-# Upstream patches to fix RHBZ#1158992
-Patch4:         0001-handle-Refuse-to-open-files-8192-bytes-in-size.patch
-Patch5:         0002-handle-Check-that-pages-do-not-extend-beyond-the-end.patch
+# Upstream patches to fix RHBZ#1158992.
+Patch0005:      0005-handle-Refuse-to-open-files-8192-bytes-in-size.patch
+Patch0006:      0006-handle-Check-that-pages-do-not-extend-beyond-the-end.patch
 
 # Fix typo in documentation (RHBZ#1099286).
-# Patch contains upstream fix + generated code.
-Patch6:         0001-generator-Fix-a-spelling-mistake-in-the-documentatio.patch
+Patch0007:      0007-generator-Fix-a-spelling-mistake-in-the-documentatio.patch
+
+# Tolerate corruption in some hives (RHBZ#1423436).
+Patch0008:      0008-add-HIVEX_OPEN_UNSAFE-flag.patch
+Patch0009:      0009-lib-change-how-hbin-sections-are-read.patch
+Patch0010:      0010-lib-allow-to-walk-registry-with-corrupted-blocks.patch
+Patch0011:      0011-hivexsh-add-u-flag-for-HIVEX_OPEN_UNSAFE.patch
+Patch0012:      0012-hivexregedit-allow-to-pass-HIVEX_OPEN_UNSAFE.patch
+
+# Patch generated code (because we can't assume we have OCaml on all
+# arches).  To construct this you need to do 'make prep', run the
+# generator by hand, and diff before and after.
+Patch9999:      generated.patch
+
+# Use git to apply patches.
+BuildRequires:  git
+
+# Since some patches touch autotools file, we need to rerun autoreconf.
+BuildRequires:  autoconf, automake, libtool, gettext-devel
 
 BuildRequires:  perl
 BuildRequires:  perl-Test-Simple
@@ -159,15 +179,22 @@ ruby-%{name} contains Ruby bindings for %{name}.
 %prep
 %setup -q
 
-%patch0 -p1 -b .dirs
-autoreconf -i
+# Use git to apply patches.
+# http://rwmj.wordpress.com/2011/08/09/nice-rpm-git-patch-management-trick/
+git init
+git config user.email "libguestfs@redhat.com"
+git config user.name "libguestfs"
+git add .
+git commit -a -q -m "%{version} baseline"
+for f in %{patches}; do
+    if [[ ! "$f" =~ generated.patch ]]; then
+	git am "$f"
+    else
+	patch -p1 < "$f"
+    fi
+done
 
-%patch1 -p1
-%patch2 -p1
-%patch3 -p1
-%patch4 -p1
-%patch5 -p1
-%patch6 -p1
+autoreconf -i
 
 %build
 %configure --disable-static
@@ -269,6 +296,11 @@ rm $RPM_BUILD_ROOT%{python_sitearch}/libhivexmod.la
 
 
 %changelog
+* Fri Feb 17 2017 Richard W.M. Jones <rjones@redhat.com> - 1.3.10-5.8
+- Tolerate corruption in some hives
+  resolves: rhbz#1423436
+- Switch to using git to manage patches.
+
 * Mon Nov 17 2014 Richard W.M. Jones <rjones@redhat.com> - 1.3.10-5.7
 - Fix: "Argument list too long" when using virt-v2v on Windows guest
   with French copy of Citrix installed