mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-30 10:17:18 +00:00
implement elf dynamic linking check
This commit is contained in:
parent
2922bb9d72
commit
9449c95ad4
1
setup.py
1
setup.py
@ -33,6 +33,7 @@ setup(
|
||||
"cerberus",
|
||||
"inflection",
|
||||
"passlib",
|
||||
"pyelftools",
|
||||
"requests",
|
||||
"srcinfo",
|
||||
],
|
||||
|
95
src/ahriman/models/package_archive.py
Normal file
95
src/ahriman/models/package_archive.py
Normal file
@ -0,0 +1,95 @@
|
||||
#
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import IO
|
||||
|
||||
from elftools.elf.elffile import ELFFile
|
||||
from elftools.elf.dynamic import DynamicSection
|
||||
from pyalpm import Package # type: ignore[import]
|
||||
|
||||
from ahriman.core.util import walk
|
||||
|
||||
|
||||
@dataclass
|
||||
class PackageArchive:
|
||||
"""
|
||||
helper for package archives
|
||||
"""
|
||||
|
||||
package: Package
|
||||
|
||||
@staticmethod
|
||||
def get_depends_paths(package_base: str, root: Path) -> tuple[set[str], set[Path]]:
|
||||
dependencies = set()
|
||||
roots = set()
|
||||
|
||||
package_dir = root / "build" / package_base / "pkg"
|
||||
for path in walk(package_dir):
|
||||
dependencies.update(PackageArchive.get_dynamic(path))
|
||||
roots.update(path.relative_to(package_dir).parents)
|
||||
|
||||
return dependencies, roots
|
||||
|
||||
@staticmethod
|
||||
def get_dynamic(binary_path: Path) -> list[str]:
|
||||
with binary_path.open("rb") as binary_file:
|
||||
if not PackageArchive.is_elf(binary_file):
|
||||
return []
|
||||
|
||||
elf_file = ELFFile(binary_file)
|
||||
dynamic_section = next((section for section in elf_file.iter_sections() if isinstance(section, DynamicSection)), None)
|
||||
if dynamic_section is None:
|
||||
return []
|
||||
|
||||
return [tag.needed for tag in dynamic_section.iter_tags() if tag.entry.d_tag == "DT_NEEDED"]
|
||||
|
||||
@staticmethod
|
||||
def get_filesystem(root: Path) -> dict[str, tuple[list[Path], list[Path]]]:
|
||||
result = {}
|
||||
for path in filter(lambda fn: fn.name == "files", walk(root / "var" / "lib" / "pacman" / "local")):
|
||||
package, *_ = path.parent.name.rsplit("-", 2)
|
||||
|
||||
directories = []
|
||||
files = []
|
||||
for entry in path.read_text(encoding="utf8").splitlines():
|
||||
if not entry or entry == "%FILES%":
|
||||
continue # header
|
||||
entry_path = Path(entry)
|
||||
if entry_path.name == "":
|
||||
directories.append(entry_path)
|
||||
else:
|
||||
files.append(entry_path)
|
||||
|
||||
result[package] = (directories, files)
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def is_elf(descriptor: IO[bytes]) -> bool:
|
||||
expected = b"\x7fELF"
|
||||
length = len(expected)
|
||||
|
||||
magic_bytes = descriptor.read(length)
|
||||
descriptor.seek(0) # reset reading position
|
||||
|
||||
return magic_bytes == expected
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user