Vincent Danen <[EMAIL PROTECTED]> writes:
> Something like StackGuard+FormatGuard (from Immunix although I think
> they're quite out-dated) would be good (cover buffer overflows and
> format string vulns all at the same time).
the later should be covered if one check compiler output with modern
gcc.
i once again promote pixel "install deps, build it, check it and offer
to upload it" script that filter output and only output stderr thus
highlighting gcc warnings:
#!/usr/bin/perl
use MDK::Common;
use POSIX;
my $rpm = "rpm --nosignature";
my $rpmdir = chomp_(`rpm --eval '%_topdir'`);
my $tmppath = chomp_(`rpm --eval '%_tmppath'`);
s|/$|| foreach $rpmdir, $tmppath;
if ($0 =~ /isrpms/i) {
@ARGV == 1 or die "isrpms <package name>\n";
my $srpm = previous_pkg('SRPMS', $ARGV[0]);
print "installing $srpm\n";
system("rpm -i $srpm");
my $name = pkg_info($srpm)->{name};
chdir "$rpmdir/SPECS";
-e "$name.spec" or die "bad spec file name, missing $name.spec\n";
system("emacsclient --no-wait $name.spec 2>/dev/null");
} elsif ($0 =~ /compare/i) {
@ARGV or die "Compare_package_files <rpm file>\n";
foreach (@ARGV) {
my $info = pkg_info($_);
my $previous = previous_pkg('RPMS', $info->{name});
compare_package_files($info, $previous);
}
} else {
goto upload;
}
exit 0;
upload:
my $short_circuit = $ARGV[0] eq '--short-circuit' && shift(@ARGV);
my ($q_spec) = @ARGV;
if ($q_spec =~ /\.src\.rpm$/) {
system("rpm", "-i", $q_spec) == 0 or die "bad srpm $q_spec\n";
($q_spec) = `$rpm -qpl $q_spec` =~ /(.*)\.spec$/m or internal_error("missing
spec");
}
-e $q_spec or $q_spec = "$rpmdir/SPECS/$q_spec.spec";
-e $q_spec && @ARGV == 1 or die "Upload <spec file>\n";
my $spec = basename($q_spec);
my $buildlog = "$tmppath/.upload-$spec";
$| = 1;
system("chmod", "644", $q_spec, grep { -f $_ } glob_("$rpmdir/SOURCES/*"));
if (system("rpmbuild -bs $q_spec > $buildlog") != 0) {
system("rpmbuild -bs $q_spec > /dev/null 2> $buildlog");
if (my @deps_needed = cat_($buildlog) =~ /^\s+(\S+)\s+.*is needed by/gm) {
foreach (@deps_needed) {
system("sudo ue -u $_");
system("sudo ue -c $_");
}
warn "Waiting for @deps_needed to be installed\n";
sleep 120;
}
if (my @deps_conflict = cat_($buildlog) =~ /^\s+(\S+)\s+.*conflicts with/gm) {
@deps_conflict = map { chomp_(`rpm -q --whatprovides --qf '%{name}\n' $_`) }
@deps_conflict;
print STDERR "There are conflicting packages.\nRemove packages @deps_conflict
(Y/n) ?";
<STDIN> !~ /n/i or exit 0;
system("sudo ue -e $_") foreach @deps_conflict;
warn "Waiting for @deps_conflict to be removed\n";
sleep 120;
}
system("rpmbuild -bs $q_spec > $buildlog") == 0 or die "rpmbuild -bs $spec
failed\n";
}
my ($srpm) = map { if_(/^Wrote: (.*)/, $1) } cat_($buildlog);
my $info = pkg_info($srpm);
my $previous_srpm = eval { previous_pkg('SRPMS', $info->{name},
"$info->{name}-$info->{version}") };
my $previous = $previous_srpm && pkg_info($previous_srpm);
my $cooker_or_contrib;
if ($previous_srpm) {
$info->{version} eq $previous->{version} && $info->{release} eq
$previous->{release}
and die "ERROR: package $info->{name} already exists in cooker
($previous_srpm)\ndid you increase the release number?\n";
if ($previous_srpm =~ m|mandrake/uploads|) {
print "package $info->{name} is already in the upload queue
($previous_srpm)\n";
print "continue anyway (y/N)? ";
<STDIN> =~ /^y/i or exit 1;
}
$cooker_or_contrib = $previous_srpm =~ m|contrib/| ? 'contrib' : 'cooker';
}
while (!$cooker_or_contrib) {
print($previous_srpm ? "Weird, $info->{name} is both in contrib and main" :
"$info->{name} is neither in contrib nor main");
print ", what do you choose (contrib/cooker)? ";
my $r = <STDIN>;
$cooker_or_contrib = 'contrib' if $r =~ /con/i;
$cooker_or_contrib = 'cooker' if $r =~ /coo/i;
$cooker_or_contrib or print qq(Bad answer, please type "cooker" or "contrib"\n");
};
if ($short_circuit) {
print "installing...\n";
system("rpmbuild -bi --short-circuit $q_spec > $buildlog") == 0 or die "rpmbuild
-bi --short-circuit $spec failed\n";
system("rpmbuild -bb --short-circuit $q_spec >> $buildlog") == 0 or die "rpmbuild
-bb --short-circuit $spec failed\n";
} else {
print "building...\n";
system("rpmbuild -bb $q_spec > $buildlog") == 0 or die "rpmbuild -bb $spec
failed\n";
}
my @rpms = map { pkg_info($_) } map { if_(/^Wrote: (.*)/, $1) } cat_($buildlog);
if ($previous_srpm) {
@rpms = compare_package_files($previous, @rpms);
compare_package_requires($previous, @rpms);
compare_package_provides($previous, @rpms);
} else {
if (any { $_->{name} =~ /-debug$/ } @rpms) {
print "Do you want to upload $info->{name}-debug (the debug version) (y/N)? ";
if (<STDIN> !~ /^y/i) {
@rpms = grep { $_->{name} !~ /-debug$/ } @rpms;
}
}
}
{
my $rpms = join(" ", map { $_->{file} } @rpms);
if (my $s = `rpmlint $srpm $rpms`) {
print "rpmlint
***********************************************************************\n";
print $s;
}
}
print
"*******************************************************************************\n";
print "test package" . (@rpms > 1 ? 's' : '') . ' ' . join(', ', map {
"$_->{name}-$_->{release}" } @rpms) . "\n";
print "then press <enter> to upload to $cooker_or_contrib (or <ctrl-C> to abort)\n";
<STDIN>;
print "ftp$cooker_or_contrib...\n";
system("sudo", "ftp$cooker_or_contrib", $srpm, map { $_->{file} } @rpms) == 0 or die
"$cooker_or_contrib failed\n";
system("rpmbuild --clean --rmsource --nodeps $q_spec");
system("rm -f $q_spec $q_spec.old $buildlog");
sub pkg_info {
my ($srpm) = @_;
my ($name, $version, $release) = split ' ', `$rpm -qp --qf '%{name} %{version}
%{release}' $srpm`;
(my $rpmdir = dirname($srpm)) =~ s/SRPMS/RPMS/;
{ name => $name, version => $version, release => $release, rpmdir => $rpmdir, file
=> $srpm };
}
sub previous_pkg {
my ($rpm_or_srpm, $name, $o_q_name) = @_;
my @dirs = map { "$_$rpm_or_srpm" } qw(/home/mandrake/uploads/cooker/
/home/mandrake/uploads/contrib/ / /contrib/);
foreach (if_($o_q_name, @dirs)) {
my @l = glob("$_/$o_q_name-*.rpm") or next;
return keep_the_one($name, @l);
}
if (my @l = (map { glob("$_/$name-*.rpm") } @dirs)) {
return keep_the_one($name, @l);
}
die "no existing package named $name\n";
}
sub keep_the_one {
my ($name, @l) = @_;
@l = grep { `$rpm -qp --queryformat "%{name}" $_` eq $name } @l if @l > 1;
if (@l == 1) {
return $l[0];
} elsif (@l) {
die "more than one package is named $name: " . join(" ", @l) . "\n";
} else {
die "no existing package named $name\n";
}
}
my $package_files_banner_displayed;
sub compare_one_package_files {
my ($rpm_info, $previous_rpm) = @_;
my @new = `$rpm -qpl $rpm_info->{file}`;
my @old = `$rpm -qpl $previous_rpm`;
@old = map { moved_files($_) } @old;
@old || $rpm_info->{name} !~ /-debug$/ or return;
compare_lists('files', $rpm_info, [EMAIL PROTECTED], [EMAIL PROTECTED]);
check_bad_files($_) foreach @new;
1;
}
sub compare_package_files {
my ($previous, @rpms) = @_;
grep {
my $previous_rpm =
"$previous->{rpmdir}/$_->{name}-$previous->{version}-$previous->{release}*.rpm";
if (compare_one_package_files($_, $previous_rpm)) {
1;
} else {
unlink $_->{file};
0;
}
} @rpms;
}
sub compare_package_requires {
my ($previous, @rpms) = @_;
foreach my $rpm_info (@rpms) {
my $previous_rpm =
"$previous->{rpmdir}/$rpm_info->{name}-$previous->{version}-$previous->{release}*.rpm";
my $non_interesting_requires = sub {
/^\Qld-linux.so.2/;
};
my @new = grep { !$non_interesting_requires->() } `$rpm -qp --requires
$rpm_info->{file}`;
my @old = grep { !$non_interesting_requires->() } `$rpm -qp --requires
$previous_rpm`;
compare_lists('requires', $rpm_info, [EMAIL PROTECTED], [EMAIL PROTECTED]);
}
}
sub compare_package_provides {
my ($previous, @rpms) = @_;
foreach my $rpm_info (@rpms) {
my $previous_rpm =
"$previous->{rpmdir}/$rpm_info->{name}-$previous->{version}-$previous->{release}*.rpm";
my $non_interesting_provides = sub {
/\Q$rpm_info->{name} = /;
};
my @new = grep { !$non_interesting_provides->() } `$rpm -qp --provides
$rpm_info->{file}`;
my @old = grep { !$non_interesting_provides->() } `$rpm -qp --provides
$previous_rpm`;
compare_lists('provides', $rpm_info, [EMAIL PROTECTED], [EMAIL PROTECTED]);
}
}
my %banner_displayed;
sub compare_lists {
my ($name, $rpm_info, $new, $old) = @_;
$new = join('', sort @$new);
$old = join('', sort @$old);
$new ne $old or return 1;
my $olddir = POSIX::getcwd();
chdir $rpmdir;
output("$rpm_info->{name}--$name.new", $new);
output("$rpm_info->{name}--$name.old", $old);
print "compare package $name
*********************************************************\n" if
!$banner_displayed{$name}++;
system("diff -u $rpm_info->{name}--$name.old $rpm_info->{name}--$name.new");
unlink "$rpm_info->{name}--$name.old", "$rpm_info->{name}--$name.new";
chdir $olddir;
0;
}
sub moved_files {
local ($_) = @_;
s|site_perl|vendor_perl|;
s|5.6.1|5.8.1|;
s|5.8.0|5.8.1|;
s|python2.2|python2.3|;
s|/man3pm/|/man3/|;
s|/i386-linux/|/i386-linux-thread-multi/|;
$_;
}
sub check_bad_files {
local ($_) = @_;
my $ok = 1;
chomp;
m|/site_perl/| and warn("ERROR: bad file $_\n"), $ok = 0;
$ok;
}