From 069fa56f1ab0d9cce8fa8e38f71e2aec27d52019 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Fri, 16 Dec 2022 16:46:04 +0000 Subject: [PATCH] Add fu_archive_firmware_get_image_fnmatch() for future use It's useful to get images from archives by a specific filename extension. --- contrib/fwupd.spec.in | 1 + libfwupdplugin/fu-archive-firmware.c | 50 ++++++++++++++++++++++++++++ libfwupdplugin/fu-archive-firmware.h | 4 +++ libfwupdplugin/fu-self-test.c | 40 ++++++++++++++++++++++ libfwupdplugin/fwupdplugin.map | 1 + libfwupdplugin/meson.build | 1 + libfwupdplugin/tests/meson.build | 13 ++++++++ 7 files changed, 110 insertions(+) diff --git a/contrib/fwupd.spec.in b/contrib/fwupd.spec.in index 321876033..3fefe3a32 100644 --- a/contrib/fwupd.spec.in +++ b/contrib/fwupd.spec.in @@ -459,6 +459,7 @@ done %{_datadir}/installed-tests/fwupd/*.test %{_datadir}/installed-tests/fwupd/*.cab %{_datadir}/installed-tests/fwupd/*.sh +%{_datadir}/installed-tests/fwupd/*.zip %if 0%{?have_uefi} %{_datadir}/installed-tests/fwupd/efi %endif diff --git a/libfwupdplugin/fu-archive-firmware.c b/libfwupdplugin/fu-archive-firmware.c index 8ddf3a6b0..bda8fb67b 100644 --- a/libfwupdplugin/fu-archive-firmware.c +++ b/libfwupdplugin/fu-archive-firmware.c @@ -12,6 +12,7 @@ #include "fu-archive-firmware.h" #include "fu-archive.h" #include "fu-common.h" +#include "fu-path.h" /** * FuArchiveFirmware: @@ -142,6 +143,55 @@ fu_archive_firmware_set_compression(FuArchiveFirmware *self, FuArchiveCompressio priv->compression = compression; } +/** + * fu_archive_firmware_get_image_fnmatch: + * @self: a #FuPlugin + * @pattern: (not nullable) a glob pattern, e.g. `*foo*` + * @error: (nullable): optional return location for an error + * + * Gets a single firmware image using the image ID pattern. It is also an error for multiple images + * to match. + * + * Returns: (transfer full): a #FuFirmware, or %NULL if the image is not found + * + * Since: 1.8.9 + **/ +FuFirmware * +fu_archive_firmware_get_image_fnmatch(FuArchiveFirmware *self, const gchar *pattern, GError **error) +{ + g_autoptr(FuFirmware) img_match = NULL; + g_autoptr(GPtrArray) imgs = fu_firmware_get_images(FU_FIRMWARE(self)); + + g_return_val_if_fail(FU_IS_ARCHIVE_FIRMWARE(self), NULL); + g_return_val_if_fail(pattern != NULL, NULL); + g_return_val_if_fail(error == NULL || *error == NULL, NULL); + + for (guint i = 0; i < imgs->len; i++) { + FuFirmware *img = g_ptr_array_index(imgs, i); + const gchar *fn = fu_firmware_get_id(img); + if (!fu_path_fnmatch(pattern, fn)) + continue; + if (img_match != NULL) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "multiple images matched %s", + pattern); + return NULL; + } + img_match = g_object_ref(img); + } + if (img_match == NULL) { + g_set_error(error, + G_IO_ERROR, + G_IO_ERROR_NOT_FOUND, + "no image matched %s", + pattern); + return NULL; + } + return g_steal_pointer(&img_match); +} + static GBytes * fu_archive_firmware_write(FuFirmware *firmware, GError **error) { diff --git a/libfwupdplugin/fu-archive-firmware.h b/libfwupdplugin/fu-archive-firmware.h index 83283e6ea..95e961193 100644 --- a/libfwupdplugin/fu-archive-firmware.h +++ b/libfwupdplugin/fu-archive-firmware.h @@ -28,3 +28,7 @@ FuArchiveCompression fu_archive_firmware_get_compression(FuArchiveFirmware *self); void fu_archive_firmware_set_compression(FuArchiveFirmware *self, FuArchiveCompression compression); +FuFirmware * +fu_archive_firmware_get_image_fnmatch(FuArchiveFirmware *self, + const gchar *pattern, + GError **error); diff --git a/libfwupdplugin/fu-self-test.c b/libfwupdplugin/fu-self-test.c index ea82b362e..fa49cebeb 100644 --- a/libfwupdplugin/fu-self-test.c +++ b/libfwupdplugin/fu-self-test.c @@ -2510,6 +2510,45 @@ fu_firmware_new_from_gtypes_func(void) g_assert_null(firmware3); } +static void +fu_firmware_archive_func(void) +{ + gboolean ret; + g_autofree gchar *fn = NULL; + g_autoptr(FuFirmware) firmware = fu_archive_firmware_new(); + g_autoptr(FuFirmware) img_asc = NULL; + g_autoptr(FuFirmware) img_bin = NULL; + g_autoptr(FuFirmware) img_both = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GFile) file = NULL; + + fn = g_test_build_filename(G_TEST_BUILT, "tests", "firmware.zip", NULL); + file = g_file_new_for_path(fn); + ret = fu_firmware_parse_file(firmware, file, FWUPD_INSTALL_FLAG_NONE, &error); + g_assert_no_error(error); + g_assert_true(ret); + g_assert_cmpint(fu_archive_firmware_get_format(FU_ARCHIVE_FIRMWARE(firmware)), + ==, + FU_ARCHIVE_FORMAT_UNKNOWN); + g_assert_cmpint(fu_archive_firmware_get_compression(FU_ARCHIVE_FIRMWARE(firmware)), + ==, + FU_ARCHIVE_COMPRESSION_UNKNOWN); + + img_bin = + fu_archive_firmware_get_image_fnmatch(FU_ARCHIVE_FIRMWARE(firmware), "*.bin", &error); + g_assert_no_error(error); + g_assert_nonnull(img_bin); + img_asc = fu_archive_firmware_get_image_fnmatch(FU_ARCHIVE_FIRMWARE(firmware), + "*.bin.asc", + &error); + g_assert_no_error(error); + g_assert_nonnull(img_bin); + img_both = + fu_archive_firmware_get_image_fnmatch(FU_ARCHIVE_FIRMWARE(firmware), "*.bin*", &error); + g_assert_error(error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT); + g_assert_null(img_both); +} + static void fu_firmware_linear_func(void) { @@ -3770,6 +3809,7 @@ main(int argc, char **argv) g_test_add_func("/fwupd/smbios{class}", fu_smbios_class_func); g_test_add_func("/fwupd/firmware", fu_firmware_func); g_test_add_func("/fwupd/firmware{common}", fu_firmware_common_func); + g_test_add_func("/fwupd/firmware{archive}", fu_firmware_archive_func); g_test_add_func("/fwupd/firmware{linear}", fu_firmware_linear_func); g_test_add_func("/fwupd/firmware{dedupe}", fu_firmware_dedupe_func); g_test_add_func("/fwupd/firmware{build}", fu_firmware_build_func); diff --git a/libfwupdplugin/fwupdplugin.map b/libfwupdplugin/fwupdplugin.map index e972257cc..e9e3ed08d 100644 --- a/libfwupdplugin/fwupdplugin.map +++ b/libfwupdplugin/fwupdplugin.map @@ -1143,6 +1143,7 @@ LIBFWUPDPLUGIN_1.8.7 { LIBFWUPDPLUGIN_1.8.9 { global: + fu_archive_firmware_get_image_fnmatch; fu_byte_array_to_string; fu_version_from_uint24; local: *; diff --git a/libfwupdplugin/meson.build b/libfwupdplugin/meson.build index 71667b6bc..db6b234a1 100644 --- a/libfwupdplugin/meson.build +++ b/libfwupdplugin/meson.build @@ -340,6 +340,7 @@ if get_option('tests') env.set('G_TEST_BUILDDIR', meson.current_build_dir()) e = executable( 'fwupdplugin-self-test', + installed_firmware_zip, sources: [ 'fu-self-test.c' ], diff --git a/libfwupdplugin/tests/meson.build b/libfwupdplugin/tests/meson.build index 74a08ca33..cad5ab138 100644 --- a/libfwupdplugin/tests/meson.build +++ b/libfwupdplugin/tests/meson.build @@ -1,2 +1,15 @@ subdir('colorhug') subdir('efi') + +installed_firmware_zip = custom_target('installed-firmware-zip', + input: [ + 'colorhug/firmware.bin', + 'colorhug/firmware.bin.asc', + ], + output: 'firmware.zip', + command: [ + python3, '-m', 'zipfile', '-c', '@OUTPUT@', '@INPUT@', + ], + install: true, + install_dir: installed_test_datadir, +)