Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 54 additions & 9 deletions src/fosslight_util/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,56 @@ def extract_rpm_payload(source_file: str, dest_path: str) -> bool:
return False


def _fix_extracted_permissions(path: str) -> None:
try:
os.chmod(path, os.stat(path).st_mode | 0o755)
except Exception:
pass
for root, dirs, files in os.walk(path, topdown=True):
dirs[:] = [
d for d in dirs
if not os.path.islink(os.path.join(root, d))
]
# Fix dirs before os.walk recurses into them.
for d in dirs:
dpath = os.path.join(root, d)
try:
os.chmod(dpath, os.stat(dpath).st_mode | 0o755)
except Exception:
pass
for f in files:
fpath = os.path.join(root, f)
if os.path.islink(fpath):
continue
try:
os.chmod(fpath, os.stat(fpath).st_mode | 0o644)
except Exception:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
pass


def _tar_extractall_safe(fname: str, open_mode: str, extract_path: str) -> None:
try:
with contextlib.closing(tarfile.open(fname, open_mode)) as tf:
tf.extractall(path=extract_path)
except PermissionError as perm_err:
logger.warning(
f"Permission error while extracting '{fname}': {perm_err}. "
f"Fixing permissions and retrying."
)
_fix_extracted_permissions(extract_path)
with contextlib.closing(tarfile.open(fname, open_mode)) as tf:
members = tf.getmembers()
for m in members:
if m.isdir():
m.mode = m.mode | 0o755
elif m.isfile():
m.mode = m.mode | 0o644
tf.extractall(path=extract_path, members=members)
else:
# extractall() may restore 0o000/0o666 modes from the archive.
_fix_extracted_permissions(extract_path)


def _extract_top_level_crates_once(extract_path: str, remove_after_extract: bool) -> bool:
"""After RPM/SRPM unpack: extract each ``*.crate`` in extract_path (non-recursive)."""
if not extract_path or not os.path.isdir(extract_path):
Expand All @@ -1025,8 +1075,7 @@ def _extract_top_level_crates_once(extract_path: str, remove_after_extract: bool
if not os.path.isfile(cp):
continue
try:
with contextlib.closing(tarfile.open(cp, "r:gz")) as t:
t.extractall(path=extract_path)
_tar_extractall_safe(cp, "r:gz", extract_path)
if remove_after_extract:
os.remove(cp)
except Exception as e:
Expand Down Expand Up @@ -1058,11 +1107,9 @@ def extract_compressed_file(fname, extract_path, remove_after_extract=True, comp
fname = os.path.splitext(fname)[0]

if fname.endswith(".tar.gz") or fname.endswith(".tgz"):
with contextlib.closing(tarfile.open(fname, "r:gz")) as t:
t.extractall(path=extract_path)
_tar_extractall_safe(fname, "r:gz", extract_path)
elif fname.endswith(".tar.xz") or fname.endswith(".tar"):
with contextlib.closing(tarfile.open(fname, "r:*")) as t:
t.extractall(path=extract_path)
_tar_extractall_safe(fname, "r:*", extract_path)
elif fname.endswith(".zip") or fname.endswith(".jar"):
unzip(fname, extract_path)
elif fname.endswith(".bz2"):
Expand Down Expand Up @@ -1093,9 +1140,7 @@ def extract_compressed_file(fname, extract_path, remove_after_extract=True, comp
if zipfile.is_zipfile(fname):
unzip(fname, extract_path)
elif tarfile.is_tarfile(fname):
with contextlib.closing(tarfile.open(fname, "r:*")) as tar:
tar.extraction_filter = getattr(tarfile, 'data_filter', (lambda member, path: member))
tar.extractall(path=extract_path)
_tar_extractall_safe(fname, "r:*", extract_path)
else:
is_compressed_file = False
if compressed_only:
Expand Down
Loading