mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
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).
This commit is contained in:
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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:
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user