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