1# ex:ts=8 sw=4: 2# $OpenBSD: Handle.pm,v 1.44 2023/06/13 09:07:17 espie Exp $ 3# 4# Copyright (c) 2007-2009 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 18# fairly non-descriptive name. Used to store various package information 19# during installs and updates. 20 21use v5.36; 22 23package OpenBSD::Handle; 24 25use OpenBSD::PackageInfo; 26use OpenBSD::Error; 27 28use constant { 29 BAD_PACKAGE => 1, 30 CANT_INSTALL => 2, 31 ALREADY_INSTALLED => 3, 32 NOT_FOUND => 4, 33 CANT_DELETE => 5, 34}; 35 36sub is_real($) { return 1; } 37 38sub cleanup($self, $error = undef, $errorinfo = undef) 39{ 40 if (defined $error) { 41 $self->{error} //= $error; 42 $self->{errorinfo} //= $errorinfo; 43 } 44 if (defined $self->location) { 45 if (defined $self->{error} && $self->{error} == BAD_PACKAGE) { 46 $self->location->close_with_client_error; 47 } else { 48 $self->location->close_now; 49 } 50 $self->location->wipe_info; 51 } 52 delete $self->{plist}; 53 delete $self->{db}; 54 delete $self->{conflict_list}; 55} 56 57sub new($class) 58{ 59 return bless {}, $class; 60} 61 62sub system($class) 63{ 64 return OpenBSD::Handle::BaseSystem->new; 65} 66 67sub pkgname($self) 68{ 69 if (!defined $self->{pkgname}) { 70 if (defined $self->{plist}) { 71 $self->{pkgname} = $self->{plist}->pkgname; 72 } elsif (defined $self->{location}) { 73 $self->{pkgname} = $self->{location}->name; 74 } elsif (defined $self->{name}) { 75 require OpenBSD::PackageName; 76 77 $self->{pkgname} = 78 OpenBSD::PackageName::url2pkgname($self->{name}); 79 } 80 } 81 82 return $self->{pkgname}; 83} 84 85sub location($self) 86{ 87 return $self->{location}; 88} 89 90sub plist($self) 91{ 92 return $self->{plist}; 93} 94 95sub dependency_info($self) 96{ 97 if (defined $self->{plist}) { 98 return $self->{plist}; 99 } elsif (defined $self->{location} && 100 defined $self->{location}{update_info}) { 101 return $self->{location}{update_info}; 102 } else { 103 return undef; 104 } 105} 106 107OpenBSD::Auto::cache(conflict_list, 108 sub($self) { 109 require OpenBSD::PkgCfl; 110 return OpenBSD::PkgCfl->make_conflict_list($self->dependency_info); 111 }); 112 113sub set_error($self, $error) 114{ 115 $self->{error} = $error; 116} 117 118sub has_error($self, $error = undef) 119{ 120 if (!defined $self->{error}) { 121 return undef; 122 } 123 if (defined $error) { 124 return $self->{error} eq $error; 125 } 126 return $self->{error}; 127} 128 129sub has_reported_error($self) 130{ 131 return $self->{error_reported}; 132} 133 134sub error_message($self) 135{ 136 my $error = $self->{error}; 137 if ($error == BAD_PACKAGE) { 138 return "bad package"; 139 } elsif ($error == CANT_INSTALL) { 140 if ($self->{errorinfo}) { 141 return "$self->{errorinfo}"; 142 } else { 143 return "can't install"; 144 } 145 } elsif ($error == NOT_FOUND) { 146 return "not found"; 147 } elsif ($error == ALREADY_INSTALLED) { 148 return "already installed"; 149 } else { 150 return "no error"; 151 } 152} 153 154sub complete_old($self) 155{ 156 my $location = $self->{location}; 157 158 if (!defined $location) { 159 $self->set_error(NOT_FOUND); 160 } else { 161 my $plist = $location->plist; 162 if (!defined $plist) { 163 $self->set_error(BAD_PACKAGE); 164 } else { 165 $self->{plist} = $plist; 166 delete $location->{contents}; 167 delete $location->{update_info}; 168 } 169 } 170} 171 172sub complete_dependency_info($self) 173{ 174 my $location = $self->{location}; 175 176 if (!defined $location) { 177 $self->set_error(NOT_FOUND); 178 } else { 179 if (!defined $self->{plist}) { 180 # trigger build 181 $location->update_info; 182 } 183 } 184} 185 186sub create_old($class, $pkgname, $state) 187{ 188 my $self= $class->new; 189 $self->{name} = $pkgname; 190 191 my $location = $state->repo->installed->find($pkgname); 192 if (defined $location) { 193 $self->{location} = $location; 194 } 195 $self->complete_dependency_info; 196 197 return $self; 198} 199 200sub create_new($class, $pkg) 201{ 202 my $handle = $class->new; 203 $handle->{name} = $pkg; 204 $handle->{tweaked} = 0; 205 return $handle; 206} 207 208sub from_location($class, $location) 209{ 210 my $handle = $class->new; 211 $handle->{location} = $location; 212 $handle->{tweaked} = 0; 213 return $handle; 214} 215 216sub get_plist($handle, $state) 217{ 218 my $location = $handle->{location}; 219 my $pkg = $handle->pkgname; 220 221 if ($state->verbose >= 2) { 222 $state->say("#1parsing #2", $state->deptree_header($pkg), $pkg); 223 } 224 my $plist = $location->plist; 225 unless (defined $plist) { 226 $state->say("Can't find CONTENTS from #1", $location->url) 227 unless $location->{error_reported}; 228 $location->close_with_client_error; 229 $location->wipe_info; 230 $handle->set_error(BAD_PACKAGE); 231 $handle->{error_reported} = 1; 232 return; 233 } 234 delete $location->{update_info}; 235 $location->decorate($plist); 236 if ($plist->localbase ne $state->{localbase}) { 237 $state->say("Localbase mismatch: package has: #1, user wants: #2", 238 $plist->localbase, $state->{localbase}); 239 $location->close_with_client_error; 240 $location->wipe_info; 241 $handle->set_error(BAD_PACKAGE); 242 return; 243 } 244 my $pkgname = $handle->{pkgname} = $plist->pkgname; 245 246 if ($pkg ne '-') { 247 if (!defined $pkgname or $pkg ne $pkgname) { 248 $state->say("Package name is not consistent ???"); 249 $location->close_with_client_error; 250 $location->wipe_info; 251 $handle->set_error(BAD_PACKAGE); 252 return; 253 } 254 } 255 $handle->{plist} = $plist; 256} 257 258sub get_location($handle, $state) 259{ 260 my $name = $handle->{name}; 261 262 my $location = $state->repo->find($name); 263 if (!$location) { 264 $state->print("#1", $state->deptree_header($name)); 265 $handle->set_error(NOT_FOUND); 266 $handle->{tweaked} = 267 OpenBSD::Add::tweak_package_status($handle->pkgname, 268 $state); 269 if (!$handle->{tweaked}) { 270 $state->say("Can't find #1", $name); 271 $handle->{error_reported} = 1; 272 eval { 273 my $r = [$name]; 274 $state->quirks->filter_obsolete($r, $state); 275 } 276 } 277 return; 278 } 279 $handle->{location} = $location; 280 $handle->{pkgname} = $location->name; 281} 282 283sub complete($handle, $state) 284{ 285 return if $handle->has_error; 286 287 if (!defined $handle->{location}) { 288 $handle->get_location($state); 289 } 290 return if $handle->has_error; 291 if (!defined $handle->{plist}) { 292 $handle->get_plist($state); 293 } 294} 295 296package OpenBSD::Handle::BaseSystem; 297our @ISA = qw(OpenBSD::Handle); 298sub pkgname($) { return "BaseSystem"; } 299 300sub is_real($) { return 0; } 301 3021; 303