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