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