1 | package Mkcd::Tools; |
---|
2 | |
---|
3 | our $VERSION = '1.0.0'; |
---|
4 | |
---|
5 | use strict; |
---|
6 | use File::NCopy qw(copy); |
---|
7 | use Image::Size qw(:all); |
---|
8 | use Mkcd::Commandline qw(parseCommandLine usage); |
---|
9 | use Digest::MD5; |
---|
10 | use MDK::Common qw(all any); |
---|
11 | require Exporter; |
---|
12 | use URPM; |
---|
13 | our @ISA = qw(Exporter); |
---|
14 | our @EXPORT = qw(printTable getTracks du cpal checkcds checkDiscs cleanrpmsrate imageSize printDiscsFile readBatchFile printBatchFile config compute_md5 log_ include_md5 convert_size compute_files_md5 fix_dir filter_path); |
---|
15 | our ($GB, $MB, $KB, $INFO_OFFSET, $SIZE_OFFSET, $SKIP); |
---|
16 | $INFO_OFFSET = 883; |
---|
17 | $SIZE_OFFSET = 84; |
---|
18 | $SKIP = 15; |
---|
19 | |
---|
20 | $KB = 1024; |
---|
21 | $MB = 1024 * 1024; |
---|
22 | $GB = $MB * 1024; |
---|
23 | |
---|
24 | =head1 NAME |
---|
25 | |
---|
26 | tools - mkcd tools |
---|
27 | |
---|
28 | =head1 SYNOPSYS |
---|
29 | |
---|
30 | require mkcd::tools; |
---|
31 | |
---|
32 | =head1 DESCRIPTION |
---|
33 | |
---|
34 | <mkcd::tools> includes mkcd tools. |
---|
35 | |
---|
36 | =head1 SEE ALSO |
---|
37 | |
---|
38 | mkcd |
---|
39 | |
---|
40 | =head1 COPYRIGHT |
---|
41 | |
---|
42 | Copyright (C) 2000-2003 Mandrakesoft <warly@mandrakesoft.com> |
---|
43 | |
---|
44 | This program is free software; you can redistribute it and/or modify |
---|
45 | it under the terms of the GNU General Public License as published by |
---|
46 | the Free Software Foundation; either version 2, or (at your option) |
---|
47 | any later version. |
---|
48 | |
---|
49 | This program is distributed in the hope that it will be useful, |
---|
50 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
51 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
52 | GNU General Public License for more details. |
---|
53 | |
---|
54 | You should have received a copy of the GNU General Public License |
---|
55 | along with this program; if not, write to the Free Software |
---|
56 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
57 | |
---|
58 | =head1 CREDITS |
---|
59 | |
---|
60 | md5 code highly inspired from Redhat anaconda md5 in ISO code |
---|
61 | |
---|
62 | =cut |
---|
63 | |
---|
64 | sub printTable { |
---|
65 | my ($a, $log) = @_; |
---|
66 | my $LOG; if ($log) { $LOG = $log } else { open $LOG, ">&STDERR" } |
---|
67 | # |
---|
68 | # iterative version of a recursive scanning of a table. |
---|
69 | # ex: @config = [[[1,3],3,[1,3,[1,3]]],3,4,[4,[4,4]]] |
---|
70 | # |
---|
71 | my @A; |
---|
72 | my @i; |
---|
73 | my @tab; |
---|
74 | my $i = 0; |
---|
75 | while ($a) { |
---|
76 | my $u = ref $a; |
---|
77 | if ($u eq 'ARRAY') { |
---|
78 | while ($i < @$a) { |
---|
79 | my $b = $a->[$i]; |
---|
80 | my $t = ref $b; |
---|
81 | if ($t eq 'ARRAY') { |
---|
82 | push @tab, "\t"; |
---|
83 | push @i, $i+1; |
---|
84 | push @A, $a; |
---|
85 | $i = 0; |
---|
86 | $a = $b; |
---|
87 | next |
---|
88 | } elsif ($t eq 'HASH') { |
---|
89 | $i++; print $LOG "@tab", join ' ', keys %$b, "\n" |
---|
90 | } else { $i++; print $LOG "@tab$b\n" } |
---|
91 | } |
---|
92 | } else { print $LOG "$a\n" } |
---|
93 | pop @tab; |
---|
94 | $i = pop @i; |
---|
95 | $a = pop @A; |
---|
96 | } |
---|
97 | |
---|
98 | } |
---|
99 | |
---|
100 | sub getTracks { |
---|
101 | my ($tracks, $log) = @_; |
---|
102 | my $LOG; if ($log) { $LOG = $log } else { open $LOG, ">&STDERR" } |
---|
103 | my @tracks = split ',',$tracks; |
---|
104 | my @t; |
---|
105 | foreach (@tracks) { |
---|
106 | /(\d+)/ and push @t, $1; |
---|
107 | /(\d+)-(\d+)/ and push @t, $1..$2 |
---|
108 | } |
---|
109 | my @ntracks; |
---|
110 | my %done; |
---|
111 | for (my $i = $#t; $i >= 0; $i--) { |
---|
112 | push @ntracks, $t[$i] if !$done{$t[$i]}; |
---|
113 | $done{$t[$i]}=1 |
---|
114 | } |
---|
115 | \@ntracks; |
---|
116 | } |
---|
117 | |
---|
118 | sub du { |
---|
119 | my ($path, $inode) = @_; |
---|
120 | my $size; |
---|
121 | $inode ||= {}; |
---|
122 | if (-d $path) { |
---|
123 | opendir O, $path; |
---|
124 | foreach (readdir O) { |
---|
125 | /^\.{1,2}$/ and next; |
---|
126 | -l "$path/$_" or $size += du("$path/$_",$inode) |
---|
127 | } |
---|
128 | } else { |
---|
129 | if (! -l $path) { |
---|
130 | my @stat = stat $path; |
---|
131 | if (!$inode->{$stat[0]}{$stat[1]}) { |
---|
132 | $size = $stat[7] + 2048; |
---|
133 | $inode->{$stat[0]}{$stat[1]} = 1 |
---|
134 | } |
---|
135 | } |
---|
136 | } |
---|
137 | $size |
---|
138 | } |
---|
139 | |
---|
140 | sub cpal { |
---|
141 | my ($source, $dest, $exclude, $verbose, $log) = @_; |
---|
142 | my $LOG; if ($log) { $LOG = $log } else { open $LOG, ">&STDERR" } |
---|
143 | if ($exclude && "$source/$_" =~ /$exclude/) { return 0 } |
---|
144 | if (!-l $source && -d $source) { |
---|
145 | mkdir $dest; |
---|
146 | opendir O, $source; |
---|
147 | foreach (readdir O) { |
---|
148 | /^\.{1,2}$/ and next; |
---|
149 | cpal("$source/$_", "$dest/$_",$exclude,$verbose) |
---|
150 | } |
---|
151 | } else { |
---|
152 | my $ok; |
---|
153 | if (-d $dest) { my ($filename) = $source =~ m,([^/]*)$,; $dest .= "/$filename" } |
---|
154 | $ok = link $source, $dest; |
---|
155 | $verbose and print $LOG "cpal: link $source -> $dest\n"; |
---|
156 | if (!$ok) { |
---|
157 | print $LOG "Linking failed $source -> $dest: $!, trying to copy\n"; |
---|
158 | $ok = copy $source, $dest; |
---|
159 | if (!$ok) { print $LOG "Copying failed $source -> $dest: $!,\n"; return 0 } |
---|
160 | } |
---|
161 | } |
---|
162 | 1 |
---|
163 | } |
---|
164 | |
---|
165 | sub checkDiscs { |
---|
166 | my ($hdlists, $depslist, $discsFiles, $check, $log) = @_; |
---|
167 | my $LOG; if ($log) { $LOG = $log } else { open $LOG, ">&STDOUT" } |
---|
168 | |
---|
169 | print $LOG "checkDiscs: depslist $depslist\n"; |
---|
170 | # |
---|
171 | # depslist hdlist consistency -> error ok (not the same as install one, but duplicate will break anyway) |
---|
172 | # |
---|
173 | # in hdlist, not in depslist -> error ok |
---|
174 | # |
---|
175 | # in hdlist, not in dir -> error ok |
---|
176 | # |
---|
177 | # in hdlist with packdrake, no with parsehdlist -> error |
---|
178 | # |
---|
179 | # in depslist, not in hdlist -> error ok |
---|
180 | # |
---|
181 | # in depslist, not in dir -> error ok |
---|
182 | # |
---|
183 | # in dir, not in hdlist -> warning ok |
---|
184 | # |
---|
185 | # in dir, not in depslist -> warning ok |
---|
186 | # |
---|
187 | # multiple version in depslist -> error ok |
---|
188 | # |
---|
189 | # multiple version in hdlist -> error ok |
---|
190 | # |
---|
191 | # multiple in dir -> warning ok |
---|
192 | # |
---|
193 | |
---|
194 | my $ok = 1; |
---|
195 | my $OK = 1; |
---|
196 | my %depslist; |
---|
197 | my %depslistname; |
---|
198 | if ($depslist) { |
---|
199 | my $i = 1; |
---|
200 | open my $A, $depslist or print $LOG "ERROR: unable to open $depslist" and return 0; |
---|
201 | print $LOG "checkDiscs: duplicate version in $depslist:"; |
---|
202 | while (<$A>) { |
---|
203 | my ($pkg, $name, $arch) = ((split)[0]) =~ m/((.*)-[^-]+-[^-]+\.([^:]+))/; |
---|
204 | $depslist{$pkg} and do { print $LOG "\n$pkg"; $ok = 0 }; |
---|
205 | $depslistname{$arch}{$name} and do { print $LOG "\n$name"; $ok = 0 }; |
---|
206 | $depslist{$pkg} = $i; |
---|
207 | $depslistname{$arch}{$name} = $i++; |
---|
208 | } |
---|
209 | close $A; |
---|
210 | } |
---|
211 | $ok or $OK = 0; |
---|
212 | $ok ? print $LOG " OK\n" : print $LOG "\nFAILED\n"; |
---|
213 | my %hdlist; |
---|
214 | print $LOG "\ncheckDiscs: duplicate version in hdlists:"; |
---|
215 | my $maxidx; |
---|
216 | my %rpm; |
---|
217 | my (@rnh, @hnd, @duprep, @rnd, @hnr, %rpmKeys, %parsehdlist, @pnh, @hnp); |
---|
218 | $ok = 1; |
---|
219 | my $parsehdlist; |
---|
220 | my $path = $0; |
---|
221 | $path =~ s,[^/]*$,,; |
---|
222 | if (-x "$path/parsehdlist") { |
---|
223 | $parsehdlist = "$path/parsehdlist" |
---|
224 | } elsif (-x "/usr/bin/parsehdlist") { |
---|
225 | $parsehdlist = "/usr/bin/parsehdlist" |
---|
226 | } else { |
---|
227 | my $err = system('parsehdlist'); |
---|
228 | if ($err) { |
---|
229 | $parsehdlist = "parsehdlist" |
---|
230 | } else { |
---|
231 | print $LOG, "ERROR checkDiscs: could not find parsehdlist command ($!)\n"; |
---|
232 | return 0 |
---|
233 | } |
---|
234 | } |
---|
235 | for (my $i = 1; $i < @$hdlists; $i++) { |
---|
236 | if (! -f $hdlists->[$i]) { |
---|
237 | print $LOG "\nWARNING checkDiscs: $hdlists->[$i] is empty, ignoring\n"; |
---|
238 | next |
---|
239 | } |
---|
240 | my $packer = new packdrake($hdlists->[$i]); |
---|
241 | my $j; |
---|
242 | foreach my $file (@{$packer->{files}}) { |
---|
243 | my ($rpm, $key) = $file =~ /([^:]*)(?::(.*))?/; |
---|
244 | $rpmKeys{key}{$rpm} = $key || $rpm; |
---|
245 | $rpmKeys{rpm}{$rpmKeys{key}{$rpm}} = $rpm; |
---|
246 | my $sok; |
---|
247 | foreach my $c (@{$check->[$i]}) { |
---|
248 | my ($cd, $rep, $list) = @$c; |
---|
249 | $discsFiles->[$cd]{$rep}{$list}{$rpmKeys{key}{$rpm}} and $sok = 1; |
---|
250 | } |
---|
251 | $sok or push @hnr, [ $i, $rpm ]; |
---|
252 | $hdlist{all}{$rpm} and do { print $LOG "\n$rpm"; $ok = 0 }; |
---|
253 | $hdlist{all}{$rpm} = 1; |
---|
254 | $hdlist{cd}{$i}{$rpm} = 1; |
---|
255 | if ($depslist) { |
---|
256 | $depslist{$rpm} or push @hnd, $rpm; |
---|
257 | $depslist{$rpm} > $j and $j = $depslist{$rpm}; |
---|
258 | $depslist{$rpm} < $maxidx and print $LOG "ERROR checkDiscs: inconsistency in position between hdlist $i rpm $rpm and depslist.ordered\n" |
---|
259 | } |
---|
260 | } |
---|
261 | foreach my $c (@{$check->[$i]}) { |
---|
262 | my ($cd, $rep, $list) = @$c; |
---|
263 | foreach my $rpm (keys %{$discsFiles->[$cd]{$rep}{$list}}) { |
---|
264 | $rpm{$rpmKeys{rpm}{$rpm}} and push @duprep, $rpm; |
---|
265 | $rpm{$rpmKeys{rpm}{$rpm}} = 1; |
---|
266 | $depslist && $depslist{$rpmKeys{rpm}{$rpm}} or push @rnd, [ $i, $cd, $rep, $rpm ]; |
---|
267 | $hdlist{cd}{$i}{$rpmKeys{rpm}{$rpm}} or push @rnh, [ $i, $rpm ] |
---|
268 | } |
---|
269 | } |
---|
270 | open my $PAR, "$parsehdlist $hdlists->[$i] |"; |
---|
271 | while (<$PAR>) { |
---|
272 | chomp; |
---|
273 | s/\.rpm$//; |
---|
274 | $parsehdlist{$i}{$_} = 1; |
---|
275 | $hdlist{cd}{$i}{$_} and next; |
---|
276 | push @pnh, $_ |
---|
277 | } |
---|
278 | foreach my $p (keys %{$hdlist{cd}{$i}}) { |
---|
279 | $parsehdlist{$i}{$p} or push @hnp, $p |
---|
280 | } |
---|
281 | $maxidx = $j; |
---|
282 | } |
---|
283 | $ok or $OK = 0; |
---|
284 | $ok ? print $LOG " OK\n" : print $LOG "\nFAILED\n"; |
---|
285 | |
---|
286 | my @dnh; |
---|
287 | $ok = 1; |
---|
288 | if ($depslist) { |
---|
289 | print $LOG "\ncheckDiscs: in depslist, not on discs:"; |
---|
290 | foreach my $rpm (keys %depslist) { |
---|
291 | $hdlist{all}{$rpm} or do { push @dnh, $rpm }; |
---|
292 | $rpm{$rpm} or do { $ok = 0; print $LOG "\n$rpm" }; |
---|
293 | } |
---|
294 | $ok or $OK = 0; |
---|
295 | $ok ? print $LOG " OK\n" : print $LOG "\nFAILED\n"; |
---|
296 | |
---|
297 | print $LOG "\ncheckDiscs: in depslist, not in hdlists:"; |
---|
298 | @dnh ? do { print $LOG " FAILED\n" and $OK = 0 } : print $LOG " OK\n"; |
---|
299 | foreach (@dnh) { |
---|
300 | print $LOG "$_\n" |
---|
301 | } |
---|
302 | } |
---|
303 | print $LOG "\ncheckDiscs: in hdlists, not on discs:"; |
---|
304 | @hnr ? do { print $LOG " FAILED\n" and $OK = 0 } : print $LOG " OK\n"; |
---|
305 | foreach (@hnr) { |
---|
306 | print $LOG "hdlist $_->[0] rpm $_->[3]\n" |
---|
307 | } |
---|
308 | print $LOG "\ncheckDiscs: in hdlists, not in depslist:"; |
---|
309 | @hnd ? do { print $LOG " FAILED\n" and $OK = 0 } : print $LOG " OK\n"; |
---|
310 | foreach (@hnd) { |
---|
311 | print $LOG "$_\n" |
---|
312 | } |
---|
313 | print $LOG "\ncheckDiscs: in hdlists, not see with parsehdlist:"; |
---|
314 | @hnp ? do { print $LOG " FAILED\n" and $OK = 0 } : print $LOG " OK\n"; |
---|
315 | foreach (@hnp) { |
---|
316 | print $LOG "$_\n" |
---|
317 | } |
---|
318 | print $LOG "\ncheckDiscs: see with parsehdlist, not with packdrake:"; |
---|
319 | @pnh ? do { print $LOG " FAILED\n" and $OK = 0 } : print $LOG " OK\n"; |
---|
320 | foreach (@pnh) { |
---|
321 | print $LOG "$_\n" |
---|
322 | } |
---|
323 | print $LOG "\ncheckDiscs: on discs, not in hdlist:"; |
---|
324 | @rnh ? print $LOG " WARNING\n" : print $LOG " OK\n"; |
---|
325 | foreach (@rnh) { |
---|
326 | print $LOG "hdlist $_->[0] rpm $_->[1]\n" |
---|
327 | } |
---|
328 | print $LOG "\ncheckDiscs: on discs, not in depslist:"; |
---|
329 | @rnd ? print $LOG " WARNING\n" : print $LOG " OK\n"; |
---|
330 | foreach (@rnd) { |
---|
331 | print $LOG "hdlist $_->[0] cd $_->[1] rep $_->[2] missing rpm $_->[3]\n" |
---|
332 | } |
---|
333 | print $LOG "\ncheckDiscs: duplicate version on discs:"; |
---|
334 | @duprep ? print $LOG " WARNING\n" : print $LOG " OK\n"; |
---|
335 | foreach (@duprep) { |
---|
336 | print $LOG "$_\n" |
---|
337 | } |
---|
338 | return $OK |
---|
339 | } |
---|
340 | |
---|
341 | # |
---|
342 | # check depslist, depslists.ordered and hdlists |
---|
343 | # |
---|
344 | sub checkcds { |
---|
345 | my (@tops) = @_; |
---|
346 | |
---|
347 | my $top = "$tops[0]/"; |
---|
348 | my $depslist = "$tops[0]/Mandrake/base/depslist.ordered"; |
---|
349 | -f $depslist or print "ERROR: could not find depslist $depslist file\n" and return 0; |
---|
350 | my $hdlists = "$top/Mandrake/base/hdlists"; |
---|
351 | open my $A, $hdlists or die "unable to open $hdlists"; |
---|
352 | my @hdlist = 0; |
---|
353 | my @discsFiles; |
---|
354 | my @check = 0; |
---|
355 | while (<$A>) { |
---|
356 | my ($hdlist, $dir, undef) = split; |
---|
357 | my ($hdid) = $hdlist =~ /(\d*).cz/; |
---|
358 | my $hdfile = "$tops[0]/Mandrake/base/$hdlist"; |
---|
359 | push @hdlist, $hdfile; |
---|
360 | push @check, [[ $hdid, $dir, 1 ]]; |
---|
361 | -f $hdfile or print "ERROR: could not find $hdfile file\n" and return 0; |
---|
362 | print "Reading $top/$dir\n"; |
---|
363 | my $C; |
---|
364 | if (! opendir $C, "$top/$dir") { |
---|
365 | foreach (@tops) { |
---|
366 | opendir $C, "$_/$dir" or next; |
---|
367 | last |
---|
368 | } |
---|
369 | } |
---|
370 | foreach (readdir $C) { |
---|
371 | /(.*)\.rpm/ or next; |
---|
372 | $discsFiles[$hdid]{$dir}{1}{$1} = 1 |
---|
373 | } |
---|
374 | |
---|
375 | } |
---|
376 | checkDiscs(\@hdlist, $depslist, \@discsFiles, \@check) |
---|
377 | } |
---|
378 | |
---|
379 | # |
---|
380 | # regexp version |
---|
381 | # |
---|
382 | sub cleanrpmsrate2 { |
---|
383 | my ($rpmsrate, @rpms) = @_; |
---|
384 | my $LOG; open $LOG, ">&STDERR"; |
---|
385 | my @rpm; |
---|
386 | foreach (@rpms) { |
---|
387 | -d $_ or print $LOG "ERROR: $_ is not a directory\n" and next; |
---|
388 | opendir my $A, $_; |
---|
389 | push @rpm, grep { s/-[^-]+-[^-]+\.[^.]+\.rpm// } all $A; |
---|
390 | } |
---|
391 | my %done; |
---|
392 | my (@flags, @c); |
---|
393 | my ($mod, $text, $prev, $rate, $current); |
---|
394 | my (%rate, %section); |
---|
395 | open my $A, $rpmsrate or print $LOG "ERROR: cannot open $rpmsrate\n"; |
---|
396 | while (<$A>) { |
---|
397 | s/#.*//; |
---|
398 | /^\s*$/ and $text .= "\n" and next; |
---|
399 | if (/^(\S+)/) { |
---|
400 | $text .= "$1\n"; |
---|
401 | $current = $1; |
---|
402 | @flags = $current; |
---|
403 | next |
---|
404 | } |
---|
405 | my ($indent, $r, $flags, $data) = /^(\s*)([1-5]?)((?:\s+(?:(?:!\s*)?[0-9A-Z_]+(?:"[^"]*")?(?:\s+(?:\|\|\s+)?)*)+\s+)|\s+)(.*)$/; |
---|
406 | if ($r) { |
---|
407 | $rate = $r |
---|
408 | } elsif ($prev) { |
---|
409 | chop $indent; |
---|
410 | $r = $prev |
---|
411 | } |
---|
412 | push @flags, split ' ', $flags; |
---|
413 | $data or $text .= "$indent$r$flags" and next; |
---|
414 | my ($postfix) = $data =~ /(\s*)$/; |
---|
415 | my @k; |
---|
416 | foreach my $n (split ' ', $data) { |
---|
417 | @c = grep { /^$n$/ } @rpm; |
---|
418 | map { if ((!$done{$_}[1] || $current eq "INSTALL") && $done{$_}[0] ne $current) { push @k, $_; @{$done{$_}} = @flags } } @c |
---|
419 | } |
---|
420 | if (@k) { $text .= "$indent$r$flags@k$postfix\n"; $prev = '' } else { $prev = $r }; |
---|
421 | @rate{@k} = ($rate) x @k; |
---|
422 | push @{$section{$current}}, @k |
---|
423 | } |
---|
424 | close A; |
---|
425 | if (@rpms) { |
---|
426 | if (open A, ">$rpmsrate") { |
---|
427 | print A $text; |
---|
428 | close A |
---|
429 | } else { |
---|
430 | @rpms and print $LOG "ERROR: cannot open $rpmsrate for writing\n"; |
---|
431 | print $text |
---|
432 | } |
---|
433 | } |
---|
434 | [\%rate, \%section, \%done]; |
---|
435 | } |
---|
436 | |
---|
437 | sub cleanrpmsrate { |
---|
438 | my ($rpmsrate, $output, $norpmsrate, $reprpms, $urpm) = @_; |
---|
439 | $norpmsrate ||= []; |
---|
440 | my $LOG; open $LOG, ">&STDERR"; |
---|
441 | open my $A, $rpmsrate or print $LOG "ERROR: cannot open $rpmsrate\n"; |
---|
442 | my (@rpmsrate, %potloc); |
---|
443 | # must preread to get locale guessed packages |
---|
444 | # postfix is just used not to break the diff when checking if the result is correct |
---|
445 | while (<$A>) { |
---|
446 | chomp; |
---|
447 | s/#.*//; |
---|
448 | #s/\s*$//; |
---|
449 | /^(\s*)$/ and push @rpmsrate, [ '', 0, '', [] ] and next; |
---|
450 | if (/^(\S+)(.*)$/) { |
---|
451 | push @rpmsrate, [ 0, 0, $1, [], $2 ]; |
---|
452 | next |
---|
453 | } |
---|
454 | if (/^(\s*)([1-5])?(\s?[0-9A-Z_]+)$/) { |
---|
455 | push @rpmsrate, [ $1, $2, $3, [] ]; |
---|
456 | next |
---|
457 | } |
---|
458 | my ($indent, $r, $flags, $data) = /^(\s*)([1-5])?(\s*(?:(?:(?:!\s*)?[0-9A-Z_]+(?:"[^"]*")?(?:\s+(?:\|\|\s+)?)*)+\s+)|\s*)(.*)$/; |
---|
459 | my ($postfix) = $data =~ /(\s*)$/; |
---|
460 | my @data; |
---|
461 | my $i; |
---|
462 | foreach ([$data =~ /(?:^|\s)(\S+)-(?:\S+)\s+\1-(?:\S+)(?:\s|$)/g], [split ' ', $data]) { |
---|
463 | $data[$i++] = [ @$norpmsrate ? any { my $r = $_; $r if !any { $r =~ /$_/ } @$norpmsrate } @$_ : @$_ ] |
---|
464 | } |
---|
465 | $potloc{$_} = [] foreach @{$data[0]}; |
---|
466 | push @rpmsrate, [ $indent,$r, $flags, $data[1], $postfix ]; |
---|
467 | } |
---|
468 | my (%rpms, $text); |
---|
469 | my (%rate, %section, %keyword); |
---|
470 | my (%locale, %localized_pkg); |
---|
471 | my $kernel_like = "((?:(?:NVIDIA_)?kernel.*)|NVIDIA_nforce.*|cm2020.*)"; |
---|
472 | my $urpm2 = new URPM; |
---|
473 | foreach my $dir (keys %$reprpms) { |
---|
474 | foreach (@{$reprpms->{$dir}}) { |
---|
475 | my $rpm = "$_.rpm"; |
---|
476 | my $key = $_; |
---|
477 | s/-[^-]+-[^-]+\.[^.]+$// or next; |
---|
478 | any { $rpm =~ /$_/ } @$norpmsrate and next; |
---|
479 | if (/(.*?)([_-]*[\d._]*)-devel$/ || /$kernel_like(-[^.]+(?:\.[^.]+){3,5}mdk)$/) { |
---|
480 | if (!$rpms{$1}) { $rpms{$1} = $2 } |
---|
481 | elsif (URPM::ranges_overlap("== $2", "> $rpms{$1}")) { $rpms{$1} = $2 } |
---|
482 | } elsif (my ($pg, $loc) = /^(.*)-([^-+]+)$/) { |
---|
483 | if ($potloc{$pg}) { |
---|
484 | my $pkg = $urpm->{rpm}{$urpm->{rpmkey}{key}{$key}} if ref $urpm; |
---|
485 | if (!$pkg) { |
---|
486 | my $id = $urpm2->parse_rpm("$dir/$rpm"); |
---|
487 | $pkg = $urpm2->{depslist}[$id]; |
---|
488 | } |
---|
489 | if (!$pkg) { |
---|
490 | print "ERROR cleanrpmsrate: parse_rpm $dir/$rpm ($key) failed\n"; |
---|
491 | next |
---|
492 | } |
---|
493 | # some i18n packages does not require the same locale, e.g. kde-i18n-nb and nn requires locales-no |
---|
494 | # if (grep { s/locales-// && $loc =~ /^$_(_|$)/ } @{$header{REQUIRENAME}}) { |
---|
495 | if (any { /^locales-..$/ } $pkg->requires) { |
---|
496 | push @{$locale{$pg}}, $loc; |
---|
497 | $localized_pkg{"$pg-$loc"} = 1 |
---|
498 | } |
---|
499 | } |
---|
500 | } |
---|
501 | } |
---|
502 | } |
---|
503 | my (%done, @flags, $prev, @tree_rate, $prev_level); |
---|
504 | foreach (@rpmsrate) { |
---|
505 | if (!$_->[0]) { |
---|
506 | $text .= "$_->[2]$_->[4]\n"; |
---|
507 | if ($_->[2]) { |
---|
508 | @flags = $_->[2] |
---|
509 | } |
---|
510 | next |
---|
511 | } |
---|
512 | my ($indent, $r, $flags, $data, $postfix) = @$_; |
---|
513 | my $level = (length $indent)/2 - 1; |
---|
514 | my $rate; |
---|
515 | if ($r) { |
---|
516 | #print "tree_rate[$level] = $r\n"; |
---|
517 | $rate = $r; |
---|
518 | $tree_rate[$level] = $r |
---|
519 | } else { |
---|
520 | if (@$data) { |
---|
521 | if ($level > $prev_level) { |
---|
522 | $level-- |
---|
523 | } else { |
---|
524 | # fix a syntax error in rpmsrate such as |
---|
525 | # A |
---|
526 | # 1 toto |
---|
527 | # B tata <--- |
---|
528 | # 4 titi |
---|
529 | @$data = () |
---|
530 | } |
---|
531 | } |
---|
532 | $rate = $tree_rate[$level]; |
---|
533 | } |
---|
534 | $prev_level = $level; |
---|
535 | @flags = @flags[0 .. $level]; |
---|
536 | push @flags, grep { s/\s//; !/(\|\||[A-Z_]+"[^"]+")/ } split(' ', $flags); |
---|
537 | my $flat_path = join ' ', @flags; |
---|
538 | if (!@$data) { $text .= "$indent$r$flags$postfix\n"; next } |
---|
539 | my @k; |
---|
540 | foreach (@$data) { |
---|
541 | my $c = $_; |
---|
542 | if (any { $flat_path eq $_ } @{$done{$_}}) { next } |
---|
543 | my ($d) = /(.*)-[^-]+/; |
---|
544 | my ($a, $b); |
---|
545 | if (($flags[0] ne "INSTALL" && s/(-devel)// ? ($b = "-devel") : /^$kernel_like/) && ($rpms{$_} || (defined $rpms{"lib$_"} and $a = "lib") || (defined $rpms{"lib64$_"} and $a = "lib64"))) { |
---|
546 | my $d = "$a$_" . $rpms{"$a$_"} . $b; |
---|
547 | $keyword{$c} = $d; |
---|
548 | if (! ref $done{$d} || $flags[0] eq "INSTALL") { push @{$done{$d}}, $flat_path; push @k, $d } |
---|
549 | } |
---|
550 | if ($locale{$d} && $localized_pkg{$c}) { |
---|
551 | foreach (sort @{$locale{$d}}) { |
---|
552 | next if any { $_ eq $flat_path } @{$done{"$d-$_"}}; |
---|
553 | push @{$done{"$d-$_"}}, $flat_path; |
---|
554 | push @k , "$d-$_" |
---|
555 | } |
---|
556 | next |
---|
557 | } |
---|
558 | push @k, $c; |
---|
559 | push @{$done{$c}}, $flat_path |
---|
560 | } |
---|
561 | if (@k) { $text .= "$indent$r$flags@k$postfix\n" } |
---|
562 | @rate{@k} = ($rate) x @k; |
---|
563 | my $path; |
---|
564 | foreach (@flags) { |
---|
565 | $path .= $path ? "/$_" : $_; |
---|
566 | push @{$section{$path}}, @k |
---|
567 | } |
---|
568 | } |
---|
569 | if (%rpms || $output) { |
---|
570 | if (%$reprpms || $output) { |
---|
571 | $output ||= $rpmsrate; |
---|
572 | if (open A, ">$output") { |
---|
573 | print A $text; |
---|
574 | close A |
---|
575 | } else { |
---|
576 | print $LOG "ERROR cleanrpmsrate: cannot open $rpmsrate for writing\n"; |
---|
577 | print $text |
---|
578 | } |
---|
579 | } |
---|
580 | } |
---|
581 | [\%rate, \%section, \%keyword] |
---|
582 | } |
---|
583 | |
---|
584 | sub imageSize { |
---|
585 | my ($file) = @_; |
---|
586 | my ($width, $height, $err) = imgsize $file; |
---|
587 | |
---|
588 | return (defined $width ? |
---|
589 | [ $width, $height ] : |
---|
590 | "error: $err") |
---|
591 | } |
---|
592 | |
---|
593 | sub printDiscsFile { |
---|
594 | my ($config, $discsFiles, $PRINT, $metagroups) = @_; |
---|
595 | my (%done, $output); |
---|
596 | my $log = $config->{LOG}; |
---|
597 | if ($PRINT) { open $output, ">$PRINT" } else { $output = $config->{LOG} } |
---|
598 | my $print_rejected = sub { |
---|
599 | my ($groups, $i, $rpm, $size) = @_; |
---|
600 | # FIXME ugly hack to display more rejected in multigroups buildings because discFiles is per disc and not per group. |
---|
601 | # $done{$groups->[$i]{urpm}{rpmkey}{rpm}{$rpm}} && ! ref $groups->[$i]{rejected}{$rpm} and return 1; |
---|
602 | $done{$groups->[$i]{urpm}{rpmkey}{rpm}{$rpm}} and return 1; |
---|
603 | $groups->[$i]{done}{rep}{$rpm} and return 1; |
---|
604 | if ($groups->[$i]{brokendeps}{$rpm} == 2) { |
---|
605 | ref $groups->[$i]{rejected}{$rpm} or print $output "ERROR printDiscsFile: this should not happen, rejected is not a table for $rpm (group $i)\n" and next; |
---|
606 | } |
---|
607 | printf $output "REJECTED master disc $groups->[$i]{installDisc} %10d $rpm (", $size; |
---|
608 | if (ref $groups->[$i]{rejected}{$rpm}) { |
---|
609 | print $output join(',', map { "$config->{rejected_options}{$_->[0]}: $_->[1]" } @{$groups->[$i]{rejected}{$rpm}}) |
---|
610 | } else { |
---|
611 | print $output "not selected" |
---|
612 | } |
---|
613 | print $output ")\n"; |
---|
614 | 0 |
---|
615 | }; |
---|
616 | my %size; |
---|
617 | # this is not really correct as multiple list may have packages with the same name but different size |
---|
618 | foreach (@$metagroups) { |
---|
619 | my $groups = $_->[0]; |
---|
620 | for (my $i; $i < @$groups; $i++) { |
---|
621 | foreach my $rpm (keys %{$groups->[$i]{size}}) { |
---|
622 | foreach my $list (keys %{$groups->[$i]{size}{$rpm}}) { |
---|
623 | $size{$rpm} = $groups->[$i]{size}{$rpm}{$list}[0] if $size{$rpm} < $groups->[$i]{size}{$rpm}{$list}[0] |
---|
624 | } |
---|
625 | } |
---|
626 | } |
---|
627 | } |
---|
628 | for (my $cd; $cd < @$discsFiles; $cd++) { |
---|
629 | $discsFiles->[$cd] or next; |
---|
630 | print $log "discsFiles: $cd\n"; |
---|
631 | my $cdname = $config->{disc}[$cd]{label}; |
---|
632 | foreach my $rep (keys %{$discsFiles->[$cd]}) { |
---|
633 | foreach my $list (keys %{$discsFiles->[$cd]{$rep}}) { |
---|
634 | foreach my $rpm (sort { $size{$a} <=> $size{$b} } keys %{$discsFiles->[$cd]{$rep}{$list}}) { |
---|
635 | #$done{$rpm} = 1; |
---|
636 | #$rpm =~ /src$/ and next; |
---|
637 | printf $output "$cdname %10d $rpm\n", $size{$rpm}; |
---|
638 | } |
---|
639 | } |
---|
640 | } |
---|
641 | } |
---|
642 | if (!$metagroups) { $output = $config->{LOG} } |
---|
643 | foreach (@$metagroups) { |
---|
644 | my $groups = $_->[0]; |
---|
645 | for (my $i; $i < @$groups; $i++) { |
---|
646 | if (ref $groups->[$i]{buildlist}) { |
---|
647 | foreach (sort { $size{$a} <=> $size{$b} } @{$groups->[$i]{buildlist}}) { |
---|
648 | $print_rejected->($groups, $i, $_, $size{$_}) and next; |
---|
649 | $done{$groups->[$i]{urpm}{rpmkey}{rpm}{$_}} = 1 |
---|
650 | } |
---|
651 | } |
---|
652 | foreach (sort { $size{$a} <=> $size{$b} } keys %{$groups->[$i]{urpm}{rpm}}) { |
---|
653 | $print_rejected->($groups, $i, $_, $size{$_}) |
---|
654 | } |
---|
655 | } |
---|
656 | } |
---|
657 | } |
---|
658 | |
---|
659 | sub printBatchFile { |
---|
660 | my ($config, $discsFiles, $PRINTSCRIPT) = @_; |
---|
661 | # FIXME to please perl_checker |
---|
662 | my $log = $config->{LOG}; |
---|
663 | if (-f $PRINTSCRIPT) { |
---|
664 | my $err = unlink $PRINTSCRIPT; |
---|
665 | if (!$err) { print $log "Unlinking failed $PRINTSCRIPT: $!\n"; return }; |
---|
666 | } |
---|
667 | my $err = copy $config->{configfile}, $PRINTSCRIPT; |
---|
668 | if (!$err) { print $log "Linking failed $PRINTSCRIPT: $!\n"; return }; |
---|
669 | open my $A, ">>$PRINTSCRIPT"; |
---|
670 | print $A "END\n"; |
---|
671 | for (my $cd; $cd < @$discsFiles; $cd++) { |
---|
672 | $discsFiles->[$cd] or next; |
---|
673 | print $log "discsFiles: $cd\n"; |
---|
674 | print $A "CD $cd\n"; |
---|
675 | foreach my $rep (keys %{$discsFiles->[$cd]}) { |
---|
676 | print $A " REP $rep\n"; |
---|
677 | foreach my $list (keys %{$discsFiles->[$cd]{$rep}}) { |
---|
678 | print $A " LIST $list\n"; |
---|
679 | foreach my $rpm (keys %{$discsFiles->[$cd]{$rep}{$list}}) { |
---|
680 | $rpm and print $A " $rpm $discsFiles->[$cd]{$rep}{$list}{$rpm}\n"; |
---|
681 | } |
---|
682 | } |
---|
683 | } |
---|
684 | } |
---|
685 | } |
---|
686 | |
---|
687 | sub readBatchFile { |
---|
688 | my ($file) = @_; |
---|
689 | local *A; open A, $file or print "ERROR readBatchFile: could not open $file for reading\n" and return 0; |
---|
690 | my @discsFiles; |
---|
691 | my @cd; |
---|
692 | while (<A>) { /^END/ and last } |
---|
693 | my ($cd, $rep, $list); |
---|
694 | while (<A>) { |
---|
695 | if (/^CD (\d+)/) { $cd = $1; next } |
---|
696 | if (/^ REP (\S+)/) { $rep = $1; next } |
---|
697 | if (/^ LIST (\d+)/) { $list = $1; next } |
---|
698 | if (/^ (\S+) (\S+)/) { |
---|
699 | $discsFiles[$cd]{$rep}{$list}{$1} = $2; |
---|
700 | push @{$cd[$cd]{$rep}{$list}{$2}}, [ 1, "$1.rpm" ]; |
---|
701 | next |
---|
702 | } |
---|
703 | } |
---|
704 | return \@discsFiles, \@cd |
---|
705 | } |
---|
706 | |
---|
707 | sub config { |
---|
708 | my ($file, $config, $functions) = @_; |
---|
709 | my $log = $config->{LOG}; |
---|
710 | open F,$file or die "ERROR config: cannot open $file\n"; |
---|
711 | while (<F>) { chomp; /^#/ or !$_ or last } |
---|
712 | chomp; |
---|
713 | $config->{name} = (split)[0]; |
---|
714 | my $match_val = q((?:([^"\s]+)|"([^\"]+)")); |
---|
715 | my $match_val2 = q(((?:[^"\s]*(?:[^"\s]+|"[^\"]+")[^"\s]*)+)); |
---|
716 | my ($cd, $fn, $nk, $type, @todo, $discMax); |
---|
717 | $config->{virtual_disc} = []; |
---|
718 | my ($line, $a); |
---|
719 | while (<F>) { |
---|
720 | /^#/ and next; |
---|
721 | chomp; |
---|
722 | $_ or next; |
---|
723 | s/#.*//; |
---|
724 | my $b = s/\\\s*$//; |
---|
725 | if ($a) { |
---|
726 | $line .= $_ |
---|
727 | } else { |
---|
728 | $line = $_ |
---|
729 | } |
---|
730 | $a = $b; |
---|
731 | $a and next; |
---|
732 | local $_ = $line; |
---|
733 | if (/^list (.*)/) { |
---|
734 | my $line = $1; |
---|
735 | my @args; |
---|
736 | while ($line =~ s/$match_val2//) { my $a = $1; $a =~ s/"//g; push @args, $a } |
---|
737 | #print "config: args (" . ( join ' | ', @args) . ")\n"; |
---|
738 | my $todo = parseCommandLine("list", \@args, $functions->{list}); |
---|
739 | $cd = $todo->[0][1][0]; |
---|
740 | #print "config: list $cd (@{$todo->[0][1]})\n"; |
---|
741 | if (!$config->{list}[$cd]) { |
---|
742 | @args and usage('list', $functions->{list}, "list $cd, list definition (@args) too many arguments"); |
---|
743 | foreach (@$todo) { |
---|
744 | log_("$_->[2]\n", $config->{verbose}, $log, 3); |
---|
745 | if (!&{$_->[0]}($cd, @{$_->[1]})) { log_("ERROR: $_->[2]\n", $config->{verbose}, $log); $nk = 1 } |
---|
746 | } |
---|
747 | $type = 1; |
---|
748 | $fn = 0 |
---|
749 | } else { |
---|
750 | $type = 0; |
---|
751 | log_("ERROR config: list $cd already defined, ignoring\n", $config->{verbose}, $log); |
---|
752 | } |
---|
753 | # FIXME keep for compatibility |
---|
754 | } elsif (/^LIST /) { |
---|
755 | if (/^LIST (\d+)(?:\s+(\S.*))*/) { |
---|
756 | $cd = $1; |
---|
757 | push @{$config->{list}[$cd]{filelist}}, (split ' ',$2) if $2; |
---|
758 | $type = 1; |
---|
759 | log_("LIST $1 $2\n", $config->{verbose}, $log, 3) |
---|
760 | } else { |
---|
761 | $nk = 1; |
---|
762 | log_("WARNING: LIST syntax error ($_)\n", $config->{verbose}, $log); |
---|
763 | log_(" LIST <list number> <file list 1> <file list 2> ... <file list n>\n", $config->{verbose}, $log) |
---|
764 | } |
---|
765 | } elsif (/^disc (.*)/) { |
---|
766 | my $line = $1; |
---|
767 | my @args; |
---|
768 | while ($line =~ s/$match_val2//) { my $a = $1; $a =~ s/"//g; push @args, $a } |
---|
769 | #print "config: args (" . ( join ' | ', @args) . ")\n"; |
---|
770 | my $todo = parseCommandLine("disc", \@args, $functions->{disc}); |
---|
771 | $cd = $todo->[0][1][0]; |
---|
772 | #print "config: disc $cd (@{$todo->[0][1]})\n"; |
---|
773 | if (!$config->{disc}[$cd]) { |
---|
774 | @args and usage('disc', $functions->{disc}, "disc $cd, disc definition (@args) too many arguments"); |
---|
775 | foreach (@$todo) { |
---|
776 | log_("$_->[2]\n", $config->{verbose}, $log, 3); |
---|
777 | if (!&{$_->[0]}($cd, @{$_->[1]})) { log_("ERROR: $_->[2]\n", $config->{verbose}, $log); $nk = 1 } |
---|
778 | } |
---|
779 | $type = 2; |
---|
780 | $fn = 0 |
---|
781 | } else { |
---|
782 | $type = 0; |
---|
783 | log_("ERROR config: disc $cd already defined, ignoring\n", $config->{verbose}, $log); |
---|
784 | } |
---|
785 | # FIXME keep for compatibility |
---|
786 | } elsif (/^DISC (.*)/) { |
---|
787 | if (/^DISC (\d+)\s+(\d+)\s+$match_val(?:\s+DISC\s+(\d+))?\s+$match_val(?:\s+$match_val)?/) { |
---|
788 | #print "1($1) 2($2) 3($3) 4($4) 5($5) 6($6) 7($7) 8($8) 8($9)\n"; |
---|
789 | $config->{disc}[$1]{size} = $2; |
---|
790 | my $disc = $config->{disc}[$1]; |
---|
791 | $disc->{serial} = substr "$3$4", 0, 128; |
---|
792 | $disc->{name} = $5; |
---|
793 | $disc->{longname} = "$6$7"; |
---|
794 | $disc->{appname} = substr("$6$7", 0, 128); |
---|
795 | $disc->{label} = substr(("$6$7" ? "$8$9" : "$6$7"), 0, 32); |
---|
796 | $cd = $1; |
---|
797 | $type = 2; |
---|
798 | $fn = 0; |
---|
799 | $4 > $discMax and $discMax = $4; |
---|
800 | log_("DISC $1 $2 $3$4 $5 $6$7 $8$9\n", $config->{verbose}, $log) |
---|
801 | } else { |
---|
802 | $nk = 1; |
---|
803 | $type = 0; |
---|
804 | log_("WARNING: DISC syntax error ($_)\n", $config->{verbose}, $log); |
---|
805 | log_(" DISC <cd number> <cd size> <cd serial name> DISC <real cd number> <disc name>\n", $config->{verbose}, $log) |
---|
806 | } |
---|
807 | } elsif (/^END/) { |
---|
808 | last |
---|
809 | } else { |
---|
810 | my @args; |
---|
811 | while (s/$match_val2//) { my $a = $1; $a =~ s/"//g; push @args, $a } |
---|
812 | my $prog = shift @args; |
---|
813 | log_("config: function $prog(" . join(' | ',@args) . ")\n", $config->{verbose}, $log,4); |
---|
814 | $type == 1 and do { |
---|
815 | if ($prog ne 'rpmlist') { |
---|
816 | push @{$config->{list}[$cd]{packages}}, { rpm => [ $prog ] , srpm => \@args } |
---|
817 | } else { |
---|
818 | push @todo, [ $prog, \@args, $cd, $fn ]; |
---|
819 | $fn++; |
---|
820 | } |
---|
821 | next |
---|
822 | }; |
---|
823 | $type == 2 and do { |
---|
824 | push @todo, [$prog, \@args, $cd, $fn]; |
---|
825 | $fn++; |
---|
826 | next |
---|
827 | } |
---|
828 | } |
---|
829 | } |
---|
830 | $config->{configfile} = $file; |
---|
831 | $config->{discMax} = $discMax; |
---|
832 | foreach (@todo) { |
---|
833 | my ($prog, $args, $cd, $fn) = @$_; |
---|
834 | if ($functions->{$prog}) { |
---|
835 | log_("FUNCTION $prog (@$args)\n", $config->{verbose}, $log,5); |
---|
836 | my $todo = parseCommandLine($prog, $args, $functions->{$prog}); |
---|
837 | @$args and usage($prog, $functions->{$prog}, "disc $cd, function $fn, @$args, too many arguments"); |
---|
838 | foreach (@$todo) { |
---|
839 | log_("config: todo $_->[2]\n", $config->{verbose}, $log, 4); |
---|
840 | if (!&{$_->[0]}($cd, $fn, @{$_->[1]})) { log_("ERROR: $_->[2]\n", $config->{verbose}, $log); $nk = 1 } |
---|
841 | } |
---|
842 | } |
---|
843 | } |
---|
844 | $nk and return 0; |
---|
845 | #printTable($config); |
---|
846 | 1 |
---|
847 | } |
---|
848 | |
---|
849 | sub compute_files_md5 { |
---|
850 | my ($md5file, $files) = @_; |
---|
851 | open my $MD5, ">$md5file"; |
---|
852 | my $text; |
---|
853 | foreach (@$files) { |
---|
854 | my $md5 = new Digest::MD5; |
---|
855 | open my $F, $_ or die "FATAL: Could not open $_\n"; |
---|
856 | $md5->addfile($F); |
---|
857 | my $digest = $md5->hexdigest; |
---|
858 | $text .= "$digest $1\n" if m,([^/]+)$, |
---|
859 | } |
---|
860 | print $MD5 $text; |
---|
861 | close $MD5 |
---|
862 | } |
---|
863 | |
---|
864 | sub compute_md5 { |
---|
865 | my ($to_check, $ignore) = @_; |
---|
866 | my @files; |
---|
867 | md5_add_tree($to_check, \@files, $ignore); |
---|
868 | my $md5 = new Digest::MD5; |
---|
869 | foreach (sort { $a->[0] cmp $b->[0] } @files) { |
---|
870 | my $f = $_->[1]; |
---|
871 | open my $A, $f; |
---|
872 | $md5->addfile($A); |
---|
873 | #my $tmpmd5 = new Digest::MD5; |
---|
874 | #local *A, open A, $f; |
---|
875 | #$tmpmd5->addfile(*A); |
---|
876 | #print "MD5: $_->[0] (", $tmpmd5->hexdigest() ,")\n"; |
---|
877 | } |
---|
878 | my $digest = $md5->hexdigest; |
---|
879 | # print "IGNORE " , join " ",keys %$ignore ,"\n"; |
---|
880 | return $digest |
---|
881 | } |
---|
882 | |
---|
883 | sub md5_add_tree { |
---|
884 | my ($to_check, $files, $ignore) = @_; |
---|
885 | foreach (@$to_check) { |
---|
886 | my ($dest, $f) = @$_; |
---|
887 | $f =~ m|/?\.{1,2}$| and next; |
---|
888 | $f =~ /~$/ and next; |
---|
889 | $f =~ s|//+|/|g; |
---|
890 | $dest =~ s|//+|/|g; |
---|
891 | $ignore->{$dest} and next; |
---|
892 | if (-d $f) { |
---|
893 | md5_add_tree([ map { [ "$dest/$_", "$f/$_" ] } all $f ], $files, $ignore) |
---|
894 | } else { |
---|
895 | push @$files, [ $dest, $f ] |
---|
896 | } |
---|
897 | } |
---|
898 | } |
---|
899 | |
---|
900 | sub log_ { |
---|
901 | my ($msg, $verbose, $log, $level) = @_; |
---|
902 | return if $level > $verbose; |
---|
903 | my $LOG; |
---|
904 | if (!$log) { open $LOG, ">&STDERR" } else { $LOG = $log } |
---|
905 | print $LOG $msg; |
---|
906 | } |
---|
907 | |
---|
908 | # TODO must add some check of maximum authorized size |
---|
909 | sub include_md5 { |
---|
910 | my ($iso, $write, $verbose) = @_; |
---|
911 | my $ISO; |
---|
912 | if ($write) { |
---|
913 | open $ISO, "+<$iso" or return "ERROR include_md5: unable to open $iso ($!)\n"; |
---|
914 | } else { |
---|
915 | open $ISO, $iso or return "ERROR include_md5: unable to open $iso ($!)\n"; |
---|
916 | } |
---|
917 | binmode $ISO; |
---|
918 | my $offset = 16*2048; |
---|
919 | # blank header |
---|
920 | seek $ISO, $offset, 0; |
---|
921 | my ($buf, $msg); |
---|
922 | while (1) { |
---|
923 | read $ISO,$buf,2048; |
---|
924 | my $c = ord $buf; |
---|
925 | last if $c == 1; |
---|
926 | return "ERROR include_md5: could not find primary volume descriptor\n" if $c == 255; |
---|
927 | $offset += 2048 |
---|
928 | } |
---|
929 | my $size = ((ord substr $buf, $SIZE_OFFSET, 1) * 0x1000000 + |
---|
930 | (ord substr $buf, $SIZE_OFFSET + 1, 1) * 0x10000 + |
---|
931 | (ord substr $buf, $SIZE_OFFSET + 2, 1) * 0x100 + |
---|
932 | (ord substr $buf, $SIZE_OFFSET + 3, 1)) * 2048; |
---|
933 | my $volume = substr $buf, 30, 40; |
---|
934 | $volume =~ s/^\s*(\S.*\S)\s*$/$1/; |
---|
935 | my $id = substr $buf, 180, 20; |
---|
936 | $msg = "include_md5: volume name $volume volume id: $id iso size $size\n"; |
---|
937 | seek $ISO, $offset + $INFO_OFFSET, 0; |
---|
938 | read $ISO, $buf,512; |
---|
939 | my ($md5sum) = $buf =~ /.md5 = (\S+)/; |
---|
940 | $msg .= "include_md5: previous data $buf\n"; |
---|
941 | seek $ISO, 0, 0; |
---|
942 | my $md5 = new Digest::MD5; |
---|
943 | my $read = read $ISO, $buf, $offset + $INFO_OFFSET; |
---|
944 | $md5->add($buf); |
---|
945 | seek $ISO, 512, 1; |
---|
946 | $read += 512; |
---|
947 | $|=1; |
---|
948 | my $val = int $size/2048/100; |
---|
949 | $verbose and print "\rReading: 0 %"; |
---|
950 | my ($i, $j); |
---|
951 | # skip last $SKIP bytes that sometimes are not correctly burned by some drives |
---|
952 | my $n = 1; |
---|
953 | while ($n && $read < $size - $SKIP * 2048) { |
---|
954 | $n = read $ISO, $buf,2048; |
---|
955 | print "\rReading: ", $j++, " %" if ($verbose && !($i++ % $val)); |
---|
956 | $md5->add($buf); |
---|
957 | $read += $n; |
---|
958 | } |
---|
959 | print "\n"; |
---|
960 | my $digest = $md5->hexdigest; |
---|
961 | $msg .= "include_md5: computed md5 $digest\n"; |
---|
962 | my $res = $md5sum eq $digest; |
---|
963 | if ($md5sum) { |
---|
964 | $msg .= "include_md5: previous md5 $md5sum\ninclude_md5: md5sum check "; |
---|
965 | $msg .= $res ? "OK\n" : "FAILED\n" |
---|
966 | } |
---|
967 | print $msg if $verbose; |
---|
968 | $write or return $res; |
---|
969 | seek $ISO, $offset + $INFO_OFFSET, 0; |
---|
970 | my $str = substr "$volume.md5 = $digest", 0, 512; |
---|
971 | my $l = length $str; |
---|
972 | print $ISO ($l > 512 ? substr $str, -1, 512 : $str . ' ' x (512 - $l)); |
---|
973 | close $ISO |
---|
974 | } |
---|
975 | |
---|
976 | sub convert_size { |
---|
977 | my ($size, $default, $LOG) = @_; |
---|
978 | if ($size =~ /[\d.]+g$/i) { |
---|
979 | $size = $size * $GB; |
---|
980 | } elsif ($size =~ /[\d+.]+m$/i) { |
---|
981 | $size = $size * $MB; |
---|
982 | } elsif ($size =~ /[\d+.]+k$/i) { |
---|
983 | $size = $size * $KB; |
---|
984 | } elsif ($size !~ /[\d+.]+$/i) { |
---|
985 | log_("ERROR disc: $size is invalid, using default ($default)\n",1,$LOG); |
---|
986 | $size = $default; |
---|
987 | } |
---|
988 | $size |
---|
989 | } |
---|
990 | |
---|
991 | sub fix_dir { |
---|
992 | chomp(my $pwd = `pwd`); |
---|
993 | return map { m,^/, or $_ = "$pwd/$_"; $_ } @_ |
---|
994 | } |
---|
995 | |
---|
996 | 1 |
---|
997 | |
---|
998 | # |
---|
999 | # Changelog |
---|
1000 | # |
---|
1001 | # 2002 02 27 |
---|
1002 | # make the locale constraint free on the right for cleanrpmsrate locale addition (kde-i18n-zh_BG and such) |
---|
1003 | # |
---|
1004 | # 2002 03 03 |
---|
1005 | # fix typo in checkdiscs |
---|
1006 | # |
---|
1007 | # 2002 03 04 |
---|
1008 | # fix checkcds pb with check[0] used. |
---|
1009 | # |
---|
1010 | # 2002 03 07 |
---|
1011 | # add possibility to remove package from rpmsrate |
---|
1012 | # |
---|
1013 | # 2002 03 12 |
---|
1014 | # add all .*kernel- in rpmsrate |
---|
1015 | # |
---|
1016 | # 2002 03 17 |
---|
1017 | # add serial name instead of cdnumber when name is not know |
---|
1018 | # |
---|
1019 | # 2002 05 07 |
---|
1020 | # add check_discs, compute_md5, write_graft, md5_add_tree |
---|
1021 | # |
---|
1022 | # 2002 05 22 |
---|
1023 | # fix a pb in md5 |
---|
1024 | # |
---|
1025 | # 2002 05 25 |
---|
1026 | # add log function |
---|
1027 | # |
---|
1028 | # 2002 06 05 |
---|
1029 | # fix md5 for isolinux |
---|
1030 | # |
---|
1031 | # 2002 08 12 |
---|
1032 | # fix/change cleanrpmsrate |
---|
1033 | # |
---|
1034 | # 2002 09 04 |
---|
1035 | # do not open for writing iso file in include_md5 if not in write mode |
---|
1036 | # |
---|
1037 | # 2002 09 25 |
---|
1038 | # add completion feedback to include_md5 |
---|