1# ex:ts=8 sw=4: 2# $OpenBSD: OldLibs.pm,v 1.12 2014/02/04 18:11:36 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 strict; 18use warnings; 19 20package OpenBSD::PackingElement; 21 22sub mark_lib 23{ 24} 25 26sub unmark_lib 27{ 28} 29 30sub separate_element 31{ 32 my ($self, $libs, $c1, $c2) = @_; 33 $c2->{$self} = 1; 34} 35 36sub special_deep_copy 37{ 38 my ($self, $copy, $h) = @_; 39 $self->clone->add_object($copy) if defined $h->{$self}; 40} 41 42package OpenBSD::PackingElement::Meta; 43 44sub separate_element 45{ 46 my ($self, $libs, $c1, $c2) = @_; 47 $c1->{$self} = 1; 48 $c2->{$self} = 1; 49} 50 51package OpenBSD::PackingElement::DigitalSignature; 52sub separate_element 53{ 54 my ($self, $libs, $c1, $c2) = @_; 55 $c2->{$self} = 1; 56} 57 58package OpenBSD::PackingElement::State; 59 60sub separate_element 61{ 62 &OpenBSD::PackingElement::Meta::separate_element; 63} 64 65package OpenBSD::PackingElement::Depend; 66sub separate_element 67{ 68 &OpenBSD::PackingElement::separate_element; 69} 70 71package OpenBSD::PackingElement::SpecialFile; 72sub separate_element 73{ 74 &OpenBSD::PackingElement::separate_element; 75} 76 77package OpenBSD::PackingElement::FCONTENTS; 78sub special_deep_copy 79{ 80} 81 82package OpenBSD::PackingElement::Lib; 83use File::Basename; 84 85sub mark_lib 86{ 87 my ($self, $libs, $libpatterns) = @_; 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 97{ 98 my ($self, $libs, $c1, $c2) = @_; 99 if ($libs->{$self->fullname}) { 100 $c1->{$self} = 1; 101 } else { 102 $c2->{$self} = 1; 103 } 104} 105 106sub unmark_lib 107{ 108 my ($self, $libs, $libpatterns) = @_; 109 my $libname = $self->fullname; 110 my ($stem, $major, $minor, $dir) = $self->parse($libname); 111 if (defined $stem) { 112 my $p = $libpatterns->{$stem}->{$dir}; 113 if (defined $p && $p->[0] == $major && $p->[1] <= $minor) { 114 my $n = $p->[2]; 115 delete $libs->{$n}; 116 } 117 } 118 delete $libs->{$libname}; 119} 120 121sub enforce_dir 122{ 123 my ($self, $path, $copy, $dirs) = @_; 124 my $d = dirname($path); 125 my $localbase = $copy->localbase; 126 127 if ($d eq "$localbase/lib" || $d eq $localbase || $d eq '/') { 128 return; 129 } 130 if ($dirs->{$d}) { 131 return; 132 } 133 $dirs->{$d} = 1; 134 $self->enforce_dir($d, $copy, $dirs); 135 my $cwd = $self->cwd; 136 $d =~ s/^\Q$cwd\E\///; 137 OpenBSD::PackingElement::Dir->add($copy, $d); 138} 139 140sub special_deep_copy 141{ 142 my ($self, $copy, $h, $dirs) = @_; 143 $self->enforce_dir($self->fullname, $copy, $dirs); 144 $self->SUPER::special_deep_copy($copy, $h, $dirs); 145} 146 147package OpenBSD::OldLibs; 148use OpenBSD::RequiredBy; 149use OpenBSD::PackageInfo; 150 151sub split_some_libs 152{ 153 my ($plist, $libs) = @_; 154 my $c1 = {}; 155 my $c2 = {}; 156 $plist->separate_element($libs, $c1, $c2); 157 my $p1 = OpenBSD::PackingList::OldLibs->new; 158 $p1->set_infodir($plist->infodir); 159 $plist->special_deep_copy($p1, $c1, {}); 160 my $p2 = $plist->make_shallow_copy($c2); 161 return ($p1, $p2); 162} 163 164# create a packing-list with only the libraries we want to keep around. 165sub split_libs 166{ 167 my ($plist, $to_split) = @_; 168 169 (my $splitted, $plist) = split_some_libs($plist, $to_split); 170 171 require OpenBSD::PackageInfo; 172 173 $splitted->set_pkgname(OpenBSD::PackageInfo::libs_package($plist->pkgname)); 174 175 if (defined $plist->{'no-default-conflict'}) { 176 # we conflict with the package we just removed... 177 OpenBSD::PackingElement::Conflict->add($splitted, $plist->pkgname); 178 } else { 179 my $stem = OpenBSD::PackageName::splitstem($plist->pkgname); 180 OpenBSD::PackingElement::Conflict->add($splitted, $stem."-*"); 181 } 182 return ($plist, $splitted); 183} 184 185sub adjust_depends_closure 186{ 187 my ($oldname, $plist, $state) = @_; 188 189 $state->say("Packages that depend on those shared libraries:") 190 if $state->verbose >= 3; 191 192 my $write = OpenBSD::RequiredBy->new($plist->pkgname); 193 for my $pkg (OpenBSD::RequiredBy->compute_closure($oldname)) { 194 $state->say("\t#1", $pkg) if $state->verbose >= 3; 195 $write->add($pkg); 196 my $r = OpenBSD::Requiring->new($pkg)->add($plist->pkgname); 197 if ($oldname =~ m/^\.libs\d*\-/o) { 198 $r->delete($oldname); 199 } 200 } 201} 202 203sub do_save_libs 204{ 205 my ($o, $libs, $state) = @_; 206 207 my $oldname = $o->pkgname; 208 209 ($o->{plist}, my $stub_list) = split_libs($o->plist, $libs); 210 my $stub_name = $stub_list->pkgname; 211 my $dest = installed_info($stub_name); 212 $state->say("Keeping them in #1", $stub_name) 213 if $state->verbose >= 2; 214 215 216 if ($state->{not}) { 217 require OpenBSD::SharedLibs; 218 219 OpenBSD::SharedLibs::add_libs_from_plist($stub_list, $state); 220 $stub_list->to_cache; 221 $o->plist->to_cache; 222 } else { 223 mkdir($dest); 224 open my $descr, '>', $dest.DESC; 225 print $descr "Stub libraries for $oldname\n"; 226 close $descr; 227 my $f = OpenBSD::PackingElement::FDESC->add($stub_list, DESC); 228 $f->{ignore} = 1; 229 $f->add_digest($f->compute_digest($dest.DESC)); 230 $stub_list->to_installation; 231 $o->plist->to_installation; 232 } 233 add_installed($stub_name); 234 235 OpenBSD::PkgCfl::register($stub_list, $state); 236 237 adjust_depends_closure($oldname, $stub_list, $state); 238} 239 240sub save_libs_from_handle 241{ 242 my ($o, $set, $state) = @_; 243 244 my $libs = {}; 245 my $p = {}; 246 247 $state->say("Looking for changes in shared libraries") 248 if $state->verbose >= 2; 249 $o->plist->mark_lib($libs, $p); 250 for my $n ($set->newer) { 251 $n->plist->unmark_lib($libs, $p); 252 } 253 for my $n ($set->kept) { 254 $n->plist->unmark_lib($libs, $p); 255 } 256 257 if (%$libs) { 258 $state->say("Libraries to keep: #1", 259 join(",", sort(keys %$libs))) if $state->verbose >= 2; 260 do_save_libs($o, $libs, $state); 261 } else { 262 $state->say("No libraries to keep") if $state->verbose >= 2; 263 } 264} 265 266sub save 267{ 268 my ($self, $set, $state) = @_; 269 270 for my $o ($set->older) { 271 save_libs_from_handle($o, $set, $state); 272 } 273} 274 2751; 276