summaryrefslogtreecommitdiff
path: root/makedumpfile-R.pl
diff options
context:
space:
mode:
Diffstat (limited to 'makedumpfile-R.pl')
-rw-r--r--makedumpfile-R.pl202
1 files changed, 202 insertions, 0 deletions
diff --git a/makedumpfile-R.pl b/makedumpfile-R.pl
new file mode 100644
index 0000000..7879d45
--- /dev/null
+++ b/makedumpfile-R.pl
@@ -0,0 +1,202 @@
+#!/usr/bin/perl
+
+# makedumpfile-R.pl
+#
+# Copyright (C) 2007, 2008 NEC Corporation
+#
+# 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.
+
+$name_dumpfile = @ARGV[0];
+$TRUE = 1;
+$FALSE = 0;
+$MAKEDUMPFILE_SIGNATURE = "makedumpfile";
+$MAX_SIZE_MDF_HEADER = 4096;
+$TYPE_FLAT_HEADER = 1;
+$END_FLAG_FLAT_HEADER = -1;
+
+print "Start re-arranging dump data of flattened format to a dumpfile.\n";
+open(FILE_DUMPFILE, ">$name_dumpfile") || die "Cannot open $name_dumpfile.\n";
+binmode(FILE_DUMPFILE);
+
+$value_64bits = &is_64bits_system;
+
+if (&rearrange_dumpdata == $TRUE) {
+ printf "The dumpfile is saved to $name_dumpfile.\n";
+ printf "Completed.\n";
+} else {
+ printf "Failed.\n";
+}
+close(FILE_DUMPFILE);
+# End
+
+
+# Re-arrange dump data of flattened format from a standard input.
+sub rearrange_dumpdata {
+ if (&read_start_flat_header != $TRUE) {
+ return $FALSE;
+ }
+ if ($value_64bits == $TRUE) {
+ $ret_seek = &seek_for_64bits_system();
+ } else {
+ $ret_seek = &seek_for_32bits_system();
+ }
+ $buf_size = &get_buf_size();
+ while (($ret_seek == $TRUE) && (0 < $buf_size)) {
+ &read_buf_from_stdin($buf_size);
+ if (syswrite(FILE_DUMPFILE, $buf, $buf_size) != $buf_size) {
+ print "Cannot write. $buf_size\n";
+ return $FALSE;
+ }
+ if ($value_64bits == $TRUE) {
+ $ret_seek = &seek_for_64bits_system();
+ } else {
+ $ret_seek = &seek_for_32bits_system();
+ }
+ $buf_size = &get_buf_size();
+ }
+ if (($ret_seek != $END_FLAG_FLAT_HEADER) || ($buf_size != $END_FLAG_FLAT_HEADER)) {
+ print "Cannot get valid end header of flattened format.\n";
+ print "ret_seek = $ret_seek, buf_size = $buf_size\n";
+ return $FALSE;
+ }
+ return $TRUE;
+}
+
+sub read_start_flat_header {
+ &read_buf_from_stdin($MAX_SIZE_MDF_HEADER);
+ if (index($buf, $MAKEDUMPFILE_SIGNATURE) != 0) {
+ print "It is not flattened format.\n";
+ return $FALSE;
+ }
+ return $TRUE;
+}
+
+sub seek_for_64bits_system {
+ my $value = 0;
+ my ($high, $low) = &read_64bits;
+
+ $value = &convert_2values_to_1value($high, $low);
+ if ($value < 0) {
+ return $value;
+ }
+ if (seek(FILE_DUMPFILE, $value, 0) == 0) {
+ print "Cannot seek.\n";
+ return $FALSE;
+ }
+ return $TRUE;
+}
+
+sub seek_for_32bits_system {
+ my ($high, $low) = &read_64bits;
+
+ # On 32bits system, a normal value cannot explain the offset of
+ # large file(4GB or larger). For solving this problem, BigInt
+ # module is used. But this module makes speed down.
+ use Math::BigInt;
+ local $value = Math::BigInt->new(1);
+
+ if ($high < 0x80000000) {
+ $value->blsft(32);
+ $value->bmul($high);
+ $value->badd($low);
+ } else {
+ # Negative value
+ $low = ($low ^ 0xffffffff);
+ $high = ($high ^ 0xffffffff);
+ $value->blsft(32);
+ $value->bmul($high);
+ $value->badd($low);
+ $value->badd(1);
+ $value->bneg();
+ }
+ if ($value < 0) {
+ return $value;
+ }
+ if (seek(FILE_DUMPFILE, $value, 0) == 0) {
+ print "Cannot seek.\n";
+ return $FALSE;
+ }
+ return $TRUE;
+}
+
+# Get buf_size of flattened data header.
+sub get_buf_size {
+ my ($high, $low) = &read_64bits;
+ return &convert_2values_to_1value($high, $low);
+}
+
+# Convert 2 values to 1 value.
+# This function should be called only if a value isn't over the size
+# of system value.
+sub convert_2values_to_1value {
+ my ($high, $low) = (@_[0], @_[1]);
+ my $value = 0;
+ if ($high < 0x80000000) {
+ $value = $high * (1 << 32) + $low;
+ } else {
+ # Negative value
+ $low = ($low ^ 0xffffffff);
+ $high = ($high ^ 0xffffffff);
+ $value = (-1) * ($high * (1 << 32) + $low + 1);
+ }
+ return $value;
+}
+
+# Get 64bits of dump data.
+# This function returns 2 values because a value of 32bits system cannot
+# explain 64bits.
+sub read_64bits {
+ my ($high, $low) = (0, 0);
+ &read_buf_from_stdin(8);
+
+ # Separate 2 values because hex() cannot support 64bits on 32bits system.
+ my ($value1, $value2) = unpack("H8 H8", $buf);
+ $value1 = hex($value1);
+ $value2 = hex($value2);
+ if (is_bigendian() == $TRUE) {
+ $low = $value1;
+ $high = $value2;
+ } else {
+ $low = $value2;
+ $high = $value1;
+ }
+ return ($high, $low);
+}
+
+# Get dump data of flattened format from a standard input.
+sub read_buf_from_stdin {
+ my $buf_size = @_[0];
+ my $read_size = 0;
+ while ($read_size < $buf_size) {
+ $read_size += sysread(STDIN, $buf, $buf_size - $read_size, $read_size);
+ }
+}
+
+# Check 64/32bits system.
+sub is_64bits_system {
+ my $temp1 = 1 << 31;
+ my $temp2 = 1 << 33;
+ if ($temp1 < $temp2) {
+ return $TRUE;
+ }
+ return $FALSE;
+}
+
+# Check big/little endian.
+sub is_bigendian {
+ my $value = pack("l", 1234);
+ $value = unpack("n", $value);
+ if ($value == 1234) {
+ return $TRUE;
+ }
+ return $FALSE;
+}
+