~ubuntu-core-dev/update-notifier/ubuntu

« back to all changes in this revision

Viewing changes to src/livepatch.c

  • Committer: Balint Reczey
  • Date: 2020-06-11 18:46:02 UTC
  • Revision ID: balint.reczey@canonical.com-20200611184602-2rv1zan3xu723x2u
Moved to git at https://git.launchpad.net/update-notifier

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifdef HAVE_CONFIG_H
2
 
#include "config.h"
3
 
#endif
4
 
 
5
 
#include <gio/gdesktopappinfo.h>
6
 
#include <glib.h>
7
 
#include <glib/gstdio.h>
8
 
#include <libnotify/notify.h>
9
 
#include <sys/sysinfo.h>
10
 
 
11
 
#include "update-notifier.h"
12
 
#include "livepatch-utils.h"
13
 
 
14
 
#define STATUS_PATH "/var/snap/canonical-livepatch/current/status"
15
 
 
16
 
static void
17
 
init_notification ()
18
 
{
19
 
    notify_init ("update-notifier");
20
 
}
21
 
 
22
 
static void
23
 
init_gettext ()
24
 
{
25
 
    setlocale (LC_ALL, "");
26
 
    bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
27
 
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
28
 
    textdomain (GETTEXT_PACKAGE);
29
 
}
30
 
 
31
 
static void
32
 
notify_action_cb (NotifyNotification *notification,
33
 
                  char *action,
34
 
                  gpointer user_data)
35
 
{
36
 
    g_autoptr(GDesktopAppInfo) info = NULL;
37
 
    g_autoptr(GdkAppLaunchContext) context = NULL;
38
 
    g_autoptr(GError) error = NULL;
39
 
 
40
 
    info = g_desktop_app_info_new (LIVEPATCH_DESKTOP_FILE);
41
 
    if (!info) {
42
 
        g_warning ("Could not find application '%s'", LIVEPATCH_DESKTOP_FILE);
43
 
        return;
44
 
    }
45
 
 
46
 
    context = gdk_display_get_app_launch_context (gdk_display_get_default ());
47
 
    if (!g_app_info_launch (G_APP_INFO (info), NULL, G_APP_LAUNCH_CONTEXT (context), &error)) {
48
 
        g_warning ("Could not launch application '%s'", LIVEPATCH_DESKTOP_FILE);
49
 
    }
50
 
}
51
 
 
52
 
static gboolean
53
 
show_notification (const char *summary, const char *body, const char *icon)
54
 
{
55
 
    NotifyNotification *n;
56
 
    g_autoptr(GError) error = NULL;
57
 
 
58
 
    n = notify_notification_new (summary, body, icon);
59
 
    notify_notification_set_timeout (n, 60000);
60
 
 
61
 
    if (livepatch_has_settings_ui()) {
62
 
        notify_notification_add_action (n, "settings", _("Show Settings…"),
63
 
                                        notify_action_cb, NULL, NULL);
64
 
        notify_notification_add_action (n, "default", _("Show Settings…"),
65
 
                                        notify_action_cb, NULL, NULL);
66
 
    } else {
67
 
        g_warning ("There is no graphical application installed to manage "
68
 
                   "Livepatch. The notification will not have a "
69
 
                   "'Show Settings…' button.");
70
 
    }
71
 
 
72
 
    g_signal_connect (n, "closed", G_CALLBACK (gtk_main_quit), NULL);
73
 
 
74
 
    if (!notify_notification_show (n, &error)) {
75
 
        g_warning ("Could not show notification: '%s", error->message);
76
 
        return FALSE;
77
 
    }
78
 
 
79
 
    return TRUE;
80
 
}
81
 
 
82
 
static long
83
 
get_uptime ()
84
 
{
85
 
    struct sysinfo info;
86
 
 
87
 
    if (sysinfo (&info) == -1) {
88
 
        g_critical ("Failed to get uptime: %m");
89
 
        return -1;
90
 
    }
91
 
 
92
 
    return info.uptime;
93
 
}
94
 
 
95
 
static gboolean
96
 
file_modified_after_boot (const char* filename)
97
 
{
98
 
    GStatBuf status_stat;
99
 
    long uptime;
100
 
    time_t boot_timestamp;
101
 
 
102
 
    /* In case of error it's safer to assume that the status file has been
103
 
       modified after boot in order to not miss the notification. */
104
 
    if (g_stat (STATUS_PATH, &status_stat) == -1)
105
 
        return TRUE;
106
 
 
107
 
    if ((uptime = get_uptime ()) == -1)
108
 
        return TRUE;
109
 
 
110
 
    boot_timestamp = time (NULL) - (time_t) uptime;
111
 
    return difftime (status_stat.st_mtim.tv_sec, boot_timestamp) >= 0;
112
 
}
113
 
 
114
 
static gboolean
115
 
show_status_notification ()
116
 
{
117
 
    g_autofree gchar *state = NULL;
118
 
    g_autoptr(GError) error = NULL;
119
 
 
120
 
    if (!g_file_test (STATUS_PATH, G_FILE_TEST_EXISTS))
121
 
        return FALSE;
122
 
 
123
 
    if (!file_modified_after_boot (STATUS_PATH))
124
 
        return FALSE;
125
 
 
126
 
    state = livepatch_get_state (&error);
127
 
    if (state == NULL) {
128
 
        g_warning ("Failed to get Livepatch state: %s", error->message);
129
 
        return FALSE;
130
 
    }
131
 
 
132
 
    if (g_strcmp0(state, "applied") != 0)
133
 
        return FALSE;
134
 
 
135
 
    return show_notification ("Livepatch", _("An update has just been applied."), NULL);
136
 
}
137
 
 
138
 
int
139
 
main (int argc, char **argv)
140
 
{
141
 
    gtk_init (&argc, &argv);
142
 
    init_notification ();
143
 
    init_gettext ();
144
 
 
145
 
    if (show_status_notification ())
146
 
        gtk_main ();
147
 
 
148
 
    return EXIT_SUCCESS;
149
 
}