From 26b3be6440f25e1fc4b1119af59a7365a4004da2 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Fri, 23 Aug 2019 16:16:03 +0100
Subject: [PATCH] wrap: Skip architecture setup for architectures the runtime
 can't run

This opens up the possibility of amd64-only or i386-only runtimes,
and in particular a SteamRT chroot created by setup_chroot.sh is
either amd64-only or i386-only.

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 README.md  |  4 ----
 src/wrap.c | 51 +++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/README.md b/README.md
index 40da0413f..4227e009f 100644
--- a/README.md
+++ b/README.md
@@ -263,10 +263,6 @@ Instructions for testing
         $ ln -s /var/chroots/steamrt_scout_amd64 \
             ~/.steam/root/common/SteamLinuxRuntime/scout-chroot/files
 
-    Note that to use a `chroot` in this way, it must have at least
-    `libc6:amd64` and `libc6:i386` installed. `pressure-vessel` does not
-    currently support containers that do not have both word-sizes.
-
 * Launch a game once without pressure-vessel
 
 * Configure the launch options for the chosen game. Either use the Steam
diff --git a/src/wrap.c b/src/wrap.c
index 4f61ccf19..21d537749 100644
--- a/src/wrap.c
+++ b/src/wrap.c
@@ -1172,7 +1172,7 @@ bind_runtime (FlatpakBwrap *bwrap,
       argv[0] = tool_path;
 
       /* This has the side-effect of testing whether we can run binaries
-       * for this architecture */
+       * for this architecture on the host system. */
       ld_so = capture_output (argv, NULL);
 
       if (ld_so != NULL)
@@ -1192,8 +1192,36 @@ bind_runtime (FlatpakBwrap *bwrap,
           g_autofree gchar *this_dri_path_in_container = g_build_filename (libdir_in_container,
                                                                            "dri", NULL);
           g_autofree gchar *libc = NULL;
+          g_autofree gchar *ld_so_in_runtime = NULL;
           const gchar *libqual = NULL;
 
+          temp_bwrap = flatpak_bwrap_new (NULL);
+          flatpak_bwrap_add_args (temp_bwrap,
+                                  bwrap->argv->pdata[0],
+                                  NULL);
+
+          if (!bind_usr (temp_bwrap, runtime, "/", error))
+            return FALSE;
+
+          flatpak_bwrap_add_args (temp_bwrap,
+                                  "readlink", "-e", ld_so,
+                                  NULL);
+          flatpak_bwrap_finish (temp_bwrap);
+
+          ld_so_in_runtime = capture_output ((const char * const *) temp_bwrap->argv->pdata,
+                                             NULL);
+
+          g_clear_pointer (&temp_bwrap, flatpak_bwrap_free);
+
+          if (ld_so_in_runtime == NULL)
+            {
+              g_debug ("Container does not have %s so it cannot run "
+                       "%s binaries", ld_so, multiarch_tuples[i]);
+              continue;
+            }
+
+          g_debug ("Container path: %s -> %s", ld_so, ld_so_in_runtime);
+
           search_path_append (dri_path, this_dri_path_in_container);
 
           g_mkdir_with_parents (libdir_on_host, 0755);
@@ -1225,19 +1253,20 @@ bind_runtime (FlatpakBwrap *bwrap,
           if (!run_bwrap (temp_bwrap, error))
             return FALSE;
 
+          g_clear_pointer (&temp_bwrap, flatpak_bwrap_free);
+
           libc = g_build_filename (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. */
           if (g_file_test (libc, G_FILE_TEST_IS_SYMLINK))
             {
-              g_autofree gchar *real_path_in_host = NULL;
-              g_autofree gchar *real_path_in_runtime = NULL;
+              g_autofree gchar *ld_so_in_host = NULL;
 
               g_debug ("Making host ld.so visible in container");
 
-              real_path_in_host = flatpak_canonicalize_filename (ld_so);
-              g_debug ("Host path: %s -> %s", ld_so, real_path_in_host);
+              ld_so_in_host = flatpak_canonicalize_filename (ld_so);
+              g_debug ("Host path: %s -> %s", ld_so, ld_so_in_host);
 
               g_clear_pointer (&temp_bwrap, flatpak_bwrap_free);
 
@@ -1254,16 +1283,10 @@ bind_runtime (FlatpakBwrap *bwrap,
                                       NULL);
               flatpak_bwrap_finish (temp_bwrap);
 
-              real_path_in_runtime = capture_output ((const char * const *) temp_bwrap->argv->pdata,
-                                                     error);
-
-              if (real_path_in_runtime == NULL)
-                return FALSE;
-
-              g_debug ("Container path: %s -> %s", ld_so, real_path_in_runtime);
+              g_debug ("Container path: %s -> %s", ld_so, ld_so_in_runtime);
               flatpak_bwrap_add_args (bwrap,
-                                      "--ro-bind", real_path_in_host,
-                                      real_path_in_runtime,
+                                      "--ro-bind", ld_so_in_host,
+                                      ld_so_in_runtime,
                                       NULL);
 
               g_debug ("Making host locale data visible in container");
-- 
GitLab