From 4a6b31229773841bc3da190e02471f4c8e2d8ac6 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Mon, 18 May 2020 13:34:03 +0100
Subject: [PATCH] runtime: Factor out a struct to hold architecture-specific
 details

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 src/runtime.c | 189 +++++++++++++++++++++++++++++++-------------------
 1 file changed, 117 insertions(+), 72 deletions(-)

diff --git a/src/runtime.c b/src/runtime.c
index e9a9a5662..3a31f3537 100644
--- a/src/runtime.c
+++ b/src/runtime.c
@@ -108,6 +108,73 @@ static const char * const libquals[] =
 G_STATIC_ASSERT (G_N_ELEMENTS (libquals)
                  == G_N_ELEMENTS (multiarch_tuples) - 1);
 
+typedef struct
+{
+  gsize multiarch_index;
+  const char *tuple;
+  gchar *capsule_capture_libs_basename;
+  gchar *capsule_capture_libs;
+  gchar *libdir_on_host;
+  gchar *libdir_in_container;
+  const char *libqual;
+  gchar *ld_so;
+} RuntimeArchitecture;
+
+static gboolean
+runtime_architecture_init (RuntimeArchitecture *self,
+                           PvRuntime *runtime)
+{
+  const gchar *argv[] = { NULL, "--print-ld.so", NULL };
+
+  g_return_val_if_fail (self->multiarch_index < G_N_ELEMENTS (libquals), FALSE);
+  g_return_val_if_fail (self->multiarch_index < G_N_ELEMENTS (multiarch_tuples) - 1,
+                        FALSE);
+  g_return_val_if_fail (self->tuple == NULL, FALSE);
+
+  self->tuple = multiarch_tuples[self->multiarch_index];
+  g_return_val_if_fail (self->tuple != NULL, FALSE);
+  self->libqual = libquals[self->multiarch_index];
+
+  self->capsule_capture_libs_basename = g_strdup_printf ("%s-capsule-capture-libs",
+                                                         self->tuple);
+  self->capsule_capture_libs = g_build_filename (runtime->tools_dir,
+                                                 self->capsule_capture_libs_basename,
+                                                 NULL);
+  self->libdir_on_host = g_build_filename (runtime->overrides, "lib",
+                                           self->tuple, NULL);
+  self->libdir_in_container = g_build_filename ("/overrides", "lib",
+                                                self->tuple, NULL);
+
+  /* This has the side-effect of testing whether we can run binaries
+   * for this architecture on the host system. */
+  argv[0] = self->capsule_capture_libs;
+  self->ld_so = pv_capture_output (argv, NULL);
+
+  if (self->ld_so == NULL)
+    {
+      g_debug ("Cannot determine ld.so for %s", self->tuple);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+runtime_architecture_clear (RuntimeArchitecture *self)
+{
+  self->multiarch_index = G_MAXSIZE;
+  self->tuple = NULL;
+  self->libqual = NULL;
+  g_clear_pointer (&self->capsule_capture_libs_basename, g_free);
+  g_clear_pointer (&self->capsule_capture_libs, g_free);
+  g_clear_pointer (&self->libdir_on_host, g_free);
+  g_clear_pointer (&self->libdir_in_container, g_free);
+  g_clear_pointer (&self->ld_so, g_free);
+}
+
+G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (RuntimeArchitecture,
+                                  runtime_architecture_clear)
+
 static gboolean pv_runtime_use_host_graphics_stack (PvRuntime *self,
                                                     FlatpakBwrap *bwrap,
                                                     GError **error);
@@ -1176,40 +1243,22 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
 
   for (i = 0; i < G_N_ELEMENTS (multiarch_tuples) - 1; i++)
     {
-      g_autofree gchar *tool = g_strdup_printf ("%s-capsule-capture-libs",
-                                                multiarch_tuples[i]);
-      g_autofree gchar *capsule_capture_libs = NULL;
-      g_autofree gchar *ld_so = NULL;
-      const gchar *argv[] = { NULL, "--print-ld.so", NULL };
+      g_auto (RuntimeArchitecture) arch_on_stack = { i };
+      RuntimeArchitecture *arch = &arch_on_stack;
 
       g_debug ("Checking for %s libraries...", multiarch_tuples[i]);
 
-      capsule_capture_libs = g_build_filename (self->tools_dir, tool, NULL);
-      argv[0] = capsule_capture_libs;
-
-      /* This has the side-effect of testing whether we can run binaries
-       * for this architecture on the host system. */
-      ld_so = pv_capture_output (argv, NULL);
-
-      if (ld_so != NULL)
+      if (runtime_architecture_init (arch, self))
         {
           g_auto(GStrv) dirs = NULL;
           g_autoptr(FlatpakBwrap) temp_bwrap = NULL;
-          g_autofree gchar *libdir_in_container = g_build_filename ("/overrides",
-                                                                    "lib",
-                                                                    multiarch_tuples[i],
-                                                                    NULL);
-          g_autofree gchar *libdir_on_host = g_build_filename (self->overrides, "lib",
-                                                               multiarch_tuples[i],
-                                                               NULL);
-          g_autofree gchar *this_dri_path_on_host = g_build_filename (libdir_on_host,
+          g_autofree gchar *this_dri_path_on_host = g_build_filename (arch->libdir_on_host,
                                                                       "dri", NULL);
-          g_autofree gchar *this_dri_path_in_container = g_build_filename (libdir_in_container,
+          g_autofree gchar *this_dri_path_in_container = g_build_filename (arch->libdir_in_container,
                                                                            "dri", NULL);
           g_autofree gchar *libc = NULL;
           g_autofree gchar *ld_so_in_runtime = NULL;
           g_autofree gchar *libdrm = NULL;
-          const gchar *libqual = NULL;
           g_autoptr(SrtObjectList) vdpau_drivers = NULL;
           g_autoptr(SrtObjectList) va_api_drivers = NULL;
 
@@ -1225,7 +1274,7 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
             return FALSE;
 
           flatpak_bwrap_add_args (temp_bwrap,
-                                  "readlink", "-e", ld_so,
+                                  "readlink", "-e", arch->ld_so,
                                   NULL);
           flatpak_bwrap_finish (temp_bwrap);
 
@@ -1237,26 +1286,28 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
           if (ld_so_in_runtime == NULL)
             {
               g_debug ("Container does not have %s so it cannot run "
-                       "%s binaries", ld_so, multiarch_tuples[i]);
+                       "%s binaries",
+                       arch->ld_so, arch->tuple);
               continue;
             }
 
           any_architecture_works = TRUE;
-          g_debug ("Container path: %s -> %s", ld_so, ld_so_in_runtime);
+          g_debug ("Container path: %s -> %s",
+                   arch->ld_so, ld_so_in_runtime);
 
           pv_search_path_append (dri_path, this_dri_path_in_container);
 
-          g_mkdir_with_parents (libdir_on_host, 0755);
+          g_mkdir_with_parents (arch->libdir_on_host, 0755);
           g_mkdir_with_parents (this_dri_path_on_host, 0755);
 
           g_debug ("Collecting graphics drivers from host system...");
 
           temp_bwrap = pv_bwrap_copy (self->container_access_adverb);
           flatpak_bwrap_add_args (temp_bwrap,
-                                  capsule_capture_libs,
+                                  arch->capsule_capture_libs,
                                   "--container", self->container_access,
                                   "--link-target", "/run/host",
-                                  "--dest", libdir_on_host,
+                                  "--dest", arch->libdir_on_host,
                                   "--provider", "/",
                                   /* Mesa GLX, etc. */
                                   "gl:",
@@ -1317,7 +1368,7 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
           g_clear_pointer (&temp_bwrap, flatpak_bwrap_free);
 
           g_debug ("Collecting %s EGL drivers from host system...",
-                   multiarch_tuples[i]);
+                   arch->tuple);
 
           for (j = 0; j < egl_icd_details->len; j++)
             {
@@ -1331,11 +1382,11 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
               g_assert (details->resolved_library != NULL);
 
               if (!bind_icd (self,
-                             i,
+                             arch->multiarch_index,
                              j,
-                             capsule_capture_libs,
-                             libdir_on_host,
-                             libdir_in_container,
+                             arch->capsule_capture_libs,
+                             arch->libdir_on_host,
+                             arch->libdir_in_container,
                              "glvnd",
                              details,
                              error))
@@ -1343,7 +1394,7 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
             }
 
           g_debug ("Collecting %s Vulkan drivers from host system...",
-                   multiarch_tuples[i]);
+                   arch->tuple);
 
           for (j = 0; j < vulkan_icd_details->len; j++)
             {
@@ -1357,20 +1408,20 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
               g_assert (details->resolved_library != NULL);
 
               if (!bind_icd (self,
-                             i,
+                             arch->multiarch_index,
                              j,
-                             capsule_capture_libs,
-                             libdir_on_host,
-                             libdir_in_container,
+                             arch->capsule_capture_libs,
+                             arch->libdir_on_host,
+                             arch->libdir_in_container,
                              "vulkan",
                              details,
                              error))
                 return FALSE;
             }
 
-          g_debug ("Enumerating %s VDPAU ICDs on host system...", multiarch_tuples[i]);
+          g_debug ("Enumerating %s VDPAU ICDs on host system...", arch->tuple);
           vdpau_drivers = srt_system_info_list_vdpau_drivers (system_info,
-                                                              multiarch_tuples[i],
+                                                              arch->tuple,
                                                               SRT_DRIVER_FLAGS_NONE);
 
           for (icd_iter = vdpau_drivers; icd_iter != NULL; icd_iter = icd_iter->next)
@@ -1384,20 +1435,21 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
                * be located in a single directory, so by definition we can't have
                * collisions */
               if (!bind_icd (self,
-                             i,
+                             arch->multiarch_index,
                              G_MAXSIZE,
-                             capsule_capture_libs,
-                             libdir_on_host,
-                             libdir_in_container,
+                             arch->capsule_capture_libs,
+                             arch->libdir_on_host,
+                             arch->libdir_in_container,
                              "vdpau",
                              details,
                              error))
                 return FALSE;
             }
 
-          g_debug ("Enumerating %s VA-API drivers on host system...", multiarch_tuples[i]);
+          g_debug ("Enumerating %s VA-API drivers on host system...",
+                   arch->tuple);
           va_api_drivers = srt_system_info_list_va_api_drivers (system_info,
-                                                                multiarch_tuples[i],
+                                                                arch->tuple,
                                                                 SRT_DRIVER_FLAGS_NONE);
 
           /* Guess that there will be about the same number of VA-API ICDs
@@ -1420,9 +1472,9 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
               if (!bind_icd (self,
                              0,
                              j,
-                             capsule_capture_libs,
-                             libdir_on_host,
-                             libdir_in_container,
+                             arch->capsule_capture_libs,
+                             arch->libdir_on_host,
+                             arch->libdir_in_container,
                              "dri",
                              details,
                              error))
@@ -1431,7 +1483,7 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
               g_ptr_array_add (va_api_icd_details, g_steal_pointer (&details));
             }
 
-          libc = g_build_filename (libdir_on_host, "libc.so.6", NULL);
+          libc = g_build_filename (arch->libdir_on_host, "libc.so.6", NULL);
 
           /* If we are going to use the host system's libc6 (likely)
            * then we have to use its ld.so too. */
@@ -1442,9 +1494,9 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
 
               g_debug ("Making host ld.so visible in container");
 
-              ld_so_in_host = flatpak_canonicalize_filename (ld_so);
-              g_debug ("Host path: %s -> %s", ld_so, ld_so_in_host);
-              g_debug ("Container path: %s -> %s", ld_so, ld_so_in_runtime);
+              ld_so_in_host = flatpak_canonicalize_filename (arch->ld_so);
+              g_debug ("Host path: %s -> %s", arch->ld_so, ld_so_in_host);
+              g_debug ("Container path: %s -> %s", arch->ld_so, ld_so_in_runtime);
               flatpak_bwrap_add_args (bwrap,
                                       "--ro-bind", ld_so_in_host,
                                       ld_so_in_runtime,
@@ -1455,10 +1507,10 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
               g_assert (temp_bwrap == NULL);
               temp_bwrap = pv_bwrap_copy (self->container_access_adverb);
               flatpak_bwrap_add_args (temp_bwrap,
-                                      capsule_capture_libs,
+                                      arch->capsule_capture_libs,
                                       "--container", self->container_access,
                                       "--link-target", "/run/host",
-                                      "--dest", libdir_on_host,
+                                      "--dest", arch->libdir_on_host,
                                       "--provider", "/",
                                       "if-exists:libidn2.so.0",
                                       NULL);
@@ -1518,7 +1570,7 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
               self->all_libc_from_host = FALSE;
             }
 
-          libdrm = g_build_filename (libdir_on_host, "libdrm.so.2", NULL);
+          libdrm = g_build_filename (arch->libdir_on_host, "libdrm.so.2", NULL);
 
           /* If we have libdrm.so.2 in overrides we also want to mount
            * ${prefix}/share/libdrm from the host. ${prefix} is derived from
@@ -1536,7 +1588,7 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
 
                   dir = g_path_get_dirname (target);
 
-                  lib_multiarch = g_build_filename ("/lib", multiarch_tuples[i], NULL);
+                  lib_multiarch = g_build_filename ("/lib", arch->tuple, NULL);
                   if (g_str_has_suffix (dir, lib_multiarch))
                     dir[strlen (dir) - strlen (lib_multiarch)] = '\0';
                   else if (g_str_has_suffix (dir, "/lib64"))
@@ -1569,29 +1621,22 @@ pv_runtime_use_host_graphics_stack (PvRuntime *self,
               all_libdrm_from_host = FALSE;
             }
 
-          /* /lib32 or /lib64 */
-          g_assert (i < G_N_ELEMENTS (libquals));
-          libqual = libquals[i];
-
           dirs = g_new0 (gchar *, 7);
-          dirs[0] = g_build_filename ("/lib", multiarch_tuples[i], NULL);
-          dirs[1] = g_build_filename ("/usr", "lib", multiarch_tuples[i], NULL);
+          dirs[0] = g_build_filename ("/lib", arch->tuple, NULL);
+          dirs[1] = g_build_filename ("/usr", "lib", arch->tuple, NULL);
           dirs[2] = g_strdup ("/lib");
           dirs[3] = g_strdup ("/usr/lib");
-          dirs[4] = g_build_filename ("/", libqual, NULL);
-          dirs[5] = g_build_filename ("/usr", libqual, NULL);
+          dirs[4] = g_build_filename ("/", arch->libqual, NULL);
+          dirs[5] = g_build_filename ("/usr", arch->libqual, NULL);
 
           for (j = 0; j < 6; j++)
             {
-              if (!try_bind_dri (self, bwrap, capsule_capture_libs, dirs[j],
-                                 libdir_on_host, error))
+              if (!try_bind_dri (self, bwrap,
+                                 arch->capsule_capture_libs,
+                                 dirs[j], arch->libdir_on_host, error))
                 return FALSE;
             }
         }
-      else
-        {
-          g_debug ("Cannot determine ld.so for %s", multiarch_tuples[i]);
-        }
     }
 
   if (!any_architecture_works)
-- 
GitLab