Merge pull request #41372 from terminalmage/issue41190

Don't use intermediate file when listing contents of tar.xz file
This commit is contained in:
Mike Place 2017-05-22 10:36:44 -05:00 committed by GitHub
commit 01b71c75c1

View File

@ -12,8 +12,8 @@ import os
import re import re
import shlex import shlex
import stat import stat
import subprocess
import tarfile import tarfile
import tempfile
import zipfile import zipfile
try: try:
from shlex import quote as _quote # pylint: disable=E0611 from shlex import quote as _quote # pylint: disable=E0611
@ -157,7 +157,10 @@ def list_(name,
files = [] files = []
links = [] links = []
try: try:
with contextlib.closing(tarfile.open(cached)) as tar_archive: open_kwargs = {'name': cached} \
if not isinstance(cached, subprocess.Popen) \
else {'fileobj': cached.stdout, 'mode': 'r|'}
with contextlib.closing(tarfile.open(**open_kwargs)) as tar_archive:
for member in tar_archive.getmembers(): for member in tar_archive.getmembers():
if member.issym(): if member.issym():
links.append(member.name) links.append(member.name)
@ -168,7 +171,15 @@ def list_(name,
return dirs, files, links return dirs, files, links
except tarfile.ReadError: except tarfile.ReadError:
if not failhard: if failhard:
if isinstance(cached, subprocess.Popen):
stderr = cached.communicate()[1]
if cached.returncode != 0:
raise CommandExecutionError(
'Failed to decompress {0}'.format(name),
info={'error': stderr}
)
else:
if not salt.utils.which('tar'): if not salt.utils.which('tar'):
raise CommandExecutionError('\'tar\' command not available') raise CommandExecutionError('\'tar\' command not available')
if decompress_cmd is not None: if decompress_cmd is not None:
@ -187,29 +198,12 @@ def list_(name,
decompress_cmd = 'xz --decompress --stdout' decompress_cmd = 'xz --decompress --stdout'
if decompress_cmd: if decompress_cmd:
fd, decompressed = tempfile.mkstemp() decompressed = subprocess.Popen(
os.close(fd) '{0} {1}'.format(decompress_cmd, _quote(cached)),
try: shell=True,
cmd = '{0} {1} > {2}'.format(decompress_cmd, stdout=subprocess.PIPE,
_quote(cached), stderr=subprocess.PIPE)
_quote(decompressed)) return _list_tar(name, decompressed, None, True)
result = __salt__['cmd.run_all'](cmd, python_shell=True)
if result['retcode'] != 0:
raise CommandExecutionError(
'Failed to decompress {0}'.format(name),
info={'error': result['stderr']}
)
return _list_tar(name, decompressed, None, True)
finally:
try:
os.remove(decompressed)
except OSError as exc:
if exc.errno != errno.ENOENT:
log.warning(
'Failed to remove intermediate '
'decompressed archive %s: %s',
decompressed, exc.__str__()
)
raise CommandExecutionError( raise CommandExecutionError(
'Unable to list contents of {0}. If this is an XZ-compressed tar ' 'Unable to list contents of {0}. If this is an XZ-compressed tar '