/
githubmirror
/
pkgconf
Обзор
Документация
Войти
/
githubmirror
/
pkgconf
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
cli/spdxtool/generate.c
248 строк
7 KB
Ariadne Conill
spdxtool: generate: do not reuse iteration node
03 июл 2026, 05:55
03 июл 2026, 05:55
ad1ed61
Код
Авторство
О чём код?
/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2025 The FreeBSD Foundation * * Portions of this software were developed by * Tuukka Pasanen <tuukka.pasanen@ilmi.fi> under sponsorship from * the FreeBSD Foundation */ #include <libpkgconf/stdinc.h> #include <libpkgconf/libpkgconf.h> #include "util.h" #include "core.h" #include "software.h" #include "serialize.h" #include "simplelicensing.h" #include "generate.h" typedef struct { spdxtool_core_spdx_document_t *document; bool failed; } generate_spdx_ctx_t; static bool generate_spdx_document_add_sbom(pkgconf_client_t *client, spdxtool_core_spdx_document_t *document, spdxtool_software_sbom_t *sbom) { pkgconf_node_t *node = calloc(1, sizeof(pkgconf_node_t)); if (!node) { pkgconf_error(client, "generate_spdx_document_add_sbom: out of memory"); return false; } pkgconf_node_insert_tail(node, sbom, &document->rootElement); return true; } // NOTE: this function is passed to pkgconf_pkg_traverse static void generate_spdx_package(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *ptr, unsigned int iter_flags) { (void) iter_flags; generate_spdx_ctx_t *ctx = ptr; spdxtool_core_spdx_document_t *document = ctx->document; pkgconf_node_t *iter = NULL; spdxtool_software_sbom_t *sbom = NULL; char *package_spdx = NULL; char *spdx_id_string = NULL; pkgconf_buffer_t spdx_id_buf = PKGCONF_BUFFER_INITIALIZER; pkgconf_buffer_t concluded_buf = PKGCONF_BUFFER_INITIALIZER; char sep = spdxtool_util_get_uri_separator(client); if (pkg->flags & PKGCONF_PKG_PROPF_VIRTUAL) return; if (ctx->failed) return; spdx_id_string = spdxtool_util_get_spdx_id_string(client, "software_Sbom", pkg->id); if (!spdx_id_string) goto err; sbom = spdxtool_software_sbom_new(client, spdx_id_string, document->creation_info, "build"); free(spdx_id_string); spdx_id_string = NULL; if (!sbom) goto err; sbom->spdx_document = document; sbom->rootElement = pkg; package_spdx = spdxtool_util_get_spdx_id_string(client, "Package", pkg->id); if (!package_spdx) goto err; if (pkgconf_tuple_add(client, &pkg->vars, "spdxId", package_spdx, false, 0) == NULL) goto err; free(package_spdx); package_spdx = NULL; if (pkgconf_tuple_add(client, &pkg->vars, "creationInfo", document->creation_info, false, 0) == NULL || pkgconf_tuple_add(client, &pkg->vars, "agent", document->agent, false, 0) == NULL) { goto err; } if (pkg->maintainer != NULL) { const char *supplier = spdxtool_core_spdx_document_add_maintainer(client, document, pkg->maintainer); if (!supplier) goto err; if (pkgconf_tuple_add(client, &pkg->vars, "suppliedBy", supplier, false, 0) == NULL) goto err; } if (pkg->license.head != NULL) { if (!pkgconf_buffer_append_fmt(&spdx_id_buf, "%s%chasDeclaredLicense", pkg->id, sep)) goto err; char *spdx_id_name = pkgconf_buffer_freeze(&spdx_id_buf); if (!spdx_id_name) goto err; package_spdx = spdxtool_util_get_spdx_id_string(client, "Relationship", spdx_id_name); free(spdx_id_name); if (!package_spdx) goto err; if (pkgconf_tuple_add(client, &pkg->vars, "hasDeclaredLicense", package_spdx, false, 0) == NULL) goto err; free(package_spdx); package_spdx = NULL; if (!pkgconf_buffer_append_fmt(&concluded_buf, "%s%chasConcludedLicense", pkg->id, sep)) goto err; spdx_id_name = pkgconf_buffer_freeze(&concluded_buf); if (!spdx_id_name) goto err; package_spdx = spdxtool_util_get_spdx_id_string(client, "Relationship", spdx_id_name); free(spdx_id_name); if (!package_spdx) goto err; if (pkgconf_tuple_add(client, &pkg->vars, "hasConcludedLicense", package_spdx, false, 0) == NULL) goto err; free(package_spdx); package_spdx = NULL; PKGCONF_FOREACH_LIST_ENTRY(pkg->license.head, iter) { const pkgconf_license_t *license = iter->data; if (license->type == PKGCONF_LICENSE_EXPRESSION) { if (!spdxtool_core_spdx_document_add_license(client, document, license->data)) goto err; } } } if (!generate_spdx_document_add_sbom(client, document, sbom)) goto err; sbom = NULL; return; err: ctx->failed = true; pkgconf_error(client, "generate_spdx_package: failed for %s", pkg->id); free(package_spdx); free(spdx_id_string); pkgconf_buffer_finalize(&spdx_id_buf); pkgconf_buffer_finalize(&concluded_buf); spdxtool_software_sbom_free(sbom); } bool spdxtool_generate(pkgconf_client_t *client, pkgconf_pkg_t *world, FILE *out, int maxdepth, const char *creation_time, const char *creation_id, const char *agent_name) { const char *agent_name_string = agent_name ? agent_name : "Default"; const char *creation_id_string = creation_id ? creation_id : "_:creationinfo_1"; const char *tool_short_name_string = "spdxtool"; const char *tool_name_string = "spdxtool"; spdxtool_core_agent_t *agent = spdxtool_core_agent_new(client, creation_id_string, agent_name_string); if (!agent) { pkgconf_error(client, "Could not create agent struct"); return false; } spdxtool_core_tool_t *tool = spdxtool_core_tool_new(client, creation_id_string, tool_short_name_string, tool_name_string); if (!tool) { pkgconf_error(client, "Could not create tool struct"); spdxtool_core_agent_free(agent); return false; } spdxtool_core_creation_info_t *creation = spdxtool_core_creation_info_new(client, agent->spdx_id, tool->spdx_id, creation_id_string, creation_time); if (!creation) { pkgconf_error(client, "Could not create creation info struct"); spdxtool_core_tool_free(tool); spdxtool_core_agent_free(agent); return false; } char *spdx_id_int = spdxtool_util_get_spdx_id_int(client, "spdxDocument"); spdxtool_core_spdx_document_t *document = spdxtool_core_spdx_document_new(client, spdx_id_int, creation_id_string, agent->spdx_id); free(spdx_id_int); if (!document) { pkgconf_error(client, "Could not create document"); spdxtool_core_creation_info_free(creation); spdxtool_core_agent_free(agent); return false; } generate_spdx_ctx_t ctx = { .document = document, }; int eflag = pkgconf_pkg_traverse(client, world, generate_spdx_package, &ctx, maxdepth, 0); if (eflag != PKGCONF_PKG_ERRF_OK || ctx.failed) { spdxtool_core_spdx_document_free(document); spdxtool_core_creation_info_free(creation); spdxtool_core_agent_free(agent); return false; } spdxtool_serialize_value_t *root = spdxtool_serialize_sbom(client, agent, tool, creation, document); if (!root) { spdxtool_core_spdx_document_free(document); spdxtool_core_creation_info_free(creation); spdxtool_core_agent_free(agent); return false; } pkgconf_buffer_t buffer = PKGCONF_BUFFER_INITIALIZER; bool ret = spdxtool_serialize_value_to_buf(&buffer, root, 0); spdxtool_serialize_value_free(root); if (ret) { ret = pkgconf_output_file_fmt(out, "%s\n", pkgconf_buffer_str(&buffer)); if (!ret) pkgconf_error(client, "spdxtool: Could not output to file: %s", strerror(errno)); } else pkgconf_error(client, "spdxtool: Could not serialize SPDX document"); pkgconf_buffer_finalize(&buffer); spdxtool_core_spdx_document_free(document); spdxtool_core_creation_info_free(creation); spdxtool_core_tool_free(tool); spdxtool_core_agent_free(agent); return ret; }