1# ex:ts=8 sw=4: 2# $OpenBSD: OldLibs.pm,v 1.17 2023/06/13 09:07:17 espie Exp $ 3# 4# Copyright (c) 2004-2010 Marc Espie <espie@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 17use v5.36; 18 19package OpenBSD::PackingElement; 20 21# $self->mark_lib($libs, $libpatterns) 22# store libs into hashes 23sub mark_lib($, $, $) 24{ 25} 26 27sub unmark_lib($, $, $) 28{ 29} 30 31# $self->separate_element($libs, $c1, $c2) 32# based on libs hash, do we sort it into clone 1 or clone 2 33sub separate_element($self, $, $, $c2) 34{ 35 $c2->{$self} = 1; 36} 37 38sub special_deep_copy($self, $copy, $h, $) 39{ 40 $self->clone->add_object($copy) if defined $h->{$self}; 41} 42 43package OpenBSD::PackingElement::Meta; 44 45# so every meta element ends up in both 46sub separate_element($self, $, $c1, $c2) 47{ 48 $c1->{$self} = 1; 49 $c2->{$self} = 1; 50} 51 52package OpenBSD::PackingElement::DigitalSignature; 53 54sub separate_element($self, $, $, $c2) 55{ 56 $c2->{$self} = 1; 57} 58 59package OpenBSD::PackingElement::State; 60 61sub separate_element # forwarder 62{ 63 &OpenBSD::PackingElement::Meta::separate_element; 64} 65 66package OpenBSD::PackingElement::Depend; 67sub separate_element # forwarder 68{ 69 &OpenBSD::PackingElement::separate_element; 70} 71 72package OpenBSD::PackingElement::SpecialFile; 73sub separate_element # forwarder 74{ 75 &OpenBSD::PackingElement::separate_element; 76} 77 78package OpenBSD::PackingElement::FCONTENTS; 79sub special_deep_copy($, $, $, $) 80{ 81} 82 83package OpenBSD::PackingElement::Lib; 84use File::Basename; 85 86sub mark_lib($self, $libs, $libpatterns) 87{ 88 my $libname = $self->fullname; 89 my ($stem, $major, $minor, $dir) = $self->parse($libname); 90 if (defined $stem) { 91 $libpatterns->{$stem}->{$dir} = [$major, $minor, $libname]; 92 } 93 $libs->{$libname} = 1; 94} 95 96sub separate_element($self, $libs, $c1, $c2) 97{ 98 if ($libs->{$self->fullname}) { 99 $c1->{$self} = 1; 100 } else { 101 $c2->{$self} = 1; 102 } 103} 104 105sub unmark_lib($self, $libs, $libpatterns) 106{ 107 my $libname = $self->fullname; 108 my ($stem, $major, $minor, $dir) = $self->parse($libname); 109 if (defined $stem) { 110 my $p = $libpatterns->{$stem}->{$dir}; 111 if (defined $p && $p->[0] == $major && $p->[1] <= $minor) { 112 my $n = $p->[2]; 113 delete $libs->{$n}; 114 } 115 } 116 delete $libs->{$libname}; 117} 118 119sub enforce_dir($self, $path, $copy, $dirs) 120{ 121 my $d = dirname($path); 122 my $localbase = $copy->localbase; 123 124 if ($d eq "$localbase/lib" || $d eq $localbase || $d eq '/') { 125 return; 126 } 127 if ($dirs->{$d}) { 128 return; 129 } 130 $dirs->{$d} = 1; 131 $self->enforce_dir($d, $copy, $dirs); 132 my $cwd = $self->cwd; 133 $d =~ s/^\Q$cwd\E\///; 134 OpenBSD::PackingElement::Dir->add($copy, $d); 135} 136 137sub special_deep_copy($self, $copy, $h, $dirs) 138{ 139 $self->enforce_dir($self->fullname, $copy, $dirs); 140 $self->SUPER::special_deep_copy($copy, $h, $dirs); 141} 142 143package OpenBSD::OldLibs; 144use OpenBSD::RequiredBy; 145use OpenBSD::PackageInfo; 146 147sub split_some_libs($plist, $libs) 148{ 149 my $c1 = {}; 150 my $c2 = {}; 151 $plist->separate_element($libs, $c1, $c2); 152 my $p1 = OpenBSD::PackingList->new; 153 $p1->set_infodir($plist->infodir); 154 $plist->special_deep_copy($p1, $c1, {}); 155 my $p2 = $plist->make_shallow_copy($c2); 156 return ($p1, $p2); 157} 158 159# create a packing-list with only the libraries we want to keep around. 160sub split_libs($plist, $to_split) 161{ 162 (my $splitted, $plist) = split_some_libs($plist, $to_split); 163 164 require OpenBSD::PackageInfo; 165 166 $splitted->set_pkgname(OpenBSD::PackageInfo::libs_package($plist->pkgname)); 167 168 if (defined $plist->{'no-default-conflict'}) { 169 # we conflict with the package we just removed... 170 OpenBSD::PackingElement::Conflict->add($splitted, $plist->pkgname); 171 } else { 172 my $stem = OpenBSD::PackageName::splitstem($plist->pkgname); 173 OpenBSD::PackingElement::Conflict->add($splitted, $stem."-*"); 174 } 175 return ($plist, $splitted); 176} 177 178sub adjust_depends_closure($oldname, $plist, $state) 179{ 180 $state->say(" Packages that depend on those shared libraries:") 181 if $state->verbose >= 3; 182 183 my $write = OpenBSD::RequiredBy->new($plist->pkgname); 184 for my $pkg (OpenBSD::RequiredBy->compute_closure($oldname)) { 185 $state->say("\t#1", $pkg) if $state->verbose >= 3; 186 $write->add($pkg); 187 my $r = OpenBSD::Requiring->new($pkg)->add($plist->pkgname); 188 if ($oldname =~ m/^\.libs\d*\-/o) { 189 $r->delete($oldname); 190 } 191 } 192} 193 194sub do_save_libs($o, $libs, $state) 195{ 196 my $oldname = $o->pkgname; 197 198 ($o->{plist}, my $stub_list) = split_libs($o->plist, $libs); 199 my $stub_name = $stub_list->pkgname; 200 my $dest = installed_info($stub_name); 201 $state->say(" (keeping them in #1)", $stub_name) 202 if $state->verbose >= 2; 203 204 205 if ($state->{not}) { 206 207 $state->shlibs->add_libs_from_plist($stub_list); 208 $stub_list->to_cache; 209 $o->plist->to_cache; 210 } else { 211 mkdir($dest); 212 open my $descr, '>', $dest.DESC; 213 print $descr "Stub libraries for $oldname\n"; 214 close $descr; 215 my $f = OpenBSD::PackingElement::FDESC->add($stub_list, DESC); 216 $f->{ignore} = 1; 217 $f->add_digest($f->compute_digest($dest.DESC)); 218 $stub_list->to_installation; 219 $o->plist->to_installation; 220 } 221 add_installed($stub_name); 222 223 OpenBSD::PkgCfl::register($stub_list, $state); 224 225 adjust_depends_closure($oldname, $stub_list, $state); 226} 227 228sub save_libs_from_handle($o, $set, $state) 229{ 230 my $libs = {}; 231 my $p = {}; 232 233 $state->say("Looking for changes in shared libraries of #1", 234 $o->pkgname) if $state->verbose >= 2; 235 $o->plist->mark_lib($libs, $p); 236 for my $n ($set->newer) { 237 $n->plist->unmark_lib($libs, $p); 238 } 239 for my $n ($set->kept) { 240 $n->plist->unmark_lib($libs, $p); 241 } 242 243 if (%$libs) { 244 $state->say(" ->Libraries to keep: #1", 245 join(",", sort(keys %$libs))) if $state->verbose >= 2; 246 do_save_libs($o, $libs, $state); 247 } else { 248 $state->say(" ->No libraries to keep") if $state->verbose >= 2; 249 } 250} 251 252sub save($self, $set, $state) 253{ 254 for my $o ($set->older) { 255 save_libs_from_handle($o, $set, $state); 256 } 257} 258 2591; 260