From a3714b893611b482ec6508474cdb7c70892c2dd2 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Tue, 29 Sep 2020 14:03:32 +0100
Subject: [PATCH] _srt_file_get_contents_in_sysroot: Add

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 steam-runtime-tools/utils-internal.h |  7 ++++
 steam-runtime-tools/utils.c          | 55 ++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/steam-runtime-tools/utils-internal.h b/steam-runtime-tools/utils-internal.h
index 308e60a1b..ca7f38f49 100644
--- a/steam-runtime-tools/utils-internal.h
+++ b/steam-runtime-tools/utils-internal.h
@@ -87,3 +87,10 @@ gchar ** _srt_json_array_to_strv (JsonObject *json_obj,
 gboolean _srt_rm_rf (const char *directory);
 
 FILE *_srt_divert_stdout_to_stderr (GError **error);
+
+G_GNUC_INTERNAL
+gboolean _srt_file_get_contents_in_sysroot (int sysroot_fd,
+                                            const char *path,
+                                            gchar **contents,
+                                            gsize *len,
+                                            GError **error);
diff --git a/steam-runtime-tools/utils.c b/steam-runtime-tools/utils.c
index cd059711b..55d2917ed 100644
--- a/steam-runtime-tools/utils.c
+++ b/steam-runtime-tools/utils.c
@@ -44,6 +44,7 @@
 #include <glib-object.h>
 #include <gio/gio.h>
 #include "steam-runtime-tools/glib-backports-internal.h"
+#include "steam-runtime-tools/resolve-in-sysroot-internal.h"
 
 #ifdef HAVE_GETAUXVAL
 #define getauxval_AT_SECURE() getauxval (AT_SECURE)
@@ -862,3 +863,57 @@ _srt_divert_stdout_to_stderr (GError **error)
 
   return g_steal_pointer (&original_stdout);
 }
+
+/*
+ * _srt_file_get_contents_in_sysroot:
+ * @sysroot_fd: A directory fd opened on the sysroot or `/`
+ * @path: Absolute or root-relative path within @sysroot_fd
+ * @contents: (out) (not optional): Used to return contents
+ * @len: (out) (optional): Used to return length
+ * @error: Used to return error on failure
+ *
+ * Like g_file_get_contents(), but the file is in a sysroot, and we
+ * follow symlinks as though @sysroot_fd was the root directory
+ * (similar to `fakechroot`).
+ *
+ * Returns: %TRUE if successful
+ */
+gboolean
+_srt_file_get_contents_in_sysroot (int sysroot_fd,
+                                   const char *path,
+                                   gchar **contents,
+                                   gsize *len,
+                                   GError **error)
+{
+  g_autofree gchar *real_path = NULL;
+  g_autofree gchar *fd_path = NULL;
+  g_autofree gchar *ignored = NULL;
+  glnx_autofd int fd = -1;
+
+  g_return_val_if_fail (sysroot_fd >= 0, FALSE);
+  g_return_val_if_fail (path != NULL, FALSE);
+  g_return_val_if_fail (contents != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  if (contents == NULL)
+    contents = &ignored;
+
+  fd = _srt_resolve_in_sysroot (sysroot_fd,
+                                path,
+                                SRT_RESOLVE_FLAGS_READABLE,
+                                &real_path,
+                                error);
+
+  if (fd < 0)
+    return FALSE;
+
+  fd_path = g_strdup_printf ("/proc/self/fd/%d", fd);
+
+  if (!g_file_get_contents (fd_path, contents, len, error))
+    {
+      g_prefix_error (error, "Unable to read %s: ", real_path);
+      return FALSE;
+    }
+
+  return TRUE;
+}
-- 
GitLab