1d15f7ce5Sespie# ex:ts=8 sw=4: 2*039cbdaaSespie# $OpenBSD: CollisionReport.pm,v 1.49 2023/06/13 09:07:17 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 18*039cbdaaSespieuse v5.36; 19d15f7ce5Sespie 2016d0b37eSespiepackage OpenBSD::PackingElement; 21*039cbdaaSespiesub handle_collisions($, $, $, $) 2216d0b37eSespie{ 2316d0b37eSespie} 2416d0b37eSespie 2516d0b37eSespiepackage OpenBSD::PackingElement::FileBase; 26*039cbdaaSespiesub handle_collisions($self, $todo, $pkg, $bypkg) 2716d0b37eSespie{ 2816d0b37eSespie my $name = $self->fullname; 2916d0b37eSespie if (defined $todo->{$name}) { 3016d0b37eSespie push(@{$bypkg->{$pkg}}, $name); 3116d0b37eSespie delete $todo->{$name}; 3216d0b37eSespie } 3316d0b37eSespie} 3416d0b37eSespie 35d15f7ce5Sespiepackage OpenBSD::CollisionReport; 36d15f7ce5Sespieuse OpenBSD::PackingList; 37d15f7ce5Sespieuse OpenBSD::PackageInfo; 38d15f7ce5Sespie 39*039cbdaaSespiesub find_collisions($todo, $state) 40d15f7ce5Sespie{ 41e74b30b0Sespie my $verbose = $state->verbose >= 3; 42d15f7ce5Sespie my $bypkg = {}; 432818ea65Sespie for my $name (keys %$todo) { 44b6ce8483Sespie my $pkg = $state->vstat->value($state->{destdir}.$name); 45b6ce8483Sespie if (defined $pkg) { 468eeac59fSespie push(@{$bypkg->{$pkg}}, $name); 472818ea65Sespie delete $todo->{$name}; 488eeac59fSespie } 498eeac59fSespie } 50d15f7ce5Sespie 512818ea65Sespie 522818ea65Sespie if (!%$todo) { 532818ea65Sespie return $bypkg; 542818ea65Sespie } 55d15f7ce5Sespie for my $pkg (installed_packages()) { 567e83eca3Sespie $state->say("Looking for collisions in #1", $pkg) if $verbose; 57af4e06d4Sespie # XXX in -n mode, some stuff is not really there 58af4e06d4Sespie # avoid warnings 59af4e06d4Sespie next unless -d installed_info($pkg); 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 68*039cbdaaSespiesub collision_report($list, $state, $set) 692818ea65Sespie{ 70d17dc12fSespie my $destdir = $state->{destdir}; 71d17dc12fSespie 72a409537dSespie if ($state->defines('removecollisions')) { 732818ea65Sespie require OpenBSD::Error; 742818ea65Sespie for my $f (@$list) { 75d17dc12fSespie $state->unlink(1, $destdir.$f->fullname); 768eeac59fSespie } 772818ea65Sespie return; 782818ea65Sespie } 79700d29cbSespie my %todo = map {($_->fullname, $_->{d})} @$list; 8045571e80Sespie my %extra = map {($_->fullname, $_->{newly_found})} @$list; 812818ea65Sespie my $clueless_bat; 822818ea65Sespie my $clueless_bat2; 832818ea65Sespie my $found = 0; 842818ea65Sespie 85b5c9b1b8Sespie $state->errsay("Collision in #1: the following files already exist", 86b5c9b1b8Sespie $set->print); 87a409537dSespie if (!$state->defines('dontfindcollisions')) { 880f0116c3Sespie my $bypkg = find_collisions(\%todo, $state); 89d15f7ce5Sespie for my $pkg (sort keys %$bypkg) { 90d15f7ce5Sespie for my $item (sort @{$bypkg->{$pkg}}) { 912818ea65Sespie $found++; 920f753b04Sespie $state->errsay("\t#1 (#2 and #3)", $item, $pkg, 930f753b04Sespie $extra{$item}); 9445571e80Sespie } 95cc24e6f2Sespie if ($pkg =~ m/^(?:partial\-|borked\.\d+$)/o) { 96eefd3b46Sespie $clueless_bat = $pkg; 97eefd3b46Sespie } 98eb9d5597Sespie if ($pkg =~ m/^\.libs\d*-*$/o) { 991c9bf27fSespie $clueless_bat2 = $pkg; 1001c9bf27fSespie } 101d15f7ce5Sespie } 1022818ea65Sespie } 1030b2ea41eSespie if (%todo) { 1040b2ea41eSespie 105d15f7ce5Sespie for my $item (sort keys %todo) { 106700d29cbSespie my $old = $todo{$item}; 1070f753b04Sespie $state->errprint("\t#1 from #2", $item, $extra{$item}); 108b6ce8483Sespie if (defined $old && -f $destdir.$item) { 109700d29cbSespie my $d = $old->new($destdir.$item); 110b6ce8483Sespie 111700d29cbSespie if ($d->equals($old)) { 112b6ce8483Sespie $state->errsay(" (same checksum)"); 1130b2ea41eSespie } else { 114b6ce8483Sespie $state->errsay(" (different checksum)"); 1150b2ea41eSespie } 116eefd3b46Sespie } else { 117b0dfb814Sespie $state->errsay; 1180b2ea41eSespie } 119d15f7ce5Sespie } 120d15f7ce5Sespie } 121a96a2504Sespie if (defined $clueless_bat) { 1227e83eca3Sespie $state->errprint("The package name #1 suggests that a former installation\n". 1237e83eca3Sespie "of a similar package got interrupted. It is likely that\n". 1247e83eca3Sespie "\tpkg_delete #1\n". 1257e83eca3Sespie "will solve the problem\n", $clueless_bat); 126eefd3b46Sespie } 127a96a2504Sespie if (defined $clueless_bat2) { 1287e83eca3Sespie $state->errprint("The package name #1 suggests remaining libraries\n". 1297e83eca3Sespie "from a former package update. It is likely that\n". 1307e83eca3Sespie "\tpkg_delete #1\n". 1317e83eca3Sespie "will solve the problem\n", $clueless_bat2); 1321c9bf27fSespie } 1332818ea65Sespie my $dorepair = 0; 1342818ea65Sespie if ($found == 0) { 135eb8b7390Sespie $dorepair = $state->defines('repair') || 136fb75580aSespie $state->confirm_defaults_to_no( 137fb75580aSespie "It seems to be a missing package registration\nRepair"); 1382818ea65Sespie } 1392818ea65Sespie if ($dorepair == 1) { 1402818ea65Sespie for my $f (@$list) { 1412818ea65Sespie 142e74b30b0Sespie if ($state->unlink($state->verbose >= 2, 143d17dc12fSespie $destdir.$f->fullname)) { 1442818ea65Sespie $state->{problems}--; 1452818ea65Sespie } else { 1462818ea65Sespie return; 1472818ea65Sespie } 1482818ea65Sespie } 1492818ea65Sespie $state->{repairdependencies} = 1; 1502818ea65Sespie } 151eefd3b46Sespie} 152d15f7ce5Sespie 153d15f7ce5Sespie1; 154