1# ex:ts=8 sw=4: 2# $OpenBSD: Installed.pm,v 1.46 2023/06/13 09:07:18 espie Exp $ 3# 4# Copyright (c) 2007-2014 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 20# XXX: we want to be able to load PackageRepository::Installed stand-alone, 21# so we put the only common method into PackageRepositoryBase. 22# 23# later, when we load the base PackageRepository, we tweak the inheritance 24# of PackageRepository::Installed to have full access... 25 26package OpenBSD::PackageRepositoryBase; 27 28my ($version, $current); 29 30sub is_local_file($) 31{ 32 return 0; 33} 34 35sub expand_locations($class, $string, $state) 36{ 37 require OpenBSD::Paths; 38 if ($string eq '%a') { 39 return OpenBSD::Paths->machine_architecture; 40 } elsif ($string eq '%v') { 41 return OpenBSD::Paths->os_version; 42 } elsif ($string eq '%m') { 43 return join('/', 44 'pub/OpenBSD', 45 '%c', 46 'packages', 47 OpenBSD::Paths->machine_architecture); 48 } 49} 50 51sub get_cached_info($repository, $name) 52{ 53 if (defined $repository->{info_cache}) { 54 return $repository->{info_cache}->get_cached_info($name); 55 } else { 56 return undef; 57 } 58} 59 60sub setup_cache($repo, $setlist) 61{ 62 my $state = $repo->{state}; 63 return if $state->defines("NO_CACHING"); 64 65 require OpenBSD::PackageRepository::Cache; 66 67 $repo->{info_cache} = 68 OpenBSD::PackageRepository::Cache->new($state, $setlist); 69 # if we're on package-stable, assume this new quirks also works 70 # with the corresponding release 71 if (defined $repo->{release}) { 72 my $url = $repo->urlscheme."://$repo->{host}$repo->{release}"; 73 my $r2 = OpenBSD::PackageRepository->parse(\$url, $state); 74 $r2->{info_cache} = $repo->{info_cache}; 75 } 76} 77 78sub parse_url($class, $r, $state) 79{ 80 my $path; 81 82 if ($$r =~ m/^(.*?)\:(.*)/) { 83 $path = $1; 84 $$r = $2; 85 } else { 86 $path = $$r; 87 $$r = ''; 88 } 89 90 $path =~ s/\%[vam]\b/$class->expand_locations($&, $state)/ge; 91 # make %c magical: if we're on a release, we expand into 92 # stable, and leave the release dir for the full object with 93 # host to push back 94 my $release; 95 if ($path =~ m/\%c\b/) { 96 my $d = $state->defines('snap') ? 97 'snapshots' : OpenBSD::Paths->os_directory; 98 if ($d ne 'snapshots' && $path =~ m,\%c/packages/,) { 99 $release = $path; 100 $release =~ s,\%c\b,$d,; 101 $path =~ s,\%c/packages/,$d/packages-stable/,; 102 } else { 103 $path =~ s,\%c\b,$d,; 104 } 105 } 106 $path .= '/' unless $path =~ m/\/$/; 107 bless { path => $path, release => $release, state => $state }, $class; 108} 109 110sub parse_fullurl($class, $r, $state) 111{ 112 $class->strip_urlscheme($r) or return undef; 113 return $class->parse_url($r, $state); 114} 115 116sub strip_urlscheme($class, $r) 117{ 118 if ($$r =~ m/^(.*?)\:(.*)$/) { 119 my $scheme = lc($1); 120 if ($scheme eq $class->urlscheme) { 121 $$r = $2; 122 return 1; 123 } 124 } 125 return 0; 126} 127 128sub match_locations($self, $search, @filters) 129{ 130 my $l = $search->match_locations($self); 131 while (my $filter = (shift @filters)) { 132 last if @$l == 0; # don't bother filtering empty list 133 $l = $filter->filter_locations($l); 134 } 135 return $l; 136} 137 138sub url($self, $name = undef) 139{ 140 return $self->urlscheme.':'.$self->relative_url($name); 141} 142 143sub finish_and_close($self, $object) 144{ 145 $self->close($object); 146} 147 148sub close_now($self, $object) 149{ 150 $self->close($object, 0); 151} 152 153sub close_after_error($self, $object) 154{ 155 $self->close($object, 1); 156} 157 158sub close_with_client_error($self, $object) 159{ 160 $self->close($object, 1); 161} 162 163sub canonicalize($self, $name) 164{ 165 if (defined $name) { 166 $name =~ s/\.tgz$//o; 167 } 168 return $name; 169} 170 171sub new_location($self, @args) 172{ 173 return $self->locationClassName->new($self, @args); 174} 175 176sub locationClassName($) 177{ "OpenBSD::PackageLocation" } 178 179sub locations_list($self) 180{ 181 if (!defined $self->{locations}) { 182 my $l = []; 183 require OpenBSD::PackageLocation; 184 185 for my $name (@{$self->list}) { 186 push @$l, $self->new_location($name); 187 } 188 $self->{locations} = $l; 189 } 190 return $self->{locations}; 191} 192 193sub reinitialize($) 194{ 195} 196 197sub decorate($self, $plist, $location) 198{ 199 unless ($plist->has('url')) { 200 OpenBSD::PackingElement::Url->add($plist, $location->url); 201 } 202 unless ($plist->has('signer')) { 203 if (exists $location->{signer}) { 204 OpenBSD::PackingElement::Signer->add($plist, 205 $location->{signer}); 206 } 207 } 208 unless ($plist->has('digital-signature')) { 209 if (exists $location->{signdate}) { 210 OpenBSD::PackingElement::DigitalSignature->add($plist, 211 join(':', 'signify2', $location->{signdate}, 212 'external')); 213 } 214 } 215} 216 217package OpenBSD::PackageRepository::Installed; 218 219our @ISA = (qw(OpenBSD::PackageRepositoryBase)); 220 221sub urlscheme($) 222{ 223 return 'inst'; 224} 225 226use OpenBSD::PackageInfo (qw(is_installed installed_info 227 installed_packages installed_stems installed_name)); 228 229sub new($class, $all, $state) 230{ 231 return bless { all => $all, state => $state }, $class; 232} 233 234sub relative_url($self, $name = '') 235{ 236 $name or ''; 237} 238 239sub close($, $, $ = undef) 240{ 241} 242 243sub make_error_file($, $) 244{ 245} 246 247sub canonicalize($self, $name) 248{ 249 return installed_name($name); 250} 251 252sub find($repository, $name) 253{ 254 my $self; 255 256 if (is_installed($name)) { 257 require OpenBSD::PackageLocation; 258 259 $self = $repository->new_location($name); 260 $self->{dir} = installed_info($name); 261 } 262 return $self; 263} 264 265sub locationClassName($) 266{ "OpenBSD::PackageLocation::Installed" } 267 268# XXX we pass a variable number of params because we 269# don't know about the default value for code 270sub grabPlist($repository, $name, $arch, @code) 271{ 272 require OpenBSD::PackingList; 273 return OpenBSD::PackingList->from_installation($name, @code) 274} 275 276sub available($self) 277{ 278 return installed_packages($self->{all}); 279} 280 281sub list($self) 282{ 283 my @list = installed_packages($self->{all}); 284 return \@list; 285} 286 287sub stemlist($) 288{ 289 return installed_stems(); 290} 291 292sub wipe_info($, $) 293{ 294} 295 296sub may_exist($self, $name) 297{ 298 return is_installed($name); 299} 300 3011; 302