(no commit message)
[opensuse:installation-images.git] / lib / AddFiles.pm
1 #! /usr/bin/perl -w
2
3 # Usage:
4 #
5 #   use AddFiles;
6 #
7 #   exported functions:
8 #     AddFiles(dir, file_list, ext_dir, tag);
9
10 =head1 AddFiles
11
12 C<AddFiles.pm> is a perl module that can be used to extract files from
13 rpms. It exports the following symbols:
14
15 =over
16
17 =item *
18
19 C<AddFiles(dir, file_list, ext_dir, tag)>
20
21 =back
22
23 =head2 Usage
24
25 use AddFiles;
26
27 =head2 Description
28
29 =over
30
31 =item *
32
33 C<AddFiles(dir, file_list, ext_dir, tag)>
34
35 C<AddFiles> extracts the files in C<file_list> and puts them into C<dir>.
36 Files that are not to be taken from rpms are copied from C<ext_dir>.
37
38 The syntax of the file list is rather simple; please have a look at those
39 provided with this package to see how it works. A syntax description follows
40 later...
41
42 On any failure, C<exit( )> is called.
43
44
45 =back
46
47 =cut
48
49
50 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
51 require Exporter;
52 @ISA = qw ( Exporter );
53 @EXPORT = qw ( AddFiles );
54
55 use strict 'vars';
56 use integer;
57
58 use ReadConfig;
59
60 sub fixup_re;
61
62 sub AddFiles
63 {
64   local $_;
65   my ($dir, $file_list, $ext_dir, $arch, $if_val, $if_taken, $tag);
66   my ($rpms, $tdir, $tfile, $p, $r, $rc, $d, $u, $g, $files);
67   my ($mod_list, @mod_list, %mod_list);
68   my ($inc_file, $inc_it, $debug, $ifmsg, $ignore);
69   my ($old_warn, $ver, $i, $cache_dir, $tmp_cache_dir, $tmp_rpm);
70   my (@scripts, $s, @s, %script, $use_cache);
71   my (@packs, $sl, $rpm_cmd);
72   my (@plog, $current_pack, %acc_all_files, %acc_pack_files, $account);
73   my ($su, @requires);
74
75   $su = "$SUBinary -q 0 " if $SUBinary;
76
77   my $account_size = sub
78   {
79     my ($dir, $s, @f);
80     local $_;
81
82     return if !defined($current_pack) || !$account;
83
84     $dir = shift;
85
86     @f = `${su}find $dir -type f`;
87
88     chomp @f;
89
90     for (@f) {
91       $acc_pack_files{$current_pack}{$_} = 1 unless exists $acc_all_files{$_};
92       $acc_all_files{$_} = 1;
93     }
94   };
95
96   ($dir, $file_list, $ext_dir, $tag, $mod_list) = @_;
97
98   $debug = "pkg";
99   $debug = $ENV{'debug'} if exists $ENV{'debug'};
100
101   $use_cache = 0;
102   $use_cache = $ENV{'cache'} if exists $ENV{'cache'};
103   if($use_cache) {
104     $cache_dir = $ConfigData{'cache_dir'};
105     $tmp_cache_dir = $ConfigData{'tmp_cache_dir'};
106   }
107
108   $ignore = $debug =~ /\bignore\b/ ? 1 : 0;
109
110   $account = $debug =~ /\baccount\b/ ? 1 : 0;
111
112   $old_warn =  $SIG{'__WARN__'};
113
114   $SIG{'__WARN__'} = sub {
115     my $a = shift;
116
117     return if $ignore >= 10;
118
119     $a =~ s/<F>/$file_list/;
120     $a =~ s/<I>/$inc_file/;
121     if($ignore) { warn $a } else { die $a }
122   };
123
124   $debug .= ',pkg';
125
126 #  if(!$AutoBuild) {
127 #    $rpms = "$ConfigData{suse_base}/suse";
128 #    die "$Script: where are the rpms?" unless $ConfigData{suse_base} && -d $rpms;
129 #    $rpms = "$rpms/*";
130 #  }
131 # else {
132 #    $rpms = $AutoBuild;
133 #    die "$Script: where are the rpms?" unless -d $rpms;
134 #    print "running in autobuild environment\n";
135 #  }
136
137   if(! -d $dir) {
138     die "$Script: failed to create $dir ($!)" unless mkdir $dir, 0755;
139   }
140
141   if(!($use_cache & 4)) {
142     $tdir = "${TmpBase}.dir";
143     die "$Script: failed to create $tdir ($!)" unless mkdir $tdir, 0777;
144   }
145   $tfile = "${TmpBase}.afile";
146
147   # see if our rpm understands --nosignature
148   $rpm_cmd = "rpm";
149   $rpm_cmd .= " --nosignature" if `$rpm_cmd --help` =~ /--nosignature/s;
150
151   # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
152   # now we really start...
153
154   die "$Script: no such file list: $file_list" unless open F, $file_list;
155
156   $arch = $ConfigData{arch};
157   $ENV{'___arch'} = $arch;
158
159   $tag = "" unless defined $tag;
160
161   $if_val = $if_taken = 0;
162
163   $current_pack = '';
164
165   while(1) {
166     $_ = $inc_it ? <I> : <F>;
167     if(!defined($_)) {
168       if($inc_it) {
169         undef $inc_it;
170         close I;
171         next;
172       } else {
173         last;
174       }
175     }
176
177     chomp;
178     next if /^(\s*|\s*#.*)$/;
179
180     s/^\s*//;
181
182     $ifmsg = sprintf " [%x|%x] %s\n", $if_val, $if_taken, $_;
183
184     s/<(kernel_ver|kernel_mods|kernel_rpm|kernel_img|suse_release|theme|product|product_name|yast_theme|splash_theme|update_dir|load_image|min_memory|instsys_build_id|instsys_complain|instsys_complain_root|arch|lib)>/$ConfigData{$1}/g;
185     for $i (qw( linuxrc lang extramod items )) {
186       s/<$i>/$ENV{$i}/g if exists $ENV{$i};
187     }
188
189     if(/^endif/) {
190       $if_val >>= 1;
191       $if_taken >>= 1;
192       print "*$ifmsg" if $debug =~ /\bif\b/;
193       next
194     }
195
196     if(/^else/) {
197       $if_val &= ~1;
198       $if_val |= $if_taken & 1;
199       print "*$ifmsg" if $debug =~ /\bif\b/;
200       next
201     }
202
203 # drop these
204 #    if(/^ifarch\s+/)  { $if_val <<= 1; $if_val |= 1 if !/\b$arch\b/ || $arch eq ""; next }
205 #    if(/^ifnarch\s+/) { $if_val <<= 1; $if_val |= 1 if  /\b$arch\b/ && $arch ne ""; next }
206 #    if(/^ifdef\s+/)   { $if_val <<= 1; $if_val |= 1 if !/\b$tag\b/  || $tag  eq ""; next }
207 #    if(/^ifndef\s+/)  { $if_val <<= 1; $if_val |= 1 if  /\b$tag\b/  && $tag  ne ""; next }
208 #    if(/^ifabuild/)   { $if_val <<= 1; $if_val |= 1 if !$AutoBuild;                 next }
209 #    if(/^ifnabuild/)  { $if_val <<= 1; $if_val |= 1 if  $AutoBuild;                 next }
210 #    if(/^ifenv\s+(\S+)\s+(\S+)/)  { $if_val <<= 1; $if_val |= 1 if $ENV{$1} ne $2;  next }
211 #    if(/^ifnenv\s+(\S+)\s+(\S+)/) { $if_val <<= 1; $if_val |= 1 if $ENV{$1} eq $2;  next }
212
213     if(/^(els)?if\s+(.+)/) {
214       no integer;
215
216       my ( $re, $i, $eif );
217
218       $eif = $1 ? 1 : 0;
219       $re = fixup_re $2;
220       if($debug =~ /\bif\b/) {
221         print "*$ifmsg";
222         printf "    # eval \"%s\"\n", $re;
223       }
224       $ignore += 10;
225       $i = eval "if($re) { 0 } else { 1 }";
226       $ignore -= 10;
227       die "$Script: syntax error in 'if' statement" unless defined $i;
228       if($eif) {
229         $if_val &= ~1;
230         $i = 0 if $i == 0 && ($if_taken & 1) == 0;
231       }
232       else {
233         $if_val <<= 1;
234         $if_taken <<= 1;
235       }
236       $if_val |= $i;
237       $if_taken |= 1 - $i;
238       next
239     }
240
241     if($if_val) {
242       print " $ifmsg" if $debug =~ /\bif\b/;
243       next
244     }
245
246     print "*$ifmsg" if $debug =~ /\bif\b/;
247
248     if(/^include\s+(\S+)$/) {
249       die "$Script: recursive include not supported" if $inc_it;
250       $inc_file = $1;
251       die "$Script: no such file list: $inc_file" unless open I, "$ext_dir/$inc_file";
252       $inc_it = 1;
253     }
254     elsif(/^(\S*):\s*(\S+)?\s*$/ || !defined($current_pack)) {
255       undef %script;
256       undef @scripts;
257       undef @requires;
258
259       $account_size->($dir);
260
261       undef $current_pack;
262
263       $p = $1;
264       if(defined $2) {
265         @scripts = split /,/, $2;
266
267         @requires = grep { $_ eq 'requires' } @scripts;
268         @scripts = grep { $_ ne 'requires' } @scripts;
269       }
270
271       next unless defined $p;
272
273       if($p eq '') {
274         $current_pack = '';
275         next;
276       }
277
278       undef $rc;
279       undef $r;
280       if($p =~ /^\//) {
281         $r = $p;
282         warn("$Script: no such package: $r"), next unless -f $r;
283       }
284       else {
285         $r = RPMFileName $p;
286
287         if($use_cache) {
288           $rc = "$cache_dir/$p.rpm";
289           $tmp_rpm = "$tmp_cache_dir/$p";
290         }
291         warn("$Script: no such package: $p.rpm"), next unless $r && -f $r;
292
293         if(($use_cache & 2) && $rc && $r && -f($r) && $rc ne $r) {
294           if(! -d($cache_dir)) {
295             SUSystem("mkdir -p $cache_dir");
296           }
297           if(-d $cache_dir) {
298             SUSystem("cp -a $r $rc");
299             if(-f $rc) {
300               $r = $rc;
301             }
302             else {
303               warn "$Script: failed to cache package $r";
304             }
305           }
306           else {
307             warn "$Script: failed to create cache dir $cache_dir";
308             $use_cache = 0;
309           }
310         }
311       }
312
313       $current_pack = $p;
314
315       $ver = (`$rpm_cmd -qp $r`)[0];
316       $ver = "" unless defined $ver;
317       $ver =~ s/\s*$//;
318       if($ver =~ /^(\S+)-([^-]+-[^-]+)$/) {
319         $ver = $1 eq $p ? " [$2]" : "";
320       }
321       else {
322         $ver = "";
323       }
324       if($use_cache) {
325         if(-d $tmp_rpm) {
326           $ver .= '#';
327         }
328         elsif(defined($rc) && $rc eq $r) {
329           $ver .= '*';
330         }
331       }
332
333       undef $sl;
334
335       @s = `$rpm_cmd -qp --qf '%|PREIN?{PREIN\n}:{}|%|POSTIN?{POSTIN\n}:{}|%|PREUN?{PREUN\n}:{}|%|POSTUN?{POSTUN\n}:{}|' $r 2>/dev/null`;
336       for $s (@s) {
337         chomp $s;
338         $sl .= "," if $sl;
339         $sl .= "\L$s";
340       }
341       $ver .= " \{$sl\}" if $sl;
342
343       push @plog, "$p$ver\n";
344
345       print "adding package $p$ver\n" if $debug =~ /\bpkg\b/;
346
347       push @packs, "$p\n";
348
349       for $s (@scripts) {
350         @{$script{$s}} =
351         @s = `$rpm_cmd --queryformat '%{\U$s\E}' -qp $r 2>/dev/null`;
352         if(@s == 0 || $s[0] =~ /^\(none\)\s*$/) {
353           warn "$Script: no \"$s\" script in $r";
354         }
355         else {
356           print "  got \"$s\" script\n" if $debug =~ /\bscripts\b/;
357           @{$script{$s}} = @s;
358         }
359       }
360
361       if(@requires) {
362         @requires = `$rpm_cmd --requires -qp $r 2>/dev/null`;
363         open R, ">$dir/$p.requires";
364         print R @requires;
365         close R;
366       }
367
368       if(!($use_cache & 4)) {
369         SUSystem "rm -rf $tdir" and die "$Script: failed to remove $tdir";
370         die "$Script: failed to create $tdir ($!)" unless mkdir $tdir, 0777;
371         SUSystem "sh -c 'cd $tdir ; rpm2cpio $r | cpio --quiet --sparse -dimu --no-absolute-filenames'" and
372           warn "$Script: failed to extract $r";
373       }
374       else {
375         $tdir = $tmp_rpm;
376         if(!-d($tdir)) {
377           die "$Script: failed to create $tdir ($!)" unless mkdir $tdir, 0777;
378           SUSystem "sh -c 'cd $tdir ; rpm2cpio $r | cpio --quiet --sparse -dimu --no-absolute-filenames'" and
379             warn "$Script: failed to extract $r";
380
381           if($p eq $ConfigData{kernel_rpm}) {
382             my ($kmp, $kmp_name);
383             for $kmp (split(',', $ConfigData{kmp_list})) {
384               ($kmp_name = $p) =~ s/^kernel/$kmp-kmp/;
385               my $r2 = RPMFileName "$kmp_name";
386               (print STDERR "$Script: no such package: ${kmp_name}.rpm\n"), next unless $r2 && -f $r2;
387               SUSystem "sh -c 'cd $tdir ; rpm2cpio $r2 | cpio --quiet --sparse -dimu --no-absolute-filenames'" and
388                 warn "$Script: failed to extract $r2";
389             }
390           }
391         }
392       }
393     }
394     elsif(!/^[a-zA-Z]\s+/ && /^(.*)$/) {
395       $files = $1;
396       $files =~ s.(^|\s)/.$1.g;
397       $files = "." if $files =~ /^\s*$/;
398       SUSystem "sh -c '( cd $tdir; tar --sparse -cf - $files 2>$tfile ) | tar -C $dir -xpf -'" and
399         warn "$Script: failed to copy $files";
400
401       my (@f, $f);
402       @f = `cat $tfile`;
403       print STDERR @f;
404       SUSystem "rm -f $tfile";
405       for $f (@f) {
406         warn "$Script: failed to copy \"$files\"" if $f =~ /tar:\s+Error/;
407       }
408     }
409     elsif(/^d\s+(.+)$/) {
410       $d = $1; $d =~ s.(^|\s)/.$1.g;
411       SUSystem "sh -c 'cd $dir; mkdir -p $d'" and
412         warn "$Script: failed to create $d";
413     }
414     elsif(/^t\s+(.+)$/) {
415       $d = $1; $d =~ s.(^|\s)/.$1.g;
416       SUSystem "sh -c 'cd $dir; touch $d'" and
417         warn "$Script: failed to touch $d";
418     }
419     elsif(/^r\s+(.+)$/) {
420       $d = $1; $d =~ s.(^|\s)/.$1.g;
421       SUSystem "sh -c 'cd $dir; rm -rf $d'" and
422         warn "$Script: failed to remove $d";
423     }
424     elsif(/^S\s+(.+)$/) {
425       $d = $1; $d =~ s.(^|\s)/.$1.g;
426       SUSystem "sh -c 'cd $dir; strip $d'" and
427         warn "$Script: failed to strip $d";
428     }
429     elsif(/^l\s+(\S+)\s+(\S+)$/) {
430       SUSystem "ln $dir/$1 $dir/$2" and
431         warn "$Script: failed to link $1 to $2";
432     }
433     elsif(/^s\s+(\S+)\s+(\S+)$/) {
434       SUSystem "ln -s $1 $dir/$2" and
435         warn "$Script: failed to symlink $1 to $2";
436     }
437     elsif(/^m\s+(\S+)\s+(\S+)$/) {
438       SUSystem "sh -c \"cp -a $tdir/$1 $dir/$2\"" and
439         warn "$Script: failed to move $1 to $2";
440     }
441     elsif(/^L\s+(\S+)\s+(\S+)$/) {
442       SUSystem "sh -c \"cp -al $tdir/$1 $dir/$2\"" and
443         warn "$Script: failed to move $1 to $2";
444     }
445     elsif(/^a\s+(\S+)\s+(\S+)$/) {
446       SUSystem "sh -c \"cp -pLR $tdir/$1 $dir/$2\"" and
447         warn "$Script: failed to move $1 to $2\n";
448     }
449     elsif(/^([fF])\s+(\S+)\s+(\S+)(\s+(\S+))?$/) {
450       my ($l, @l, $src, $name, $dst, $start_dir);
451
452       $src = $2;
453       $name = $3;
454       $dst = $5;
455       $start_dir = $1 eq "F" ? "/" : $tdir;
456       $src =~ s#^/*##;
457       SUSystem "sh -c \"cd $start_dir ; find $src -type f -name '$name'\" >$tfile";
458
459       open F1, "$tfile";
460       @l = (<F1>);
461       close F1;
462       SUSystem "rm -f $tfile";
463       chomp @l;
464
465       if(@l == 0) {
466         warn "$Script: \"$name\" not found in \"$src\"";
467       }
468
469       if($dst) {
470         for $l (@l) {
471           SUSystem "sh -c \"cp -a $start_dir/$l $dir/$dst\"" and
472             print "$Script: $l not copied to $dst (ignored)\n";
473         }
474       }
475       else {
476         for $l (@l) {
477           SUSystem "sh -c '( cd $start_dir; tar -cf - $l 2>$tfile ) | tar -C $dir -xpf -'" and
478             warn "$Script: failed to copy $files";
479
480           my (@f, $f);
481           @f = `cat $tfile`;
482           print STDERR @f;
483           SUSystem "rm -f $tfile";
484           for $f (@f) {
485             warn "$Script: failed to copy \"$l\"" if $f =~ /tar:\s+Error/;
486           }
487         }
488       }
489     }
490     elsif(/^p\s+(\S+)$/) {
491       SUSystem "patch -d $dir -p0 --no-backup-if-mismatch <$ext_dir/$1 >/dev/null" and
492         warn "$Script: failed to apply patch $1";
493     }
494     elsif(/^A\s+(\S+)\s+(\S+)$/) {
495       SUSystem "sh -c 'cat $ext_dir/$1 >>$dir/$2'" and
496         warn "$Script: failed to append $1 to $2";
497     }
498     elsif(/^x\s+(\S+)\s+(\S+)$/) {
499       SUSystem "cp -dR $ext_dir/$1 $dir/$2" and
500         warn "$Script: failed to move $1 to $2";
501     }
502     elsif(/^X\s+(\S+)\s+(\S+)$/) {
503       SUSystem "cp -dR $1 $dir/$2 2>/dev/null" and
504         print "$Script: $1 not copied to $2 (ignored)\n";
505     }
506     elsif(/^g\s+(\S+)\s+(\S+)$/) {
507       SUSystem "sh -c 'gunzip -c $tdir/$1 >$dir/$2'" and
508         warn "$Script: could not uncompress $1 to $2";
509     }
510     elsif(/^c\s+(\d+)\s+(\S+)\s+(\S+)\s+(.+)$/) {
511       $p = $1; $u = $2; $g = $3;
512       $d = $4; $d =~ s.(^|\s)/.$1.g;
513       SUSystem "sh -c 'cd $dir; chown $u:$g $d'" and
514         warn "$Script: failto to change owner of $d to $u:$g";
515       SUSystem "sh -c 'cd $dir; chmod $p $d'" and
516         warn "$Script: failto to change perms of $d to $p";
517     }
518     elsif(/^b\s+(\d+)\s+(\d+)\s+(\S+)$/) {
519       SUSystem "mknod $dir/$3 b $1 $2" and
520         warn "$Script: failto to make block dev $3 ($1, $2)";
521     }
522     elsif(/^C\s+(\d+)\s+(\d+)\s+(\S+)$/) {
523       SUSystem "mknod $dir/$3 c $1 $2" and
524         warn "$Script: failto to make char dev $3 ($1, $2)";
525     }
526     elsif(/^n\s+(.+)$/) {
527       SUSystem "mknod $dir/$1 p" and
528         warn "$Script: failto to make named pipe $1";
529     }
530 =head1
531     elsif(/^M\s+(\S+)\s+(\S+)$/) {
532       SUSystem "sh -c \"cp -av $tdir/$1 $dir/$2\" >$tfile" and
533         print "$Script: $1 not copied to $2 (ignored)\n";
534
535       my ($f, $g);
536       for $f (`cat $tfile`) {
537         if($f =~ /\s->\s$dir\/(.*)\n?$/) {
538           $g = $1; $g =~ s/^\/*//;
539           push @mod_list, "$g\n" unless exists $mod_list{$g};
540           $mod_list{$g} = 1;
541         }
542         elsif($f =~ /\s->\s\`$dir\/(.*)\'\n?$/) {
543           $g = $1; $g =~ s/^\/*//;
544           push @mod_list, "$g\n" unless exists $mod_list{$g};
545           $mod_list{$g} = 1;
546         }
547       }
548     }
549 =cut
550     elsif(/^M\s+(.*)$/) {
551       my ($ml, @ml);
552
553       $ml = $1;
554       @ml = split ' ', $ml;
555       if($ml !~ m#/#) {
556         @ml = map { $_ = "modules/$_.o\n" } @ml;
557       }
558       else {
559         @ml = map { $_ .= "\n" } @ml;
560       }
561       push @mod_list, @ml
562     }
563     elsif(/^([eE])\s+(.+)$/) {
564       my ($cmd, $xdir, $basedir, $r, $e, $pm, $is_script);
565
566       $e = $1;
567       $cmd = $2;
568       $xdir = $dir;
569       $xdir =~ s#/*$##;
570       $basedir = $1 if $xdir =~ s#(.*)/##;
571       $is_script = exists $script{$cmd};
572       $pm = $is_script ? "$cmd script" : "\"$cmd\"";
573
574       die "internal oops" unless $basedir ne "" && $xdir ne "";
575
576       if($is_script) {
577         SUSystem "sh -c 'mkdir $dir/install && chmod 777 $dir/install'" and
578           die "$Script: failed to create $dir/install";
579         die "$Script: unable to create $pm" unless open W, ">$dir/install/inst.sh";
580         print W @{$script{$cmd}};
581         close W;
582
583         $e = 'E' if $xdir eq 'base';
584       }
585
586       print "running $pm\n" if $debug =~ /\bpkg\b/;
587       if($e eq 'e') {
588         SUSystem "mv $dir $basedir/base/xxxx" and die "oops";
589         if($is_script) {
590           $r = SUSystem "chroot $basedir/base /bin/sh -c 'cd xxxx ; sh install/inst.sh 1'";
591         }
592         else {
593           $r = SUSystem "chroot $basedir/base /bin/sh -c 'cd xxxx ; $cmd'";
594         }
595         SUSystem "mv $basedir/base/xxxx $dir" and die "oops";
596       }
597       else {
598         if($is_script) {
599           $r = SUSystem "chroot $dir /bin/sh -c 'sh install/inst.sh 1'";
600         }
601         else {
602           $r = SUSystem "chroot $dir /bin/sh -c '$cmd'";
603         }
604       }
605       warn "$Script: execution of $pm failed" if $r;
606
607       SUSystem "rm -rf $dir/install" if $is_script;
608     }
609     elsif(/^R\s+(.+?)\s+(\S+)$/) {
610       my ($file, $re, @f, $i);
611
612       $file = $2;
613       $re = $1 . '; 1';         # fixup_re($1) ?
614
615       # die "$Script: $file: no such file" unless -f "$dir/$file";
616       system "touch $tfile" and die "unable to access $file";
617       SUSystem "cp $dir/$file $tfile" and die "unable to access $file";
618
619       die "$Script: $file: $!" unless open F1, "$tfile";
620       @f = (<F1>);
621       close F1;
622       SUSystem "rm -f $tfile";
623
624       if($re =~ /\/s; 1$/) {    # multi line
625         $_ = join '', @f;
626         $ignore += 10;
627         $i = eval $re;
628         $ignore -= 10;
629         die "$Script: syntax error in expression" unless defined $i;
630         @f = ( $_ );
631       }
632       else {
633         for (@f) {
634           $ignore += 10;
635           $i = eval $re;
636           $ignore -= 10;
637           die "$Script: syntax error in expression" unless defined $i;
638         }
639       }
640       die "$Script: $file: $!" unless open F1, ">$tfile";
641       print F1 @f;
642       close F1;
643
644       SUSystem "cp $tfile $dir/$file" and die "unable to access $file";
645       SUSystem "rm -f $tfile";
646     }
647     else {
648       die "$Script: unknown entry: \"$_\"\n";
649     }
650   }
651
652   close F;
653
654   $account_size->($dir);
655
656   if(!($use_cache & 4)) {
657     SUSystem "rm -rf $tdir";
658   }
659   SUSystem "rm -f $tfile";
660
661   open F, ">${dir}.rpms";
662   print F @packs;
663   close F;
664
665   open F, ">${dir}.rpmlog";
666   print F @plog;
667   close F;
668
669   if(%acc_pack_files) {
670     open F, ">${dir}.size";
671     for $p (sort keys %acc_pack_files) {
672       # print "$p:\n";
673       my $size = 0;
674       my $s = 0;
675       for (keys %{$acc_pack_files{$p}}) {
676         $size += (split ' ', `${su}du -bsk $_ 2>/dev/null`)[0];
677         # print "$_: $size\n";
678       }
679       printf F "%-24s %s\n", $p eq '' ? 'no package' : $p, $size;
680     }
681     close F;
682   }
683
684   if($ENV{'nomods'}) {
685     for (split /,/, $ENV{'nomods'}) {
686       push @mod_list, "modules/$_.o\n"
687     }
688   }
689
690   if(@mod_list && $mod_list) {
691     open F, ">$mod_list";
692     print F @mod_list;
693     close F;
694   }
695
696   $SIG{'__WARN__'} = $old_warn;
697
698   return 1;
699 }
700
701
702 sub fixup_re
703 {
704   local ($_);
705   my ($re, $re0, $val);
706
707   $re0 = $re = shift;
708   $re0 =~ s/(('[^']*')|("[^"]*")|\b(defined|lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b|(\(|\)))/' ' x length($1)/ge;
709   while($re0 =~ s/^((.*)(\b[a-zA-Z]\w+\b))/$2 . (' ' x length($3))/e) {
710 #    print "    >>$3<<\n";
711     if(exists $ConfigData{$3}) {
712       $val = "\$ConfigData{'$3'}";
713     }
714     else {
715       $val = "\$ENV{'$3'}";
716     }
717     $val = $ENV{'___arch'} if $3 eq 'arch';
718     substr($re, length($2), length($3)) = $val;
719   }
720
721   return $re;
722 }
723
724
725 1;