xref: /openbsd-src/usr.sbin/pkg_add/OpenBSD/PackageRepository/Persistent.pm (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
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