1d15f7ce5Sespie# ex:ts=8 sw=4: 2*fb75580aSespie# $OpenBSD: CollisionReport.pm,v 1.47 2018/02/27 22:46:53 espie Exp $ 3d15f7ce5Sespie# 41144937fSespie# Copyright (c) 2003-2006 Marc Espie <espie@openbsd.org> 5d15f7ce5Sespie# 6d15f7ce5Sespie# Permission to use, copy, modify, and distribute this software for any 7d15f7ce5Sespie# purpose with or without fee is hereby granted, provided that the above 8d15f7ce5Sespie# copyright notice and this permission notice appear in all copies. 9d15f7ce5Sespie# 10d15f7ce5Sespie# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11d15f7ce5Sespie# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12d15f7ce5Sespie# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13d15f7ce5Sespie# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14d15f7ce5Sespie# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15d15f7ce5Sespie# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16d15f7ce5Sespie# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 170fbefeddSespie 18d15f7ce5Sespieuse strict; 19d15f7ce5Sespieuse warnings; 20d15f7ce5Sespie 2116d0b37eSespiepackage OpenBSD::PackingElement; 2216d0b37eSespiesub handle_collisions 2316d0b37eSespie{ 2416d0b37eSespie} 2516d0b37eSespie 2616d0b37eSespiepackage OpenBSD::PackingElement::FileBase; 2716d0b37eSespiesub handle_collisions 2816d0b37eSespie{ 2916d0b37eSespie my ($self, $todo, $pkg, $bypkg) = @_; 3016d0b37eSespie my $name = $self->fullname; 3116d0b37eSespie if (defined $todo->{$name}) { 3216d0b37eSespie push(@{$bypkg->{$pkg}}, $name); 3316d0b37eSespie delete $todo->{$name}; 3416d0b37eSespie } 3516d0b37eSespie} 3616d0b37eSespie 37d15f7ce5Sespiepackage OpenBSD::CollisionReport; 38d15f7ce5Sespieuse OpenBSD::PackingList; 39d15f7ce5Sespieuse OpenBSD::PackageInfo; 40d15f7ce5Sespie 412818ea65Sespiesub find_collisions 42d15f7ce5Sespie{ 430f0116c3Sespie my ($todo, $state) = @_; 44e74b30b0Sespie my $verbose = $state->verbose >= 3; 45d15f7ce5Sespie my $bypkg = {}; 462818ea65Sespie for my $name (keys %$todo) { 47b6ce8483Sespie my $pkg = $state->vstat->value($state->{destdir}.$name); 48b6ce8483Sespie if (defined $pkg) { 498eeac59fSespie push(@{$bypkg->{$pkg}}, $name); 502818ea65Sespie delete $todo->{$name}; 518eeac59fSespie } 528eeac59fSespie } 53d15f7ce5Sespie 542818ea65Sespie 552818ea65Sespie if (!%$todo) { 562818ea65Sespie return $bypkg; 572818ea65Sespie } 58d15f7ce5Sespie for my $pkg (installed_packages()) { 597e83eca3Sespie $state->say("Looking for collisions in #1", $pkg) if $verbose; 60d15f7ce5Sespie my $plist = OpenBSD::PackingList->from_installation($pkg, 61d15f7ce5Sespie \&OpenBSD::PackingList::FilesOnly); 628ee98284Sespie next if !defined $plist; 6316d0b37eSespie $plist->handle_collisions($todo, $pkg, $bypkg); 64d15f7ce5Sespie } 652818ea65Sespie return $bypkg; 66d15f7ce5Sespie} 672818ea65Sespie 68b5c9b1b8Sespiesub collision_report 692818ea65Sespie{ 70b5c9b1b8Sespie my ($list, $state, $set) = @_; 712818ea65Sespie 72d17dc12fSespie my $destdir = $state->{destdir}; 73d17dc12fSespie 74a409537dSespie if ($state->defines('removecollisions')) { 752818ea65Sespie require OpenBSD::Error; 762818ea65Sespie for my $f (@$list) { 77d17dc12fSespie $state->unlink(1, $destdir.$f->fullname); 788eeac59fSespie } 792818ea65Sespie return; 802818ea65Sespie } 81700d29cbSespie my %todo = map {($_->fullname, $_->{d})} @$list; 8245571e80Sespie my %extra = map {($_->fullname, $_->{newly_found})} @$list; 832818ea65Sespie my $clueless_bat; 842818ea65Sespie my $clueless_bat2; 852818ea65Sespie my $found = 0; 862818ea65Sespie 87b5c9b1b8Sespie $state->errsay("Collision in #1: the following files already exist", 88b5c9b1b8Sespie $set->print); 89a409537dSespie if (!$state->defines('dontfindcollisions')) { 900f0116c3Sespie my $bypkg = find_collisions(\%todo, $state); 91d15f7ce5Sespie for my $pkg (sort keys %$bypkg) { 92d15f7ce5Sespie for my $item (sort @{$bypkg->{$pkg}}) { 932818ea65Sespie $found++; 940f753b04Sespie $state->errsay("\t#1 (#2 and #3)", $item, $pkg, 950f753b04Sespie $extra{$item}); 9645571e80Sespie } 97cc24e6f2Sespie if ($pkg =~ m/^(?:partial\-|borked\.\d+$)/o) { 98eefd3b46Sespie $clueless_bat = $pkg; 99eefd3b46Sespie } 100eb9d5597Sespie if ($pkg =~ m/^\.libs\d*-*$/o) { 1011c9bf27fSespie $clueless_bat2 = $pkg; 1021c9bf27fSespie } 103d15f7ce5Sespie } 1042818ea65Sespie } 1050b2ea41eSespie if (%todo) { 1060b2ea41eSespie 107d15f7ce5Sespie for my $item (sort keys %todo) { 108700d29cbSespie my $old = $todo{$item}; 1090f753b04Sespie $state->errprint("\t#1 from #2", $item, $extra{$item}); 110b6ce8483Sespie if (defined $old && -f $destdir.$item) { 111700d29cbSespie my $d = $old->new($destdir.$item); 112b6ce8483Sespie 113700d29cbSespie if ($d->equals($old)) { 114b6ce8483Sespie $state->errsay(" (same checksum)"); 1150b2ea41eSespie } else { 116b6ce8483Sespie $state->errsay(" (different checksum)"); 1170b2ea41eSespie } 118eefd3b46Sespie } else { 119b0dfb814Sespie $state->errsay; 1200b2ea41eSespie } 121d15f7ce5Sespie } 122d15f7ce5Sespie } 123a96a2504Sespie if (defined $clueless_bat) { 1247e83eca3Sespie $state->errprint("The package name #1 suggests that a former installation\n". 1257e83eca3Sespie "of a similar package got interrupted. It is likely that\n". 1267e83eca3Sespie "\tpkg_delete #1\n". 1277e83eca3Sespie "will solve the problem\n", $clueless_bat); 128eefd3b46Sespie } 129a96a2504Sespie if (defined $clueless_bat2) { 1307e83eca3Sespie $state->errprint("The package name #1 suggests remaining libraries\n". 1317e83eca3Sespie "from a former package update. It is likely that\n". 1327e83eca3Sespie "\tpkg_delete #1\n". 1337e83eca3Sespie "will solve the problem\n", $clueless_bat2); 1341c9bf27fSespie } 1352818ea65Sespie my $dorepair = 0; 1362818ea65Sespie if ($found == 0) { 137eb8b7390Sespie $dorepair = $state->defines('repair') || 138*fb75580aSespie $state->confirm_defaults_to_no( 139*fb75580aSespie "It seems to be a missing package registration\nRepair"); 1402818ea65Sespie } 1412818ea65Sespie if ($dorepair == 1) { 1422818ea65Sespie for my $f (@$list) { 1432818ea65Sespie 144e74b30b0Sespie if ($state->unlink($state->verbose >= 2, 145d17dc12fSespie $destdir.$f->fullname)) { 1462818ea65Sespie $state->{problems}--; 1472818ea65Sespie } else { 1482818ea65Sespie return; 1492818ea65Sespie } 1502818ea65Sespie } 1512818ea65Sespie $state->{repairdependencies} = 1; 1522818ea65Sespie } 153eefd3b46Sespie} 154d15f7ce5Sespie 155d15f7ce5Sespie1; 156