1 package Packages::Release;
10 my $config = shift || {};
13 bless( $self, $classname );
15 $self->{config} = $config;
16 if ($config->{file}) {
24 my ($self, $file, $config) = @_;
26 $self->config(%$config) if $config;
28 $self->{config}{file} = $file if $file;
29 return unless $self->{config}{file};
33 open(my $rf, '<', $self->{config}{file})
34 or die "$self->{config}{file}: $!\n";
37 die "too many paragraphs in release file $self->{config}{file})"
39 return unless @content && $content[0] !~ /^\s*$/;
45 while (/^(\S+):\s*(.*)\s*$/mg) {
46 my ($key, $value) = ($1, $2);
47 $value =~ s/\377/\n /g;
48 $key =~ tr [A-Z] [a-z];
52 $data{components} = [ split(/\s+/, $data{components}||'') ];
53 $data{architectures} = [ split(/\s+/, $data{architectures}||'') ];
54 $data{timestamp} = str2time($data{date}) if $data{date};
56 read_files_field( \%data, 'md5sum' );
57 read_files_field( \%data, 'sha1' );
58 read_files_field( \%data, 'sha256' );
60 $self->{data} = \%data;
63 sub read_files_field {
64 my ($data, $fieldname) = @_;
66 return unless $data->{$fieldname};
67 my @lines = split /\n/, $data->{$fieldname};
75 my ($checksum, $size, $name) = split /\s+/, $_, 3;
76 # warn "($checksum, $size, $name)\n";
78 (my $basename = $name) =~ s/\.(gz|bz2)$//o;
79 my $ext = 'uncompressed';
80 if ($basename ne $name) {
84 if ($data->{files}{$basename}{$ext}{size}
85 and $data->{files}{$basename}{$ext}{size} != $size) {
86 die "conflicting sizes for $name: $data->{files}{$basename}{$ext}{size} != $size\n";
88 $data->{files}{$basename}{$ext}{size} = $size;
89 $data->{files}{$basename}{$ext}{$fieldname} = $checksum;
92 delete($data->{$fieldname});
96 my ($self, $base, $config) = @_;
98 $self->config(%$config) if $config;
100 return unless $self->{config}{file};
101 my $sigfile = "$self->{config}{file}.gpg";
103 if ($self->{config}{keyring}) {
104 $self->_v("checking signature\n");
106 die "$self->{config}{keyring} not readable\n"
107 unless -r $self->{config}{keyring};
110 '--trust-model', 'always', '--no-default-keyring',
111 '--keyring', $self->{config}{keyring}, '--verify',
112 $sigfile, $self->{config}{file})) {
113 die "signature check failed.\n";
117 $self->{config}{base} = $base if $base;
118 return unless $self->{config}{base};
119 return unless -d $self->{config}{base};
120 return unless $self->{data}{files};
122 foreach my $f (sort keys %{$self->{data}{files}}) {
123 $self->_v("checking file $f:\n");
125 $self->_check_file($f);
126 $self->_check_file($f, 'gz');
127 $self->_check_file($f, 'bz2');
132 my ($self, $file, $ext) = @_;
134 my $f = "$self->{config}{base}/$file";
135 $f .= ".$ext" if $ext;
136 $ext ||= 'uncompressed';
138 return unless exists $self->{data}{files}{$file}{$ext};
141 warn "\t$f doesn't exist or is not a file\n"
142 unless $self->{config}{ignoremissing};
147 $self->_v("\t$ext: ");
148 if ($size == $self->{data}{files}{$file}{$ext}{size}) {
149 $self->_v('size ok');
151 $self->_ce("$f size NOT OK: $size != $self->{data}{files}{$file}{$ext}{size}");
152 $self->{errors}{$file}{$ext}{size} = $size;
156 my %checksums = %{ get_checksums($f) };
158 foreach (qw(md5sum sha1 sha256)) {
160 if (!exists $self->{data}{files}{$file}{$ext}{$_}) {
161 $self->_v("$_ not available");
162 } elsif ($checksums{$_} eq $self->{data}{files}{$file}{$ext}{$_}) {
165 $self->_ce("$f $_ NOT OK: $checksums{$_} ne $self->{data}{files}{$file}{$ext}{$_}");
166 $self->{errors}{$file}{$ext}{$_} = $checksums{$_};
178 $checksums{md5sum} = `md5sum $file 2>/dev/null`;
179 $checksums{sha1} = `sha1sum $file 2>/dev/null`;
180 $checksums{sha256} = `sha256sum $file 2>/dev/null`;
182 foreach (qw(md5sum sha1 sha256)) {
183 chomp $checksums{$_};
184 $checksums{$_} = (split(/\s+/, $checksums{$_}, 2))[0];
191 my ($self, @text) = @_;
193 print(STDERR @text) if $self->{config}{verbose};
197 my ($self, @text) = @_;
199 if ($self->{config}{dieoncheckerror}) {
207 my ($self, %config) = @_;
209 while (my ($k, $v) = each %config) {
210 $self->{config}{$k} = $v;