Files

149 lines
4.8 KiB
Python

import argparse
import lzma
import os
import subprocess
import tempfile
from typing import List, Dict, Optional
import requests
import rpmfile
from debian import debfile
DWARF2JSON = "./dwarf2json"
class Downloader:
def __init__(self, url_lists: List[List[str]]) -> None:
self.url_lists = url_lists
def download_lists(self, keep=False):
for url_list in self.url_lists:
print("Downloading files...")
files_for_processing = self.download_list(url_list)
self.process_files(files_for_processing)
if not keep:
for fname in files_for_processing.values():
if fname:
os.unlink(fname)
def download_list(self, urls: List[str]) -> Dict[str, str]:
processed_files = {}
for url in urls:
print(f" - Downloading {url}")
data = requests.get(url)
with tempfile.NamedTemporaryFile() as archivedata:
archivedata.write(data.content)
archivedata.seek(0)
if url.endswith(".rpm"):
processed_files[url] = self.process_rpm(archivedata)
elif url.endswith(".deb"):
processed_files[url] = self.process_deb(archivedata)
return processed_files
def process_rpm(self, archivedata) -> Optional[str]:
rpm = rpmfile.RPMFile(fileobj=archivedata)
member = None
extracted = None
for member in rpm.getmembers():
if "vmlinux" in member.name or "System.map" in member.name:
print(f" - Extracting {member.name}")
extracted = rpm.extractfile(member)
break
if not member or not extracted:
return None
with tempfile.NamedTemporaryFile(
delete=False, prefix="vmlinux" if "vmlinux" in member.name else "System.map"
) as output:
print(f" - Writing to {output.name}")
output.write(extracted.read())
return output.name
def process_deb(self, archivedata) -> Optional[str]:
deb = debfile.DebFile(fileobj=archivedata)
member = None
extracted = None
for member in deb.data.tgz().getmembers():
if member.name.endswith("vmlinux") or "System.map" in member.name:
print(f" - Extracting {member.name}")
extracted = deb.data.get_file(member.name)
break
if not member or not extracted:
return None
with tempfile.NamedTemporaryFile(
delete=False, prefix="vmlinux" if "vmlinux" in member.name else "System.map"
) as output:
print(f" - Writing to {output.name}")
output.write(extracted.read())
return output.name
def process_files(self, named_files: Dict[str, str]):
"""Runs the dwarf2json binary across the files"""
print("Processing Files...")
for i in named_files:
if named_files[i] is None:
print(f"FAILURE: None encountered for {i}")
return
args = [DWARF2JSON, "linux"]
output_filename = "unknown-kernel.json"
for named_file in named_files:
prefix = "--system-map"
if "System" not in named_files[named_file]:
prefix = "--elf"
output_filename = (
"./"
+ "-".join((named_file.split("/")[-1]).split("-")[2:])[:-4]
+ ".json.xz"
)
args += [prefix, named_files[named_file]]
print(f" - Running {args}")
proc = subprocess.run(args, capture_output=True)
print(f" - Writing to {output_filename}")
with lzma.open(output_filename, "w") as f:
f.write(proc.stdout)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Takes a list of URLs for Centos and downloads them"
)
parser.add_argument(
"-f",
"--file",
dest="filename",
metavar="FILENAME",
help="Filename to be read",
required=True,
)
parser.add_argument(
"-d",
"--dwarf2json",
dest="dwarfpath",
metavar="PATH",
default=DWARF2JSON,
help="Path to the dwarf2json binary",
required=True,
)
parser.add_argument(
"-k",
"--keep",
dest="keep",
action="store_true",
help="Keep extracted temporary files after completion",
default=False,
)
args = parser.parse_args()
DWARF2JSON = args.dwarfpath
with open(args.filename) as f:
lines = f.readlines()
urls = []
for i in range(len(lines) // 2):
urls += [[lines[2 * i].strip(), lines[(2 * i) + 1].strip()]]
d = Downloader(urls)
d.download_lists(keep=args.keep)