summaryrefslogtreecommitdiff
path: root/makedumpfile-R.pl
blob: 7879d457bd05553eb6870c48ba5410443f917de1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
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;
}