File: //bin/makedumpfile-R.pl
#!/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;
}