Blob Blame History Raw
#!/usr/bin/python3
"""
Fix paths in /boot/loader/entries

Fixes paths in /boot/loader/entries that have incorrect paths for /boot.

This happens because some boot loader config tools (e.g. grub2-mkrelpath)
examine /proc/self/mountinfo to find the "real" path to /boot, and find the
path to the osbuild tree - which won't be valid at boot time for this image.

The paths in the Bootloader Specification are relative to the partition
they are located on, i.e. `/boot/loader/...` if `/boot` is on the root
file-system partition. If `/boot` is on a separate partition, the correct
path would be `/loader/.../` The `prefix` can be used to adjust for that.
By default it is `/boot`, i.e. assumes `/boot` is on the root file-system.

This stage reads and (re)writes all .conf files in /boot/loader/entries.
"""


import glob
import json
import re
import sys

SCHEMA = """
"additionalProperties": false,
"properties": {
  "prefix": {
    "description": "Prefix to use, normally `/boot`",
    "type": "string",
    "default": "/boot"
  }
}
"""


def main(tree, options):
    """Fix broken paths in /boot/loader/entries.

    grub2-mkrelpath uses /proc/self/mountinfo to find the source of the file
    system it is installed to. This breaks in a container, because we
    bind-mount the tree from the host.
    """
    prefix = options.get("prefix", "/boot")

    path_re = re.compile(r"(/.*)+/boot")

    for name in glob.glob(f"{tree}/boot/loader/entries/*.conf"):
        with open(name) as f:
            entry = f.read().splitlines(keepends=True)

        with open(name, "w") as f:
            for line in entry:
                f.write(path_re.sub(prefix, line))

    return 0


if __name__ == '__main__':
    args = json.load(sys.stdin)
    r = main(args["tree"], args["options"])
    sys.exit(r)