Skip to content

Commit 63ed384

Browse files
committed
Make utils.extract_tar work
The same way as it was working with extractcode. Signed-off-by: Philippe Ombredanne <[email protected]>
1 parent 5b61891 commit 63ed384

File tree

3 files changed

+49
-30
lines changed

3 files changed

+49
-30
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ v31.0.0
66

77
This is a major release with bug fixes and API changes.
88

9-
- Remove dependency on extractcode. "extract_tar" has been removed too. Use
10-
instead extract_tar_with_symlinks.
11-
- Adopted the latest skeleton.
12-
- Add new os tests
9+
- Remove dependency on extractcode as images only need basic tar to extract.
10+
- "utils.extract_tar" function now accepts a skip_symlink argument
11+
- Adopt the latest skeleton.
12+
- Add new os-release tests
1313

1414

1515
v30.0.0

src/container_inspector/image.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -450,14 +450,15 @@ def get_installed_packages(self, packages_getter):
450450
yield purl, package, layer
451451

452452
@staticmethod
453-
def extract(archive_location, extracted_location):
453+
def extract(archive_location, extracted_location, skip_symlinks=False):
454454
"""
455455
Extract the image archive tarball at ``archive_location`` to
456-
``extracted_location``.
456+
``extracted_location``. Skip symlinks and links if ``skip_symlinks`` is True.
457457
"""
458-
utils.extract_tar_keeping_symlinks(
458+
utils.extract_tar(
459459
location=archive_location,
460460
target_dir=extracted_location,
461+
skip_symlinks=skip_symlinks,
461462
)
462463

463464
@staticmethod
@@ -1070,15 +1071,16 @@ def __attrs_post_init__(self, *args, **kwargs):
10701071
if not self.size:
10711072
self.size = os.path.getsize(self.archive_location)
10721073

1073-
def extract(self, extracted_location):
1074+
def extract(self, extracted_location, skip_symlinks=True):
10741075
"""
10751076
Extract this layer archive in the `extracted_location` directory and set
10761077
this Layer ``extracted_location`` attribute to ``extracted_location``.
10771078
"""
10781079
self.extracted_location = extracted_location
1079-
utils.extract_tar_keeping_symlinks(
1080+
utils.extract_tar(
10801081
location=self.archive_location,
10811082
target_dir=extracted_location,
1083+
skip_symlinks=skip_symlinks,
10821084
)
10831085

10841086
def get_resources(self, with_dir=False, walker=os.walk):

src/container_inspector/utils.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -80,40 +80,57 @@ def get_labels(config, container_config):
8080
return dict(sorted(labels.items()))
8181

8282

83-
def extract_tar(location, target_dir):
83+
def extract_tar(location, target_dir, skip_symlinks=True):
8484
"""
8585
Extract a tar archive at `location` in the `target_dir` directory.
86-
Ignore special device files and symlinks and hardlinks.
87-
Do not preserve the permissions and owners.
88-
Raise an Exception on error.
89-
"""
90-
raise NotImplementedError('This function has been removed, use extract_tar_keeping_symlinks instead')
91-
92-
93-
def extract_tar_keeping_symlinks(location, target_dir):
94-
"""
95-
Extract a tar archive at `location` in the `target_dir` directory.
96-
Ignore special device files. Keep symlinks and hardlinks
86+
Ignore special device files. Skip symlinks and hardlinks if skip_symlinks is True.
9787
Do not preserve the permissions and owners.
9888
Raise exceptions on possible problematic relative paths.
89+
Issue a warning if skip_symlinks is True and links target are missing.
9990
"""
10091
import tarfile
101-
if TRACE: logger.debug(f'extract_tar_keeping_symlinks: {location} to {target_dir}')
92+
tarfile.TarInfo
93+
if TRACE: logger.debug(f'_extract_tar: {location} to {target_dir} skip_symlinks: {skip_symlinks}')
10294

10395
fileutils.create_dir(target_dir)
10496

10597
with tarfile.open(location) as tarball:
10698
# never extract character device, block and fifo files:
10799
# we extract dirs, files and links only
108-
for tinfo in tarball:
109-
if tinfo.isdev():
100+
to_extract = []
101+
for tarinfo in tarball:
102+
if TRACE: logger.debug(f'_extract_tar: {tarinfo}')
103+
104+
if tarinfo.isdev() or tarinfo.ischr() or tarinfo.isblk() or tarinfo.isfifo() or tarinfo.sparse:
105+
if TRACE:
106+
logger.debug(f'_extract_tar: skipping unsupported {tarinfo} file type: block, chr, dev or sparse file')
110107
continue
111-
if TRACE: logger.debug(f'extract_tar_keeping_symlinks: {tinfo}')
112-
tarball.extract(
113-
member=tinfo,
114-
path=target_dir,
115-
set_attrs=False,
116-
)
108+
109+
if '..' in tarinfo.name:
110+
if TRACE: logger.debug(f'_extract_tar: skipping unsupported {tarinfo} with relative path')
111+
continue
112+
113+
if tarinfo.islnk() or tarinfo.issym():
114+
try:
115+
target = tarball._find_link_target(tarinfo)
116+
if not target:
117+
if TRACE:
118+
logger.debug(f'_extract_tar: skipping link with missing target: {tarinfo}')
119+
continue
120+
121+
except Exception:
122+
import traceback
123+
if TRACE:
124+
logger.debug(f'_extract_tar: skipping link with missing target: {tarinfo}: {traceback.format_exc()}')
125+
continue
126+
127+
tarinfo.mode = 0o755
128+
tarinfo.name = tarinfo.name.lstrip('/')
129+
tarball.extract(member=tarinfo, path=target_dir, set_attrs=False,)
130+
131+
132+
def extract_tar_with_symlinks(location, target_dir):
133+
return extract_tar(location, target_dir, skip_symlinks=False)
117134

118135

119136
def lower_keys(mapping):

0 commit comments

Comments
 (0)