[sysprof/wip/chergert/sysprof-3] sysprofd: add API to get a FD for a file in proc
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof/wip/chergert/sysprof-3] sysprofd: add API to get a FD for a file in proc
- Date: Sun, 12 May 2019 23:07:30 +0000 (UTC)
commit 64fdd9f763bc547f0167f7e8a83b8caf6626d3cc
Author: Christian Hergert <chergert redhat com>
Date: Sun May 12 16:06:02 2019 -0700
sysprofd: add API to get a FD for a file in proc
This is useful for optimized parsing of proc files such as necessary by
the memory source to seek() back to the start (instead of re-opening a
new file).
src/helpers.c | 20 +++++++++++++++
src/helpers.h | 2 ++
src/libsysprof/sysprof-helpers.c | 50 ++++++++++++++++++++++++++++++++++++++
src/libsysprof/sysprof-helpers.h | 5 ++++
src/org.gnome.Sysprof3.Service.xml | 20 ++++++++++++++-
src/sysprofd/ipc-service-impl.c | 46 +++++++++++++++++++++++++++++++++++
6 files changed, 142 insertions(+), 1 deletion(-)
---
diff --git a/src/helpers.c b/src/helpers.c
index b806466..ebba685 100644
--- a/src/helpers.c
+++ b/src/helpers.c
@@ -22,6 +22,7 @@
#include "config.h"
+#include <fcntl.h>
#include <gio/gio.h>
#include <errno.h>
#ifdef __linux__
@@ -281,6 +282,25 @@ helpers_get_proc_file (const gchar *path,
g_file_get_contents (canon, contents, len, NULL);
}
+gboolean
+helpers_get_proc_fd (const gchar *path,
+ gint *out_fd)
+{
+ g_autofree gchar *canon = NULL;
+ g_autoptr(GFile) file = NULL;
+
+ g_assert (path != NULL);
+ g_assert (out_fd != NULL);
+
+ /* Canonicalize filename */
+ file = g_file_new_for_path (path);
+ canon = g_file_get_path (file);
+
+ return g_file_is_native (file) &&
+ (g_str_has_prefix (canon, "/proc/") || g_str_has_prefix (canon, "/sys/")) &&
+ -1 != (*out_fd = open (canon, O_RDONLY | O_CLOEXEC));
+}
+
gboolean
helpers_can_see_pids (void)
{
diff --git a/src/helpers.h b/src/helpers.h
index 430a4e2..212106b 100644
--- a/src/helpers.h
+++ b/src/helpers.h
@@ -39,5 +39,7 @@ gboolean helpers_perf_event_open (GVariant *options,
gboolean helpers_get_proc_file (const gchar *path,
gchar **contents,
gsize *len);
+gboolean helpers_get_proc_fd (const gchar *path,
+ gint *out_fd);
G_END_DECLS
diff --git a/src/libsysprof/sysprof-helpers.c b/src/libsysprof/sysprof-helpers.c
index f02c63e..d577286 100644
--- a/src/libsysprof/sysprof-helpers.c
+++ b/src/libsysprof/sysprof-helpers.c
@@ -229,6 +229,56 @@ sysprof_helpers_list_processes_finish (SysprofHelpers *self,
return FALSE;
}
+gboolean
+sysprof_helpers_get_proc_fd (SysprofHelpers *self,
+ const gchar *path,
+ GCancellable *cancellable,
+ gint *out_fd,
+ GError **error)
+{
+ g_return_val_if_fail (SYSPROF_IS_HELPERS (self), FALSE);
+ g_return_val_if_fail (path != NULL, FALSE);
+ g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (out_fd != NULL, FALSE);
+
+ *out_fd = -1;
+
+ if (self->proxy != NULL)
+ {
+ g_autoptr(GVariant) reply = NULL;
+ g_autoptr(GUnixFDList) out_fd_list = NULL;
+
+ reply = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (self->proxy),
+ "GetProcFd",
+ g_variant_new ("(^ay)", path),
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1,
+ NULL,
+ &out_fd_list,
+ cancellable,
+ error);
+
+ if (reply != NULL && out_fd_list != NULL)
+ {
+ gint handle = -1;
+
+ g_variant_get (reply, "(h)", &handle);
+
+ if (handle < g_unix_fd_list_get_length (out_fd_list))
+ {
+ *out_fd = g_unix_fd_list_get (out_fd_list, handle, error);
+ return *out_fd != -1;
+ }
+ }
+ }
+
+ if (!helpers_get_proc_fd (path, out_fd))
+ return FALSE;
+
+ g_clear_error (error);
+ return TRUE;
+}
+
static void
sysprof_helpers_get_proc_file_cb (IpcService *service,
GAsyncResult *result,
diff --git a/src/libsysprof/sysprof-helpers.h b/src/libsysprof/sysprof-helpers.h
index 517ba49..99aae85 100644
--- a/src/libsysprof/sysprof-helpers.h
+++ b/src/libsysprof/sysprof-helpers.h
@@ -54,6 +54,11 @@ gboolean sysprof_helpers_list_processes_finish (SysprofHelpers
gint32 **processes,
gsize *n_processes,
GError **error);
+gboolean sysprof_helpers_get_proc_fd (SysprofHelpers *self,
+ const gchar *path,
+ GCancellable *cancellable,
+ gint *out_fd,
+ GError **error);
gboolean sysprof_helpers_get_proc_file (SysprofHelpers *self,
const gchar *path,
GCancellable *cancellable,
diff --git a/src/org.gnome.Sysprof3.Service.xml b/src/org.gnome.Sysprof3.Service.xml
index d39f68c..fad593a 100644
--- a/src/org.gnome.Sysprof3.Service.xml
+++ b/src/org.gnome.Sysprof3.Service.xml
@@ -27,7 +27,7 @@
GetProcFile:
@path: the path including "/proc/" prefix.
- Gets a file from /proc.
+ Gets a file from /proc/ or /sys/.
The file must be a C-string (no embedded NUL bytes) but need not be UTF-8.
@@ -40,6 +40,24 @@
<arg name="contents" type="ay" direction="out"/>
</method>
+ <!--
+ GetProcFd:
+ @path: the path within /proc or /sys
+
+ Like GetProcFile, but returns a FD for the file.
+
+ This is useful for situations where you need to seek() back to 0 to
+ optimize the parsing of the file contents.
+
+ Returns: a file-descriptor
+
+ Since: 3.34
+ -->
+ <method name="GetProcFd">
+ <arg name="path" type="ay" direction="in"/>
+ <arg name="fd" type="h" direction="out"/>
+ </method>
+
<!--
ListProcesses:
diff --git a/src/sysprofd/ipc-service-impl.c b/src/sysprofd/ipc-service-impl.c
index b1be108..163794e 100644
--- a/src/sysprofd/ipc-service-impl.c
+++ b/src/sysprofd/ipc-service-impl.c
@@ -23,6 +23,7 @@
#include "config.h"
#include <errno.h>
+#include <fcntl.h>
#include <gio/gunixfdlist.h>
#include <polkit/polkit.h>
#include <string.h>
@@ -88,6 +89,50 @@ ipc_service_impl_handle_get_proc_file (IpcService *service,
return TRUE;
}
+static gboolean
+ipc_service_impl_handle_get_proc_fd (IpcService *service,
+ GDBusMethodInvocation *invocation,
+ const gchar *path)
+{
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *canon = NULL;
+
+ g_assert (IPC_IS_SERVICE_IMPL (service));
+ g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
+
+ file = g_file_new_for_path (path);
+ canon = g_file_get_path (file);
+
+ if (g_str_has_prefix (canon, "/proc/") || g_str_has_prefix (canon, "/sys/"))
+ {
+ gint fd = open (canon, O_RDONLY | O_CLOEXEC);
+
+ if (fd != -1)
+ {
+ g_autoptr(GUnixFDList) fd_list = g_unix_fd_list_new ();
+ gint handle = g_unix_fd_list_append (fd_list, fd, &error);
+
+ close (fd);
+
+ if (handle != -1)
+ {
+ g_dbus_method_invocation_return_value_with_unix_fd_list (g_steal_pointer (&invocation),
+ g_variant_new ("(h)", handle),
+ fd_list);
+ return TRUE;
+ }
+ }
+ }
+
+ g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_ACCESS_DENIED,
+ "Failed to load proc fd");
+
+ return TRUE;
+}
+
static gboolean
ipc_service_impl_handle_perf_event_open (IpcService *service,
GDBusMethodInvocation *invocation,
@@ -343,6 +388,7 @@ init_service_iface (IpcServiceIface *iface)
{
iface->handle_list_processes = ipc_service_impl_handle_list_processes;
iface->handle_get_proc_file = ipc_service_impl_handle_get_proc_file;
+ iface->handle_get_proc_fd = ipc_service_impl_handle_get_proc_fd;
iface->handle_perf_event_open = ipc_service_impl_handle_perf_event_open;
iface->handle_get_process_info = ipc_service_impl_handle_get_process_info;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]