1# ex:ts=8 sw=4: 2# $OpenBSD: Persistent.pm,v 1.4 2023/06/13 09:07:18 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 v5.36; 19 20package OpenBSD::PackageRepository::Persistent; 21our @ISA=qw(OpenBSD::PackageRepository::Distant); 22 23our %distant = (); 24 25sub may_exist($self, $name) 26{ 27 my $l = $self->list; 28 return grep {$_ eq $name } @$l; 29} 30 31sub grab_object($self, $object) 32{ 33 my $cmdfh = $self->{cmdfh}; 34 my $getfh = $self->{getfh}; 35 36 print $cmdfh "ABORT\n"; 37 while (<$getfh>) { 38 last if m/^ABORTED/o; 39 } 40 print $cmdfh "GET ", $self->{path}.$object->{name}.".tgz", "\n"; 41 CORE::close($cmdfh); 42 $_ = <$getfh>; 43 chomp; 44 if (m/^ERROR:/o) { 45 $self->{state}->fatal("transfer error: #1", $_); 46 } 47 if (m/^TRANSFER:\s+(\d+)/o) { 48 my $buffsize = 10 * 1024; 49 my $buffer; 50 my $size = $1; 51 my $remaining = $size; 52 my $n; 53 54 do { 55 $n = read($getfh, $buffer, 56 $remaining < $buffsize ? $remaining :$buffsize); 57 if (!defined $n) { 58 $self->{state}->fatal("Error reading: #1", $!); 59 } 60 $remaining -= $n; 61 if ($n > 0) { 62 syswrite STDOUT, $buffer; 63 } 64 } while ($n != 0 && $remaining != 0); 65 } 66 delete $self->{controller}; 67 CORE::close($getfh); 68} 69 70sub maxcount($) 71{ 72 return 1; 73} 74 75sub opened($self) 76{ 77 my $k = $self->{host}; 78 if (!defined $distant{$k}) { 79 $distant{$k} = []; 80 } 81 return $distant{$k}; 82} 83 84sub list($self) 85{ 86 if (!defined $self->{list}) { 87 if (!defined $self->{controller}) { 88 $self->initiate; 89 } 90 my $cmdfh = $self->{cmdfh}; 91 my $getfh = $self->{getfh}; 92 my $path = $self->{path}; 93 my $l = []; 94 print $cmdfh "LIST $path\n"; 95 $_ = <$getfh>; 96 if (!defined $_) { 97 $self->{state}->fatal("Could not initiate #1 session", 98 $self->urlscheme); 99 } 100 chomp; 101 if (m/^ERROR:/o) { 102 $self->{state}->fatal("#1", $_); 103 } 104 if (!m/^SUCCESS:/o) { 105 $self->{state}->fatal("Synchronization error"); 106 } 107 while (<$getfh>) { 108 chomp; 109 last if $_ eq ''; 110 push(@$l, $_); 111 } 112 $self->{list} = $l; 113 } 114 return $self->{list}; 115} 116 117sub cleanup($self) 118{ 119 if (defined $self->{controller}) { 120 my $cmdfh = $self->{cmdfh}; 121 my $getfh = $self->{getfh}; 122 print $cmdfh "ABORT\nBYE\nBYE\n"; 123 CORE::close($cmdfh); 124 CORE::close($getfh); 125 waitpid($self->{controller}, 0); 126 delete $self->{controller}; 127 } 128} 129 130sub dont_cleanup($self) 131{ 132 CORE::close($self->{cmdfh}); 133 CORE::close($self->{getfh}); 134 delete $self->{controller}; 135} 136 137sub reinitialize($self) 138{ 139 $self->initiate; 140} 141 1421; 143