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 $self->_v("checking Release file $self->{config}{file}\n");
102 my $sigfile = "$self->{config}{file}.gpg";
104 if ($self->{config}{keyring}) {
105 $self->_v("\tchecking signature\n");
107 die "$self->{config}{keyring} not readable\n"
108 unless -r $self->{config}{keyring};
111 '--trust-model', 'always', '--no-default-keyring',
112 '--keyring', $self->{config}{keyring}, '--verify',
113 $sigfile, $self->{config}{file})) {
114 die "signature check failed.\n";
118 $self->{config}{base} = $base if $base;
119 return unless $self->{config}{base};
120 return unless -d $self->{config}{base};
121 return unless $self->{data}{files};
123 foreach my $f (sort keys %{$self->{data}{files}}) {
124 $self->_v("checking file $f:\n");
126 $self->_check_file($f);
127 $self->_check_file($f, 'gz');
128 $self->_check_file($f, 'bz2');
133 my ($self, $file, $ext) = @_;
135 my $f = "$self->{config}{base}/$file";
136 $f .= ".$ext" if $ext;
137 $ext ||= 'uncompressed';
139 return unless exists $self->{data}{files}{$file}{$ext};
142 warn "\t$f doesn't exist or is not a file\n"
143 unless $self->{config}{ignoremissing};
148 $self->_v("\t$ext: ");
149 if ($size == $self->{data}{files}{$file}{$ext}{size}) {
150 $self->_v('size ok');
152 $self->_ce("$f size NOT OK: $size != $self->{data}{files}{$file}{$ext}{size}");
153 $self->{errors}{$file}{$ext}{size} = $size;
157 my %checksums = %{ get_checksums($f) };
159 foreach (qw(md5sum sha1 sha256)) {
161 if (!exists $self->{data}{files}{$file}{$ext}{$_}) {
162 $self->_v("$_ not available");
163 } elsif ($checksums{$_} eq $self->{data}{files}{$file}{$ext}{$_}) {
166 $self->_ce("$f $_ NOT OK: $checksums{$_} ne $self->{data}{files}{$file}{$ext}{$_}");
167 $self->{errors}{$file}{$ext}{$_} = $checksums{$_};
179 $checksums{md5sum} = `md5sum $file 2>/dev/null`;
180 $checksums{sha1} = `sha1sum $file 2>/dev/null`;
181 $checksums{sha256} = `sha256sum $file 2>/dev/null`;
183 foreach (qw(md5sum sha1 sha256)) {
184 chomp $checksums{$_};
185 $checksums{$_} = (split(/\s+/, $checksums{$_}, 2))[0];
192 my ($self, @text) = @_;
194 print(STDERR @text) if $self->{config}{verbose};
198 my ($self, @text) = @_;
200 if ($self->{config}{dieoncheckerror}) {
208 my ($self, %config) = @_;
210 while (my ($k, $v) = each %config) {
211 $self->{config}{$k} = $v;