diff options
Diffstat (limited to 'osinfo/osinfo_os.c')
-rw-r--r-- | osinfo/osinfo_os.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/osinfo/osinfo_os.c b/osinfo/osinfo_os.c index eeafee1..022bfe4 100644 --- a/osinfo/osinfo_os.c +++ b/osinfo/osinfo_os.c @@ -1523,6 +1523,112 @@ OsinfoFirmwareList *osinfo_os_get_firmware_list(OsinfoOs *os, OsinfoFilter *filt return foreach_data.firmwares; } +static void get_all_firmwares_cb(OsinfoProduct *product, gpointer user_data) +{ + OsinfoFirmwareList *out; + OsinfoOs *os = OSINFO_OS(product); + gsize len, i; + gsize current_list_len, j; + struct GetAllFirmwaresData *foreach_data = user_data; + + g_return_if_fail(OSINFO_IS_OS(os)); + + out = OSINFO_FIRMWARELIST(osinfo_list_new_copy(OSINFO_LIST(foreach_data->firmwares))); + + len = osinfo_list_get_length(OSINFO_LIST(os->priv->firmwares)); + current_list_len = osinfo_list_get_length(OSINFO_LIST(foreach_data->firmwares)); + for (i = 0; i < len; i++) { + OsinfoFirmware *firmware; + const gchar *arch; + const gchar *type; + gboolean requested_by_caller; + gboolean already_in = FALSE; + + firmware = OSINFO_FIRMWARE(osinfo_list_get_nth(OSINFO_LIST(os->priv->firmwares), i)); + arch = osinfo_firmware_get_architecture(firmware); + type = osinfo_firmware_get_firmware_type(firmware); + requested_by_caller = TRUE; + + /* + * In case there's no filter, the firmware can be considered as + * requested_by_caller. + * + * In case there's a filter, let's ensure the firmware matches the + * filter before adding it to the final firmwares' list. + */ + if (foreach_data->filter != NULL && + !osinfo_filter_matches(foreach_data->filter, OSINFO_ENTITY(firmware))) + requested_by_caller = FALSE; + + /* + * In case the firmware is valid to be added, let's ensure the firmware + * is not already part of the firmware list. + * + * We can safely do this check here as the _foreach() function ensures + * we iterate through the latest child all the way back to the parent. + */ + if (requested_by_caller) { + for (j = 0; j < current_list_len; j++) { + OsinfoFirmware *in; + const gchar *in_arch; + const gchar *in_type; + + in = OSINFO_FIRMWARE( + osinfo_list_get_nth(OSINFO_LIST(foreach_data->firmwares), j)); + in_arch = osinfo_firmware_get_architecture(in); + in_type = osinfo_firmware_get_firmware_type(in); + + if (g_str_equal(arch, in_arch) && + g_str_equal(type, in_type)) { + already_in = TRUE; + break; + } + } + } + + /* + * Only add the firmware to the final list of firmwares in case it is + * requested by the caller and a newer entry is not yet part of the + * list. + */ + if (requested_by_caller && !already_in) + osinfo_list_add(OSINFO_LIST(out), OSINFO_ENTITY(firmware)); + } + + g_object_unref(foreach_data->firmwares); + foreach_data->firmwares = out; +} + +/** + * osinfo_os_get_complete_firmware_list: + * @os: an operating system + * @filter: (allow-none)(transfer none): an optional firmware property filter + * + * Get the complete firmwares matching a given filter, including the non-supported ones. + * + * Returns: (transfer full): A list of firmwares + * + * Since: 1.10.0 + */ +OsinfoFirmwareList *osinfo_os_get_complete_firmware_list(OsinfoOs *os, OsinfoFilter *filter) +{ + struct GetAllFirmwaresData foreach_data; + + g_return_val_if_fail(OSINFO_IS_OS(os), NULL); + g_return_val_if_fail(!filter || OSINFO_IS_FILTER(filter), NULL); + + foreach_data.filter = filter; + foreach_data.firmwares = osinfo_firmwarelist_new(); + + osinfo_product_foreach_related(OSINFO_PRODUCT(os), + OSINFO_PRODUCT_FOREACH_FLAG_DERIVES_FROM | + OSINFO_PRODUCT_FOREACH_FLAG_CLONES, + get_all_firmwares_cb, + &foreach_data); + + return foreach_data.firmwares; +} + /** * osinfo_os_add_firmware: * @os: an operating system |