xref: /openbsd/usr.sbin/pkg_add/OpenBSD/Temp.pm (revision 09467b48)
1# ex:ts=8 sw=4:
2# $OpenBSD: Temp.pm,v 1.38 2019/07/24 09:03:12 espie Exp $
3#
4# Copyright (c) 2003-2005 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::Temp;
22
23use OpenBSD::MkTemp;
24use OpenBSD::Paths;
25use OpenBSD::Error;
26
27our $tempbase = $ENV{'PKG_TMPDIR'} || OpenBSD::Paths->vartmp;
28
29# stuff that should be cleaned up on exit, registered by pid,
30# so that it gets cleaned on exit from the correct process
31
32my $dirs = {};
33my $files = {};
34
35my ($lastname, $lasterror, $lasttype);
36
37OpenBSD::Handler->atend(
38    sub {
39	while (my ($name, $pid) = each %$files) {
40		unlink($name) if $pid == $$;
41	}
42	while (my ($dir, $pid) = each %$dirs) {
43		OpenBSD::Error->rmtree([$dir]) if $pid == $$;
44	}
45    });
46
47
48sub dir
49{
50	my $caught;
51	my $h = sub { $caught = shift; };
52	my $dir;
53
54	{
55	    local $SIG{'INT'} = $h;
56	    local $SIG{'QUIT'} = $h;
57	    local $SIG{'HUP'} = $h;
58	    local $SIG{'KILL'} = $h;
59	    local $SIG{'TERM'} = $h;
60	    $dir = permanent_dir($tempbase, "pkginfo");
61	    if (defined $dir) {
62		    $dirs->{$dir} = $$;
63	    }
64	}
65	if (defined $caught) {
66		kill $caught, $$;
67	}
68	if (defined $dir) {
69		return "$dir/";
70	} else {
71		return undef;
72	}
73}
74
75sub fh_file
76{
77	my ($stem, $cleanup) = @_;
78	my $caught;
79	my $h = sub { $caught = shift; };
80	my ($fh, $file);
81
82	{
83	    local $SIG{'INT'} = $h;
84	    local $SIG{'QUIT'} = $h;
85	    local $SIG{'HUP'} = $h;
86	    local $SIG{'KILL'} = $h;
87	    local $SIG{'TERM'} = $h;
88	    ($fh, $file) = permanent_file($tempbase, $stem);
89	    if (defined $file) {
90		    &$cleanup($file);
91	    }
92	}
93	if (defined $caught) {
94		kill $caught, $$;
95	}
96	return ($fh, $file);
97}
98
99sub file
100{
101	return (fh_file("pkgout",
102	    sub { my $n = shift; $files->{$n} = $$; })) [1];
103}
104
105sub reclaim
106{
107	my ($class, $name) = @_;
108	delete $files->{$name};
109	delete $dirs->{$name};
110}
111
112sub permanent_file
113{
114	my ($dir, $stem) = @_;
115	my $template = "$stem.XXXXXXXXXX";
116	if (defined $dir) {
117		$template = "$dir/$template";
118	}
119	if (my @l = OpenBSD::MkTemp::mkstemp($template)) {
120		return @l;
121	}
122	($lastname, $lasttype, $lasterror) = ($template, 'file', $!);
123	return ();
124}
125
126sub permanent_dir
127{
128	my ($dir, $stem) = @_;
129	my $template = "$stem.XXXXXXXXXX";
130	if (defined $dir) {
131		$template = "$dir/$template";
132	}
133	if (my $d = OpenBSD::MkTemp::mkdtemp($template)) {
134		return $d;
135	}
136	($lastname, $lasttype, $lasterror) = ($template, 'dir', $!);
137	return undef;
138}
139
140sub last_error
141{
142	my ($class, $template) = @_;
143
144	my ($user) = getpwuid($>);
145	$template //= "User #1 couldn't create temp #2 as #3: #4";
146	return ($template, $user, $lasttype, $lastname, $lasterror);
147}
1481;
149