diff --git a/meson.build b/meson.build index d47859f9f..2de78d74e 100644 --- a/meson.build +++ b/meson.build @@ -227,6 +227,7 @@ plugin_deps += giounix plugin_deps += gmodule plugin_deps += gusb plugin_deps += soup +plugin_deps += libarchive subdir('data') subdir('docs') diff --git a/plugins/raspberrypi/fu-plugin-raspberrypi.c b/plugins/raspberrypi/fu-plugin-raspberrypi.c index 02ed29f29..6797dad41 100644 --- a/plugins/raspberrypi/fu-plugin-raspberrypi.c +++ b/plugins/raspberrypi/fu-plugin-raspberrypi.c @@ -22,8 +22,6 @@ #include "config.h" #include -#include -#include #include #include "fu-plugin.h" @@ -143,23 +141,6 @@ fu_plugin_raspberrypi_parse_firmware (FuDevice *device, const gchar *fn, GError return TRUE; } -static gboolean -fu_plugin_raspberrypi_explode_file (struct archive_entry *entry, const gchar *dir) -{ - const gchar *tmp; - g_autofree gchar *buf = NULL; - - /* no output file */ - if (archive_entry_pathname (entry) == NULL) - return FALSE; - - /* update output path */ - tmp = archive_entry_pathname (entry); - buf = g_build_filename (dir, tmp, NULL); - archive_entry_update_pathname_utf8 (entry, buf); - return TRUE; -} - gboolean fu_plugin_update_online (FuPlugin *plugin, FuDevice *device, @@ -168,75 +149,19 @@ fu_plugin_update_online (FuPlugin *plugin, GError **error) { FuPluginData *data = fu_plugin_get_data (plugin); - gboolean ret = TRUE; - gboolean valid; - int r; - struct archive *arch = NULL; - struct archive_entry *entry; g_autofree gchar *fwfn = NULL; /* decompress anything matching either glob */ - fu_plugin_set_status (plugin, FWUPD_STATUS_DECOMPRESSING); - arch = archive_read_new (); - archive_read_support_format_all (arch); - archive_read_support_filter_all (arch); - r = archive_read_open_memory (arch, - (void *) g_bytes_get_data (blob_fw, NULL), - (size_t) g_bytes_get_size (blob_fw)); - if (r) { - ret = FALSE; - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_INTERNAL, - "Cannot open: %s", - archive_error_string (arch)); - goto out; - } fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_WRITE); - for (;;) { - g_autofree gchar *path = NULL; - r = archive_read_next_header (arch, &entry); - if (r == ARCHIVE_EOF) - break; - if (r != ARCHIVE_OK) { - ret = FALSE; - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_INTERNAL, - "Cannot read header: %s", - archive_error_string (arch)); - goto out; - } - - /* only extract if valid */ - valid = fu_plugin_raspberrypi_explode_file (entry, data->fw_dir); - if (!valid) - continue; - r = archive_read_extract (arch, entry, 0); - if (r != ARCHIVE_OK) { - ret = FALSE; - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_INTERNAL, - "Cannot extract: %s", - archive_error_string (arch)); - goto out; - } - } + if (!fu_common_extract_archive (blob_fw, data->fw_dir, error)) + return FALSE; /* get the new VC build info */ fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_VERIFY); fwfn = g_build_filename (data->fw_dir, FU_PLUGIN_RPI_FIRMWARE_FILENAME, NULL); - if (!fu_plugin_raspberrypi_parse_firmware (device, fwfn, error)) - return FALSE; -out: - if (arch != NULL) { - archive_read_close (arch); - archive_read_free (arch); - } - return ret; + return fu_plugin_raspberrypi_parse_firmware (device, fwfn, error); } void diff --git a/plugins/raspberrypi/fu-self-test.c b/plugins/raspberrypi/fu-self-test.c index 7c8d68c52..b60f5d3a7 100644 --- a/plugins/raspberrypi/fu-self-test.c +++ b/plugins/raspberrypi/fu-self-test.c @@ -108,7 +108,7 @@ fu_plugin_raspberrypi_func (void) FWUPD_INSTALL_FLAG_NONE, &error); g_assert_no_error (error); g_assert (ret); - g_assert_cmpint (cnt, ==, 3); + g_assert_cmpint (cnt, ==, 2); /* check the file was exploded to the right place */ g_assert (g_file_test ("/tmp/rpiboot/start.elf", G_FILE_TEST_EXISTS)); diff --git a/plugins/raspberrypi/meson.build b/plugins/raspberrypi/meson.build index 6b267ab88..a8864d6ad 100644 --- a/plugins/raspberrypi/meson.build +++ b/plugins/raspberrypi/meson.build @@ -19,7 +19,6 @@ shared_module('fu_plugin_raspberrypi', ], dependencies : [ plugin_deps, - libarchive, ], ) @@ -41,7 +40,6 @@ if get_option('enable-tests') dependencies : [ plugin_deps, sqlite, - libarchive, valgrind, ], link_with : [ diff --git a/src/fu-common.c b/src/fu-common.c index 5f64a8eb0..c42c31225 100644 --- a/src/fu-common.c +++ b/src/fu-common.c @@ -22,6 +22,8 @@ #include #include +#include +#include #include "fwupd-error.h" @@ -110,3 +112,93 @@ fu_common_get_contents_fd (gint fd, gsize count, GError **error) } return g_steal_pointer (&blob); } + +static gboolean +fu_common_extract_archive_entry (struct archive_entry *entry, const gchar *dir) +{ + const gchar *tmp; + g_autofree gchar *buf = NULL; + + /* no output file */ + if (archive_entry_pathname (entry) == NULL) + return FALSE; + + /* update output path */ + tmp = archive_entry_pathname (entry); + buf = g_build_filename (dir, tmp, NULL); + archive_entry_update_pathname_utf8 (entry, buf); + return TRUE; +} + +/** + * fu_common_extract_archive: + * @blob: a #GBytes archive as a blob + * @directory: a directory name to extract to + * @error: A #GError, or %NULL + * + * Extracts an achive to a directory. + * + * Returns: %TRUE for success + **/ +gboolean +fu_common_extract_archive (GBytes *blob, const gchar *dir, GError **error) +{ + gboolean ret = TRUE; + int r; + struct archive *arch = NULL; + struct archive_entry *entry; + + /* decompress anything matching either glob */ + arch = archive_read_new (); + archive_read_support_format_all (arch); + archive_read_support_filter_all (arch); + r = archive_read_open_memory (arch, + (void *) g_bytes_get_data (blob, NULL), + (size_t) g_bytes_get_size (blob)); + if (r != 0) { + ret = FALSE; + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "Cannot open: %s", + archive_error_string (arch)); + goto out; + } + for (;;) { + gboolean valid; + g_autofree gchar *path = NULL; + r = archive_read_next_header (arch, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + ret = FALSE; + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "Cannot read header: %s", + archive_error_string (arch)); + goto out; + } + + /* only extract if valid */ + valid = fu_common_extract_archive_entry (entry, dir); + if (!valid) + continue; + r = archive_read_extract (arch, entry, 0); + if (r != ARCHIVE_OK) { + ret = FALSE; + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "Cannot extract: %s", + archive_error_string (arch)); + goto out; + } + } +out: + if (arch != NULL) { + archive_read_close (arch); + archive_read_free (arch); + } + return ret; +} diff --git a/src/fu-common.h b/src/fu-common.h index 8b951e197..903affafd 100644 --- a/src/fu-common.h +++ b/src/fu-common.h @@ -32,5 +32,8 @@ GBytes *fu_common_get_contents_bytes (const gchar *filename, GBytes *fu_common_get_contents_fd (gint fd, gsize count, GError **error); +gboolean fu_common_extract_archive (GBytes *blob, + const gchar *dir, + GError **error); #endif /* __FU_COMMON_H__ */ diff --git a/src/fu-plugin.h b/src/fu-plugin.h index 6bcfab73a..c01da174b 100644 --- a/src/fu-plugin.h +++ b/src/fu-plugin.h @@ -27,6 +27,7 @@ #include #include +#include "fu-common.h" #include "fu-device.h" #include "fu-hwids.h" diff --git a/src/meson.build b/src/meson.build index 5a7953261..8ba61192c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -7,6 +7,7 @@ install_data(['org.freedesktop.fwupd.xml'], libfwupdprivate = static_library( 'fwupdprivate', sources : [ + 'fu-common.c', 'fu-device.c', 'fu-hwids.c', 'fu-pending.c', @@ -52,6 +53,7 @@ executable( polkit, soup, sqlite, + libarchive, ], link_with : [ fwupd, @@ -104,6 +106,7 @@ executable( gpgme, gpgerror, valgrind, + libarchive, ], link_with : fwupd, c_args : [