[sysprof/wip/chergert/sysprof-3] libsysprof-capture: add file reader helper



commit 5b0395a8169322c46c2c3af8b176d3c51c3fcfd5
Author: Christian Hergert <chergert redhat com>
Date:   Mon May 27 15:59:05 2019 -0700

    libsysprof-capture: add file reader helper

 src/libsysprof-capture/sysprof-capture-reader.c | 65 +++++++++++++++++++++++++
 src/libsysprof-capture/sysprof-capture-reader.h |  4 ++
 src/tests/test-capture.c                        | 12 +++++
 3 files changed, 81 insertions(+)
---
diff --git a/src/libsysprof-capture/sysprof-capture-reader.c b/src/libsysprof-capture/sysprof-capture-reader.c
index b65fe67..1819f3f 100644
--- a/src/libsysprof-capture/sysprof-capture-reader.c
+++ b/src/libsysprof-capture/sysprof-capture-reader.c
@@ -1168,6 +1168,10 @@ sysprof_capture_reader_read_file (SysprofCaptureReader *self)
   if ((self->pos % SYSPROF_CAPTURE_ALIGN) != 0)
     return NULL;
 
+  /* Make sure len is < the extra frame data */
+  if (file_chunk->len > (file_chunk->frame.len - sizeof *file_chunk))
+    return NULL;
+
   /* Ensure trailing \0 in .path */
   file_chunk->path[sizeof file_chunk->path - 1] = 0;
 
@@ -1209,3 +1213,64 @@ sysprof_capture_reader_list_files (SysprofCaptureReader *self)
 
   return (gchar **)g_ptr_array_free (g_steal_pointer (&ar), FALSE);
 }
+
+gboolean
+sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self,
+                                     const gchar          *path,
+                                     gint                  fd)
+{
+  g_assert (self != NULL);
+  g_assert (path != NULL);
+  g_assert (fd > -1);
+
+  for (;;)
+    {
+      SysprofCaptureFrameType type;
+      const SysprofCaptureFileChunk *file;
+      const guint8 *buf;
+      gsize to_write;
+
+      if (!sysprof_capture_reader_peek_type (self, &type))
+        return FALSE;
+
+      if (type != SYSPROF_CAPTURE_FRAME_FILE_CHUNK)
+        goto skip;
+
+      if (!(file = sysprof_capture_reader_read_file (self)))
+        return FALSE;
+
+      if (g_strcmp0 (path, file->path) != 0)
+        goto skip;
+
+      buf = file->data;
+      to_write = file->len;
+
+      while (to_write > 0)
+        {
+          gssize written;
+
+          written = _sysprof_write (fd, buf, to_write);
+          if (written < 0)
+            return FALSE;
+
+          if (written == 0 && errno != EAGAIN)
+            return FALSE;
+
+          g_assert (written <= (gssize)to_write);
+
+          buf += written;
+          to_write -= written;
+        }
+
+      if (!file->is_last)
+        continue;
+
+      return TRUE;
+
+    skip:
+      if (!sysprof_capture_reader_skip (self))
+        return FALSE;
+    }
+
+  g_return_val_if_reached (FALSE);
+}
diff --git a/src/libsysprof-capture/sysprof-capture-reader.h b/src/libsysprof-capture/sysprof-capture-reader.h
index 3256003..8ee2ea2 100644
--- a/src/libsysprof-capture/sysprof-capture-reader.h
+++ b/src/libsysprof-capture/sysprof-capture-reader.h
@@ -99,6 +99,10 @@ void                                    sysprof_capture_reader_set_stat
                                                                                     const SysprofCaptureStat 
*st_buf);
 SYSPROF_AVAILABLE_IN_ALL
 gchar                                 **sysprof_capture_reader_list_files          (SysprofCaptureReader     
*self);
+SYSPROF_AVAILABLE_IN_ALL
+gboolean                                sysprof_capture_reader_read_file_fd        (SysprofCaptureReader     
*self,
+                                                                                    const gchar              
*path,
+                                                                                    gint                     
 fd);
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureReader, sysprof_capture_reader_unref)
 
diff --git a/src/tests/test-capture.c b/src/tests/test-capture.c
index 8c2b2a5..5c2bf2b 100644
--- a/src/tests/test-capture.c
+++ b/src/tests/test-capture.c
@@ -27,6 +27,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include "sysprof-platform.h"
+
 static void
 test_reader_basic (void)
 {
@@ -725,6 +727,7 @@ test_reader_writer_file (void)
   gsize data_len;
   guint count = 0;
   gint fd;
+  gint new_fd;
   gint r;
 
   writer = sysprof_capture_writer_new ("file1.syscap", 0);
@@ -779,6 +782,15 @@ test_reader_writer_file (void)
   g_assert_cmpstr (files[0], ==, "/proc/kallsyms");
   g_assert_null (files[1]);
 
+  sysprof_capture_reader_reset (reader);
+  new_fd = sysprof_memfd_create ("[sysprof-capture-file]");
+  g_assert_cmpint (new_fd, !=, -1);
+
+  r = sysprof_capture_reader_read_file_fd (reader, "/proc/kallsyms", new_fd);
+  g_assert_true (r);
+
+  close (new_fd);
+
   g_clear_pointer (&reader, sysprof_capture_reader_unref);
   g_clear_pointer (&buf, g_byte_array_unref);
 


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