LCOV - code coverage report
Current view: top level - timedate - timedatectl.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 25 415 6.0 %
Date: 2019-08-23 13:36:53 Functions: 4 27 14.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 7 301 2.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <getopt.h>
       4                 :            : #include <locale.h>
       5                 :            : #include <math.h>
       6                 :            : #include <stdbool.h>
       7                 :            : #include <stdlib.h>
       8                 :            : 
       9                 :            : #include "sd-bus.h"
      10                 :            : 
      11                 :            : #include "bus-error.h"
      12                 :            : #include "bus-util.h"
      13                 :            : #include "in-addr-util.h"
      14                 :            : #include "main-func.h"
      15                 :            : #include "pager.h"
      16                 :            : #include "parse-util.h"
      17                 :            : #include "pretty-print.h"
      18                 :            : #include "spawn-polkit-agent.h"
      19                 :            : #include "sparse-endian.h"
      20                 :            : #include "string-table.h"
      21                 :            : #include "strv.h"
      22                 :            : #include "terminal-util.h"
      23                 :            : #include "util.h"
      24                 :            : #include "verbs.h"
      25                 :            : 
      26                 :            : static PagerFlags arg_pager_flags = 0;
      27                 :            : static bool arg_ask_password = true;
      28                 :            : static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
      29                 :            : static char *arg_host = NULL;
      30                 :            : static bool arg_adjust_system_clock = false;
      31                 :            : static bool arg_monitor = false;
      32                 :            : static char **arg_property = NULL;
      33                 :            : static bool arg_value = false;
      34                 :            : static bool arg_all = false;
      35                 :            : 
      36                 :            : typedef struct StatusInfo {
      37                 :            :         usec_t time;
      38                 :            :         const char *timezone;
      39                 :            : 
      40                 :            :         usec_t rtc_time;
      41                 :            :         bool rtc_local;
      42                 :            : 
      43                 :            :         bool ntp_capable;
      44                 :            :         bool ntp_active;
      45                 :            :         bool ntp_synced;
      46                 :            : } StatusInfo;
      47                 :            : 
      48                 :          0 : static void print_status_info(const StatusInfo *i) {
      49                 :          0 :         const char *old_tz = NULL, *tz;
      50                 :          0 :         bool have_time = false;
      51                 :            :         char a[LINE_MAX];
      52                 :            :         struct tm tm;
      53                 :            :         time_t sec;
      54                 :            :         size_t n;
      55                 :            :         int r;
      56                 :            : 
      57         [ #  # ]:          0 :         assert(i);
      58                 :            : 
      59                 :            :         /* Save the old $TZ */
      60                 :          0 :         tz = getenv("TZ");
      61         [ #  # ]:          0 :         if (tz)
      62                 :          0 :                 old_tz = strdupa(tz);
      63                 :            : 
      64                 :            :         /* Set the new $TZ */
      65   [ #  #  #  # ]:          0 :         if (setenv("TZ", isempty(i->timezone) ? "UTC" : i->timezone, true) < 0)
      66         [ #  # ]:          0 :                 log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m");
      67                 :            :         else
      68                 :          0 :                 tzset();
      69                 :            : 
      70         [ #  # ]:          0 :         if (i->time != 0) {
      71                 :          0 :                 sec = (time_t) (i->time / USEC_PER_SEC);
      72                 :          0 :                 have_time = true;
      73   [ #  #  #  # ]:          0 :         } else if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) {
      74                 :          0 :                 sec = time(NULL);
      75                 :          0 :                 have_time = true;
      76                 :            :         } else
      77         [ #  # ]:          0 :                 log_warning("Could not get time from timedated and not operating locally, ignoring.");
      78                 :            : 
      79         [ #  # ]:          0 :         if (have_time) {
      80                 :          0 :                 n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm));
      81         [ #  # ]:          0 :                 printf("               Local time: %s\n", n > 0 ? a : "n/a");
      82                 :            : 
      83                 :          0 :                 n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm));
      84         [ #  # ]:          0 :                 printf("           Universal time: %s\n", n > 0 ? a : "n/a");
      85                 :            :         } else {
      86                 :          0 :                 printf("               Local time: %s\n", "n/a");
      87                 :          0 :                 printf("           Universal time: %s\n", "n/a");
      88                 :            :         }
      89                 :            : 
      90         [ #  # ]:          0 :         if (i->rtc_time > 0) {
      91                 :            :                 time_t rtc_sec;
      92                 :            : 
      93                 :          0 :                 rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC);
      94                 :          0 :                 n = strftime(a, sizeof a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm));
      95         [ #  # ]:          0 :                 printf("                 RTC time: %s\n", n > 0 ? a : "n/a");
      96                 :            :         } else
      97                 :          0 :                 printf("                 RTC time: %s\n", "n/a");
      98                 :            : 
      99         [ #  # ]:          0 :         if (have_time)
     100                 :          0 :                 n = strftime(a, sizeof a, "%Z, %z", localtime_r(&sec, &tm));
     101                 :            : 
     102                 :            :         /* Restore the $TZ */
     103         [ #  # ]:          0 :         if (old_tz)
     104                 :          0 :                 r = setenv("TZ", old_tz, true);
     105                 :            :         else
     106                 :          0 :                 r = unsetenv("TZ");
     107         [ #  # ]:          0 :         if (r < 0)
     108         [ #  # ]:          0 :                 log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m");
     109                 :            :         else
     110                 :          0 :                 tzset();
     111                 :            : 
     112         [ #  # ]:          0 :         printf("                Time zone: %s (%s)\n"
     113                 :            :                "System clock synchronized: %s\n"
     114                 :            :                "              NTP service: %s\n"
     115                 :            :                "          RTC in local TZ: %s\n",
     116         [ #  # ]:          0 :                strna(i->timezone), have_time && n > 0 ? a : "n/a",
     117                 :          0 :                yes_no(i->ntp_synced),
     118   [ #  #  #  # ]:          0 :                i->ntp_capable ? (i->ntp_active ? "active" : "inactive") : "n/a",
     119                 :          0 :                yes_no(i->rtc_local));
     120                 :            : 
     121         [ #  # ]:          0 :         if (i->rtc_local)
     122                 :          0 :                 printf("\n%s"
     123                 :            :                        "Warning: The system is configured to read the RTC time in the local time zone.\n"
     124                 :            :                        "         This mode cannot be fully supported. It will create various problems\n"
     125                 :            :                        "         with time zone changes and daylight saving time adjustments. The RTC\n"
     126                 :            :                        "         time is never updated, it relies on external facilities to maintain it.\n"
     127                 :            :                        "         If at all possible, use RTC in UTC by calling\n"
     128                 :            :                        "         'timedatectl set-local-rtc 0'.%s\n", ansi_highlight(), ansi_normal());
     129                 :          0 : }
     130                 :            : 
     131                 :          0 : static int show_status(int argc, char **argv, void *userdata) {
     132                 :          0 :         StatusInfo info = {};
     133                 :            :         static const struct bus_properties_map map[]  = {
     134                 :            :                 { "Timezone",        "s", NULL, offsetof(StatusInfo, timezone)    },
     135                 :            :                 { "LocalRTC",        "b", NULL, offsetof(StatusInfo, rtc_local)   },
     136                 :            :                 { "NTP",             "b", NULL, offsetof(StatusInfo, ntp_active)  },
     137                 :            :                 { "CanNTP",          "b", NULL, offsetof(StatusInfo, ntp_capable) },
     138                 :            :                 { "NTPSynchronized", "b", NULL, offsetof(StatusInfo, ntp_synced)  },
     139                 :            :                 { "TimeUSec",        "t", NULL, offsetof(StatusInfo, time)        },
     140                 :            :                 { "RTCTimeUSec",     "t", NULL, offsetof(StatusInfo, rtc_time)    },
     141                 :            :                 {}
     142                 :            :         };
     143                 :            : 
     144                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     145                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
     146                 :          0 :         sd_bus *bus = userdata;
     147                 :            :         int r;
     148                 :            : 
     149         [ #  # ]:          0 :         assert(bus);
     150                 :            : 
     151                 :          0 :         r = bus_map_all_properties(bus,
     152                 :            :                                    "org.freedesktop.timedate1",
     153                 :            :                                    "/org/freedesktop/timedate1",
     154                 :            :                                    map,
     155                 :            :                                    BUS_MAP_BOOLEAN_AS_BOOL,
     156                 :            :                                    &error,
     157                 :            :                                    &m,
     158                 :            :                                    &info);
     159         [ #  # ]:          0 :         if (r < 0)
     160         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to query server: %s", bus_error_message(&error, r));
     161                 :            : 
     162                 :          0 :         print_status_info(&info);
     163                 :            : 
     164                 :          0 :         return r;
     165                 :            : }
     166                 :            : 
     167                 :          0 : static int show_properties(int argc, char **argv, void *userdata) {
     168                 :          0 :         sd_bus *bus = userdata;
     169                 :            :         int r;
     170                 :            : 
     171         [ #  # ]:          0 :         assert(bus);
     172                 :            : 
     173                 :          0 :         r = bus_print_all_properties(bus,
     174                 :            :                                      "org.freedesktop.timedate1",
     175                 :            :                                      "/org/freedesktop/timedate1",
     176                 :            :                                      NULL,
     177                 :            :                                      arg_property,
     178                 :            :                                      arg_value,
     179                 :            :                                      arg_all,
     180                 :            :                                      NULL);
     181         [ #  # ]:          0 :         if (r < 0)
     182         [ #  # ]:          0 :                 return bus_log_parse_error(r);
     183                 :            : 
     184                 :          0 :         return 0;
     185                 :            : }
     186                 :            : 
     187                 :          0 : static int set_time(int argc, char **argv, void *userdata) {
     188                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     189                 :          0 :         bool relative = false, interactive = arg_ask_password;
     190                 :          0 :         sd_bus *bus = userdata;
     191                 :            :         usec_t t;
     192                 :            :         int r;
     193                 :            : 
     194                 :          0 :         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
     195                 :            : 
     196                 :          0 :         r = parse_timestamp(argv[1], &t);
     197         [ #  # ]:          0 :         if (r < 0)
     198         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to parse time specification '%s': %m", argv[1]);
     199                 :            : 
     200                 :          0 :         r = sd_bus_call_method(bus,
     201                 :            :                                "org.freedesktop.timedate1",
     202                 :            :                                "/org/freedesktop/timedate1",
     203                 :            :                                "org.freedesktop.timedate1",
     204                 :            :                                "SetTime",
     205                 :            :                                &error,
     206                 :            :                                NULL,
     207                 :            :                                "xbb", (int64_t) t, relative, interactive);
     208         [ #  # ]:          0 :         if (r < 0)
     209         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to set time: %s", bus_error_message(&error, r));
     210                 :            : 
     211                 :          0 :         return 0;
     212                 :            : }
     213                 :            : 
     214                 :          0 : static int set_timezone(int argc, char **argv, void *userdata) {
     215                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     216                 :          0 :         sd_bus *bus = userdata;
     217                 :            :         int r;
     218                 :            : 
     219                 :          0 :         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
     220                 :            : 
     221                 :          0 :         r = sd_bus_call_method(bus,
     222                 :            :                                "org.freedesktop.timedate1",
     223                 :            :                                "/org/freedesktop/timedate1",
     224                 :            :                                "org.freedesktop.timedate1",
     225                 :            :                                "SetTimezone",
     226                 :            :                                &error,
     227                 :            :                                NULL,
     228                 :          0 :                                "sb", argv[1], arg_ask_password);
     229         [ #  # ]:          0 :         if (r < 0)
     230         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to set time zone: %s", bus_error_message(&error, r));
     231                 :            : 
     232                 :          0 :         return 0;
     233                 :            : }
     234                 :            : 
     235                 :          0 : static int set_local_rtc(int argc, char **argv, void *userdata) {
     236                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     237                 :          0 :         sd_bus *bus = userdata;
     238                 :            :         int r, b;
     239                 :            : 
     240                 :          0 :         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
     241                 :            : 
     242                 :          0 :         b = parse_boolean(argv[1]);
     243         [ #  # ]:          0 :         if (b < 0)
     244         [ #  # ]:          0 :                 return log_error_errno(b, "Failed to parse local RTC setting '%s': %m", argv[1]);
     245                 :            : 
     246                 :          0 :         r = sd_bus_call_method(bus,
     247                 :            :                                "org.freedesktop.timedate1",
     248                 :            :                                "/org/freedesktop/timedate1",
     249                 :            :                                "org.freedesktop.timedate1",
     250                 :            :                                "SetLocalRTC",
     251                 :            :                                &error,
     252                 :            :                                NULL,
     253                 :            :                                "bbb", b, arg_adjust_system_clock, arg_ask_password);
     254         [ #  # ]:          0 :         if (r < 0)
     255         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to set local RTC: %s", bus_error_message(&error, r));
     256                 :            : 
     257                 :          0 :         return 0;
     258                 :            : }
     259                 :            : 
     260                 :          0 : static int set_ntp(int argc, char **argv, void *userdata) {
     261                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     262                 :          0 :         sd_bus *bus = userdata;
     263                 :            :         int b, r;
     264                 :            : 
     265                 :          0 :         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
     266                 :            : 
     267                 :          0 :         b = parse_boolean(argv[1]);
     268         [ #  # ]:          0 :         if (b < 0)
     269         [ #  # ]:          0 :                 return log_error_errno(b, "Failed to parse NTP setting '%s': %m", argv[1]);
     270                 :            : 
     271                 :          0 :         r = sd_bus_call_method(bus,
     272                 :            :                                "org.freedesktop.timedate1",
     273                 :            :                                "/org/freedesktop/timedate1",
     274                 :            :                                "org.freedesktop.timedate1",
     275                 :            :                                "SetNTP",
     276                 :            :                                &error,
     277                 :            :                                NULL,
     278                 :            :                                "bb", b, arg_ask_password);
     279         [ #  # ]:          0 :         if (r < 0)
     280         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to set ntp: %s", bus_error_message(&error, r));
     281                 :            : 
     282                 :          0 :         return 0;
     283                 :            : }
     284                 :            : 
     285                 :          0 : static int list_timezones(int argc, char **argv, void *userdata) {
     286                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     287                 :          0 :         sd_bus *bus = userdata;
     288                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     289                 :            :         int r;
     290                 :            :         char** zones;
     291                 :            : 
     292                 :          0 :         r = sd_bus_call_method(bus,
     293                 :            :                                "org.freedesktop.timedate1",
     294                 :            :                                "/org/freedesktop/timedate1",
     295                 :            :                                "org.freedesktop.timedate1",
     296                 :            :                                "ListTimezones",
     297                 :            :                                &error,
     298                 :            :                                &reply,
     299                 :            :                                NULL);
     300         [ #  # ]:          0 :         if (r < 0)
     301         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to request list of time zones: %s",
     302                 :            :                                        bus_error_message(&error, r));
     303                 :            : 
     304                 :          0 :         r = sd_bus_message_read_strv(reply, &zones);
     305         [ #  # ]:          0 :         if (r < 0)
     306         [ #  # ]:          0 :                 return bus_log_parse_error(r);
     307                 :            : 
     308                 :          0 :         (void) pager_open(arg_pager_flags);
     309                 :          0 :         strv_print(zones);
     310                 :            : 
     311                 :          0 :         return 0;
     312                 :            : }
     313                 :            : 
     314                 :            : typedef struct NTPStatusInfo {
     315                 :            :         const char *server_name;
     316                 :            :         char *server_address;
     317                 :            :         usec_t poll_interval, poll_max, poll_min;
     318                 :            :         usec_t root_distance_max;
     319                 :            : 
     320                 :            :         uint32_t leap, version, mode, stratum;
     321                 :            :         int32_t precision;
     322                 :            :         usec_t root_delay, root_dispersion;
     323                 :            :         union {
     324                 :            :                 char str[5];
     325                 :            :                 uint32_t val;
     326                 :            :         } reference;
     327                 :            :         usec_t origin, recv, trans, dest;
     328                 :            : 
     329                 :            :         bool spike;
     330                 :            :         uint64_t packet_count;
     331                 :            :         usec_t jitter;
     332                 :            : 
     333                 :            :         int64_t freq;
     334                 :            : } NTPStatusInfo;
     335                 :            : 
     336                 :          0 : static void ntp_status_info_clear(NTPStatusInfo *p) {
     337                 :          0 :         p->server_address = mfree(p->server_address);
     338                 :          0 : }
     339                 :            : 
     340                 :            : static const char * const ntp_leap_table[4] = {
     341                 :            :         [0] = "normal",
     342                 :            :         [1] = "last minute of the day has 61 seconds",
     343                 :            :         [2] = "last minute of the day has 59 seconds",
     344                 :            :         [3] = "not synchronized",
     345                 :            : };
     346                 :            : 
     347                 :            : #pragma GCC diagnostic push
     348                 :            : #pragma GCC diagnostic ignored "-Wtype-limits"
     349         [ #  # ]:          0 : DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ntp_leap, uint32_t);
     350                 :            : #pragma GCC diagnostic pop
     351                 :            : 
     352                 :          0 : static void print_ntp_status_info(NTPStatusInfo *i) {
     353                 :            :         char ts[FORMAT_TIMESPAN_MAX], tmin[FORMAT_TIMESPAN_MAX], tmax[FORMAT_TIMESPAN_MAX];
     354                 :            :         usec_t delay, t14, t23, offset, root_distance;
     355                 :            :         bool offset_sign;
     356                 :            : 
     357         [ #  # ]:          0 :         assert(i);
     358                 :            : 
     359                 :            :         /*
     360                 :            :          * "Timestamp Name          ID   When Generated
     361                 :            :          *  ------------------------------------------------------------
     362                 :            :          *  Originate Timestamp     T1   time request sent by client
     363                 :            :          *  Receive Timestamp       T2   time request received by server
     364                 :            :          *  Transmit Timestamp      T3   time reply sent by server
     365                 :            :          *  Destination Timestamp   T4   time reply received by client
     366                 :            :          *
     367                 :            :          *  The round-trip delay, d, and system clock offset, t, are defined as:
     368                 :            :          *  d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2"
     369                 :            :          */
     370                 :            : 
     371                 :          0 :         printf("       Server: %s (%s)\n",
     372                 :            :                i->server_address, i->server_name);
     373                 :          0 :         printf("Poll interval: %s (min: %s; max %s)\n",
     374                 :            :                format_timespan(ts, sizeof(ts), i->poll_interval, 0),
     375                 :            :                format_timespan(tmin, sizeof(tmin), i->poll_min, 0),
     376                 :            :                format_timespan(tmax, sizeof(tmax), i->poll_max, 0));
     377                 :            : 
     378         [ #  # ]:          0 :         if (i->packet_count == 0) {
     379                 :          0 :                 printf(" Packet count: 0\n");
     380                 :          0 :                 return;
     381                 :            :         }
     382                 :            : 
     383   [ #  #  #  #  :          0 :         if (i->dest < i->origin || i->trans < i->recv || i->dest - i->origin < i->trans - i->recv) {
                   #  # ]
     384         [ #  # ]:          0 :                 log_error("Invalid NTP response");
     385                 :          0 :                 return;
     386                 :            :         }
     387                 :            : 
     388                 :          0 :         delay = (i->dest - i->origin) - (i->trans - i->recv);
     389                 :            : 
     390                 :          0 :         t14 = i->origin + i->dest;
     391                 :          0 :         t23 = i->recv + i->trans;
     392                 :          0 :         offset_sign = t14 < t23;
     393         [ #  # ]:          0 :         offset = (offset_sign ? t23 - t14 : t14 - t23) / 2;
     394                 :            : 
     395                 :          0 :         root_distance = i->root_delay / 2 + i->root_dispersion;
     396                 :            : 
     397                 :          0 :         printf("         Leap: %s\n"
     398                 :            :                "      Version: %" PRIu32 "\n"
     399                 :            :                "      Stratum: %" PRIu32 "\n",
     400                 :            :                ntp_leap_to_string(i->leap),
     401                 :            :                i->version,
     402                 :            :                i->stratum);
     403         [ #  # ]:          0 :         if (i->stratum <= 1)
     404                 :          0 :                 printf("    Reference: %s\n", i->reference.str);
     405                 :            :         else
     406                 :          0 :                 printf("    Reference: %" PRIX32 "\n", be32toh(i->reference.val));
     407                 :          0 :         printf("    Precision: %s (%" PRIi32 ")\n",
     408                 :          0 :                format_timespan(ts, sizeof(ts), DIV_ROUND_UP((nsec_t) (exp2(i->precision) * NSEC_PER_SEC), NSEC_PER_USEC), 0),
     409                 :            :                i->precision);
     410                 :          0 :         printf("Root distance: %s (max: %s)\n",
     411                 :            :                format_timespan(ts, sizeof(ts), root_distance, 0),
     412                 :            :                format_timespan(tmax, sizeof(tmax), i->root_distance_max, 0));
     413         [ #  # ]:          0 :         printf("       Offset: %s%s\n",
     414                 :            :                offset_sign ? "+" : "-",
     415                 :            :                format_timespan(ts, sizeof(ts), offset, 0));
     416                 :          0 :         printf("        Delay: %s\n",
     417                 :            :                format_timespan(ts, sizeof(ts), delay, 0));
     418                 :          0 :         printf("       Jitter: %s\n",
     419                 :            :                format_timespan(ts, sizeof(ts), i->jitter, 0));
     420                 :          0 :         printf(" Packet count: %" PRIu64 "\n", i->packet_count);
     421                 :            : 
     422         [ #  # ]:          0 :         if (!i->spike)
     423                 :          0 :                 printf("    Frequency: %+.3fppm\n",
     424                 :          0 :                        (double) i->freq / 0x10000);
     425                 :            : }
     426                 :            : 
     427                 :          0 : static int map_server_address(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
     428                 :          0 :         char **p = (char **) userdata;
     429                 :            :         const void *d;
     430                 :            :         int family, r;
     431                 :            :         size_t sz;
     432                 :            : 
     433         [ #  # ]:          0 :         assert(p);
     434                 :            : 
     435                 :          0 :         r = sd_bus_message_enter_container(m, 'r', "iay");
     436         [ #  # ]:          0 :         if (r < 0)
     437                 :          0 :                 return r;
     438                 :            : 
     439                 :          0 :         r = sd_bus_message_read(m, "i", &family);
     440         [ #  # ]:          0 :         if (r < 0)
     441                 :          0 :                 return r;
     442                 :            : 
     443                 :          0 :         r = sd_bus_message_read_array(m, 'y', &d, &sz);
     444         [ #  # ]:          0 :         if (r < 0)
     445                 :          0 :                 return r;
     446                 :            : 
     447                 :          0 :         r = sd_bus_message_exit_container(m);
     448         [ #  # ]:          0 :         if (r < 0)
     449                 :          0 :                 return r;
     450                 :            : 
     451   [ #  #  #  # ]:          0 :         if (sz == 0 && family == AF_UNSPEC) {
     452                 :          0 :                 *p = mfree(*p);
     453                 :          0 :                 return 0;
     454                 :            :         }
     455                 :            : 
     456   [ #  #  #  # ]:          0 :         if (!IN_SET(family, AF_INET, AF_INET6))
     457         [ #  # ]:          0 :                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     458                 :            :                                        "Unknown address family %i", family);
     459                 :            : 
     460         [ #  # ]:          0 :         if (sz != FAMILY_ADDRESS_SIZE(family))
     461         [ #  # ]:          0 :                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     462                 :            :                                        "Invalid address size");
     463                 :            : 
     464                 :          0 :         r = in_addr_to_string(family, d, p);
     465         [ #  # ]:          0 :         if (r < 0)
     466                 :          0 :                 return r;
     467                 :            : 
     468                 :          0 :         return 0;
     469                 :            : }
     470                 :            : 
     471                 :          0 : static int map_ntp_message(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
     472                 :          0 :         NTPStatusInfo *p = userdata;
     473                 :            :         const void *d;
     474                 :            :         size_t sz;
     475                 :            :         int32_t b;
     476                 :            :         int r;
     477                 :            : 
     478         [ #  # ]:          0 :         assert(p);
     479                 :            : 
     480                 :          0 :         r = sd_bus_message_enter_container(m, 'r', "uuuuittayttttbtt");
     481         [ #  # ]:          0 :         if (r < 0)
     482                 :          0 :                 return r;
     483                 :            : 
     484                 :          0 :         r = sd_bus_message_read(m, "uuuuitt",
     485                 :            :                                 &p->leap, &p->version, &p->mode, &p->stratum, &p->precision,
     486                 :            :                                 &p->root_delay, &p->root_dispersion);
     487         [ #  # ]:          0 :         if (r < 0)
     488                 :          0 :                 return r;
     489                 :            : 
     490                 :          0 :         r = sd_bus_message_read_array(m, 'y', &d, &sz);
     491         [ #  # ]:          0 :         if (r < 0)
     492                 :          0 :                 return r;
     493                 :            : 
     494                 :          0 :         r = sd_bus_message_read(m, "ttttbtt",
     495                 :            :                                 &p->origin, &p->recv, &p->trans, &p->dest,
     496                 :            :                                 &b, &p->packet_count, &p->jitter);
     497         [ #  # ]:          0 :         if (r < 0)
     498                 :          0 :                 return r;
     499                 :            : 
     500                 :          0 :         r = sd_bus_message_exit_container(m);
     501         [ #  # ]:          0 :         if (r < 0)
     502                 :          0 :                 return r;
     503                 :            : 
     504         [ #  # ]:          0 :         if (sz != 4)
     505                 :          0 :                 return -EINVAL;
     506                 :            : 
     507                 :          0 :         memcpy(p->reference.str, d, sz);
     508                 :            : 
     509                 :          0 :         p->spike = b;
     510                 :            : 
     511                 :          0 :         return 0;
     512                 :            : }
     513                 :            : 
     514                 :          0 : static int show_timesync_status_once(sd_bus *bus) {
     515                 :            :         static const struct bus_properties_map map_timesync[]  = {
     516                 :            :                 { "ServerName",           "s",                  NULL,               offsetof(NTPStatusInfo, server_name)       },
     517                 :            :                 { "ServerAddress",        "(iay)",              map_server_address, offsetof(NTPStatusInfo, server_address)    },
     518                 :            :                 { "PollIntervalUSec",     "t",                  NULL,               offsetof(NTPStatusInfo, poll_interval)     },
     519                 :            :                 { "PollIntervalMinUSec",  "t",                  NULL,               offsetof(NTPStatusInfo, poll_min)          },
     520                 :            :                 { "PollIntervalMaxUSec",  "t",                  NULL,               offsetof(NTPStatusInfo, poll_max)          },
     521                 :            :                 { "RootDistanceMaxUSec",  "t",                  NULL,               offsetof(NTPStatusInfo, root_distance_max) },
     522                 :            :                 { "NTPMessage",           "(uuuuittayttttbtt)", map_ntp_message,    0                                          },
     523                 :            :                 { "Frequency",            "x",                  NULL,               offsetof(NTPStatusInfo, freq)              },
     524                 :            :                 {}
     525                 :            :         };
     526                 :          0 :         _cleanup_(ntp_status_info_clear) NTPStatusInfo info = {};
     527                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     528                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
     529                 :            :         int r;
     530                 :            : 
     531         [ #  # ]:          0 :         assert(bus);
     532                 :            : 
     533                 :          0 :         r = bus_map_all_properties(bus,
     534                 :            :                                    "org.freedesktop.timesync1",
     535                 :            :                                    "/org/freedesktop/timesync1",
     536                 :            :                                    map_timesync,
     537                 :            :                                    BUS_MAP_BOOLEAN_AS_BOOL,
     538                 :            :                                    &error,
     539                 :            :                                    &m,
     540                 :            :                                    &info);
     541         [ #  # ]:          0 :         if (r < 0)
     542         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to query server: %s", bus_error_message(&error, r));
     543                 :            : 
     544   [ #  #  #  # ]:          0 :         if (arg_monitor && !terminal_is_dumb())
     545                 :          0 :                 fputs(ANSI_HOME_CLEAR, stdout);
     546                 :            : 
     547                 :          0 :         print_ntp_status_info(&info);
     548                 :            : 
     549                 :          0 :         return 0;
     550                 :            : }
     551                 :            : 
     552                 :          0 : static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
     553                 :            :         const char *name;
     554                 :            :         int r;
     555                 :            : 
     556         [ #  # ]:          0 :         assert(m);
     557                 :            : 
     558                 :          0 :         r = sd_bus_message_read(m, "s", &name);
     559         [ #  # ]:          0 :         if (r < 0)
     560         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to read interface name: %m");
     561                 :            : 
     562         [ #  # ]:          0 :         if (!streq_ptr(name, "org.freedesktop.timesync1.Manager"))
     563                 :          0 :                 return 0;
     564                 :            : 
     565                 :          0 :         return show_timesync_status_once(sd_bus_message_get_bus(m));
     566                 :            : }
     567                 :            : 
     568                 :          0 : static int show_timesync_status(int argc, char **argv, void *userdata) {
     569                 :          0 :         _cleanup_(sd_event_unrefp) sd_event *event = NULL;
     570                 :          0 :         sd_bus *bus = userdata;
     571                 :            :         int r;
     572                 :            : 
     573         [ #  # ]:          0 :         assert(bus);
     574                 :            : 
     575                 :          0 :         r = show_timesync_status_once(bus);
     576         [ #  # ]:          0 :         if (r < 0)
     577                 :          0 :                 return r;
     578                 :            : 
     579         [ #  # ]:          0 :         if (!arg_monitor)
     580                 :          0 :                 return 0;
     581                 :            : 
     582                 :          0 :         r = sd_event_default(&event);
     583         [ #  # ]:          0 :         if (r < 0)
     584         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get event loop: %m");
     585                 :            : 
     586                 :          0 :         r = sd_bus_match_signal(bus,
     587                 :            :                                 NULL,
     588                 :            :                                 "org.freedesktop.timesync1",
     589                 :            :                                 "/org/freedesktop/timesync1",
     590                 :            :                                 "org.freedesktop.DBus.Properties",
     591                 :            :                                 "PropertiesChanged",
     592                 :            :                                 on_properties_changed, NULL);
     593         [ #  # ]:          0 :         if (r < 0)
     594         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to request match for PropertiesChanged signal: %m");
     595                 :            : 
     596                 :          0 :         r = sd_bus_attach_event(bus, event, SD_EVENT_PRIORITY_NORMAL);
     597         [ #  # ]:          0 :         if (r < 0)
     598         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
     599                 :            : 
     600                 :          0 :         r = sd_event_loop(event);
     601         [ #  # ]:          0 :         if (r < 0)
     602         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to run event loop: %m");
     603                 :            : 
     604                 :          0 :         return 0;
     605                 :            : }
     606                 :            : 
     607                 :          0 : static int print_timesync_property(const char *name, const char *expected_value, sd_bus_message *m, bool value, bool all) {
     608                 :            :         char type;
     609                 :            :         const char *contents;
     610                 :            :         int r;
     611                 :            : 
     612         [ #  # ]:          0 :         assert(name);
     613         [ #  # ]:          0 :         assert(m);
     614                 :            : 
     615                 :          0 :         r = sd_bus_message_peek_type(m, &type, &contents);
     616         [ #  # ]:          0 :         if (r < 0)
     617                 :          0 :                 return r;
     618                 :            : 
     619         [ #  # ]:          0 :         switch (type) {
     620                 :            : 
     621                 :          0 :         case SD_BUS_TYPE_STRUCT:
     622         [ #  # ]:          0 :                 if (streq(name, "NTPMessage")) {
     623                 :          0 :                         _cleanup_(ntp_status_info_clear) NTPStatusInfo i = {};
     624                 :            :                         char ts[FORMAT_TIMESPAN_MAX], stamp[FORMAT_TIMESTAMP_MAX];
     625                 :            : 
     626                 :          0 :                         r = map_ntp_message(NULL, NULL, m, NULL, &i);
     627         [ #  # ]:          0 :                         if (r < 0)
     628                 :          0 :                                 return r;
     629                 :            : 
     630         [ #  # ]:          0 :                         if (i.packet_count == 0)
     631                 :          0 :                                 return 1;
     632                 :            : 
     633         [ #  # ]:          0 :                         if (!value) {
     634                 :          0 :                                 fputs(name, stdout);
     635                 :          0 :                                 fputc('=', stdout);
     636                 :            :                         }
     637                 :            : 
     638                 :          0 :                         printf("{ Leap=%u, Version=%u, Mode=%u, Stratum=%u, Precision=%i,",
     639                 :            :                                i.leap, i.version, i.mode, i.stratum, i.precision);
     640                 :          0 :                         printf(" RootDelay=%s,",
     641                 :            :                                format_timespan(ts, sizeof(ts), i.root_delay, 0));
     642                 :          0 :                         printf(" RootDispersion=%s,",
     643                 :            :                                format_timespan(ts, sizeof(ts), i.root_dispersion, 0));
     644                 :            : 
     645         [ #  # ]:          0 :                         if (i.stratum == 1)
     646                 :          0 :                                 printf(" Reference=%s,", i.reference.str);
     647                 :            :                         else
     648                 :          0 :                                 printf(" Reference=%" PRIX32 ",", be32toh(i.reference.val));
     649                 :            : 
     650                 :          0 :                         printf(" OriginateTimestamp=%s,",
     651                 :            :                                format_timestamp(stamp, sizeof(stamp), i.origin));
     652                 :          0 :                         printf(" ReceiveTimestamp=%s,",
     653                 :            :                                format_timestamp(stamp, sizeof(stamp), i.recv));
     654                 :          0 :                         printf(" TransmitTimestamp=%s,",
     655                 :            :                                format_timestamp(stamp, sizeof(stamp), i.trans));
     656                 :          0 :                         printf(" DestinationTimestamp=%s,",
     657                 :            :                                format_timestamp(stamp, sizeof(stamp), i.dest));
     658                 :          0 :                         printf(" Ignored=%s PacketCount=%" PRIu64 ",",
     659                 :          0 :                                yes_no(i.spike), i.packet_count);
     660                 :          0 :                         printf(" Jitter=%s }\n",
     661                 :            :                                format_timespan(ts, sizeof(ts), i.jitter, 0));
     662                 :            : 
     663                 :          0 :                         return 1;
     664                 :            : 
     665         [ #  # ]:          0 :                 } else if (streq(name, "ServerAddress")) {
     666                 :          0 :                         _cleanup_free_ char *str = NULL;
     667                 :            : 
     668                 :          0 :                         r = map_server_address(NULL, NULL, m, NULL, &str);
     669         [ #  # ]:          0 :                         if (r < 0)
     670                 :          0 :                                 return r;
     671                 :            : 
     672   [ #  #  #  # ]:          0 :                         if (arg_all || !isempty(str))
     673                 :          0 :                                 bus_print_property_value(name, expected_value, value, str);
     674                 :            : 
     675                 :          0 :                         return 1;
     676                 :            :                 }
     677                 :          0 :                 break;
     678                 :            :         }
     679                 :            : 
     680                 :          0 :         return 0;
     681                 :            : }
     682                 :            : 
     683                 :          0 : static int show_timesync(int argc, char **argv, void *userdata) {
     684                 :          0 :         sd_bus *bus = userdata;
     685                 :            :         int r;
     686                 :            : 
     687         [ #  # ]:          0 :         assert(bus);
     688                 :            : 
     689                 :          0 :         r = bus_print_all_properties(bus,
     690                 :            :                                      "org.freedesktop.timesync1",
     691                 :            :                                      "/org/freedesktop/timesync1",
     692                 :            :                                      print_timesync_property,
     693                 :            :                                      arg_property,
     694                 :            :                                      arg_value,
     695                 :            :                                      arg_all,
     696                 :            :                                      NULL);
     697         [ #  # ]:          0 :         if (r < 0)
     698         [ #  # ]:          0 :                 return bus_log_parse_error(r);
     699                 :            : 
     700                 :          0 :         return 0;
     701                 :            : }
     702                 :            : 
     703                 :          0 : static int parse_ifindex_bus(sd_bus *bus, const char *str, int *ret) {
     704                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     705                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
     706                 :            :         int32_t i;
     707                 :            :         int r;
     708                 :            : 
     709         [ #  # ]:          0 :         assert(bus);
     710         [ #  # ]:          0 :         assert(str);
     711         [ #  # ]:          0 :         assert(ret);
     712                 :            : 
     713                 :          0 :         r = parse_ifindex(str, ret);
     714         [ #  # ]:          0 :         if (r >= 0)
     715                 :          0 :                 return 0;
     716                 :            : 
     717                 :          0 :         r = sd_bus_call_method(
     718                 :            :                         bus,
     719                 :            :                         "org.freedesktop.network1",
     720                 :            :                         "/org/freedesktop/network1",
     721                 :            :                         "org.freedesktop.network1.Manager",
     722                 :            :                         "GetLinkByName",
     723                 :            :                         &error,
     724                 :            :                         &reply,
     725                 :            :                         "s", str);
     726         [ #  # ]:          0 :         if (r < 0)
     727         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get ifindex of interfaces %s: %s", str, bus_error_message(&error, r));
     728                 :            : 
     729                 :          0 :         r = sd_bus_message_read(reply, "io", &i, NULL);
     730         [ #  # ]:          0 :         if (r < 0)
     731         [ #  # ]:          0 :                 return bus_log_create_error(r);
     732                 :            : 
     733                 :          0 :         *ret = i;
     734                 :          0 :         return 0;
     735                 :            : }
     736                 :            : 
     737                 :          0 : static int verb_ntp_servers(int argc, char **argv, void *userdata) {
     738                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     739                 :          0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
     740                 :          0 :         sd_bus *bus = userdata;
     741                 :            :         int ifindex, r;
     742                 :            : 
     743         [ #  # ]:          0 :         assert(bus);
     744                 :            : 
     745                 :          0 :         r = parse_ifindex_bus(bus, argv[1], &ifindex);
     746         [ #  # ]:          0 :         if (r < 0)
     747                 :          0 :                 return r;
     748                 :            : 
     749                 :          0 :         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
     750                 :            : 
     751                 :          0 :         r = sd_bus_message_new_method_call(
     752                 :            :                         bus,
     753                 :            :                         &req,
     754                 :            :                         "org.freedesktop.network1",
     755                 :            :                         "/org/freedesktop/network1",
     756                 :            :                         "org.freedesktop.network1.Manager",
     757                 :            :                         "SetLinkNTP");
     758         [ #  # ]:          0 :         if (r < 0)
     759         [ #  # ]:          0 :                 return bus_log_create_error(r);
     760                 :            : 
     761                 :          0 :         r = sd_bus_message_append(req, "i", ifindex);
     762         [ #  # ]:          0 :         if (r < 0)
     763         [ #  # ]:          0 :                 return bus_log_create_error(r);
     764                 :            : 
     765                 :          0 :         r = sd_bus_message_append_strv(req, argv + 2);
     766         [ #  # ]:          0 :         if (r < 0)
     767         [ #  # ]:          0 :                 return bus_log_create_error(r);
     768                 :            : 
     769                 :          0 :         r = sd_bus_call(bus, req, 0, &error, NULL);
     770         [ #  # ]:          0 :         if (r < 0)
     771         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to set NTP servers: %s", bus_error_message(&error, r));
     772                 :            : 
     773                 :          0 :         return 0;
     774                 :            : }
     775                 :            : 
     776                 :          0 : static int verb_revert(int argc, char **argv, void *userdata) {
     777                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     778                 :          0 :         sd_bus *bus = userdata;
     779                 :            :         int ifindex, r;
     780                 :            : 
     781         [ #  # ]:          0 :         assert(bus);
     782                 :            : 
     783                 :          0 :         r = parse_ifindex_bus(bus, argv[1], &ifindex);
     784         [ #  # ]:          0 :         if (r < 0)
     785                 :          0 :                 return r;
     786                 :            : 
     787                 :          0 :         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
     788                 :            : 
     789                 :          0 :         r = sd_bus_call_method(
     790                 :            :                         bus,
     791                 :            :                         "org.freedesktop.network1",
     792                 :            :                         "/org/freedesktop/network1",
     793                 :            :                         "org.freedesktop.network1.Manager",
     794                 :            :                         "RevertLinkNTP",
     795                 :            :                         &error,
     796                 :            :                         NULL,
     797                 :            :                         "i", ifindex);
     798         [ #  # ]:          0 :         if (r < 0)
     799         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r));
     800                 :            : 
     801                 :          0 :         return 0;
     802                 :            : }
     803                 :            : 
     804                 :         12 : static int help(void) {
     805                 :         12 :         _cleanup_free_ char *link = NULL;
     806                 :            :         int r;
     807                 :            : 
     808                 :         12 :         r = terminal_urlify_man("timedatectl", "1", &link);
     809         [ -  + ]:         12 :         if (r < 0)
     810                 :          0 :                 return log_oom();
     811                 :            : 
     812                 :         12 :         printf("%s [OPTIONS...] COMMAND ...\n\n"
     813                 :            :                "Query or change system time and date settings.\n\n"
     814                 :            :                "  -h --help                Show this help message\n"
     815                 :            :                "     --version             Show package version\n"
     816                 :            :                "     --no-pager            Do not pipe output into a pager\n"
     817                 :            :                "     --no-ask-password     Do not prompt for password\n"
     818                 :            :                "  -H --host=[USER@]HOST    Operate on remote host\n"
     819                 :            :                "  -M --machine=CONTAINER   Operate on local container\n"
     820                 :            :                "     --adjust-system-clock Adjust system clock when changing local RTC mode\n"
     821                 :            :                "     --monitor             Monitor status of systemd-timesyncd\n"
     822                 :            :                "  -p --property=NAME       Show only properties by this name\n"
     823                 :            :                "  -a --all                 Show all properties, including empty ones\n"
     824                 :            :                "     --value               When showing properties, only print the value\n"
     825                 :            :                "\n"
     826                 :            :                "Commands:\n"
     827                 :            :                "  status                   Show current time settings\n"
     828                 :            :                "  show                     Show properties of systemd-timedated\n"
     829                 :            :                "  set-time TIME            Set system time\n"
     830                 :            :                "  set-timezone ZONE        Set system time zone\n"
     831                 :            :                "  list-timezones           Show known time zones\n"
     832                 :            :                "  set-local-rtc BOOL       Control whether RTC is in local time\n"
     833                 :            :                "  set-ntp BOOL             Enable or disable network time synchronization\n"
     834                 :            :                "\n"
     835                 :            :                "systemd-timesyncd Commands:\n"
     836                 :            :                "  timesync-status          Show status of systemd-timesyncd\n"
     837                 :            :                "  show-timesync            Show properties of systemd-timesyncd\n"
     838                 :            :                "\nSee the %s for details.\n"
     839                 :            :                , program_invocation_short_name
     840                 :            :                , link
     841                 :            :         );
     842                 :            : 
     843                 :         12 :         return 0;
     844                 :            : }
     845                 :            : 
     846                 :          0 : static int verb_help(int argc, char **argv, void *userdata) {
     847                 :          0 :         return help();
     848                 :            : }
     849                 :            : 
     850                 :         16 : static int parse_argv(int argc, char *argv[]) {
     851                 :            : 
     852                 :            :         enum {
     853                 :            :                 ARG_VERSION = 0x100,
     854                 :            :                 ARG_NO_PAGER,
     855                 :            :                 ARG_ADJUST_SYSTEM_CLOCK,
     856                 :            :                 ARG_NO_ASK_PASSWORD,
     857                 :            :                 ARG_MONITOR,
     858                 :            :                 ARG_VALUE,
     859                 :            :         };
     860                 :            : 
     861                 :            :         static const struct option options[] = {
     862                 :            :                 { "help",                no_argument,       NULL, 'h'                     },
     863                 :            :                 { "version",             no_argument,       NULL, ARG_VERSION             },
     864                 :            :                 { "no-pager",            no_argument,       NULL, ARG_NO_PAGER            },
     865                 :            :                 { "host",                required_argument, NULL, 'H'                     },
     866                 :            :                 { "machine",             required_argument, NULL, 'M'                     },
     867                 :            :                 { "no-ask-password",     no_argument,       NULL, ARG_NO_ASK_PASSWORD     },
     868                 :            :                 { "adjust-system-clock", no_argument,       NULL, ARG_ADJUST_SYSTEM_CLOCK },
     869                 :            :                 { "monitor",             no_argument,       NULL, ARG_MONITOR             },
     870                 :            :                 { "property",            required_argument, NULL, 'p'                     },
     871                 :            :                 { "all",                 no_argument,       NULL, 'a'                     },
     872                 :            :                 { "value",               no_argument,       NULL, ARG_VALUE               },
     873                 :            :                 {}
     874                 :            :         };
     875                 :            : 
     876                 :            :         int c, r;
     877                 :            : 
     878         [ -  + ]:         16 :         assert(argc >= 0);
     879         [ -  + ]:         16 :         assert(argv);
     880                 :            : 
     881         [ +  - ]:         16 :         while ((c = getopt_long(argc, argv, "hH:M:p:a", options, NULL)) >= 0)
     882                 :            : 
     883   [ +  -  -  -  :         16 :                 switch (c) {
          -  -  -  -  -  
             -  -  +  - ]
     884                 :            : 
     885                 :         12 :                 case 'h':
     886                 :         12 :                         return help();
     887                 :            : 
     888                 :          0 :                 case ARG_VERSION:
     889                 :          0 :                         return version();
     890                 :            : 
     891                 :          0 :                 case 'H':
     892                 :          0 :                         arg_transport = BUS_TRANSPORT_REMOTE;
     893                 :          0 :                         arg_host = optarg;
     894                 :          0 :                         break;
     895                 :            : 
     896                 :          0 :                 case 'M':
     897                 :          0 :                         arg_transport = BUS_TRANSPORT_MACHINE;
     898                 :          0 :                         arg_host = optarg;
     899                 :          0 :                         break;
     900                 :            : 
     901                 :          0 :                 case ARG_NO_ASK_PASSWORD:
     902                 :          0 :                         arg_ask_password = false;
     903                 :          0 :                         break;
     904                 :            : 
     905                 :          0 :                 case ARG_ADJUST_SYSTEM_CLOCK:
     906                 :          0 :                         arg_adjust_system_clock = true;
     907                 :          0 :                         break;
     908                 :            : 
     909                 :          0 :                 case ARG_NO_PAGER:
     910                 :          0 :                         arg_pager_flags |= PAGER_DISABLE;
     911                 :          0 :                         break;
     912                 :            : 
     913                 :          0 :                 case ARG_MONITOR:
     914                 :          0 :                         arg_monitor = true;
     915                 :          0 :                         break;
     916                 :            : 
     917                 :          0 :                 case 'p': {
     918                 :          0 :                         r = strv_extend(&arg_property, optarg);
     919         [ #  # ]:          0 :                         if (r < 0)
     920                 :          0 :                                 return log_oom();
     921                 :            : 
     922                 :            :                         /* If the user asked for a particular
     923                 :            :                          * property, show it to him, even if it is
     924                 :            :                          * empty. */
     925                 :          0 :                         arg_all = true;
     926                 :          0 :                         break;
     927                 :            :                 }
     928                 :            : 
     929                 :          0 :                 case 'a':
     930                 :          0 :                         arg_all = true;
     931                 :          0 :                         break;
     932                 :            : 
     933                 :          0 :                 case ARG_VALUE:
     934                 :          0 :                         arg_value = true;
     935                 :          0 :                         break;
     936                 :            : 
     937                 :          4 :                 case '?':
     938                 :          4 :                         return -EINVAL;
     939                 :            : 
     940                 :          0 :                 default:
     941                 :          0 :                         assert_not_reached("Unhandled option");
     942                 :            :                 }
     943                 :            : 
     944                 :          0 :         return 1;
     945                 :            : }
     946                 :            : 
     947                 :          0 : static int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
     948                 :            :         static const Verb verbs[] = {
     949                 :            :                 { "status",          VERB_ANY, 1,        VERB_DEFAULT, show_status          },
     950                 :            :                 { "show",            VERB_ANY, 1,        0,            show_properties      },
     951                 :            :                 { "set-time",        2,        2,        0,            set_time             },
     952                 :            :                 { "set-timezone",    2,        2,        0,            set_timezone         },
     953                 :            :                 { "list-timezones",  VERB_ANY, 1,        0,            list_timezones       },
     954                 :            :                 { "set-local-rtc",   2,        2,        0,            set_local_rtc        },
     955                 :            :                 { "set-ntp",         2,        2,        0,            set_ntp              },
     956                 :            :                 { "timesync-status", VERB_ANY, 1,        0,            show_timesync_status },
     957                 :            :                 { "show-timesync",   VERB_ANY, 1,        0,            show_timesync        },
     958                 :            :                 { "ntp-servers",     3,        VERB_ANY, 0,            verb_ntp_servers     },
     959                 :            :                 { "revert",          2,        2,        0,            verb_revert          },
     960                 :            :                 { "help",            VERB_ANY, VERB_ANY, 0,            verb_help            }, /* Not documented, but supported since it is created. */
     961                 :            :                 {}
     962                 :            :         };
     963                 :            : 
     964                 :          0 :         return dispatch_verb(argc, argv, verbs, bus);
     965                 :            : }
     966                 :            : 
     967                 :         16 : static int run(int argc, char *argv[]) {
     968                 :         16 :         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
     969                 :            :         int r;
     970                 :            : 
     971                 :         16 :         setlocale(LC_ALL, "");
     972                 :         16 :         log_show_color(true);
     973                 :         16 :         log_parse_environment();
     974                 :         16 :         log_open();
     975                 :            : 
     976                 :         16 :         r = parse_argv(argc, argv);
     977         [ +  - ]:         16 :         if (r <= 0)
     978                 :         16 :                 return r;
     979                 :            : 
     980                 :          0 :         r = bus_connect_transport(arg_transport, arg_host, false, &bus);
     981         [ #  # ]:          0 :         if (r < 0)
     982         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to create bus connection: %m");
     983                 :            : 
     984                 :          0 :         return timedatectl_main(bus, argc, argv);
     985                 :            : }
     986                 :            : 
     987                 :         16 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14