xref: /openbmc/openbmc/poky/meta/lib/oe/sbom.py (revision 220dafdb)
15199d831SAndrew Geissler#
292b42cb3SPatrick Williams# Copyright OpenEmbedded Contributors
392b42cb3SPatrick Williams#
45199d831SAndrew Geissler# SPDX-License-Identifier: GPL-2.0-only
55199d831SAndrew Geissler#
65199d831SAndrew Geissler
75199d831SAndrew Geisslerimport collections
85199d831SAndrew Geissler
95199d831SAndrew GeisslerDepRecipe = collections.namedtuple("DepRecipe", ("doc", "doc_sha1", "recipe"))
105199d831SAndrew GeisslerDepSource = collections.namedtuple("DepSource", ("doc", "doc_sha1", "recipe", "file"))
115199d831SAndrew Geissler
125199d831SAndrew Geissler
135199d831SAndrew Geisslerdef get_recipe_spdxid(d):
145199d831SAndrew Geissler    return "SPDXRef-%s-%s" % ("Recipe", d.getVar("PN"))
155199d831SAndrew Geissler
165199d831SAndrew Geissler
176aa7eec5SAndrew Geisslerdef get_download_spdxid(d, idx):
186aa7eec5SAndrew Geissler    return "SPDXRef-Download-%s-%d" % (d.getVar("PN"), idx)
196aa7eec5SAndrew Geissler
206aa7eec5SAndrew Geissler
215199d831SAndrew Geisslerdef get_package_spdxid(pkg):
225199d831SAndrew Geissler    return "SPDXRef-Package-%s" % pkg
235199d831SAndrew Geissler
245199d831SAndrew Geissler
255199d831SAndrew Geisslerdef get_source_file_spdxid(d, idx):
265199d831SAndrew Geissler    return "SPDXRef-SourceFile-%s-%d" % (d.getVar("PN"), idx)
275199d831SAndrew Geissler
285199d831SAndrew Geissler
295199d831SAndrew Geisslerdef get_packaged_file_spdxid(pkg, idx):
305199d831SAndrew Geissler    return "SPDXRef-PackagedFile-%s-%d" % (pkg, idx)
315199d831SAndrew Geissler
325199d831SAndrew Geissler
335199d831SAndrew Geisslerdef get_image_spdxid(img):
345199d831SAndrew Geissler    return "SPDXRef-Image-%s" % img
355199d831SAndrew Geissler
365199d831SAndrew Geissler
377e0e3c0cSAndrew Geisslerdef get_sdk_spdxid(sdk):
387e0e3c0cSAndrew Geissler    return "SPDXRef-SDK-%s" % sdk
397e0e3c0cSAndrew Geissler
407e0e3c0cSAndrew Geissler
41*220dafdbSAndrew Geisslerdef _doc_path_by_namespace(spdx_deploy, arch, doc_namespace):
42*220dafdbSAndrew Geissler    return spdx_deploy / "by-namespace" / arch / doc_namespace.replace("/", "_")
43b542dec1SPatrick Williams
44b542dec1SPatrick Williams
45*220dafdbSAndrew Geisslerdef doc_find_by_namespace(spdx_deploy, search_arches, doc_namespace):
46*220dafdbSAndrew Geissler    for pkgarch in search_arches:
47*220dafdbSAndrew Geissler        p = _doc_path_by_namespace(spdx_deploy, pkgarch, doc_namespace)
48*220dafdbSAndrew Geissler        if os.path.exists(p):
49*220dafdbSAndrew Geissler            return p
50*220dafdbSAndrew Geissler    return None
51*220dafdbSAndrew Geissler
52*220dafdbSAndrew Geissler
53*220dafdbSAndrew Geisslerdef _doc_path_by_hashfn(spdx_deploy, arch, doc_name, hashfn):
54*220dafdbSAndrew Geissler    return (
55*220dafdbSAndrew Geissler        spdx_deploy / "by-hash" / arch / hashfn.split()[1] / (doc_name + ".spdx.json")
56*220dafdbSAndrew Geissler    )
57*220dafdbSAndrew Geissler
58*220dafdbSAndrew Geissler
59*220dafdbSAndrew Geisslerdef doc_find_by_hashfn(spdx_deploy, search_arches, doc_name, hashfn):
60*220dafdbSAndrew Geissler    for pkgarch in search_arches:
61*220dafdbSAndrew Geissler        p = _doc_path_by_hashfn(spdx_deploy, pkgarch, doc_name, hashfn)
62*220dafdbSAndrew Geissler        if os.path.exists(p):
63*220dafdbSAndrew Geissler            return p
64*220dafdbSAndrew Geissler    return None
65b542dec1SPatrick Williams
66b542dec1SPatrick Williams
67b542dec1SPatrick Williamsdef doc_path(spdx_deploy, doc_name, arch, subdir):
68b542dec1SPatrick Williams    return spdx_deploy / arch / subdir / (doc_name + ".spdx.json")
69b542dec1SPatrick Williams
70b542dec1SPatrick Williams
71b542dec1SPatrick Williamsdef write_doc(d, spdx_doc, arch, subdir, spdx_deploy=None, indent=None):
725199d831SAndrew Geissler    from pathlib import Path
735199d831SAndrew Geissler
745199d831SAndrew Geissler    if spdx_deploy is None:
755199d831SAndrew Geissler        spdx_deploy = Path(d.getVar("SPDXDEPLOY"))
765199d831SAndrew Geissler
77b542dec1SPatrick Williams    dest = doc_path(spdx_deploy, spdx_doc.name, arch, subdir)
785199d831SAndrew Geissler    dest.parent.mkdir(exist_ok=True, parents=True)
795199d831SAndrew Geissler    with dest.open("wb") as f:
80615f2f11SAndrew Geissler        doc_sha1 = spdx_doc.to_json(f, sort_keys=True, indent=indent)
815199d831SAndrew Geissler
82*220dafdbSAndrew Geissler    l = _doc_path_by_namespace(spdx_deploy, arch, spdx_doc.documentNamespace)
83b542dec1SPatrick Williams    l.parent.mkdir(exist_ok=True, parents=True)
84b542dec1SPatrick Williams    l.symlink_to(os.path.relpath(dest, l.parent))
85b542dec1SPatrick Williams
86*220dafdbSAndrew Geissler    l = _doc_path_by_hashfn(
87*220dafdbSAndrew Geissler        spdx_deploy, arch, spdx_doc.name, d.getVar("BB_HASHFILENAME")
88*220dafdbSAndrew Geissler    )
895199d831SAndrew Geissler    l.parent.mkdir(exist_ok=True, parents=True)
905199d831SAndrew Geissler    l.symlink_to(os.path.relpath(dest, l.parent))
915199d831SAndrew Geissler
925199d831SAndrew Geissler    return doc_sha1
935199d831SAndrew Geissler
945199d831SAndrew Geissler
955199d831SAndrew Geisslerdef read_doc(fn):
965199d831SAndrew Geissler    import hashlib
975199d831SAndrew Geissler    import oe.spdx
985199d831SAndrew Geissler    import io
995199d831SAndrew Geissler    import contextlib
1005199d831SAndrew Geissler
1015199d831SAndrew Geissler    @contextlib.contextmanager
1025199d831SAndrew Geissler    def get_file():
1035199d831SAndrew Geissler        if isinstance(fn, io.IOBase):
1045199d831SAndrew Geissler            yield fn
1055199d831SAndrew Geissler        else:
1065199d831SAndrew Geissler            with fn.open("rb") as f:
1075199d831SAndrew Geissler                yield f
1085199d831SAndrew Geissler
1095199d831SAndrew Geissler    with get_file() as f:
1105199d831SAndrew Geissler        sha1 = hashlib.sha1()
1115199d831SAndrew Geissler        while True:
1125199d831SAndrew Geissler            chunk = f.read(4096)
1135199d831SAndrew Geissler            if not chunk:
1145199d831SAndrew Geissler                break
1155199d831SAndrew Geissler            sha1.update(chunk)
1165199d831SAndrew Geissler
1175199d831SAndrew Geissler        f.seek(0)
1185199d831SAndrew Geissler        doc = oe.spdx.SPDXDocument.from_json(f)
1195199d831SAndrew Geissler
1205199d831SAndrew Geissler    return (doc, sha1.hexdigest())
121