From 18934d424912f0bf7707839d6b70b7646ee3d7df Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Thu, 24 Oct 2019 17:38:16 +0200 Subject: [PATCH] tools/image-info: add support for naked partitions In case there is no partition table, we assume the whole image is one big partition and treat is as such. Signed-off-by: Tom Gundersen --- tools/image-info | 104 +++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 43 deletions(-) diff --git a/tools/image-info b/tools/image-info index 092559034..ee773283a 100755 --- a/tools/image-info +++ b/tools/image-info @@ -59,25 +59,32 @@ def read_image_format(device): return qemu["format"] +def read_partition(device, bootable, typ=None, start=0, size=0, type=None): + blkid = subprocess_check_output(["blkid", "--output", "export", device], parse_environment_vars) + return { + "label": blkid.get("LABEL"), # doesn't exist for mbr + "type": typ, + "uuid": blkid["UUID"], + "fstype": blkid["TYPE"], + "bootable": bootable, + "start": start, + "size": size + } + + def read_partition_table(device): - sfdisk = subprocess_check_output(["sfdisk", "--json", device], json.loads) - ptable = sfdisk["partitiontable"] - assert ptable["unit"] == "sectors" - partitions = [] - for p in ptable["partitions"]: - blkid = subprocess_check_output(["blkid", "--output", "export", p["node"]], parse_environment_vars) - partitions.append({ - "label": blkid.get("LABEL"), # doesn't exist for mbr - "type": p["type"], - "uuid": blkid["UUID"], - "fstype": blkid["TYPE"], - "bootable": p.get("bootable", False), - "start": p["start"] * 512, - "size": p["size"] * 512 - }) - - return ptable["label"], ptable["id"], partitions + try: + sfdisk = subprocess_check_output(["sfdisk", "--json", device], json.loads) + except subprocess.CalledProcessError: + partitions.append(read_partition(device, False)) + return None, None, partitions + else: + ptable = sfdisk["partitiontable"] + assert ptable["unit"] == "sectors" + for p in ptable["partitions"]: + partitions.append(read_partition(p["node"], p.get("bootable", False), p["type"], p["start"] * 512, p["size"] * 512)) + return ptable["label"], ptable["id"], partitions def read_bootloader_type(device): @@ -123,38 +130,49 @@ def rpm_verify(tree): } +def append_filesystem(report, tree): + if os.path.exists(f"{tree}/etc/os-release"): + report["packages"] = sorted(subprocess_check_output(["rpm", "--root", tree, "-qa"], str.split)) + report["rpm-verify"] = rpm_verify(tree) + + with open(f"{tree}/etc/os-release") as f: + report["os-release"] = parse_environment_vars(f.read()) + + try: + with open(f"{tree}/etc/fstab") as f: + report["fstab"] = sorted([line.split() for line in f.read().split("\n") if line and not line.startswith("#")]) + except FileNotFoundError: + pass + + with open(f"{tree}/etc/passwd") as f: + report["passwd"] = sorted(f.read().strip().split("\n")) + + with open(f"{tree}/etc/group") as f: + report["groups"] = sorted(f.read().strip().split("\n")) + + if os.path.exists(f"{tree}/boot") and len(os.listdir(f"{tree}/boot")) > 0: + assert "bootmenu" not in report + report["bootmenu"] = read_boot_entries(f"{tree}/boot") + + elif len(glob.glob(f"{tree}/vmlinuz-*")) > 0: + assert "bootmenu" not in report + report["bootmenu"] = read_boot_entries(tree) + + report = {} with nbd_connect(image) as device: report["image-format"] = read_image_format(image) report["bootloader"] = read_bootloader_type(device) report["partition-table"], report["partition-table-id"], report["partitions"] = read_partition_table(device) - n_partitions = len(report["partitions"]) - for n in range(1, n_partitions + 1): - with mount(device + f"p{n}") as tree: - if os.path.exists(f"{tree}/etc/os-release"): - report["packages"] = sorted(subprocess_check_output(["rpm", "--root", tree, "-qa"], str.split)) - report["rpm-verify"] = rpm_verify(tree) - - with open(f"{tree}/etc/os-release") as f: - report["os-release"] = parse_environment_vars(f.read()) - - with open(f"{tree}/etc/fstab") as f: - report["fstab"] = sorted([line.split() for line in f.read().split("\n") if line and not line.startswith("#")]) - - with open(f"{tree}/etc/passwd") as f: - report["passwd"] = sorted(f.read().strip().split("\n")) - - with open(f"{tree}/etc/group") as f: - report["groups"] = sorted(f.read().strip().split("\n")) - - if os.path.exists(f"{tree}/boot") and len(os.listdir(f"{tree}/boot")) > 0: - assert "bootmenu" not in report - report["bootmenu"] = read_boot_entries(f"{tree}/boot") - - elif len(glob.glob(f"{tree}/vmlinuz-*")) > 0: - assert "bootmenu" not in report - report["bootmenu"] = read_boot_entries(tree) + if report["partition-table"]: + n_partitions = len(report["partitions"]) + for n in range(1, n_partitions + 1): + with mount(device + f"p{n}") as tree: + append_filesystem(report, tree) + else: + with mount(device) as tree: + append_filesystem(report, tree) json.dump(report, sys.stdout, sort_keys=True, indent=2)