Skip to content

Commit 1e39199

Browse files
committed
Fix product builds with packages/files containing special characters
1 parent 23167b8 commit 1e39199

File tree

3 files changed

+67
-27
lines changed

3 files changed

+67
-27
lines changed

PBuild/Checker.pm

+1-1
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ sub check_product {
519519
next if $seen_fn{$fn};
520520
next if $fn =~ /^::import::(.*?)::(.*)$/ && $seen_fn{$2};
521521
my $b = $bininfo->{$fn};
522-
push @rpms, { %{$bininfo->{$fn}}, 'package' => $apackid };
522+
push @rpms, { %{$bininfo->{$fn}}, 'package' => $apackid, 'fn' => $fn };
523523
$seen_fn{$fn} = 1;
524524
push @next_unneeded_na, $na unless $ba eq 'src' || $ba eq 'nosrc';
525525
}

PBuild/OBS.pm

+18-24
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ sub fetch_gbininfo {
387387
my $packagebinaryversionlist = PBuild::Structured::fromxml($data, $dtd_packagebinaryversionlist, 0, 1);
388388
my $gbininfo = {};
389389
for my $binaryversionlist (@{$packagebinaryversionlist->{'binaryversionlist'} || []}) {
390-
my $location = "${baseurl}build/$prp/$arch/$binaryversionlist->{'package'}/";
390+
my $location = "${baseurl}build/$prp/$arch/".PBuild::Util::urlencode("$binaryversionlist->{'package'}/");
391391
my %bins;
392392
for my $binary (@{$binaryversionlist->{'binary'} || []}) {
393393
my $filename = $binary->{'name'};
@@ -407,7 +407,11 @@ sub fetch_gbininfo {
407407
$bin->{'hdrmd5'} = $binary->{'hdrmd5'} if $binary->{'hdrmd5'};
408408
$bin->{'leadsigmd5'} = $binary->{'leadsigmd5'} if $binary->{'leadsigmd5'};
409409
$bin->{'md5sum'} = $binary->{'md5sum'} if $binary->{'md5sum'};
410-
$bin->{'location'} = $location . $filename;
410+
if ($filename =~ /([\000-\040<>;\"#\?&\+=%[\177-\377])/s) {
411+
$bin->{'location'} = $location . PBuild::Util::urlencode($filename);
412+
} else {
413+
$bin->{'location'} = $location . $filename;
414+
}
411415
$bins{$filename} = $bin;
412416
}
413417
$gbininfo->{$binaryversionlist->{'package'}} = \%bins;
@@ -435,46 +439,35 @@ sub fetch_gbininfo_cookie {
435439
}
436440

437441
sub fetch_productbinaries_cpioextract {
438-
my ($ent, $xfile, $repodir, $packid, $files) = @_;
442+
my ($ent, $xfile, $repodir, $packid, $files, $callback) = @_;
439443
return undef unless $ent->{'cpiotype'} == 8;
440444
my $name = $ent->{'name'};
441-
PBuild::Verify::verify_filename("$packid-$name");
442-
my $tmpname = "$repodir/.$$.$packid-$name";
445+
my $binname = "$packid-$name";
446+
PBuild::Verify::verify_filename($binname);
447+
my $tmpname = ".$$.$binname";
443448
if (!defined($xfile)) {
444449
return undef unless $files->{$name};
445-
return $tmpname; # ok, extract this one!
450+
return "$repodir/$tmpname"; # ok, extract this one!
446451
}
447452
my $bin = $files->{$name};
448-
die unless $bin;
449-
if ($bin->{'md5sum'}) {
450-
Build::Download::checkfiledigest($tmpname, "md5:$bin->{'md5sum'}");
451-
} elsif ($bin->{'hdrmd5'} || $bin->{'leadsigmd5'}) {
452-
my $leadsigmd5;
453-
my $hdrmd5 = Build::Rpm::queryhdrmd5($tmpname, \$leadsigmd5);
454-
die("downloaded binary does not match hdrmd5\n") if $bin->{'hdrmd5'} && $bin->{'hdrmd5'} ne ($hdrmd5 || '');
455-
die("downloaded binary does not match leadsigmd5\n") if $bin->{'leadsigmd5'} && $bin->{'leadsigmd5'} ne ($leadsigmd5 || '');
456-
}
457-
rename($tmpname, "$repodir/_gbins/$packid-$name") || die("rename $tmpname $repodir/_gbins/$packid-$name: $!\n");
458-
die unless ($bin->{'package'} || '') eq $packid;
459-
$bin->{'filename'} = "$packid-$name";
460-
return undef; # continue extracting
453+
die unless $bin && ($bin->{'package'} || '') eq $packid;
454+
$callback->($repodir, $tmpname, $binname, $bin);
455+
return undef; # continue extracting
461456
}
462457

463458
sub fetch_productbinaries {
464-
my ($url, $repodir, $bins) = @_;
459+
my ($url, $repodir, $bins, $callback) = @_;
465460
# group by package
466461
my %packages;
467462
my $location;
468463
for my $bin (@$bins) {
469464
my $l = $bin->{'location'};
470465
die("fetch_productbinaries: missing location\n") unless $l;
471466
die("fetch_productbinaries: bad location $l\n") unless $l =~ /^(.+)\/([^\/]+)\/([^\/]+)$/;
472-
die("fetch_productbinaries: package mismatch$l\n") unless $2 eq $bin->{'package'};
473467
$location = $1 unless defined $location;
474468
die("fetch_productbinaries: location conflict\n") unless $1 eq $location;
475-
$packages{$2}->{$3} = $bin;
469+
$packages{$bin->{'package'}}->{$bin->{'fn'}} = $bin;
476470
}
477-
PBuild::Util::mkdir_p("$repodir/_gbins");
478471
my $ua = create_ua();
479472
for my $packid (sort keys %packages) {
480473
my $files = $packages{$packid};
@@ -484,9 +477,10 @@ sub fetch_productbinaries {
484477
$requrl .= "&binary=".PBuild::Util::urlencode($_, 1) for sort keys %$files;
485478
my $tmpcpio = "$repodir/.$$.binaries.cpio";
486479
Build::Download::download($requrl, $tmpcpio, undef, 'ua' => $ua, 'retry' => 3);
487-
PBuild::Cpio::cpio_extract($tmpcpio, sub {fetch_productbinaries_cpioextract($_[0], $_[1], $repodir, $packid, $files)});
480+
PBuild::Cpio::cpio_extract($tmpcpio, sub {fetch_productbinaries_cpioextract($_[0], $_[1], $repodir, $packid, $files, $callback)});
488481
unlink($tmpcpio);
489482
}
483+
return $ua;
490484
}
491485

492486
1;

PBuild/RemoteRepo.pm

+48-2
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ sub is_matching_binary {
436436
return 0 if $b1->{'version'} ne $b2->{'version'};
437437
return 0 if ($b1->{'epoch'} || 0) ne ($b2->{'epoch'} || 0);
438438
return 0 if (defined $b1->{'release'} ? $b1->{'release'} : '__undef__') ne (defined $b2->{'release'} ? $b2->{'release'} : '__undef__');
439+
return 0 if $b1->{'hdrmd5'} && $b2->{'hdrmd5'} && $b1->{'hdrmd5'} ne $b2->{'hdrmd5'};
440+
return 0 if $b1->{'leadsigmd5'} && $b2->{'leadsigmd5'} && $b1->{'leadsigmd5'} ne $b2->{'leadsigmd5'};
439441
return 1;
440442
}
441443

@@ -531,15 +533,59 @@ sub fetchbinaries {
531533
PBuild::Util::store("$repodir/._metadata.$$", "$repodir/_metadata", $meta->{'metadata'});
532534
}
533535

536+
#
537+
# Check if the downloaded binary matches and set the local filename
538+
#
539+
sub fetchproductbinaries_replace {
540+
my ($repodir, $tmpname, $binname, $bin) = @_;
541+
Build::Download::checkfiledigest("$repodir/$tmpname", $bin->{'checksum'}) if $bin->{'checksum'};
542+
if ($bin->{'md5sum'}) {
543+
Build::Download::checkfiledigest("$repodir/$tmpname", $bin->{'checksum'}) if "md5:$bin->{'md5sum'}";
544+
} elsif ($bin->{'hdrmd5'}) {
545+
my $leadsigmd5;
546+
my $hdrmd5 = Build::queryhdrmd5("$repodir/$tmpname", \$leadsigmd5);
547+
die("downloaded product binary $binname does not match repository metadata (hdrmd5)\n") unless ($hdrmd5 || '') eq $bin->{'hdrmd5'};
548+
die("downloaded product binary $binname does not match repository metadata (leadsigmd5)\n") unless !$bin->{'leadsigmd5'} || ($leadsigmd5 || '') eq $bin->{'leadsigmd5'};
549+
}
550+
PBuild::Verify::verify_filename($binname);
551+
rename("$repodir/$tmpname", "$repodir/_gbins/$binname") || die("rename $repodir/$tmpname $repodir/_gbins/$binname: $!\n");
552+
$bin->{'filename'} = $binname;
553+
}
554+
534555
#
535556
# Download missing gbininfo product binaries from a remote repository
536557
#
537558
sub fetchproductbinaries {
538559
my ($meta, $bins) = @_;
539560
my $repodir = $meta->{'repodir'};
540561
print "fetching ".PBuild::Util::plural(scalar(@$bins), 'product binary')." from $meta->{'url'}\n";
541-
die("unsupported repo type $meta->{'repotype'}\n") unless $meta->{'repotype'} eq 'obs';
542-
PBuild::OBS::fetch_productbinaries($meta->{'url'}, $repodir, $bins);
562+
my $repodir = $meta->{'repodir'};
563+
PBuild::Util::mkdir_p("$repodir/_gbins");
564+
my $ua;
565+
$ua = PBuild::OBS::fetch_productbinaries($meta->{'url'}, $repodir, $bins, \&fetchproductbinaries_replace);
566+
for my $bin (@$bins) {
567+
next if $bin->{'filename'};
568+
my $location = $bin->{'location'};
569+
die("missing location for binary $bin->{'name'}\n") unless $location;
570+
die("bad location: $location\n") unless $location =~ /^(?:https?|zypp):\/\//;
571+
my $packid = $bin->{'package'};
572+
my $fn = $bin->{'fn'};
573+
die unless $packid && $fn;
574+
my $binname = "$packid-$fn";
575+
PBuild::Verify::verify_filename($binname);
576+
my $tmpname = ".$$.$binname";
577+
$ua ||= Build::Download::create_ua();
578+
download($location, "$repodir/$tmpname", undef, undef, $ua);
579+
fetchproductbinaries_replace($repodir, $tmpname, $binname, $bin);
580+
}
581+
# copy filename into real gbininfo as we clone the bininfo in the Checker
582+
my $gbininfo = $meta->{'metadata'}->{'gbininfo'};
583+
for my $bin (@{$bins}) {
584+
next unless $bin->{'filename'} && $bin->{'fn'} && $bin->{'package'};
585+
my $bininfo = $gbininfo->{$bin->{'package'}};
586+
die unless $bininfo && $bininfo->{$bin->{'fn'}};
587+
$bininfo->{$bin->{'fn'}}->{'filename'} = $bin->{'filename'};
588+
}
543589
# updata meta data
544590
PBuild::Util::store("$repodir/._gbininfo.$$", "$repodir/_gbininfo", $meta->{'metadata'});
545591
}

0 commit comments

Comments
 (0)