1# ex:ts=8 sw=4: 2# $OpenBSD: Add.pm,v 1.172 2016/08/27 18:17:46 espie Exp $ 3# 4# Copyright (c) 2003-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 strict; 19use warnings; 20 21package OpenBSD::Add; 22use OpenBSD::Error; 23use OpenBSD::PackageInfo; 24use OpenBSD::ArcCheck; 25use OpenBSD::Paths; 26use File::Copy; 27 28sub manpages_index 29{ 30 my ($state) = @_; 31 return unless defined $state->{addman}; 32 my $destdir = $state->{destdir}; 33 34 # fudge verbose for API differences 35 while (my ($k, $v) = each %{$state->{addman}}) { 36 my @l = map { "$destdir$k/$_" } @$v; 37 if ($state->{not}) { 38 $state->say("Merging manpages in #1: #2", 39 $destdir.$k, join(' ', @l)) if $state->verbose; 40 } else { 41 $state->run_makewhatis(['-d', $destdir.$k], \@l); 42 } 43 } 44 delete $state->{addman}; 45} 46 47sub register_installation 48{ 49 my ($plist, $state) = @_; 50 if ($state->{not}) { 51 $plist->to_cache; 52 } else { 53 my $dest = installed_info($plist->pkgname); 54 mkdir($dest); 55 $plist->copy_info($dest, $state); 56 $plist->set_infodir($dest); 57 $plist->to_installation; 58 } 59} 60 61sub validate_plist 62{ 63 my ($plist, $state, $set) = @_; 64 65 $plist->prepare_for_addition($state, $plist->pkgname, $set); 66} 67 68sub record_partial_installation 69{ 70 my ($plist, $state, $h) = @_; 71 72 use OpenBSD::PackingElement; 73 74 my $n = $plist->make_shallow_copy($h); 75 my $borked = borked_package($plist->pkgname); 76 $n->set_pkgname($borked); 77 78 # last file may have not copied correctly 79 my $last = $n->{state}->{lastfile}; 80 if (defined $last && defined($last->{d})) { 81 82 my $old = $last->{d}; 83 my $lastname = $last->realname($state); 84 if (-f $lastname) { 85 $last->{d} = $last->compute_digest($lastname, $old); 86 if (!$old->equals($last->{d})) { 87 $state->say("Adjusting #1 for #2 from #3 to #4", 88 $old->keyword, $lastname, $old->stringize, 89 $last->{d}->stringize); 90 } 91 } else { 92 delete $last->{d}; 93 } 94 } 95 register_installation($n, $state); 96 return $borked; 97} 98 99sub perform_installation 100{ 101 my ($handle, $state) = @_; 102 103 $state->{partial} = $handle->{partial}; 104 $state->progress->visit_with_size($handle->{plist}, 'install'); 105 if ($handle->{location}{early_close}) { 106 $handle->{location}->close_now; 107 } else { 108 $handle->{location}->finish_and_close; 109 } 110} 111 112sub perform_extraction 113{ 114 my ($handle, $state) = @_; 115 116 $handle->{partial} = {}; 117 $state->{partial} = $handle->{partial}; 118 $state->{archive} = $handle->{location}; 119 $state->{check_digest} = $handle->{plist}{check_digest}; 120 my ($wanted, $tied) = ({}, {}); 121 $handle->{plist}->find_extractible($state, $wanted, $tied); 122 my $p = $state->progress->new_sizer($handle->{plist}, $state); 123 while (my $file = $state->{archive}->next) { 124 if (keys %$wanted == 0) { 125 for my $e (values %$tied) { 126 $e->tie($state); 127 } 128 if (keys %$tied > 0) { 129 $handle->{location}{early_close} = 1; 130 } 131 last; 132 } 133 my $e = $tied->{$file->name}; 134 if (defined $e) { 135 delete $tied->{$file->name}; 136 $e->prepare_to_extract($state, $file); 137 $e->tie($state); 138 $state->{archive}->skip; 139 $p->advance($e); 140 # skip to next; 141 next; 142 } 143 $e = $wanted->{$file->name}; 144 if (!defined $e) { 145 $state->fatal("archive member not found #1", 146 $file->name); 147 } 148 delete $wanted->{$file->name}; 149 $e->prepare_to_extract($state, $file); 150 $e->extract($state, $file); 151 $p->advance($e); 152 } 153 if (keys %$wanted > 0) { 154 $state->fatal("Truncated archive"); 155 } 156 $p->saved; 157} 158 159my $user_tagged = {}; 160 161sub extract_pkgname 162{ 163 my $pkgname = shift; 164 $pkgname =~ s/^.*\///; 165 $pkgname =~ s/\.tgz$//; 166 return $pkgname; 167} 168 169sub tweak_package_status 170{ 171 my ($pkgname, $state) = @_; 172 173 $pkgname = extract_pkgname($pkgname); 174 return 0 unless is_installed($pkgname); 175 return 0 unless $user_tagged->{$pkgname}; 176 return 1 if $state->{not}; 177 my $plist = OpenBSD::PackingList->from_installation($pkgname); 178 if ($plist->has('manual-installation') && $state->{automatic} > 1) { 179 delete $plist->{'manual-installation'}; 180 $plist->to_installation; 181 return 1; 182 } elsif (!$plist->has('manual-installation') && !$state->{automatic}) { 183 OpenBSD::PackingElement::ManualInstallation->add($plist); 184 $plist->to_installation; 185 return 1; 186 } 187 return 0; 188} 189 190sub tweak_plist_status 191{ 192 my ($plist, $state) = @_; 193 194 my $pkgname = $plist->pkgname; 195 if ($state->defines('FW_UPDATE')) { 196 $plist->has('firmware') or 197 OpenBSD::PackingElement::Firmware->add($plist); 198 } 199 return 0 unless $user_tagged->{$pkgname}; 200 if (!$plist->has('manual-installation') && !$state->{automatic}) { 201 OpenBSD::PackingElement::ManualInstallation->add($plist); 202 } 203} 204 205sub tag_user_packages 206{ 207 for my $set (@_) { 208 for my $n ($set->newer_names) { 209 $user_tagged->{OpenBSD::PackageName::url2pkgname($n)} = 1; 210 } 211 } 212} 213 214# used by newuser/newgroup to deal with options. 215package OpenBSD::PackingElement; 216use OpenBSD::Error; 217 218my ($uidcache, $gidcache); 219 220sub prepare_for_addition 221{ 222} 223 224sub find_extractible 225{ 226} 227 228sub extract 229{ 230 my ($self, $state) = @_; 231 $state->{partial}{$self} = 1; 232 if ($state->{interrupted}) { 233 die "Interrupted"; 234 } 235} 236 237sub install 238{ 239 my ($self, $state) = @_; 240 # XXX "normal" items are already in partial, but NOT stuff 241 # that's install-only, like symlinks and dirs... 242 $state->{partial}{$self} = 1; 243 if ($state->{interrupted}) { 244 die "Interrupted"; 245 } 246} 247 248sub copy_info 249{ 250} 251 252sub set_modes 253{ 254 my ($self, $state, $name) = @_; 255 256 if (defined $self->{owner} || defined $self->{group}) { 257 require OpenBSD::IdCache; 258 259 if (!defined $uidcache) { 260 $uidcache = OpenBSD::UidCache->new; 261 $gidcache = OpenBSD::GidCache->new; 262 } 263 my ($uid, $gid) = (-1, -1); 264 if (defined $self->{owner}) { 265 $uid = $uidcache->lookup($self->{owner}, $uid); 266 } 267 if (defined $self->{group}) { 268 $gid = $gidcache->lookup($self->{group}, $gid); 269 } 270 chown $uid, $gid, $name; 271 } 272 if (defined $self->{mode}) { 273 my $v = $self->{mode}; 274 if ($v =~ m/^\d+$/o) { 275 chmod oct($v), $name; 276 } else { 277 $state->system(OpenBSD::Paths->chmod, 278 $self->{mode}, $name); 279 } 280 } 281 if (defined $self->{ts}) { 282 utime $self->{ts}, $self->{ts}, $name; 283 } 284} 285 286package OpenBSD::PackingElement::Meta; 287 288# XXX stuff that's invisible to find_extractible should be considered extracted 289# for the most part, otherwise we create broken partial packages 290sub find_extractible 291{ 292 my ($self, $state, $wanted, $tied) = @_; 293 $state->{partial}{$self} = 1; 294} 295 296package OpenBSD::PackingElement::ExtraInfo; 297use OpenBSD::Error; 298 299sub prepare_for_addition 300{ 301 my ($self, $state, $pkgname) = @_; 302 303 if ($state->{cdrom_only} && $self->{cdrom} ne 'yes') { 304 $state->errsay("Package #1 is not for cdrom", $pkgname); 305 $state->{problems}++; 306 } 307 if ($state->{ftp_only} && $self->{ftp} ne 'yes') { 308 $state->errsay("Package #1 is not for ftp", $pkgname); 309 $state->{problems}++; 310 } 311} 312 313package OpenBSD::PackingElement::NewAuth; 314use OpenBSD::Error; 315 316sub add_entry 317{ 318 shift; # get rid of self 319 my $l = shift; 320 while (@_ >= 2) { 321 my $f = shift; 322 my $v = shift; 323 next if !defined $v or $v eq ''; 324 if ($v =~ m/^\!(.*)$/o) { 325 push(@$l, $f, $1); 326 } else { 327 push(@$l, $f, $v); 328 } 329 } 330} 331 332sub prepare_for_addition 333{ 334 my ($self, $state, $pkgname) = @_; 335 my $ok = $self->check; 336 if (defined $ok) { 337 if ($ok == 0) { 338 $state->errsay("#1 #2 does not match", 339 $self->type, $self->name); 340 $state->{problems}++; 341 } 342 } 343 $self->{okay} = $ok; 344} 345 346sub install 347{ 348 my ($self, $state) = @_; 349 $self->SUPER::install($state); 350 my $auth = $self->name; 351 $state->say("adding #1 #2", $self->type, $auth) if $state->verbose >= 2; 352 return if $state->{not}; 353 return if defined $self->{okay}; 354 my $l=[]; 355 push(@$l, "-v") if $state->verbose >= 2; 356 $self->build_args($l); 357 $state->vsystem($self->command,, @$l, '--', $auth); 358} 359 360package OpenBSD::PackingElement::NewUser; 361 362sub command { OpenBSD::Paths->useradd } 363 364sub build_args 365{ 366 my ($self, $l) = @_; 367 368 $self->add_entry($l, 369 '-u', $self->{uid}, 370 '-g', $self->{group}, 371 '-L', $self->{class}, 372 '-c', $self->{comment}, 373 '-d', $self->{home}, 374 '-s', $self->{shell}); 375} 376 377package OpenBSD::PackingElement::NewGroup; 378 379sub command { OpenBSD::Paths->groupadd } 380 381sub build_args 382{ 383 my ($self, $l) = @_; 384 385 $self->add_entry($l, '-g', $self->{gid}); 386} 387 388package OpenBSD::PackingElement::Sysctl; 389use OpenBSD::Error; 390 391sub install 392{ 393 my ($self, $state) = @_; 394 395 my $name = $self->name; 396 $self->SUPER::install($state); 397 open(my $pipe, '-|', OpenBSD::Paths->sysctl, '-n', '--', $name); 398 my $actual = <$pipe>; 399 chomp $actual; 400 if ($self->{mode} eq '=' && $actual eq $self->{value}) { 401 return; 402 } 403 if ($self->{mode} eq '>=' && $actual >= $self->{value}) { 404 return; 405 } 406 if ($state->{not}) { 407 $state->say("sysctl -w #1 =! #2", 408 $name, $self->{value}) if $state->verbose >= 2; 409 return; 410 } 411 $state->vsystem(OpenBSD::Paths->sysctl, '--', $name.'='.$self->{value}); 412} 413 414package OpenBSD::PackingElement::FileBase; 415use OpenBSD::Error; 416use File::Basename; 417use File::Path; 418use OpenBSD::Temp; 419 420sub find_extractible 421{ 422 my ($self, $state, $wanted, $tied) = @_; 423 if ($self->{tieto} || $self->{link} || $self->{symlink}) { 424 $tied->{$self->name} = $self; 425 } else { 426 $wanted->{$self->name} = $self; 427 } 428} 429 430sub prepare_for_addition 431{ 432 my ($self, $state, $pkgname) = @_; 433 my $fname = $state->{destdir}.$self->fullname; 434 # check for collisions with existing stuff 435 if ($state->vstat->exists($fname)) { 436 push(@{$state->{colliding}}, $self); 437 $self->{newly_found} = $pkgname; 438 $state->{problems}++; 439 return; 440 } 441 my $s = $state->vstat->add($fname, $self->{tieto} ? 0 : $self->{size}, 442 $pkgname); 443 return unless defined $s; 444 if ($s->ro) { 445 $s->report_ro($state, $fname); 446 } 447 if ($s->avail < 0) { 448 $s->report_overflow($state, $fname); 449 } 450} 451 452sub prepare_to_extract 453{ 454 my ($self, $state, $file) = @_; 455 my $fullname = $self->fullname; 456 my $destdir = $state->{destdir}; 457 458 $file->{cwd} = $self->cwd; 459 if (!$file->validate_meta($self)) { 460 $state->fatal("can't continue"); 461 } 462 463 $file->set_name($fullname); 464 $file->{destdir} = $destdir; 465} 466 467sub create_temp 468{ 469 my ($self, $d, $state, $fullname) = @_; 470 if (!-e _) { 471 $state->make_path($d, $fullname); 472 } 473 my ($fh, $tempname) = OpenBSD::Temp::permanent_file($d, "pkg"); 474 $self->{tempname} = $tempname; 475 if (!defined $tempname) { 476 if ($state->allow_nonroot($fullname)) { 477 $state->errsay("Can't create temp file outside localbase for #1", $fullname); 478 return undef; 479 } 480 $state->fatal("create temporary file in #1: #2", $d, $!); 481 } 482 return ($fh, $tempname); 483} 484 485sub tie 486{ 487 my ($self, $state) = @_; 488 if (defined $self->{link} || defined $self->{symlink}) { 489 return; 490 } 491 492 $self->SUPER::extract($state); 493 494 # figure out a safe directory where to put the temp file 495 my $d = dirname($state->{destdir}.$self->fullname); 496 # we go back up until we find an existing directory. 497 # hopefully this will be on the same file system. 498 while (!-d $d && -e _) { 499 $d = dirname($d); 500 } 501 if ($state->{not}) { 502 $state->say("link #1 -> #2", 503 $self->name, $d) if $state->verbose >= 3; 504 } else { 505 my ($fh, $tempname) = $self->create_temp($d, $state, 506 $self->fullname); 507 508 return if !defined $tempname; 509 my $src = $self->{tieto}->realname($state); 510 unlink($tempname); 511 $state->say("link #1 -> #2", $src, $tempname) 512 if $state->verbose >= 3; 513 link($src, $tempname) || $state->copy_file($src, $tempname); 514 } 515} 516 517sub extract 518{ 519 my ($self, $state, $file) = @_; 520 521 $self->SUPER::extract($state); 522 523 # figure out a safe directory where to put the temp file 524 my $d = dirname($file->{destdir}.$file->name); 525 # we go back up until we find an existing directory. 526 # hopefully this will be on the same file system. 527 while (!-d $d && -e _) { 528 $d = dirname($d); 529 } 530 if ($state->{not}) { 531 $state->say("extract #1 -> #2", 532 $self->name, $d) if $state->verbose >= 3; 533 $state->{archive}->skip; 534 } else { 535 my ($fh, $tempname) = $self->create_temp($d, $state, 536 $file->name); 537 if (!defined $tempname) { 538 $state->{archive}->skip; 539 return; 540 } 541 542 # XXX don't apply destdir twice 543 $file->{destdir} = ''; 544 $file->set_name($tempname); 545 546 $state->say("extract #1 -> #2", $self->name, $tempname) 547 if $state->verbose >= 3; 548 549 550 if (!$file->isFile) { 551 $state->fatal("can't extract #1, it's not a file", 552 $self->stringize); 553 } 554 $file->create; 555 $self->may_check_digest($file, $state); 556 } 557} 558 559sub install 560{ 561 my ($self, $state) = @_; 562 $self->SUPER::install($state); 563 my $fullname = $self->fullname; 564 my $destdir = $state->{destdir}; 565 if ($fullname =~ m,^$state->{localbase}/share/doc/pkg-readmes/,) { 566 $state->{readmes}++; 567 } 568 569 if ($state->{not}) { 570 $state->say("moving tempfile -> #1", 571 $destdir.$fullname) if $state->verbose >= 5; 572 return; 573 } 574 $state->make_path(dirname($destdir.$fullname), $fullname); 575 if (defined $self->{link}) { 576 link($destdir.$self->{link}, $destdir.$fullname); 577 } elsif (defined $self->{symlink}) { 578 symlink($self->{symlink}, $destdir.$fullname); 579 } else { 580 if (!defined $self->{tempname}) { 581 return if $state->allow_nonroot($fullname); 582 $state->fatal("No tempname for #1", $fullname); 583 } 584 rename($self->{tempname}, $destdir.$fullname) or 585 $state->fatal("can't move #1 to #2: #3", 586 $self->{tempname}, $fullname, $!); 587 $state->say("moving #1 -> #2", 588 $self->{tempname}, $destdir.$fullname) 589 if $state->verbose >= 5; 590 delete $self->{tempname}; 591 } 592 $self->set_modes($state, $destdir.$fullname); 593} 594 595package OpenBSD::PackingElement::RcScript; 596sub install 597{ 598 my ($self, $state) = @_; 599 $state->{add_rcscripts}{$self->fullname} = 1; 600 $self->SUPER::install($state); 601} 602 603package OpenBSD::PackingElement::Sample; 604use OpenBSD::Error; 605use File::Copy; 606 607sub prepare_for_addition 608{ 609 my ($self, $state, $pkgname) = @_; 610 if (!defined $self->{copyfrom}) { 611 $state->errsay("\@sample element #1 does not reference a valid file", 612 $self->fullname); 613 $state->{problems}++; 614 } 615 my $fname = $state->{destdir}.$self->fullname; 616 # If file already exists, we won't change it 617 if ($state->vstat->exists($fname)) { 618 return; 619 } 620 my $size = $self->{copyfrom}->{size}; 621 my $s = $state->vstat->add($fname, $size, $pkgname); 622 return unless defined $s; 623 if ($s->ro) { 624 $s->report_ro($state, $fname); 625 } 626 if ($s->avail < 0) { 627 $s->report_overflow($state, $fname); 628 } 629} 630 631sub find_extractible 632{ 633} 634 635sub extract 636{ 637} 638 639sub install 640{ 641 my ($self, $state) = @_; 642 643 $self->SUPER::install($state); 644 my $destdir = $state->{destdir}; 645 my $filename = $destdir.$self->fullname; 646 my $orig = $self->{copyfrom}; 647 my $origname = $destdir.$orig->fullname; 648 if (-e $filename) { 649 if ($state->verbose) { 650 $state->say("The existing file #1 has NOT been changed", 651 $filename); 652 if (defined $orig->{d}) { 653 654 # XXX assume this would be the same type of file 655 my $d = $self->compute_digest($filename, $orig->{d}); 656 if ($d->equals($orig->{d})) { 657 $state->say("(but it seems to match the sample file #1)", $origname); 658 } else { 659 $state->say("It does NOT match the sample file #1", 660 $origname); 661 $state->say("You may wish to update it manually"); 662 } 663 } 664 } 665 } else { 666 if ($state->{not}) { 667 $state->say("The file #1 would be installed from #2", 668 $filename, $origname) if $state->verbose >= 2; 669 } else { 670 if (!copy($origname, $filename)) { 671 $state->errsay("File #1 could not be installed:\n\t#2", $filename, $!); 672 } 673 $self->set_modes($state, $filename); 674 if ($state->verbose >= 2) { 675 $state->say("installed #1 from #2", 676 $filename, $origname); 677 } 678 } 679 } 680} 681 682package OpenBSD::PackingElement::Sampledir; 683sub extract 684{ 685} 686 687sub install 688{ 689 &OpenBSD::PackingElement::Dir::install; 690} 691 692package OpenBSD::PackingElement::Mandir; 693 694sub install 695{ 696 my ($self, $state) = @_; 697 $self->SUPER::install($state); 698 if (!$state->{current_set}{known_mandirs}{$self->fullname}) { 699 $state->log("You may wish to add #1 to /etc/man.conf", 700 $self->fullname); 701 } 702} 703 704package OpenBSD::PackingElement::Manpage; 705 706sub install 707{ 708 my ($self, $state) = @_; 709 $self->SUPER::install($state); 710 $self->register_manpage($state, 'addman'); 711} 712 713package OpenBSD::PackingElement::InfoFile; 714use File::Basename; 715use OpenBSD::Error; 716 717sub install 718{ 719 my ($self, $state) = @_; 720 $self->SUPER::install($state); 721 return if $state->{not}; 722 my $fullname = $state->{destdir}.$self->fullname; 723 $state->vsystem(OpenBSD::Paths->install_info, 724 "--info-dir=".dirname($fullname), '--', $fullname); 725} 726 727package OpenBSD::PackingElement::Shell; 728sub install 729{ 730 my ($self, $state) = @_; 731 $self->SUPER::install($state); 732 return if $state->{not}; 733 my $fullname = $self->fullname; 734 my $destdir = $state->{destdir}; 735 # go append to /etc/shells if needed 736 open(my $shells, '<', $destdir.OpenBSD::Paths->shells) or return; 737 while(<$shells>) { 738 s/^\#.*//o; 739 return if m/^\Q$fullname\E\s*$/; 740 } 741 close($shells); 742 open(my $shells2, '>>', $destdir.OpenBSD::Paths->shells) or return; 743 print $shells2 $fullname, "\n"; 744 close $shells2; 745 $state->say("Shell #1 appended to #2", $fullname, 746 $destdir.OpenBSD::Paths->shells) if $state->verbose; 747} 748 749package OpenBSD::PackingElement::Dir; 750sub extract 751{ 752 my ($self, $state) = @_; 753 my $fullname = $self->fullname; 754 my $destdir = $state->{destdir}; 755 756 return if -e $destdir.$fullname; 757 $self->SUPER::extract($state); 758 $state->say("new directory #1", $destdir.$fullname) 759 if $state->verbose >= 3; 760 return if $state->{not}; 761 $state->make_path($destdir.$fullname, $fullname); 762} 763 764sub install 765{ 766 my ($self, $state) = @_; 767 $self->SUPER::install($state); 768 my $fullname = $self->fullname; 769 my $destdir = $state->{destdir}; 770 771 $state->say("new directory #1", $destdir.$fullname) 772 if $state->verbose >= 5; 773 return if $state->{not}; 774 $state->make_path($destdir.$fullname, $fullname); 775 $self->set_modes($state, $destdir.$fullname); 776} 777 778package OpenBSD::PackingElement::Exec; 779use OpenBSD::Error; 780 781sub install 782{ 783 my ($self, $state) = @_; 784 785 $self->SUPER::install($state); 786 if ($self->should_run($state)) { 787 $self->run($state); 788 } 789} 790 791sub should_run() { 1 } 792 793package OpenBSD::PackingElement::ExecAdd; 794sub should_run 795{ 796 my ($self, $state) = @_; 797 return !$state->replacing; 798} 799 800package OpenBSD::PackingElement::ExecUpdate; 801sub should_run 802{ 803 my ($self, $state) = @_; 804 return $state->replacing; 805} 806 807package OpenBSD::PackingElement::Lib; 808 809sub install 810{ 811 my ($self, $state) = @_; 812 $self->SUPER::install($state); 813 $self->mark_ldconfig_directory($state); 814} 815 816package OpenBSD::PackingElement::SpecialFile; 817use OpenBSD::PackageInfo; 818use OpenBSD::Error; 819 820sub prepare_for_addition 821{ 822 my ($self, $state, $pkgname) = @_; 823 824 my $fname = installed_info($pkgname).$self->name; 825 my $cname = $self->fullname; 826 my $size = $self->{size}; 827 if (!defined $size) { 828 $size = (stat $cname)[7]; 829 } 830 my $s = $state->vstat->add($fname, $self->{size}, $pkgname); 831 return unless defined $s; 832 if ($s->ro) { 833 $s->report_ro($state, $fname); 834 } 835 if ($s->avail < 0) { 836 $s->report_overflow($state, $fname); 837 } 838} 839 840sub copy_info 841{ 842 my ($self, $dest, $state) = @_; 843 require File::Copy; 844 845 File::Copy::move($self->fullname, $dest) or 846 $state->errsay("Problem while moving #1 into #2: #3", 847 $self->fullname, $dest, $!); 848} 849 850sub extract 851{ 852 my ($self, $state) = @_; 853 $self->may_verify_digest($state); 854} 855 856sub find_extractible 857{ 858 my ($self, $state) = @_; 859 $self->may_verify_digest($state); 860} 861 862package OpenBSD::PackingElement::FCONTENTS; 863sub copy_info 864{ 865} 866 867package OpenBSD::PackingElement::AskUpdate; 868sub prepare_for_addition 869{ 870 my ($self, $state, $pkgname, $set) = @_; 871 my @old = $set->older_names; 872 if ($self->spec->match_ref(\@old) > 0) { 873 my $key = "update_".OpenBSD::PackageName::splitstem($pkgname); 874 return if $state->defines($key); 875 if ($state->is_interactive) { 876 if ($state->confirm($pkgname.":".$self->{message}."\n". 877 "Do you want to update now", 0)) { 878 return; 879 } 880 } else { 881 $state->errsay("Can't update #1 now: #2", 882 $pkgname, $self->{message}); 883 } 884 $state->{problems}++; 885 } 886} 887 888package OpenBSD::PackingElement::FDISPLAY; 889sub install 890{ 891 my ($self, $state) = @_; 892 my $d = $self->{d}; 893 if (!$state->{current_set}{known_displays}{$self->{d}->key}) { 894 $self->prepare($state); 895 } 896 $self->SUPER::install($state); 897} 898 899package OpenBSD::PackingElement::FUNDISPLAY; 900sub find_extractible 901{ 902 my ($self, $state, $wanted, $tied) = @_; 903 $state->{current_set}{known_displays}{$self->{d}->key} = 1; 904 $self->SUPER::find_extractible($state, $wanted, $tied); 905} 906 9071; 908