xref: /openbsd/usr.sbin/pkg_add/OpenBSD/OldLibs.pm (revision 039cbdaa)
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