From 5e6cbfcecfd826a758bcaf095ac15e8d79f7249d Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Fri, 7 Feb 2025 11:59:09 +0000
Subject: [PATCH] pv-wrap: Build adverb arguments from PvAdverbPreloadModule
 structs

This means all the parsing and serialization is in one place, and we
can round-trip between the struct representation and the command-line
option representation.

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 pressure-vessel/adverb-preload.c       | 26 +++++++++++++++++
 pressure-vessel/adverb-preload.h       |  2 ++
 pressure-vessel/wrap-setup.c           | 39 ++++++++------------------
 tests/pressure-vessel/adverb-preload.c | 23 ++++++++++++++-
 4 files changed, 61 insertions(+), 29 deletions(-)

diff --git a/pressure-vessel/adverb-preload.c b/pressure-vessel/adverb-preload.c
index f6b8de831..082614c2d 100644
--- a/pressure-vessel/adverb-preload.c
+++ b/pressure-vessel/adverb-preload.c
@@ -261,3 +261,29 @@ pv_adverb_preload_module_parse_adverb_cli (PvAdverbPreloadModule *self,
   self->abi_index = abi_index;
   return TRUE;
 }
+
+gchar *
+pv_adverb_preload_module_to_adverb_cli (PvAdverbPreloadModule *self)
+{
+  g_autoptr(GString) buf = NULL;
+  const PvPreloadVariable *variable;
+
+  g_return_val_if_fail (self->index_in_preload_variables < G_N_ELEMENTS (pv_preload_variables), NULL);
+  g_return_val_if_fail (self->name != NULL, NULL);
+  g_return_val_if_fail (self->abi_index == PV_UNSPECIFIED_ABI
+                        || self->abi_index < PV_N_SUPPORTED_ARCHITECTURES,
+                        NULL);
+
+  variable = &pv_preload_variables[self->index_in_preload_variables];
+  buf = g_string_new (variable->adverb_option);
+  g_string_append_c (buf, '=');
+  g_string_append (buf, self->name);
+
+  if (self->abi_index != PV_UNSPECIFIED_ABI)
+    {
+      g_string_append (buf, ":abi=");
+      g_string_append (buf, pv_multiarch_tuples[self->abi_index]);
+    }
+
+  return g_string_free (g_steal_pointer (&buf), FALSE);
+}
diff --git a/pressure-vessel/adverb-preload.h b/pressure-vessel/adverb-preload.h
index 0e76b9e77..4c79b4f69 100644
--- a/pressure-vessel/adverb-preload.h
+++ b/pressure-vessel/adverb-preload.h
@@ -56,6 +56,8 @@ pv_adverb_preload_module_clear (gpointer p)
 
 G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (PvAdverbPreloadModule, pv_adverb_preload_module_clear)
 
+gchar *pv_adverb_preload_module_to_adverb_cli (PvAdverbPreloadModule *self);
+
 gboolean pv_adverb_preload_module_parse_adverb_cli (PvAdverbPreloadModule *self,
                                                     const char *option,
                                                     PvPreloadVariableIndex which,
diff --git a/pressure-vessel/wrap-setup.c b/pressure-vessel/wrap-setup.c
index 93ba72891..8570ea535 100644
--- a/pressure-vessel/wrap-setup.c
+++ b/pressure-vessel/wrap-setup.c
@@ -556,49 +556,28 @@ append_preload_internal (GPtrArray *argv,
                          PvRuntime *runtime,
                          FlatpakExports *exports)
 {
-  const char *option = pv_preload_variables[which].adverb_option;
-  const char *multiarch_tuple;
+  g_auto(PvAdverbPreloadModule) module = PV_ADVERB_PRELOAD_MODULE_INIT;
+  g_autofree gchar *arg = NULL;
   gboolean flatpak_subsandbox = ((flags & PV_APPEND_PRELOAD_FLAGS_FLATPAK_SUBSANDBOX) != 0);
 
-  g_return_if_fail (abi_index == PV_UNSPECIFIED_ABI
-                    || abi_index < PV_N_SUPPORTED_ARCHITECTURES);
-
-  if (abi_index == PV_UNSPECIFIED_ABI)
-    multiarch_tuple = NULL;
-  else
-    multiarch_tuple = pv_multiarch_tuples[abi_index];
+  module.index_in_preload_variables = which;
+  module.abi_index = abi_index;
 
   if (runtime != NULL
       && (g_str_has_prefix (original_path, "/usr/")
           || g_str_has_prefix (original_path, "/lib")
           || (flatpak_subsandbox && g_str_has_prefix (original_path, "/app/"))))
     {
-      g_autofree gchar *adjusted_path = NULL;
       const char *target = flatpak_subsandbox ? "/run/parent" : "/run/host";
 
-      adjusted_path = g_build_filename (target, original_path, NULL);
-      g_debug ("%s -> %s", original_path, adjusted_path);
-
-      if (multiarch_tuple != NULL)
-        g_ptr_array_add (argv, g_strdup_printf ("%s=%s:abi=%s",
-                                                option, adjusted_path,
-                                                multiarch_tuple));
-      else
-        g_ptr_array_add (argv, g_strdup_printf ("%s=%s",
-                                                option, adjusted_path));
+      module.name = g_build_filename (target, original_path, NULL);
+      g_debug ("%s -> %s", original_path, module.name);
     }
   else
     {
+      module.name = g_strdup (original_path);
       g_debug ("%s -> unmodified", original_path);
 
-      if (multiarch_tuple != NULL)
-        g_ptr_array_add (argv, g_strdup_printf ("%s=%s:abi=%s",
-                                                option, original_path,
-                                                multiarch_tuple));
-      else
-        g_ptr_array_add (argv, g_strdup_printf ("%s=%s",
-                                                option, original_path));
-
       if (exports != NULL && export_path != NULL && export_path[0] == '/')
         {
           const gchar *steam_path = g_environ_getenv (env, "STEAM_COMPAT_CLIENT_INSTALL_PATH");
@@ -619,6 +598,10 @@ append_preload_internal (GPtrArray *argv,
             }
         }
     }
+
+  arg = pv_adverb_preload_module_to_adverb_cli (&module);
+  g_return_if_fail (arg != NULL);
+  g_ptr_array_add (argv, g_steal_pointer (&arg));
 }
 
 /*
diff --git a/tests/pressure-vessel/adverb-preload.c b/tests/pressure-vessel/adverb-preload.c
index 744a91805..3024a7595 100644
--- a/tests/pressure-vessel/adverb-preload.c
+++ b/tests/pressure-vessel/adverb-preload.c
@@ -420,12 +420,33 @@ test_cli (Fixture *f,
         }
       else
         {
+          g_autofree gchar *serialized = NULL;
+          g_auto(PvAdverbPreloadModule) reparsed = PV_ADVERB_PRELOAD_MODULE_INIT;
+          gchar *equals;
+
           g_assert_no_error (local_error);
           g_assert_true (ret);
           g_assert_cmpstr (actual.name, ==, test->expected.name);
           g_assert_cmpuint (actual.abi_index, ==, test->expected.abi_index);
           g_assert_cmpuint (actual.index_in_preload_variables, ==, which);
-          pv_adverb_preload_module_clear (&actual);
+
+          /* Check that it round-trips */
+          serialized = pv_adverb_preload_module_to_adverb_cli (&actual);
+          g_assert_true (g_str_has_prefix (serialized, option));
+          equals = serialized + strlen (option);
+          g_assert_cmpint (*equals, ==, '=');
+          *equals = '\0';
+
+          ret = pv_adverb_preload_module_parse_adverb_cli (&reparsed,
+                                                           option,
+                                                           which,
+                                                           equals + 1,
+                                                           &local_error);
+          g_assert_no_error (local_error);
+          g_assert_true (ret);
+          g_assert_cmpstr (reparsed.name, ==, test->expected.name);
+          g_assert_cmpuint (reparsed.abi_index, ==, test->expected.abi_index);
+          g_assert_cmpuint (reparsed.index_in_preload_variables, ==, which);
         }
     }
 }
-- 
GitLab