1# ex:ts=8 sw=4:
2# $OpenBSD: SharedItems.pm,v 1.34 2023/06/13 09:07:17 espie Exp $
3#
4# Copyright (c) 2004-2006 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# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18use v5.36;
19
20package OpenBSD::SharedItems;
21
22use OpenBSD::Error;
23use OpenBSD::PackageInfo;
24use OpenBSD::PackingList;
25use OpenBSD::Paths;
26
27sub find_items_in_installed_packages($state)
28{
29	my $db = OpenBSD::SharedItemsRecorder->new;
30	$state->status->what("Read")->object("shared items");
31	$state->progress->for_list("Read shared items", [installed_packages()],
32	    sub($e) {
33		my $plist = OpenBSD::PackingList->from_installation($e,
34		    \&OpenBSD::PackingList::SharedItemsOnly) or return;
35		return if !defined $plist;
36		$plist->record_shared($db, $e);
37	    });
38	return $db;
39}
40
41sub check_shared($set, $o)
42{
43	if (!defined $set->{db}) {
44		$set->{db} = OpenBSD::SharedItemsRecorder->new;
45		for my $pkg (installed_packages()) {
46			next if $set->{older}{$pkg};
47			my $plist = OpenBSD::PackingList->from_installation($pkg,
48			    \&OpenBSD::PackingList::SharedItemsOnly) or next;
49			next if !defined $plist;
50			$plist->record_shared($set->{db}, $pkg);
51		}
52	}
53	if (defined $set->{db}{dirs}{$o->fullname}) {
54		return 1;
55	} else {
56		push(@{$set->{old_shared}{$o->fullname}}, $o);
57		return 0;
58	}
59}
60
61sub wipe_directory($state, $h, $d)
62{
63	my $realname = $state->{destdir}.$d;
64
65	for my $i (@{$h->{$d}}) {
66		$i->cleanup($state);
67	}
68	if (!rmdir $realname) {
69		$state->log("Error deleting directory #1: #2",
70		    $realname, $!)
71			unless $state->{dirs_okay}{$d};
72		return 0;
73	}
74	return 1;
75}
76
77sub cleanup($recorder, $state)
78{
79	my $remaining = find_items_in_installed_packages($state);
80
81	$state->progress->clear;
82	$state->status->what("Clean");
83	$state->progress->set_header("Clean shared items");
84	my $h = $recorder->{dirs};
85	my $u = $recorder->{users};
86	my $g = $recorder->{groups};
87	my $total = 0;
88	$total += keys %$h if defined $h;
89	$total += keys %$u if defined $u;
90	$total += keys %$g if defined $g;
91	my $done = 0;
92
93	for my $d (sort {$b cmp $a} keys %$h) {
94		$state->progress->show($done, $total);
95		if (defined $remaining->{dirs}{$d}) {
96			for my $i (@{$h->{$d}}) {
97				$state->log->set_context('-'.$i->{pkgname});
98				$i->reload($state);
99			}
100		} else {
101			wipe_directory($state, $h, $d);
102		}
103		$done++;
104	}
105	while (my ($user, $pkgname) = each %$u) {
106		$state->progress->show($done, $total);
107		next if $remaining->{users}{$user};
108		if ($state->{extra}) {
109			$state->system(OpenBSD::Paths->userdel, '--',
110			    $user);
111		} else {
112			$state->log->set_context('-'.$pkgname);
113			$state->log("You should also run /usr/sbin/userdel #1", $user);
114		}
115		$done++;
116	}
117	while (my ($group, $pkgname) = each %$g) {
118		$state->progress->show($done, $total);
119		next if $remaining->{groups}{$group};
120		if ($state->{extra}) {
121			$state->system(OpenBSD::Paths->groupdel, '--',
122			    $group);
123		} else {
124			$state->log->set_context('-'.$pkgname);
125			$state->log("You should also run /usr/sbin/groupdel #1", $group);
126		}
127		$done++;
128	}
129	if ($state->verbose >= 2) {
130		$state->progress->next;
131	} else {
132		$state->progress->clear;
133	}
134}
135
136package OpenBSD::PackingElement;
137sub cleanup($, $)
138{
139}
140
141sub reload($, $)
142{
143}
144
145package OpenBSD::PackingElement::Mandir;
146sub cleanup($self, $state)
147{
148	my $fullname = $state->{destdir}.$self->fullname;
149	$state->log->set_context('-'.$self->{pkgname});
150	$state->log("You may wish to remove #1 from man.conf", $fullname);
151	for my $f (OpenBSD::Paths->man_cruft) {
152		unlink("$fullname/$f");
153	}
154}
155
156package OpenBSD::PackingElement::Fontdir;
157sub cleanup($self, $state)
158{
159	my $fullname = $state->{destdir}.$self->fullname;
160	$state->log->set_context('-'.$self->{pkgname});
161	$state->log("You may wish to remove #1 from your font path", $fullname);
162	for my $f (OpenBSD::Paths->font_cruft) {
163		unlink("$fullname/$f");
164	}
165}
166
167package OpenBSD::PackingElement::Infodir;
168sub cleanup($self, $state)
169{
170	my $fullname = $state->{destdir}.$self->fullname;
171	for my $f (OpenBSD::Paths->info_cruft) {
172		unlink("$fullname/$f");
173	}
174}
175
1761;
177