LCOV - code coverage report
Current view: top level - malcontent-webd-update - main.c (source / functions) Coverage Total Hit
Test: 2 coverage DB files Lines: 86.0 % 57 49
Test Date: 2025-09-15 13:55:46 Functions: 83.3 % 6 5
Branches: 55.6 % 18 10

             Branch data     Line data    Source code
       1                 :             : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
       2                 :             :  *
       3                 :             :  * Copyright 2025 GNOME Foundation, Inc.
       4                 :             :  *
       5                 :             :  * SPDX-License-Identifier: GPL-2.0-or-later
       6                 :             :  *
       7                 :             :  * This program is free software; you can redistribute it and/or modify
       8                 :             :  * it under the terms of the GNU General Public License as published by
       9                 :             :  * the Free Software Foundation; either version 2 of the License, or
      10                 :             :  * (at your option) any later version.
      11                 :             :  *
      12                 :             :  * This program is distributed in the hope that it will be useful,
      13                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :             :  * GNU General Public License for more details.
      16                 :             :  *
      17                 :             :  * You should have received a copy of the GNU General Public License
      18                 :             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19                 :             :  *
      20                 :             :  * Authors:
      21                 :             :  *  - Philip Withnall <pwithnall@gnome.org>
      22                 :             :  */
      23                 :             : 
      24                 :             : #include "config.h"
      25                 :             : 
      26                 :             : #include <gio/gio.h>
      27                 :             : #include <glib.h>
      28                 :             : #include <glib/gi18n.h>
      29                 :             : #include <glib/gstdio.h>
      30                 :             : #include <glib-unix.h>
      31                 :             : #include <locale.h>
      32                 :             : #include <signal.h>
      33                 :             : #include <sysexits.h>
      34                 :             : 
      35                 :             : 
      36                 :             : typedef unsigned int SourceHandle;
      37                 :             : 
      38                 :             : static void
      39                 :           2 : source_handle_clear (SourceHandle *handle)
      40                 :             : {
      41         [ +  - ]:           2 :   g_clear_handle_id (handle, g_source_remove);
      42                 :           2 : }
      43                 :             : 
      44                 :           2 : G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (SourceHandle, source_handle_clear)
      45                 :             : 
      46                 :             : const char *error_file = "/var/lib/malcontent-webd/update-error";
      47                 :             : const char *error_file_group = "Web Filter Update Error";
      48                 :             : 
      49                 :             : /* Writes out a file like the following, containing error information if the
      50                 :             :  * malcontent-webd process failed. This can then be reported to the parent when
      51                 :             :  * they next log in or check web filtering settings.
      52                 :             :  *
      53                 :             :  * ```
      54                 :             :  * [Web Filter Update Error]
      55                 :             :  * ErrorCode=org.freedesktop.MalcontentWeb1.Filtering.Error.Downloading
      56                 :             :  * ErrorMessage[en_GB]=There was an error downloading foo from blah.
      57                 :             :  * ```
      58                 :             :  *
      59                 :             :  * Returns an exit status.
      60                 :             :  */
      61                 :             : static int
      62                 :           1 : report_error (const GError *error)
      63                 :             : {
      64                 :           1 :   g_autoptr(GKeyFile) key_file = NULL;
      65                 :           1 :   g_autoptr(GError) local_error = NULL;
      66                 :           1 :   const char *current_locale = setlocale (LC_ALL, NULL);
      67                 :           1 :   g_autoptr(GError) stripped_error = NULL;
      68                 :           2 :   g_autofree char *error_code = g_dbus_error_get_remote_error (error);
      69                 :           1 :   g_autofree char *key_file_data = NULL;
      70                 :           1 :   size_t key_file_data_length = 0;
      71                 :             : 
      72                 :             :   /* Output a copy of the error to the journal. */
      73                 :           1 :   stripped_error = g_error_copy (error);
      74                 :           1 :   g_dbus_error_strip_remote_error (stripped_error);
      75                 :             : 
      76                 :           1 :   g_log_structured (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
      77                 :             :                     "CODE_FILE", __FILE__,
      78                 :             :                     "CODE_LINE", G_STRINGIFY (__LINE__),
      79                 :             :                     "CODE_FUNC", G_STRFUNC,
      80                 :             :                     "SYSLOG_IDENTIFIER", g_get_prgname (),
      81                 :           1 :                     "ERROR_CODE", (error_code != NULL) ? error_code : "",
      82                 :             :                     "MESSAGE_ID", "e91b59b0c8e24b9b99a15e0004c2f1d0",
      83         [ +  - ]:           1 :                     "MESSAGE", "%s", stripped_error->message);
      84                 :             : 
      85                 :             :   /* If we were cancelled, just ignore everything. */
      86         [ -  + ]:           1 :   if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
      87                 :           0 :     return EX_TEMPFAIL;
      88                 :             : 
      89                 :           1 :   key_file = g_key_file_new ();
      90                 :             : 
      91         [ +  - ]:           1 :   if (error_code != NULL)
      92                 :           1 :     g_key_file_set_string (key_file, error_file_group, "ErrorCode", error_code);
      93                 :           1 :   g_key_file_set_locale_string (key_file, error_file_group, "ErrorMessage", current_locale, stripped_error->message);
      94                 :             : 
      95                 :             :   /* Save it using g_file_set_contents_full() so we can set the permissions so
      96                 :             :    * all users can read. */
      97                 :           1 :   key_file_data = g_key_file_to_data (key_file, &key_file_data_length, &local_error);
      98   [ +  -  +  - ]:           2 :   if (key_file_data == NULL ||
      99                 :           1 :       !g_file_set_contents_full (error_file, key_file_data, key_file_data_length,
     100                 :             :                                  G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_DURABLE,
     101                 :             :                                  0644, &local_error))
     102                 :             :     {
     103                 :           1 :       g_warning (_("Error updating error file ‘%s’: %s"), error_file, local_error->message);
     104                 :             :     }
     105                 :             : 
     106                 :           1 :   return EX_UNAVAILABLE;
     107                 :             : }
     108                 :             : 
     109                 :             : static void
     110                 :           1 : clear_error (void)
     111                 :             : {
     112                 :           1 :   g_unlink (error_file);
     113                 :           1 : }
     114                 :             : 
     115                 :             : static gboolean
     116                 :           0 : sigint_cb (void *user_data)
     117                 :             : {
     118                 :           0 :   GCancellable *cancellable = G_CANCELLABLE (user_data);
     119                 :             : 
     120                 :           0 :   g_cancellable_cancel (cancellable);
     121                 :             : 
     122                 :           0 :   return G_SOURCE_CONTINUE;
     123                 :             : }
     124                 :             : 
     125                 :             : int
     126                 :           2 : main (int   argc,
     127                 :             :       char *argv[])
     128                 :             : {
     129                 :           2 :   g_autoptr(GOptionContext) context = NULL;
     130                 :           2 :   g_autoptr(GCancellable) cancellable = NULL;
     131                 :           2 :   g_auto(SourceHandle) sigint_id = 0;
     132                 :           2 :   g_autoptr(GDBusConnection) connection = NULL;
     133                 :           2 :   g_autoptr(GVariant) reply = NULL;
     134                 :           2 :   g_autoptr(GError) local_error = NULL;
     135                 :             : 
     136                 :           2 :   setlocale (LC_ALL, "");
     137                 :             : 
     138                 :             :   /* --help handling */
     139                 :           2 :   context = g_option_context_new (_("- trigger a web filter update"));
     140         [ -  + ]:           2 :   if (!g_option_context_parse (context, &argc, &argv, &local_error))
     141                 :             :     {
     142                 :           0 :       g_warning ("%s", local_error->message);
     143                 :           0 :       return EX_USAGE;
     144                 :             :     }
     145                 :             : 
     146                 :             :   /* Handle cancellation, since everything here runs sync. */
     147                 :           2 :   cancellable = g_cancellable_new ();
     148                 :           2 :   sigint_id = g_unix_signal_add_full (G_PRIORITY_DEFAULT, SIGINT, sigint_cb,
     149                 :             :                                       g_object_ref (cancellable), g_object_unref);
     150                 :             : 
     151                 :             :   /* Call the malcontent-webd daemon via D-Bus and get it to update all the
     152                 :             :    * users’ web filters. */
     153                 :           2 :   connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, &local_error);
     154                 :             : 
     155         [ -  + ]:           2 :   if (connection == NULL)
     156                 :           0 :     return report_error (local_error);
     157                 :             : 
     158                 :           2 :   reply = g_dbus_connection_call_sync (connection,
     159                 :             :                                        "org.freedesktop.MalcontentWeb1",
     160                 :             :                                        "/org/freedesktop/MalcontentWeb1",
     161                 :             :                                        "org.freedesktop.MalcontentWeb1.Filtering",
     162                 :             :                                        "UpdateFilters",
     163                 :             :                                        g_variant_new ("(u)", 0),  /* zero means ‘all users’ */
     164                 :             :                                        NULL,
     165                 :             :                                        G_DBUS_CALL_FLAGS_NONE,
     166                 :             :                                        -1,  /* timeout */
     167                 :             :                                        cancellable,
     168                 :             :                                        &local_error);
     169                 :             : 
     170         [ +  + ]:           2 :   if (reply == NULL)
     171                 :           1 :     return report_error (local_error);
     172                 :             : 
     173                 :           1 :   clear_error ();
     174                 :             : 
     175                 :           1 :   return 0;
     176                 :             : }
     177                 :             : 
        

Generated by: LCOV version 2.0-1