[gnome-builder] io: avoid incremental reading of file data



commit 8907269a8d1c5220517750907d42a693bc221bea
Author: Christian Hergert <chergert redhat com>
Date:   Tue Feb 23 20:10:11 2021 -0800

    io: avoid incremental reading of file data
    
    Instead, we can just write to a temporary file from the host side and then
    read it back in one swoop afterwards.
    
    Related #1399

 src/libide/io/ide-gfile.c | 64 ++++++++++++++++++++++++++---------------------
 1 file changed, 36 insertions(+), 28 deletions(-)
---
diff --git a/src/libide/io/ide-gfile.c b/src/libide/io/ide-gfile.c
index b42cfba11..2b185c164 100644
--- a/src/libide/io/ide-gfile.c
+++ b/src/libide/io/ide-gfile.c
@@ -22,6 +22,9 @@
 
 #include "config.h"
 
+#include <glib/gstdio.h>
+#include <errno.h>
+
 #include <libide-threading.h>
 
 #include "ide-gfile.h"
@@ -685,6 +688,12 @@ ide_g_host_file_get_contents (const gchar  *path,
                               gsize        *len,
                               GError      **error)
 {
+  g_autoptr(IdeSubprocessLauncher) launcher = NULL;
+  g_autoptr(IdeSubprocess) subprocess = NULL;
+  char tmpfile[32] = "ide-host-file-XXXXXX";
+  gboolean ret = FALSE;
+  int fd;
+
   g_return_val_if_fail (path != NULL, FALSE);
 
   if (contents != NULL)
@@ -696,40 +705,39 @@ ide_g_host_file_get_contents (const gchar  *path,
   if (!ide_is_flatpak ())
     return g_file_get_contents (path, contents, len, error);
 
-  {
-    g_autoptr(IdeSubprocessLauncher) launcher = NULL;
-    g_autoptr(IdeSubprocess) subprocess = NULL;
-    g_autoptr(GBytes) stdout_buf = NULL;
-
-    launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE |
-                                            G_SUBPROCESS_FLAGS_STDERR_SILENCE);
-    ide_subprocess_launcher_set_run_on_host (launcher, TRUE);
-    ide_subprocess_launcher_push_argv (launcher, "cat");
-    ide_subprocess_launcher_push_argv (launcher, path);
+  /* We open a FD locally that we can write to and then pass that as our
+   * stdout across the boundary so we can avoid incrementally reading
+   * and instead do it once at the end.
+   */
+  if (-1 == (fd = g_mkstemp (tmpfile)))
+    {
+      int errsv = errno;
+      g_set_error_literal (error,
+                           G_FILE_ERROR,
+                           g_file_error_from_errno (errsv),
+                           g_strerror (errsv));
+      goto failure;
+    }
 
-    if (!(subprocess = ide_subprocess_launcher_spawn (launcher, NULL, error)))
-      return FALSE;
+  launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE |
+                                          G_SUBPROCESS_FLAGS_STDERR_SILENCE);
+  ide_subprocess_launcher_take_stdout_fd (launcher, fd);
+  ide_subprocess_launcher_set_run_on_host (launcher, TRUE);
+  ide_subprocess_launcher_push_argv (launcher, "cat");
+  ide_subprocess_launcher_push_argv (launcher, path);
 
-    if (!ide_subprocess_communicate (subprocess, NULL, NULL, &stdout_buf, NULL, error))
-      return FALSE;
+  if (!(subprocess = ide_subprocess_launcher_spawn (launcher, NULL, error)))
+    goto failure;
 
-    if (len != NULL)
-      *len = g_bytes_get_size (stdout_buf);
+  if (!ide_subprocess_wait_check (subprocess, NULL, error))
+    goto failure;
 
-    if (contents != NULL)
-      {
-        const guint8 *data;
-        gsize n;
+  ret = g_file_get_contents (tmpfile, contents, len, error);
 
-        /* g_file_get_contents() gurantees a trailing null byte */
-        data = g_bytes_get_data (stdout_buf, &n);
-        *contents = g_malloc (n + 1);
-        memcpy (*contents, data, n);
-        (*contents)[n] = '\0';
-      }
-  }
+failure:
+  g_unlink (tmpfile);
 
-  return TRUE;
+  return ret;
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]