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