Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
Philip Withnall 2020-01-28 13:47:11 +00:00
parent 106dc900c5
commit 844507bf25
6 changed files with 344 additions and 1 deletions

View File

@ -29,6 +29,7 @@
#include <libmalcontent/app-filter.h> #include <libmalcontent/app-filter.h>
#include <libmalcontent/manager.h> #include <libmalcontent/manager.h>
#include <libmalcontent/session-limits.h> #include <libmalcontent/session-limits.h>
#include <systemd/sd-journal.h>
#include "libmalcontent/app-filter-private.h" #include "libmalcontent/app-filter-private.h"
#include "libmalcontent/session-limits-private.h" #include "libmalcontent/session-limits-private.h"
@ -1333,3 +1334,132 @@ mct_manager_set_session_limits_finish (MctManager *self,
return g_task_propagate_boolean (G_TASK (result), error); return g_task_propagate_boolean (G_TASK (result), error);
} }
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (sd_journal, sd_journal_close)
/* TODO Docs */
MctSessionHistory *
mct_manager_get_session_history (MctManager *self,
uid_t user_id,
GDateTime *start,
GDateTime *end,
MctManagerGetValueFlags flags,
GCancellable *cancellable,
GError **error)
{
g_auto(sd_journal) *journal = NULL;
int ret;
const gchar * const match_message_ids[] =
{
"MESSAGE_ID=8d45620c1a4348dbb17410da57c60c66", /* new session */
"MESSAGE_ID=3354939424b4456d9802ca8333ed424a", /* session ended */
"MESSAGE_ID=6bbd95ee977941e497c48be27c254128", /* entering sleep */
"MESSAGE_ID=8811e6df2a8e40f58a94cea26f8ebf14", /* leaving sleep */
"MESSAGE_ID=b07a249cd024414a82dd00cd181378ff", /* startup complete */
"MESSAGE_ID=98268866d1d54a499c4e98921d93bc40", /* starting to shut down */
/* TODO: need to add messages to gnome-shell for when the user locks and unlocks the screen,
* including logging in and out and switching user */
};
const size_t message_id_len = sizeof (match_message_ids[0]);
g_autoptr(GPtrArray) active_periods = g_ptr_array_new_with_free_func (NULL); /* TODO */
g_return_val_if_fail (MCT_IS_MANAGER (self), NULL);
g_return_val_if_fail (start != NULL, NULL);
g_return_val_if_fail (end != NULL, NULL);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
ret = sd_journal_open (&journal, SD_JOURNAL_SYSTEM);
if (ret < 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Error opening journal: %s", g_strerror (-ret));
return NULL;
}
/* TODO: work out what data threshold is needed and set with sd_journal_set_data_threshold() */
/* Add matches. */
for (gsize i = 0; i < G_N_ELEMENTS (match_message_ids); i++)
{
ret = sd_journal_add_match (journal, "MESSAGE_ID=TODO", 0);
if (ret < 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, /* TODO More specific error codes throughout */
"Error applying matches in journal: %s", g_strerror (-ret));
return NULL;
}
}
ret = sd_journal_seek_realtime_usec (journal, (uint64_t) g_date_time_to_unix (start) * G_USEC_PER_SEC);
if (ret < 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, /* TODO More specific error codes throughout */
"Error finding start entry in journal: %s", g_strerror (-ret));
return NULL;
}
while (TRUE)
{
uint64_t entry_realtime = 0;
const void *data = NULL;
size_t data_len = 0;
ret = sd_journal_next (journal);
if (ret < 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Error seeking journal: %s", g_strerror (-ret));
return NULL;
}
else if (ret == 0)
{
/* Reached EOF. */
break;
}
ret = sd_journal_get_realtime_usec (journal, &entry_realtime);
if (ret < 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Error reading journal: %s", g_strerror (-ret));
return NULL;
}
if (entry_realtime / G_USEC_PER_SEC >= g_date_time_to_unix (end))
{
/* Reached the end of the search range. */
break;
}
/* Check the type of the record. */
ret = sd_journal_get_data (journal, "MESSAGE_ID", &data, &data_len);
if (ret < 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Error reading journal: %s", g_strerror (-ret));
return NULL;
}
if (data_len != message_id_len)
{
g_debug ("Unexpected field %s, ignoring", data);
continue;
}
/* TODO: need to filter by uid */
if (memcmp (data, "MESSAGE_ID=8d45620c1a4348dbb17410da57c60c66", message_id_len) == 0)
{
/* New session. */
g_ptr_array_add (active_periods, TODO);
}
/* TODO */
"MESSAGE_ID=3354939424b4456d9802ca8333ed424a", /* session ended */
"MESSAGE_ID=6bbd95ee977941e497c48be27c254128", /* entering sleep */
"MESSAGE_ID=8811e6df2a8e40f58a94cea26f8ebf14", /* leaving sleep */
"MESSAGE_ID=b07a249cd024414a82dd00cd181378ff", /* startup complete */
"MESSAGE_ID=98268866d1d54a499c4e98921d93bc40", /* starting to shut down */
}
}

View File

@ -168,4 +168,13 @@ gboolean mct_manager_set_session_limits_finish (MctManager *
GAsyncResult *result, GAsyncResult *result,
GError **error); GError **error);
/* TODO */
MctSessionHistory *mct_manager_get_session_history (MctManager *self,
uid_t user_id,
GDateTime *start,
GDateTime *end,
MctManagerGetValueFlags flags,
GCancellable *cancellable,
GError **error);
G_END_DECLS G_END_DECLS

View File

@ -3,16 +3,19 @@ libmalcontent_api_name = 'malcontent-' + libmalcontent_api_version
libmalcontent_sources = [ libmalcontent_sources = [
'app-filter.c', 'app-filter.c',
'manager.c', 'manager.c',
'session-history.c',
'session-limits.c', 'session-limits.c',
] ]
libmalcontent_headers = [ libmalcontent_headers = [
'app-filter.h', 'app-filter.h',
'malcontent.h', 'malcontent.h',
'manager.h', 'manager.h',
'session-history.h',
'session-limits.h', 'session-limits.h',
] ]
libmalcontent_private_headers = [ libmalcontent_private_headers = [
'app-filter-private.h', 'app-filter-private.h',
'session-history-private.h',
'session-limits-private.h', 'session-limits-private.h',
] ]
@ -68,4 +71,4 @@ gnome.generate_gir(libmalcontent,
dependencies: libmalcontent_dep, dependencies: libmalcontent_dep,
) )
subdir('tests') subdir('tests')

View File

@ -0,0 +1,42 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright © 2020 Endless Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
* - Philip Withnall <withnall@endlessm.com>
*/
#pragma once
#include <gio/gio.h>
#include <glib.h>
#include <glib-object.h>
#include <libmalcontent/session-history.h>
G_BEGIN_DECLS
struct _MctSessionHistory
{
gint ref_count;
uid_t user_id;
GDateTime *start; /* (owned) */
GDateTime *end; /* (owned) */
};
G_END_DECLS

View File

@ -0,0 +1,100 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright © 2020 Endless Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
* - Philip Withnall <withnall@endlessm.com>
*/
#include "config.h"
#include <glib.h>
#include <glib-object.h>
#include <glib/gi18n-lib.h>
#include <gio/gio.h>
#include <libmalcontent/session-history.h>
#include "libmalcontent/session-history-private.h"
/* struct _MctSessionHistory is defined in session-history-private.h */
G_DEFINE_BOXED_TYPE (MctSessionHistory, mct_session_history,
mct_session_history_ref, mct_session_history_unref)
/**
* mct_session_history_ref:
* @history: (transfer none): an #MctSessionHistory
*
* Increment the reference count of @history, and return the same pointer to it.
*
* Returns: (transfer full): the same pointer as @history
* Since: 0.5.0
*/
MctSessionHistory *
mct_session_history_ref (MctSessionHistory *history)
{
g_return_val_if_fail (history != NULL, NULL);
g_return_val_if_fail (history->ref_count >= 1, NULL);
g_return_val_if_fail (history->ref_count <= G_MAXINT - 1, NULL);
history->ref_count++;
return history;
}
/**
* mct_session_history_unref:
* @history: (transfer full): an #MctSessionHistory
*
* Decrement the reference count of @history. If the reference count reaches
* zero, free the @history and all its resources.
*
* Since: 0.5.0
*/
void
mct_session_history_unref (MctSessionHistory *history)
{
g_return_if_fail (history != NULL);
g_return_if_fail (history->ref_count >= 1);
history->ref_count--;
if (history->ref_count <= 0)
{
g_clear_pointer (&history->start, g_date_time_unref);
g_clear_pointer (&history->end, g_date_time_unref);
g_free (history);
}
}
/**
* mct_session_history_get_user_id:
* @history: an #MctSessionHistory
*
* Get the user ID of the user this #MctSessionHistory is for.
*
* Returns: user ID of the relevant user
* Since: 0.5.0
*/
uid_t
mct_session_history_get_user_id (MctSessionHistory *history)
{
g_return_val_if_fail (history != NULL, (uid_t) -1);
g_return_val_if_fail (history->ref_count >= 1, (uid_t) -1);
return history->user_id;
}

View File

@ -0,0 +1,59 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright © 2020 Endless Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
* - Philip Withnall <withnall@endlessm.com>
*/
#pragma once
#include <gio/gio.h>
#include <glib.h>
#include <glib-object.h>
G_BEGIN_DECLS
/**
* MctSessionHistory:
*
* TODO
* #MctSessionLimits is an opaque, immutable structure which contains a snapshot
* of the session limits settings for a user at a given time. This includes
* whether session limits are being enforced, and the limit policy for
* example, the times of day when a user is allowed to use the computer.
*
* Typically, session limits settings can only be changed by the administrator,
* and are read-only for non-administrative users. The precise policy is set
* using polkit.
*
* Since: 0.5.0
*/
typedef struct _MctSessionHistory MctSessionHistory;
GType mct_session_history_get_type (void);
#define MCT_TYPE_SESSION_HISTORY mct_session_history_get_type ()
MctSessionHistory *mct_session_history_ref (MctSessionHistory *history);
void mct_session_history_unref (MctSessionHistory *history);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MctSessionHistory, mct_session_history_unref)
uid_t mct_session_history_get_user_id (MctSessionHistory *history);
GDateTime *mct_session_history_get_start (MctSessionHistory *history);
GDateTime *mct_session_history_get_end (MctSessionHistory *history);
G_END_DECLS