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