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

« back to all changes in this revision

Viewing changes to src/livepatch.c

  • Committer: Jeremy Bicha
  • Date: 2019-02-09 14:25:07 UTC
  • Revision ID: jbicha@ubuntu.com-20190209142507-45fc0sqnn4uqdl7j
Try adding gnome-shell as alternate dependency of notification-daemon

as part of an effort to drop notification-daemon to universe

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 <errno.h>
 
6
#include <glib.h>
 
7
#include <glib/gstdio.h>
 
8
#include <libnotify/notify.h>
 
9
#include <stdlib.h>
 
10
#include <sys/sysinfo.h>
 
11
 
 
12
#include "update-notifier.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
show_notification (const char *summary, const char *body, const char *icon)
 
33
{
 
34
    NotifyNotification *n = notify_notification_new (summary, body, icon);
 
35
    notify_notification_set_timeout (n, 60000);
 
36
    notify_notification_show (n, NULL);
 
37
    g_object_unref (n);
 
38
}
 
39
 
 
40
static void
 
41
get_event_from_file (const char* filename, char **event, char **description)
 
42
{
 
43
    g_autofree gchar *content = NULL;
 
44
 
 
45
    g_return_if_fail (filename != NULL);
 
46
    g_return_if_fail (event != NULL);
 
47
    g_return_if_fail (description != NULL);
 
48
 
 
49
    *event = *description = NULL;
 
50
 
 
51
    g_file_get_contents (filename, &content, NULL, NULL);
 
52
 
 
53
    if (content) {
 
54
        gchar **strings = g_strsplit (content, " ", 2);
 
55
 
 
56
        if (g_strv_length (strings) > 0)
 
57
            *event = g_strdup (g_strstrip (strings[0]));
 
58
        if (g_strv_length (strings) > 1)
 
59
            *description = g_strdup (g_strstrip (strings[1]));
 
60
 
 
61
        g_strfreev (strings);
 
62
    }
 
63
}
 
64
 
 
65
static long
 
66
get_uptime ()
 
67
{
 
68
    struct sysinfo info;
 
69
 
 
70
    if (sysinfo (&info) == -1) {
 
71
        g_critical ("Failed to get uptime: %m");
 
72
        return -1;
 
73
    }
 
74
 
 
75
    return info.uptime;
 
76
}
 
77
 
 
78
static gboolean
 
79
file_modified_after_boot (const char* filename)
 
80
{
 
81
    GStatBuf status_stat;
 
82
    long uptime;
 
83
    time_t boot_timestamp;
 
84
 
 
85
    /* In case of error it's safer to assume that the status file has been
 
86
       modified after boot in order to not miss the notification. */
 
87
    if (g_stat (STATUS_PATH, &status_stat) == -1)
 
88
        return TRUE;
 
89
 
 
90
    if ((uptime = get_uptime ()) == -1)
 
91
        return TRUE;
 
92
 
 
93
    boot_timestamp = time (NULL) - (time_t) uptime;
 
94
    return difftime (status_stat.st_mtim.tv_sec, boot_timestamp) >= 0;
 
95
}
 
96
 
 
97
static void
 
98
show_status_notification ()
 
99
{
 
100
    g_autofree gchar *event = NULL;
 
101
    g_autofree gchar *description = NULL;
 
102
 
 
103
    if (!g_file_test (STATUS_PATH, G_FILE_TEST_EXISTS))
 
104
        return;
 
105
 
 
106
    if (!file_modified_after_boot (STATUS_PATH))
 
107
        return;
 
108
 
 
109
    get_event_from_file (STATUS_PATH, &event, &description);
 
110
 
 
111
    if (g_strcmp0 (event, "applied") == 0) {
 
112
        g_autofree gchar *body = NULL;
 
113
        gchar *endptr;
 
114
        gboolean is_overflow, conversion_failed;
 
115
 
 
116
        errno = 0;
 
117
        guint64 num_updates = g_ascii_strtoull (description, &endptr, 10);
 
118
        is_overflow = (num_updates == G_MAXUINT64 && errno == ERANGE);
 
119
        conversion_failed = (num_updates == 0 && description == endptr);
 
120
 
 
121
        if (is_overflow || conversion_failed) {
 
122
            g_warning ("Failed to parse the status file");
 
123
        } else if (num_updates != 0) {
 
124
            body = g_strdup_printf (
 
125
                ngettext ("%" G_GUINT64_FORMAT " Livepatch update has been successfully applied.",
 
126
                          "%" G_GUINT64_FORMAT " Livepatch updates have been successfully applied.",
 
127
                          num_updates),
 
128
                num_updates);
 
129
 
 
130
            show_notification (_("Canonical Livepatch"), body, NULL);
 
131
        }
 
132
    }
 
133
}
 
134
 
 
135
int
 
136
main (int argc, char **argv)
 
137
{
 
138
    init_notification ();
 
139
    init_gettext ();
 
140
 
 
141
    show_status_notification ();
 
142
 
 
143
    return EXIT_SUCCESS;
 
144
}