PNG  IHDR* pHYs+ IDATx]n#; cdLb Ǚ[at¤_:uP}>!Usă cag޿ ֵNu`ݼTâabO7uL&y^wFٝA"l[|ŲHLN밪4*sG3|Dv}?+y߉{OuOAt4Jj.u]Gz*҉sP'VQKbA1u\`& Af;HWj hsO;ogTu uj7S3/QzUr&wS`M$X_L7r2;aE+ώ%vikDA:dR+%KzƉo>eOth$z%: :{WwaQ:wz%4foɹE[9<]#ERINƻv溂E%P1i01 |Jvҗ&{b?9g=^wζXn/lK::90KwrюO\!ջ3uzuGv^;騢wq<Iatv09:tt~hEG`v;3@MNZD.1]L:{ծI3`L(÷ba")Y.iljCɄae#I"1 `3*Bdz>j<fU40⨬%O$3cGt]j%Fߠ_twJ;ABU8vP3uEԑwQ V:h%))LfraqX-ۿX]v-\9I gl8tzX ]ecm)-cgʒ#Uw=Wlێn(0hPP/ӨtQ“&J35 $=]r1{tLuǮ*i0_;NƝ8;-vݏr8+U-kruȕYr0RnC]*ެ(M:]gE;{]tg(#ZJ9y>utRDRMdr9㪩̞zֹb<ģ&wzJM"iI( .ꮅX)Qw:9,i좜\Ԛi7&N0:asϓc];=ΗOӣ APqz93 y $)A*kVHZwBƺnWNaby>XMN*45~ղM6Nvm;A=jֲ.~1}(9`KJ/V F9[=`~[;sRuk]rєT!)iQO)Y$V ی ۤmzWz5IM Zb )ˆC`6 rRa}qNmUfDsWuˤV{ Pݝ'=Kֳbg,UҘVz2ﴻnjNgBb{? ߮tcsͻQuxVCIY۠:(V뺕 ٥2;t`@Fo{Z9`;]wMzU~%UA蛚dI vGq\r82iu +St`cR.6U/M9IENDB`# This file is part of cloud-init. See LICENSE file for license information. import contextlib import errno import logging import os import shutil import tempfile from cloudinit import util LOG = logging.getLogger(__name__) _TMPDIR = None _ROOT_TMPDIR = "/run/cloud-init/tmp" _EXE_ROOT_TMPDIR = "/var/tmp/cloud-init" def get_tmp_ancestor(odir=None, needs_exe: bool = False): if odir is not None: return odir if needs_exe: return _EXE_ROOT_TMPDIR if _TMPDIR: return _TMPDIR if os.getuid() == 0: return _ROOT_TMPDIR return os.environ.get("TMPDIR", "/tmp") def _tempfile_dir_arg(odir=None, needs_exe: bool = False): """Return the proper 'dir' argument for tempfile functions. When root, cloud-init will use /run/cloud-init/tmp to avoid any cleaning that a distro boot might do on /tmp (such as systemd-tmpfiles-clean). If the caller of this function (mkdtemp or mkstemp) was provided with a 'dir' argument, then that is respected. @param odir: original 'dir' arg to 'mkdtemp' or other. @param needs_exe: Boolean specifying whether or not exe permissions are needed for tempdir. This is needed because /run is mounted noexec. """ tdir = get_tmp_ancestor(odir, needs_exe) if not os.path.isdir(tdir): os.makedirs(tdir) os.chmod(tdir, 0o1777) if needs_exe: if util.has_mount_opt(tdir, "noexec"): LOG.warning( "Requested temporal dir with exe permission `%s` is" " mounted as noexec", tdir, ) if odir is None and not needs_exe: global _TMPDIR _TMPDIR = tdir return tdir def ExtendedTemporaryFile(**kwargs): kwargs["dir"] = _tempfile_dir_arg( kwargs.pop("dir", None), kwargs.pop("needs_exe", False) ) fh = tempfile.NamedTemporaryFile(**kwargs) # Replace its unlink with a quiet version # that does not raise errors when the # file to unlink has been unlinked elsewhere.. def _unlink_if_exists(path): try: os.unlink(path) except OSError as e: if e.errno != errno.ENOENT: raise e fh.unlink = _unlink_if_exists # Add a new method that will unlink # right 'now' but still lets the exit # method attempt to remove it (which will # not throw due to our del file being quiet # about files that are not there) def unlink_now(): fh.unlink(fh.name) setattr(fh, "unlink_now", unlink_now) return fh @contextlib.contextmanager def tempdir(rmtree_ignore_errors=False, **kwargs): # This seems like it was only added in python 3.2 # Make it since its useful... # See: http://bugs.python.org/file12970/tempdir.patch tdir = mkdtemp(**kwargs) try: yield tdir finally: shutil.rmtree(tdir, ignore_errors=rmtree_ignore_errors) def mkdtemp(dir=None, needs_exe: bool = False, **kwargs): dir = _tempfile_dir_arg(dir, needs_exe) return tempfile.mkdtemp(dir=dir, **kwargs) def mkstemp(dir=None, needs_exe: bool = False, **kwargs): dir = _tempfile_dir_arg(dir, needs_exe) return tempfile.mkstemp(dir=dir, **kwargs)