summaryrefslogtreecommitdiffstats
path: root/pm/MGATools/iso.pm
blob: b1ab04d28f8d21344303c535fac96e0c92480e67 (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
package MGATools::iso;

use strict;
use Digest::MD5;

require Exporter;
use URPM;
our @ISA = qw(Exporter);
our @EXPORT = qw(include_md5);
our ($INFO_OFFSET, $SIZE_OFFSET, $SKIP);
$INFO_OFFSET = 883;
$SIZE_OFFSET = 84;
$SKIP = 15;

=head1 NAME

Mageia iso tools

=head1 SYNOPSYS

    require MGATools::iso;

=head1 DESCRIPTION

<MGATools::iso> includes Mageia iso tools.

=head1 SEE ALSO

mkcd

=head1 COPYRIGHT

Copyright (C) 2000,2001,2002,2003,2004 Mandriva <warly@mandriva.com>

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, 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

=head1 CREDITS

md5 code highly inspired from Redhat anaconda md5 in ISO code

=cut


# function copied from Mkcd::Tools
# TODO must add some check of maximum authorized size
sub include_md5 {
    my ($iso, $write, $verbose) = @_;
    my $ISO; 
    if ($write) {
	open $ISO, "+<$iso" or return "ERROR include_md5: unable to open $iso ($!)\n";	
    } else {
	open $ISO, $iso or return "ERROR include_md5: unable to open $iso ($!)\n";	
    }
    binmode $ISO;
    my $offset = 16*2048;
    # blank header
    seek $ISO, $offset, 0;
    my ($buf, $msg);
    while (1) {
	read $ISO,$buf,2048;
	my $c = ord $buf;
	last if $c == 1;
	return "ERROR include_md5: could not find primary volume descriptor\n" if $c == 255;
	$offset += 2048
    }
    my $size = ((ord substr $buf, $SIZE_OFFSET, 1) * 0x1000000 + 
                (ord substr $buf, $SIZE_OFFSET + 1, 1) * 0x10000 + 
		(ord substr $buf, $SIZE_OFFSET + 2, 1) * 0x100 + 
		(ord substr $buf, $SIZE_OFFSET + 3, 1)) * 2048;
    my ($system, $volume, $publisher, $prep, $app) = map { $a = $_ ; $a =~ s/^\s*//; $a =~ s/\s*$//; $a } (substr($buf, 8, 22), substr($buf, 30, 40), substr($buf, 318, 128), substr($buf, 446, 32), substr($buf, 574, 128)); 
    print "include_md5:\nSystem: \t$system\nVolume: \t$volume\nPublisher: \t$publisher\nData preparer: \t$prep\nApplication: \t$app\nISO size: \t$size\n" if $verbose;
    seek $ISO, $offset + $INFO_OFFSET, 0;
    read $ISO, $buf,512;
    my ($md5sum) = $buf =~ /.md5 = (\S+)/;
    $msg .= "include_md5: previous data $buf\n";
    seek $ISO, 0, 0;
    my $md5 = new Digest::MD5;
    my $read = read $ISO, $buf, $offset + $INFO_OFFSET;
    $md5->add($buf);
    seek $ISO, 512, 1;
    $read += 512;
    $|=1;
    my $val = int $size/2048/100;
    $verbose and print "\rReading: 0 %";
    my ($i, $j);
    # skip last $SKIP bytes that sometimes are not correctly burned by some drives
    my $n = 1;
    while ($n && $read < $size - $SKIP * 2048) {
	$n = read $ISO, $buf,2048;
	print "\rReading: ", $j++, " %" if ($verbose && !($i++ % $val));
	$md5->add($buf);
	$read += $n;
    }
    print "\n";
    my $digest = $md5->hexdigest;
    $msg .= "include_md5: computed md5 $digest\n";
    my $res = $md5sum eq $digest;
    if ($md5sum) {
	$msg .= "include_md5: previous md5 $md5sum\ninclude_md5: md5sum check ";
	$msg .= $res ? "OK\n" : "FAILED\n"
    }
    print $msg if $verbose;
    $write or return $res;
    seek $ISO, $offset + $INFO_OFFSET, 0;
    my $str = substr "$volume.md5 = $digest", 0, 512;
    my $l = length $str;
    print $ISO ($l > 512 ? substr $str, -1, 512 : $str . ' ' x (512 - $l));
    close $ISO
}

1