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