/*
Copyright (C) 2011 ABRT Team
Copyright (C) 2011 RedHat inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "abrt_glib.h"
#include "internal_libabrt.h"
static GDBusProxy *get_dbus_proxy(void)
{
static GDBusProxy *proxy;
/* we cache it, so we can't free it! */
if (proxy != NULL)
return proxy;
GError *error = NULL;
proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
ABRT_DBUS_NAME,
ABRT_DBUS_OBJECT,
ABRT_DBUS_IFACE,
NULL,
&error);
if (error)
{
error_msg(_("Can't connect to system DBus: %s"), error->message);
g_error_free(error);
/* proxy is NULL in this case */
}
return proxy;
}
int chown_dir_over_dbus(const char *problem_dir_path)
{
INITIALIZE_LIBABRT();
GDBusProxy *proxy = get_dbus_proxy();
if (!proxy)
return 1;
GError *error = NULL;
g_dbus_proxy_call_sync(proxy,
"ChownProblemDir",
g_variant_new("(s)", problem_dir_path),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error)
{
error_msg(_("Can't chown '%s': %s"), problem_dir_path, error->message);
g_error_free(error);
return 1;
}
return 0;
}
int delete_problem_dirs_over_dbus(const GList *problem_dir_paths)
{
INITIALIZE_LIBABRT();
GDBusProxy *proxy = get_dbus_proxy();
if (!proxy)
return 1;
GVariant *parameters = variant_from_string_list(problem_dir_paths);
GError *error = NULL;
g_dbus_proxy_call_sync(proxy,
"DeleteProblem",
parameters,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
//g_variant_unref(parameters); -- need this??? no?? why?
if (error)
{
error_msg(_("Deleting problem directory failed: %s"), error->message);
g_error_free(error);
return 1;
}
return 0;
}
int fill_problem_data_over_dbus(const char *problem_id, const char **elements, problem_data_t *problem_data)
{
INITIALIZE_LIBABRT();
GDBusProxy *proxy = get_dbus_proxy();
if (!proxy)
return -1;
GVariantBuilder *args_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
for (const char **iter = elements; *iter; ++iter)
g_variant_builder_add(args_builder, "s", *iter);
GVariant *params = g_variant_new("(sas)", problem_id, args_builder);
g_variant_builder_unref(args_builder);
GError *error = NULL;
GVariant *result = g_dbus_proxy_call_sync(proxy,
"GetInfo",
params,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error)
{
error_msg(_("D-Bus GetInfo method call failed: %s"), error->message);
g_error_free(error);
return -2;
}
char *key, *val;
GVariantIter *iter;
g_variant_get(result, "(a{ss})", &iter);
while (g_variant_iter_loop(iter, "{ss}", &key, &val))
problem_data_add_text_noteditable(problem_data, key, val);
g_variant_unref(result);
return 0;
}
problem_data_t *get_problem_data_dbus(const char *problem_dir_path)
{
INITIALIZE_LIBABRT();
static const char *elements[] = {
FILENAME_TIME,
FILENAME_REASON,
FILENAME_NOT_REPORTABLE,
FILENAME_COMPONENT,
FILENAME_EXECUTABLE,
FILENAME_REPORTED_TO,
NULL,
};
problem_data_t *pd = problem_data_new();
if (fill_problem_data_over_dbus(problem_dir_path, elements, pd) != 0)
{
error_msg(_("Can't get problem data from abrt-dbus"));
problem_data_free(pd);
return ERR_PTR;
}
return pd;
}
GList *get_problems_over_dbus(bool authorize)
{
INITIALIZE_LIBABRT();
GDBusProxy *proxy = get_dbus_proxy();
if (!proxy)
return ERR_PTR;
GError *error = NULL;
GVariant *result = g_dbus_proxy_call_sync(proxy,
authorize ? "GetAllProblems" : "GetProblems",
g_variant_new("()"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error)
{
error_msg(_("Can't get problem list from abrt-dbus: %s"), error->message);
g_error_free(error);
return ERR_PTR;
}
GList *list = NULL;
if (result)
{
/* Fetch "as" from "(as)" */
GVariant *array = g_variant_get_child_value(result, 0);
list = string_list_from_variant(array);
g_variant_unref(array);
g_variant_unref(result);
}
return list;
}
problem_data_t *get_full_problem_data_over_dbus(const char *problem_dir_path)
{
INITIALIZE_LIBABRT();
GDBusProxy *proxy = get_dbus_proxy();
if (!proxy)
return ERR_PTR;
GError *error = NULL;
GVariant *result = g_dbus_proxy_call_sync(proxy,
"GetProblemData",
g_variant_new("(s)", problem_dir_path),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error)
{
error_msg(_("Can't get problem data from abrt-dbus: %s"), error->message);
g_error_free(error);
return ERR_PTR;
}
GVariantIter *iter = NULL;
g_variant_get(result, "(a{s(its)})", &iter);
gchar *name = NULL;
gint flags;
gulong size;
gchar *value = NULL;
problem_data_t *pd = problem_data_new();
while (g_variant_iter_loop(iter, "{&s(it&s)}", &name, &flags, &size, &value))
problem_data_add_ext(pd, name, value, flags, size);
problem_data_add(pd, CD_DUMPDIR, problem_dir_path,
CD_FLAG_TXT + CD_FLAG_ISNOTEDITABLE + CD_FLAG_LIST);
g_variant_unref(result);
return pd;
}
int test_exist_over_dbus(const char *problem_id, const char *element_name)
{
INITIALIZE_LIBABRT();
GDBusProxy *proxy = get_dbus_proxy();
if (!proxy)
return -1;
GError *error = NULL;
GVariant *result = g_dbus_proxy_call_sync(proxy,
"TestElementExists",
g_variant_new("(ss)", problem_id, element_name),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error)
{
error_msg(_("Can't test whether the element exists over abrt-dbus: %s"), error->message);
g_error_free(error);
return -1;
}
gboolean retval;
g_variant_get(result, "(b)", &retval);
g_variant_unref(result);
return retval;
}
int dbus_problem_is_complete(const char *problem_id)
{
return test_exist_over_dbus(problem_id, FILENAME_COUNT);
}
char *load_text_over_dbus(const char *problem_id, const char *element_name)
{
INITIALIZE_LIBABRT();
GDBusProxy *proxy = get_dbus_proxy();
if (!proxy)
return ERR_PTR;
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
g_variant_builder_add(builder, "s", element_name);
GVariant *params = g_variant_new("(sas)", problem_id, builder);
g_variant_builder_unref(builder);
GError *error = NULL;
GVariant *result = g_dbus_proxy_call_sync(proxy,
"GetInfo",
params,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (error)
{
error_msg(_("Can't get problem data from abrt-dbus: %s"), error->message);
g_error_free(error);
return ERR_PTR;
}
GVariant *values = g_variant_get_child_value(result, 0);
g_variant_unref(result);
char *retval = NULL;
if (g_variant_n_children(values) == 1)
{
GVariant *contents = g_variant_get_child_value(values, 0);
gchar *key;
g_variant_get(contents, "{&ss}", &key, &retval);
}
g_variant_unref(values);
return retval;
}