2
* Copyright (C) 2019 Andrea Azzarone <andrea.azzarone@canonical.com>
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the
16
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor
17
* Boston, MA 02110-1301 USA.
20
#include "livepatch-utils.h"
22
#include <gio/gdesktopappinfo.h>
24
#include <json-glib/json-glib.h>
26
#define OS_RELEASE_PATH "/etc/os-release"
29
livepatch_error_quark(void)
34
q = g_quark_from_static_string("livepatch-error-quark");
42
g_autoptr(GKeyFile) keys;
43
g_autofree gchar *content = NULL;
44
g_autofree gchar *content_with_group = NULL;
45
const gchar *group = "[os-release]\n";
46
g_autoptr(GError) error = NULL;
48
if (!g_file_get_contents(OS_RELEASE_PATH, &content, NULL, &error))
50
g_warning("Failed to read '%s', error: %s",
51
OS_RELEASE_PATH, error->message);
55
content_with_group = g_strdup_printf("%s%s", group, content);
57
keys = g_key_file_new();
58
if (!g_key_file_load_from_data(keys, content_with_group, -1,
59
G_KEY_FILE_NONE, &error))
61
g_warning("Failed to parse /etc/os-release: %s", error->message);
65
return g_steal_pointer(&keys);
69
livepatch_get_status(GError **error)
71
g_autofree gchar *standard_output = NULL;
72
g_autoptr(JsonParser) json_parser = NULL;
74
if (!g_spawn_command_line_sync("canonical-livepatch status --format=json",
75
&standard_output, NULL, NULL, error))
78
json_parser = json_parser_new();
79
if (!json_parser_load_from_data(json_parser, standard_output, -1, error))
82
return json_node_copy(json_parser_get_root(json_parser));
86
livepatch_get_status_node(const gchar *expr, GError **error)
88
g_autoptr(JsonNode) root = NULL;
90
root = livepatch_get_status(error);
94
return json_path_query(expr, root, error);
98
livepatch_has_settings_ui()
100
g_autoptr(GDesktopAppInfo) info = NULL;
102
info = g_desktop_app_info_new(LIVEPATCH_DESKTOP_FILE);
107
livepatch_is_supported()
109
g_autoptr(GKeyFile) file = NULL;
110
g_autofree gchar *version = NULL;
111
g_autoptr(GError) error = NULL;
113
file = parse_osrelease();
117
version = g_key_file_get_string(file, "os-release", "VERSION", &error);
120
g_warning("Failed to get the version from the file %s: %s",
121
OS_RELEASE_PATH, error->message);
125
return g_strstr_len(version, -1, "LTS") != NULL;
129
livepatch_is_running()
131
g_autoptr(JsonNode) result_node = NULL;
132
JsonNode *running_node = NULL;
133
JsonArray *result_array;
135
result_node = livepatch_get_status_node("$.Status[0].Running", NULL);
136
if (result_node == NULL)
139
result_array = json_node_get_array(result_node);
141
if (json_array_get_length(result_array) == 0)
144
running_node = json_array_get_element(result_array, 0);
145
return json_node_get_boolean(running_node);
149
livepatch_get_state(GError **error)
151
g_autoptr(JsonNode) result_node = NULL;
152
JsonNode *state_node = NULL;
153
JsonArray *result_array;
154
const gchar *expr = "$.Status[0].Livepatch.State";
156
result_node = livepatch_get_status_node(expr, error);
157
if (result_node == NULL)
160
result_array = json_node_get_array(result_node);
162
if (json_array_get_length(result_array) == 0)
165
LIVEPATCH_ERROR, LIVEPATCH_ERROR_NOMATCH,
166
"No matches for: %s", expr);
170
state_node = json_array_get_element(result_array, 0);
171
return g_strdup(json_node_get_string(state_node));
175
livepatch_get_check_state(GError **error)
177
g_autoptr(JsonNode) result_node = NULL;
178
JsonNode *state_node = NULL;
179
JsonArray *result_array;
180
const gchar *expr = "$.Status[0].Livepatch.CheckState";
182
result_node = livepatch_get_status_node(expr, error);
183
if (result_node == NULL)
186
result_array = json_node_get_array(result_node);
188
if (json_array_get_length(result_array) == 0)
191
LIVEPATCH_ERROR, LIVEPATCH_ERROR_NOMATCH,
192
"No matches for: %s", expr);
196
state_node = json_array_get_element(result_array, 0);
197
return g_strdup(json_node_get_string(state_node));
201
livepatch_get_num_fixes(GError **error)
203
g_autoptr(JsonNode) node = NULL;
206
node = livepatch_get_status_node("$.Status[0].Livepatch.Fixes[*]", error);
210
array = json_node_get_array(node);
211
return json_array_get_length(array);