From d721b352cd9fbee23086845d5e1d3111ffd3795a Mon Sep 17 00:00:00 2001 From: Simon McVittie <smcv@collabora.com> Date: Thu, 10 Dec 2020 20:47:34 +0000 Subject: [PATCH] runtime: Factor out code to take glibc-related things from provider Signed-off-by: Simon McVittie <smcv@collabora.com> --- pressure-vessel/runtime.c | 217 ++++++++++++++++++++------------------ 1 file changed, 115 insertions(+), 102 deletions(-) diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c index 30ee1ee21..925d96ea3 100644 --- a/pressure-vessel/runtime.c +++ b/pressure-vessel/runtime.c @@ -3049,6 +3049,119 @@ pv_runtime_finish_libdrm_data (PvRuntime *self, } } +static gboolean +pv_runtime_finish_libc_family (PvRuntime *self, + FlatpakBwrap *bwrap, + GHashTable *gconv_in_provider, + GError **error) +{ + g_autofree gchar *localedef = NULL; + g_autofree gchar *ldconfig = NULL; + g_autofree gchar *locale = NULL; + GHashTableIter iter; + const gchar *gconv_path; + + if (self->any_libc_from_provider && !self->all_libc_from_provider) + { + /* + * This shouldn't happen. It would mean that there exist at least + * two architectures (let's say aaa and bbb) for which we have: + * provider libc6:aaa < container libc6 < provider libc6:bbb + * (we know that the container's libc6:aaa and libc6:bbb are + * constrained to be the same version because that's how multiarch + * works). + * + * If the provider system locales work OK with both the aaa and bbb + * versions, let's assume they will also work with the intermediate + * version from the container... + */ + g_warning ("Using glibc from provider system for some but not all " + "architectures! Arbitrarily using provider locales."); + } + + if (self->any_libc_from_provider) + { + g_debug ("Making provider locale data visible in container"); + + if (!pv_runtime_take_from_provider (self, bwrap, + "/usr/lib/locale", + "/usr/lib/locale", + TAKE_FROM_PROVIDER_FLAGS_IF_EXISTS, + error)) + return FALSE; + + if (!pv_runtime_take_from_provider (self, bwrap, + "/usr/share/i18n", + "/usr/share/i18n", + TAKE_FROM_PROVIDER_FLAGS_IF_EXISTS, + error)) + return FALSE; + + localedef = pv_runtime_search_in_path_and_bin (self, "localedef"); + + if (localedef == NULL) + { + g_warning ("Cannot find localedef"); + } + else if (!pv_runtime_take_from_provider (self, bwrap, localedef, + "/usr/bin/localedef", + TAKE_FROM_PROVIDER_FLAGS_IF_CONTAINER_COMPATIBLE, + error)) + { + return FALSE; + } + + locale = pv_runtime_search_in_path_and_bin (self, "locale"); + + if (locale == NULL) + { + g_warning ("Cannot find locale"); + } + else if (!pv_runtime_take_from_provider (self, bwrap, locale, + "/usr/bin/locale", + TAKE_FROM_PROVIDER_FLAGS_IF_CONTAINER_COMPATIBLE, + error)) + { + return FALSE; + } + + ldconfig = pv_runtime_search_in_path_and_bin (self, "ldconfig"); + + if (ldconfig == NULL) + { + g_warning ("Cannot find ldconfig"); + } + else if (!pv_runtime_take_from_provider (self, bwrap, + ldconfig, + "/sbin/ldconfig", + TAKE_FROM_PROVIDER_FLAGS_NONE, + error)) + { + return FALSE; + } + + g_debug ("Making provider gconv modules visible in container"); + + g_hash_table_iter_init (&iter, gconv_in_provider); + while (g_hash_table_iter_next (&iter, (gpointer *)&gconv_path, NULL)) + { + if (!pv_runtime_take_from_provider (self, bwrap, + gconv_path, + gconv_path, + TAKE_FROM_PROVIDER_FLAGS_IF_DIR, + error)) + return FALSE; + } + } + else + { + g_debug ("Using included locale data from container"); + g_debug ("Using included gconv modules from container"); + } + + return TRUE; +} + static gboolean pv_runtime_use_provider_graphics_stack (PvRuntime *self, FlatpakBwrap *bwrap, @@ -3066,9 +3179,6 @@ pv_runtime_use_provider_graphics_stack (PvRuntime *self, g_autoptr(GString) vulkan_imp_layer_path = g_string_new (""); g_autoptr(GString) va_api_path = g_string_new (""); gboolean any_architecture_works = FALSE; - g_autofree gchar *localedef = NULL; - g_autofree gchar *ldconfig = NULL; - g_autofree gchar *locale = NULL; g_autoptr(SrtSystemInfo) system_info = srt_system_info_new (NULL); g_autoptr(SrtObjectList) egl_icds = NULL; g_autoptr(SrtObjectList) vulkan_icds = NULL; @@ -3088,8 +3198,6 @@ pv_runtime_use_provider_graphics_stack (PvRuntime *self, g_free, NULL); g_autoptr(GHashTable) gconv_in_provider = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - GHashTableIter iter; - const gchar *gconv_path; g_autofree gchar *provider_in_container_namespace_guarded = NULL; if (g_str_has_suffix (self->provider_in_container_namespace, "/")) provider_in_container_namespace_guarded = @@ -3480,103 +3588,8 @@ pv_runtime_use_provider_graphics_stack (PvRuntime *self, return FALSE; } - if (self->any_libc_from_provider && !self->all_libc_from_provider) - { - /* - * This shouldn't happen. It would mean that there exist at least - * two architectures (let's say aaa and bbb) for which we have: - * provider libc6:aaa < container libc6 < provider libc6:bbb - * (we know that the container's libc6:aaa and libc6:bbb are - * constrained to be the same version because that's how multiarch - * works). - * - * If the provider system locales work OK with both the aaa and bbb - * versions, let's assume they will also work with the intermediate - * version from the container... - */ - g_warning ("Using glibc from provider system for some but not all " - "architectures! Arbitrarily using provider locales."); - } - - if (self->any_libc_from_provider) - { - g_debug ("Making provider locale data visible in container"); - - if (!pv_runtime_take_from_provider (self, bwrap, - "/usr/lib/locale", - "/usr/lib/locale", - TAKE_FROM_PROVIDER_FLAGS_IF_EXISTS, - error)) - return FALSE; - - if (!pv_runtime_take_from_provider (self, bwrap, - "/usr/share/i18n", - "/usr/share/i18n", - TAKE_FROM_PROVIDER_FLAGS_IF_EXISTS, - error)) - return FALSE; - - localedef = pv_runtime_search_in_path_and_bin (self, "localedef"); - - if (localedef == NULL) - { - g_warning ("Cannot find localedef"); - } - else if (!pv_runtime_take_from_provider (self, bwrap, localedef, - "/usr/bin/localedef", - TAKE_FROM_PROVIDER_FLAGS_IF_CONTAINER_COMPATIBLE, - error)) - { - return FALSE; - } - - locale = pv_runtime_search_in_path_and_bin (self, "locale"); - - if (locale == NULL) - { - g_warning ("Cannot find locale"); - } - else if (!pv_runtime_take_from_provider (self, bwrap, locale, - "/usr/bin/locale", - TAKE_FROM_PROVIDER_FLAGS_IF_CONTAINER_COMPATIBLE, - error)) - { - return FALSE; - } - - ldconfig = pv_runtime_search_in_path_and_bin (self, "ldconfig"); - - if (ldconfig == NULL) - { - g_warning ("Cannot find ldconfig"); - } - else if (!pv_runtime_take_from_provider (self, bwrap, - ldconfig, - "/sbin/ldconfig", - TAKE_FROM_PROVIDER_FLAGS_NONE, - error)) - { - return FALSE; - } - - g_debug ("Making provider gconv modules visible in container"); - - g_hash_table_iter_init (&iter, gconv_in_provider); - while (g_hash_table_iter_next (&iter, (gpointer *)&gconv_path, NULL)) - { - if (!pv_runtime_take_from_provider (self, bwrap, - gconv_path, - gconv_path, - TAKE_FROM_PROVIDER_FLAGS_IF_DIR, - error)) - return FALSE; - } - } - else - { - g_debug ("Using included locale data from container"); - g_debug ("Using included gconv modules from container"); - } + if (!pv_runtime_finish_libc_family (self, bwrap, gconv_in_provider, error)) + return FALSE; if (!pv_runtime_finish_libdrm_data (self, bwrap, all_libdrm_from_provider, libdrm_data_in_provider, error)) -- GitLab