diff options
| author | Pierre Pronchery <khorben@FreeBSD.org> | 2026-06-24 19:47:19 +0000 |
|---|---|---|
| committer | Pierre Pronchery <khorben@FreeBSD.org> | 2026-06-29 05:21:29 +0000 |
| commit | ebcc78644e0cbc4141807c0887ef8d902cb91bb4 (patch) | |
| tree | da5efe7c3c9ae0f140e24a1b69833a476fb09f01 /cli/spdxtool/util.c | |
| parent | 6294b6ab217a2d5f1d2bc23a64505a228294c508 (diff) | |
Diffstat (limited to 'cli/spdxtool/util.c')
| -rw-r--r-- | cli/spdxtool/util.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/cli/spdxtool/util.c b/cli/spdxtool/util.c new file mode 100644 index 000000000000..e47bf0a1e61f --- /dev/null +++ b/cli/spdxtool/util.c @@ -0,0 +1,331 @@ +/* + * 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/libpkgconf.h> +#include <libpkgconf/stdinc.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include "util.h" + +/* + * !doc + * + * .. c:function:: void spdxtool_util_set_key(pkgconf_client_t *client, const char *key, const char *key_value, const char *key_default) + * + * Set key wit default value. Default value is used if key is NULL + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :param const char *key: Key to be preserved + * :param const char *key_value: Value for key + * :param const char *key_default: Default value if key_value is NULL + * :return: nothing + */ +void +spdxtool_util_set_key(pkgconf_client_t *client, const char *key, const char *key_value, const char *key_default) +{ + PKGCONF_TRACE(client, "set uri_root to: %s", key_value != NULL ? key_value : key_default); + pkgconf_tuple_add_global(client, key, key_value != NULL ? key_value : key_default); +} + +/* + * !doc + * + * .. c:function:: void spdxtool_util_set_uri_root(pkgconf_client_t *client, const char *uri_root) + * + * Set URI/URL root for spdxId. Type for this is 'xsd:anyURI' which means + * it can they may be absolute or relative. + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :param const char *uri_root: URI root. + * :return: nothing + */ +void +spdxtool_util_set_uri_root(pkgconf_client_t *client, const char *uri_root) +{ + spdxtool_util_set_key(client, "spdx_uri_root", uri_root, "https://github.com/pkgconf/pkgconf"); +} + +/* + * !doc + * + * .. c:function:: const char *spdxtool_util_get_uri_root(pkgconf_client_t *client) + * + * Get current URI + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :return: URI or NULL + */ +const char * +spdxtool_util_get_uri_root(pkgconf_client_t *client) +{ + return pkgconf_tuple_find_global(client, "spdx_uri_root"); +} + +/* + * !doc + * + * .. c:function:: void spdxtool_util_set_uri_separator_colon(pkgconf_client_t *client, bool is_colon) + * + * when using URI rather than URL change separator from slash '/' to colon ':'. + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :param bool is_colon If true use colon ':' is separator and otherwise slash '/' + * :return: nothing + */ +void +spdxtool_util_set_uri_separator_colon(pkgconf_client_t *client, bool is_colon) +{ + if (is_colon == true) + client->flags |= SPDXTOOL_SEPARATOR_COLON; + else + client->flags = client->flags & ~SPDXTOOL_SEPARATOR_COLON; +} + +/* + * !doc + * + * .. c:function:: char spdxtool_util_get_uri_separator(pkgconf_client_t *client) + * + * Get separator char + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :return: Colon ':' or slash '/' + */ +char +spdxtool_util_get_uri_separator(pkgconf_client_t *client) +{ + if (client->flags & SPDXTOOL_SEPARATOR_COLON) + return ':'; + + return '/'; +} + +/* + * !doc + * + * .. c:function:: void spdxtool_util_set_spdx_version(pkgconf_client_t *client, const char *spdx_version) + * + * Set current SPDX SBOM Spec version. If not set it's 3.0.1 + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :param char* spdx_version: SPDX specification version. + * :return: nothing + */ +void +spdxtool_util_set_spdx_version(pkgconf_client_t *client, const char *spdx_version) +{ + spdxtool_util_set_key(client, "spdx_version", spdx_version, "3.0.1"); +} + +/* + * !doc + * + * .. c:function:: const char *spdxtool_util_get_spdx_version(pkgconf_client_t *client) + * + * Get SPDX SBOM specification version in use + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :return: Spec version + */ +const char * +spdxtool_util_get_spdx_version(pkgconf_client_t *client) +{ + return pkgconf_tuple_find_global(client, "spdx_version"); +} + +/* + * !doc + * + * .. c:function:: void spdxtool_util_set_spdx_license(pkgconf_client_t *client, const char *spdx_license) + * + * Under which license SBOM is released. License string should be in + * SPDX style. Something like: FreeBSD-DOC, CC0-1.0 or MIT + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :param const char *spdx_license: SPDX compatible license + * :return: nothing + */ +void +spdxtool_util_set_spdx_license(pkgconf_client_t *client, const char *spdx_license) +{ + spdxtool_util_set_key(client, "spdx_license", spdx_license, "CC0-1.0"); +} + +/* + * !doc + * + * .. c:function:: const char *spdxtool_util_get_spdx_license(pkgconf_client_t *client) + * + * Get license which SBOM is release in + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :return: SPDX license + */ +const char * +spdxtool_util_get_spdx_license(pkgconf_client_t *client) +{ + return pkgconf_tuple_find_global(client, "spdx_license"); +} + +static size_t last_id = 0; + +/* + * !doc + * + * .. c:function:: char *spdxtool_util_get_spdx_id_int(pkgconf_client_t *client, char *part) + * + * Get spdxId with current URI. + * URI is lookg like https://test/part/1 + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :param char *part: Addition subdir part before number + * :return: URI + */ +char * +spdxtool_util_get_spdx_id_int(pkgconf_client_t *client, const char *part) +{ + const char *global_xsd_any_uri = spdxtool_util_get_uri_root(client); + char sep = spdxtool_util_get_uri_separator(client); + pkgconf_buffer_t current_uri = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_join(¤t_uri, sep, global_xsd_any_uri, part, NULL); + pkgconf_buffer_append_fmt(¤t_uri, "%c" SIZE_FMT_SPECIFIER, sep, ++last_id); + + return pkgconf_buffer_freeze(¤t_uri); +} + +/* + * !doc + * + * .. c:function:: char *spdxtool_util_get_spdx_id_string(pkgconf_client_t *client, const char *part, const char *string_id) + * + * Get string id URI + * looks something like: https://test/part/string_id + * + * :param pkgconf_client_t* client: The pkgconf client being accessed. + * :param const char* part: subdir part of URI. + * :param const char* string_id: String ID. + * :return: URI + */ +char * +spdxtool_util_get_spdx_id_string(pkgconf_client_t *client, const char *part, const char *string_id) +{ + const char *global_xsd_any_uri = spdxtool_util_get_uri_root(client); + char sep = spdxtool_util_get_uri_separator(client); + pkgconf_buffer_t current_uri = PKGCONF_BUFFER_INITIALIZER; + + pkgconf_buffer_join(¤t_uri, sep, global_xsd_any_uri, part, string_id, NULL); + + return pkgconf_buffer_freeze(¤t_uri); +} + +/* + * !doc + * + * .. c:function:: char *spdxtool_util_get_iso8601_time(time_t *wanted_time) + * + * Get ISO8601 time string + * + * :param time_t *wanted_time: Time to be converted + * :return: Time string in ISO8601 format + */ +char * +spdxtool_util_get_iso8601_time(time_t *wanted_time) +{ + char buf[PKGCONF_ITEM_SIZE]; + + if (!wanted_time) + return NULL; + + struct tm *tm_info = gmtime(wanted_time); + if (!tm_info) + return NULL; + + /* ISO8601 time with Z at the end */ + strftime(buf, sizeof buf, "%Y-%m-%dT%H:%M:%SZ", tm_info); + return strdup(buf); +} + +/* + * !doc + * + * .. c:function:: char *spdxtool_util_get_current_iso8601_time(void) + * + * Get ISO8601 current timestamp + * + * :return: Time string in ISO8601 format + */ +char * +spdxtool_util_get_current_iso8601_time(void) +{ + time_t now; + time(&now); + return spdxtool_util_get_iso8601_time(&now); +} + +/* + * !doc + * + * .. c:function:: char *spdxtool_util_string_correction(char *str) + * + * Lowercase string and change spaces to '_' + * + * :param char *str: String to be converted + * :return: Converted string + */ +char * +spdxtool_util_string_correction(char *str) +{ + char *ptr = str; + /* Lowecase string and make spaces '_' */ + for ( ; *ptr; ++ptr) + { + *ptr = (char) tolower(*ptr); + if(isspace((unsigned char) *ptr)) + { + *ptr = '_'; + } + } + + return str; +} + +/* + * !doc + * + * .. c:function:: char *spdxtool_util_tuple_lookup(pkgconf_client_t *client, pkgconf_list_t *vars, const char *key) + * + * Lowercase string and change spaces to '_' + * + * :param pkgconf_client_t *client: client to use for the lookup + * :param pkgconf_list_t *vars: locally-scoped vars to look through + * :param char *key: key to lookup + * :return: Converted string + */ +char * +spdxtool_util_tuple_lookup(pkgconf_client_t *client, pkgconf_list_t *vars, const char *key) +{ + pkgconf_buffer_t buf = PKGCONF_BUFFER_INITIALIZER; + pkgconf_bytecode_eval_ctx_t ctx = { + .client = client, + .vars = vars, + }; + + pkgconf_variable_t *v = pkgconf_bytecode_eval_lookup_var(&ctx, key, strlen(key)); + if (v == NULL) + return NULL; + + if (!pkgconf_variable_eval(client, vars, v, &buf, NULL)) + return NULL; + + return pkgconf_buffer_freeze(&buf); +} |
