1# ex:ts=8 sw=4: 2# $OpenBSD: Persistent.pm,v 1.2 2016/06/27 08:38:15 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 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 exit(0); 70 } 71} 72 73sub maxcount 74{ 75 return 1; 76} 77 78sub opened 79{ 80 my $self = $_[0]; 81 my $k = $self->{host}; 82 if (!defined $distant{$k}) { 83 $distant{$k} = []; 84 } 85 return $distant{$k}; 86} 87 88sub list 89{ 90 my ($self) = @_; 91 if (!defined $self->{list}) { 92 if (!defined $self->{controller}) { 93 $self->initiate; 94 } 95 my $cmdfh = $self->{cmdfh}; 96 my $getfh = $self->{getfh}; 97 my $path = $self->{path}; 98 my $l = []; 99 print $cmdfh "LIST $path\n"; 100 $_ = <$getfh>; 101 if (!defined $_) { 102 $self->{state}->fatal("Could not initiate #1 session", 103 $self->urlscheme); 104 } 105 chomp; 106 if (m/^ERROR:/o) { 107 $self->{state}->fatal("#1", $_); 108 } 109 if (!m/^SUCCESS:/o) { 110 $self->{state}->fatal("Synchronization error"); 111 } 112 while (<$getfh>) { 113 chomp; 114 last if $_ eq ''; 115 push(@$l, $_); 116 } 117 $self->{list} = $l; 118 } 119 return $self->{list}; 120} 121 122sub cleanup 123{ 124 my $self = shift; 125 if (defined $self->{controller}) { 126 my $cmdfh = $self->{cmdfh}; 127 my $getfh = $self->{getfh}; 128 print $cmdfh "ABORT\nBYE\nBYE\n"; 129 CORE::close($cmdfh); 130 CORE::close($getfh); 131 waitpid($self->{controller}, 0); 132 delete $self->{controller}; 133 } 134} 135 136sub dont_cleanup 137{ 138 my $self = shift; 139 CORE::close($self->{cmdfh}); 140 CORE::close($self->{getfh}); 141 delete $self->{controller}; 142} 143 144sub reinitialize 145{ 146 my $self = shift; 147 $self->initiate; 148} 149 1501; 151