+# Only used when merging to map downloaded hive names to hive handles.
+my %hives;
+
+if (!$merge) { # Export mode.
+ die __"expecting 1 or 2 more parameters, subkey path and optionally the value to export\n"
+ if @ARGV < 1 || @ARGV > 2;
+
+ my $path = shift @ARGV;
+ my $name = shift @ARGV; # or undef
+
+ # Map this to the hive name. This function dies on failure.
+ my ($hivename, $prefix);
+ ($hivename, $path, $prefix) = map_path_to_hive ($path);
+
+ # Download the chosen hive.
+ download_hive ($hivename);
+
+ # Open it.
+ my $h = Win::Hivex->open ("$tmpdir/$hivename", debug => $debug);
+
+ unless ($name) {
+ # Export it.
+ warn "exporting $path from $hivename with prefix $prefix ..." if $debug;
+ reg_export ($h, $path, \*STDOUT, prefix => $prefix);
+ } else {
+ # Export a single key using hivexget.
+ my @args = ("hivexget", "$tmpdir/$hivename", $path, $name);
+ warn "running ", join (" ", @args), " ..." if $debug;
+ system (@args) == 0 or die "hivexget failed: $?"
+ }
+}
+else { # Import mode.
+ if (@ARGV == 0) {
+ reg_import (\*STDIN, \&import_mapper, encoding => $encoding);
+ } else {
+ foreach (@ARGV) {
+ open my $fh, $_ or die "open: $_: $!";
+ reg_import ($fh, \&import_mapper, encoding => $encoding);
+ }
+ }
+
+ # Now we've done importing, commit all the hive handles and
+ # close them all.
+ $_->commit (undef) foreach values %hives;
+ %hives = ();
+
+ # Look in the tmpdir for all the hive files which have been
+ # downloaded / modified by the import mapper, and upload
+ # each one.
+ opendir my $dh, $tmpdir or die "$tmpdir: $!";
+ foreach (readdir $dh) {
+ unless (/^\./) {
+ upload_hive ($_)
+ }
+ }
+
+ # Sync everything.
+ $g->umount_all ();
+ $g->sync ();
+}
+
+exit 0;
+
+# map function passed to reg_import.
+sub import_mapper
+{
+ local $_ = shift;
+
+ my ($hivename, $path, $prefix) = map_path_to_hive ($_);