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