LCOV - code coverage report
Current view: top level - core - dbus-timer.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 168 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "alloc-util.h"
       4             : #include "bus-util.h"
       5             : #include "dbus-timer.h"
       6             : #include "dbus-util.h"
       7             : #include "strv.h"
       8             : #include "timer.h"
       9             : #include "unit.h"
      10             : 
      11           0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, timer_result, TimerResult);
      12             : 
      13           0 : static int property_get_monotonic_timers(
      14             :                 sd_bus *bus,
      15             :                 const char *path,
      16             :                 const char *interface,
      17             :                 const char *property,
      18             :                 sd_bus_message *reply,
      19             :                 void *userdata,
      20             :                 sd_bus_error *error) {
      21             : 
      22           0 :         Timer *t = userdata;
      23             :         TimerValue *v;
      24             :         int r;
      25             : 
      26           0 :         assert(bus);
      27           0 :         assert(reply);
      28           0 :         assert(t);
      29             : 
      30           0 :         r = sd_bus_message_open_container(reply, 'a', "(stt)");
      31           0 :         if (r < 0)
      32           0 :                 return r;
      33             : 
      34           0 :         LIST_FOREACH(value, v, t->values) {
      35           0 :                 _cleanup_free_ char *buf = NULL;
      36             :                 const char *s;
      37             :                 size_t l;
      38             : 
      39           0 :                 if (v->base == TIMER_CALENDAR)
      40           0 :                         continue;
      41             : 
      42           0 :                 s = timer_base_to_string(v->base);
      43           0 :                 assert(endswith(s, "Sec"));
      44             : 
      45             :                 /* s/Sec/USec/ */
      46           0 :                 l = strlen(s);
      47           0 :                 buf = new(char, l+2);
      48           0 :                 if (!buf)
      49           0 :                         return -ENOMEM;
      50             : 
      51           0 :                 memcpy(buf, s, l-3);
      52           0 :                 memcpy(buf+l-3, "USec", 5);
      53             : 
      54           0 :                 r = sd_bus_message_append(reply, "(stt)", buf, v->value, v->next_elapse);
      55           0 :                 if (r < 0)
      56           0 :                         return r;
      57             :         }
      58             : 
      59           0 :         return sd_bus_message_close_container(reply);
      60             : }
      61             : 
      62           0 : static int property_get_calendar_timers(
      63             :                 sd_bus *bus,
      64             :                 const char *path,
      65             :                 const char *interface,
      66             :                 const char *property,
      67             :                 sd_bus_message *reply,
      68             :                 void *userdata,
      69             :                 sd_bus_error *error) {
      70             : 
      71           0 :         Timer *t = userdata;
      72             :         TimerValue *v;
      73             :         int r;
      74             : 
      75           0 :         assert(bus);
      76           0 :         assert(reply);
      77           0 :         assert(t);
      78             : 
      79           0 :         r = sd_bus_message_open_container(reply, 'a', "(sst)");
      80           0 :         if (r < 0)
      81           0 :                 return r;
      82             : 
      83           0 :         LIST_FOREACH(value, v, t->values) {
      84           0 :                 _cleanup_free_ char *buf = NULL;
      85             : 
      86           0 :                 if (v->base != TIMER_CALENDAR)
      87           0 :                         continue;
      88             : 
      89           0 :                 r = calendar_spec_to_string(v->calendar_spec, &buf);
      90           0 :                 if (r < 0)
      91           0 :                         return r;
      92             : 
      93           0 :                 r = sd_bus_message_append(reply, "(sst)", timer_base_to_string(v->base), buf, v->next_elapse);
      94           0 :                 if (r < 0)
      95           0 :                         return r;
      96             :         }
      97             : 
      98           0 :         return sd_bus_message_close_container(reply);
      99             : }
     100             : 
     101           0 : static int property_get_next_elapse_monotonic(
     102             :                 sd_bus *bus,
     103             :                 const char *path,
     104             :                 const char *interface,
     105             :                 const char *property,
     106             :                 sd_bus_message *reply,
     107             :                 void *userdata,
     108             :                 sd_bus_error *error) {
     109             : 
     110           0 :         Timer *t = userdata;
     111             : 
     112           0 :         assert(bus);
     113           0 :         assert(reply);
     114           0 :         assert(t);
     115             : 
     116           0 :         return sd_bus_message_append(reply, "t",
     117           0 :                                      (uint64_t) usec_shift_clock(t->next_elapse_monotonic_or_boottime,
     118           0 :                                                                  TIMER_MONOTONIC_CLOCK(t), CLOCK_MONOTONIC));
     119             : }
     120             : 
     121             : const sd_bus_vtable bus_timer_vtable[] = {
     122             :         SD_BUS_VTABLE_START(0),
     123             :         SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
     124             :         SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
     125             :         SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
     126             :         SD_BUS_PROPERTY("OnClockChange", "b", bus_property_get_bool, offsetof(Timer, on_clock_change), SD_BUS_VTABLE_PROPERTY_CONST),
     127             :         SD_BUS_PROPERTY("OnTimezoneChange", "b", bus_property_get_bool, offsetof(Timer, on_timezone_change), SD_BUS_VTABLE_PROPERTY_CONST),
     128             :         SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     129             :         SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     130             :         BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     131             :         SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
     132             :         SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
     133             :         SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
     134             :         SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
     135             :         SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
     136             :         SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
     137             :         SD_BUS_VTABLE_END
     138             : };
     139             : 
     140           0 : static int timer_add_one_monotonic_spec(
     141             :                 Timer *t,
     142             :                 const char *name,
     143             :                 TimerBase base,
     144             :                 UnitWriteFlags flags,
     145             :                 usec_t usec,
     146             :                 sd_bus_error *error) {
     147             : 
     148           0 :         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
     149             :                 char ts[FORMAT_TIMESPAN_MAX];
     150             :                 TimerValue *v;
     151             : 
     152           0 :                 unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name,
     153             :                                     "%s=%s",
     154             :                                     timer_base_to_string(base),
     155             :                                     format_timespan(ts, sizeof ts, usec, USEC_PER_MSEC));
     156             : 
     157           0 :                 v = new(TimerValue, 1);
     158           0 :                 if (!v)
     159           0 :                         return -ENOMEM;
     160             : 
     161           0 :                 *v = (TimerValue) {
     162             :                         .base = base,
     163             :                         .value = usec,
     164             :                 };
     165             : 
     166           0 :                 LIST_PREPEND(value, t->values, v);
     167             :         }
     168             : 
     169           0 :         return 1;
     170             : }
     171             : 
     172           0 : static int timer_add_one_calendar_spec(
     173             :                 Timer *t,
     174             :                 const char *name,
     175             :                 TimerBase base,
     176             :                 UnitWriteFlags flags,
     177             :                 const char *str,
     178             :                 sd_bus_error *error) {
     179             : 
     180           0 :         _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
     181             :         int r;
     182             : 
     183           0 :         r = calendar_spec_from_string(str, &c);
     184           0 :         if (r == -EINVAL)
     185           0 :                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid calendar spec");
     186           0 :         if (r < 0)
     187           0 :                 return r;
     188             : 
     189           0 :         if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
     190           0 :                 unit_write_settingf(UNIT(t), flags|UNIT_ESCAPE_SPECIFIERS, name,
     191             :                                     "%s=%s", timer_base_to_string(base), str);
     192             : 
     193           0 :                 TimerValue *v = new(TimerValue, 1);
     194           0 :                 if (!v)
     195           0 :                         return -ENOMEM;
     196             : 
     197           0 :                 *v = (TimerValue) {
     198             :                         .base = base,
     199           0 :                         .calendar_spec = TAKE_PTR(c),
     200             :                 };
     201             : 
     202           0 :                 LIST_PREPEND(value, t->values, v);
     203             :         }
     204             : 
     205           0 :         return 1;
     206             : };
     207             : 
     208           0 : static int bus_timer_set_transient_property(
     209             :                 Timer *t,
     210             :                 const char *name,
     211             :                 sd_bus_message *message,
     212             :                 UnitWriteFlags flags,
     213             :                 sd_bus_error *error) {
     214             : 
     215           0 :         Unit *u = UNIT(t);
     216             :         int r;
     217             : 
     218           0 :         assert(t);
     219           0 :         assert(name);
     220           0 :         assert(message);
     221             : 
     222           0 :         flags |= UNIT_PRIVATE;
     223             : 
     224           0 :         if (streq(name, "AccuracyUSec"))
     225           0 :                 return bus_set_transient_usec(u, name, &t->accuracy_usec, message, flags, error);
     226             : 
     227           0 :         if (streq(name, "AccuracySec")) {
     228           0 :                 log_notice("Client is using obsolete AccuracySec= transient property, please use AccuracyUSec= instead.");
     229           0 :                 return bus_set_transient_usec(u, "AccuracyUSec", &t->accuracy_usec, message, flags, error);
     230             :         }
     231             : 
     232           0 :         if (streq(name, "RandomizedDelayUSec"))
     233           0 :                 return bus_set_transient_usec(u, name, &t->random_usec, message, flags, error);
     234             : 
     235           0 :         if (streq(name, "WakeSystem"))
     236           0 :                 return bus_set_transient_bool(u, name, &t->wake_system, message, flags, error);
     237             : 
     238           0 :         if (streq(name, "Persistent"))
     239           0 :                 return bus_set_transient_bool(u, name, &t->persistent, message, flags, error);
     240             : 
     241           0 :         if (streq(name, "RemainAfterElapse"))
     242           0 :                 return bus_set_transient_bool(u, name, &t->remain_after_elapse, message, flags, error);
     243             : 
     244           0 :         if (streq(name, "OnTimezoneChange"))
     245           0 :                 return bus_set_transient_bool(u, name, &t->on_timezone_change, message, flags, error);
     246             : 
     247           0 :         if (streq(name, "OnClockChange"))
     248           0 :                 return bus_set_transient_bool(u, name, &t->on_clock_change, message, flags, error);
     249             : 
     250           0 :         if (streq(name, "TimersMonotonic")) {
     251             :                 const char *base_name;
     252             :                 usec_t usec;
     253           0 :                 bool empty = true;
     254             : 
     255           0 :                 r = sd_bus_message_enter_container(message, 'a', "(st)");
     256           0 :                 if (r < 0)
     257           0 :                         return r;
     258             : 
     259           0 :                 while ((r = sd_bus_message_read(message, "(st)", &base_name, &usec)) > 0) {
     260             :                         TimerBase b;
     261             : 
     262           0 :                         b = timer_base_from_string(base_name);
     263           0 :                         if (b < 0 || b == TIMER_CALENDAR)
     264           0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     265             :                                                          "Invalid timer base: %s", base_name);
     266             : 
     267           0 :                         r = timer_add_one_monotonic_spec(t, name, b, flags, usec, error);
     268           0 :                         if (r < 0)
     269           0 :                                 return r;
     270             : 
     271           0 :                         empty = false;
     272             :                 }
     273           0 :                 if (r < 0)
     274           0 :                         return r;
     275             : 
     276           0 :                 r = sd_bus_message_exit_container(message);
     277           0 :                 if (r < 0)
     278           0 :                         return r;
     279             : 
     280           0 :                 if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
     281           0 :                         timer_free_values(t);
     282           0 :                         unit_write_setting(u, flags, name, "OnActiveSec=");
     283             :                 }
     284             : 
     285           0 :                 return 1;
     286             : 
     287           0 :         } else if (streq(name, "TimersCalendar")) {
     288             :                 const char *base_name, *str;
     289           0 :                 bool empty = true;
     290             : 
     291           0 :                 r = sd_bus_message_enter_container(message, 'a', "(ss)");
     292           0 :                 if (r < 0)
     293           0 :                         return r;
     294             : 
     295           0 :                 while ((r = sd_bus_message_read(message, "(ss)", &base_name, &str)) > 0) {
     296             :                         TimerBase b;
     297             : 
     298           0 :                         b = timer_base_from_string(base_name);
     299           0 :                         if (b != TIMER_CALENDAR)
     300           0 :                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
     301             :                                                          "Invalid timer base: %s", base_name);
     302             : 
     303           0 :                         r = timer_add_one_calendar_spec(t, name, b, flags, str, error);
     304           0 :                         if (r < 0)
     305           0 :                                 return r;
     306             : 
     307           0 :                         empty = false;
     308             :                 }
     309           0 :                 if (r < 0)
     310           0 :                         return r;
     311             : 
     312           0 :                 r = sd_bus_message_exit_container(message);
     313           0 :                 if (r < 0)
     314           0 :                         return r;
     315             : 
     316           0 :                 if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
     317           0 :                         timer_free_values(t);
     318           0 :                         unit_write_setting(u, flags, name, "OnCalendar=");
     319             :                 }
     320             : 
     321           0 :                 return 1;
     322             : 
     323           0 :         } else if (STR_IN_SET(name,
     324             :                        "OnActiveSec",
     325             :                        "OnBootSec",
     326             :                        "OnStartupSec",
     327             :                        "OnUnitActiveSec",
     328             :                        "OnUnitInactiveSec")) {
     329             : 
     330             :                 TimerBase b;
     331             :                 usec_t usec;
     332             : 
     333           0 :                 log_notice("Client is using obsolete %s= transient property, please use TimersMonotonic= instead.", name);
     334             : 
     335           0 :                 b = timer_base_from_string(name);
     336           0 :                 if (b < 0)
     337           0 :                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown timer base");
     338             : 
     339           0 :                 r = sd_bus_message_read(message, "t", &usec);
     340           0 :                 if (r < 0)
     341           0 :                         return r;
     342             : 
     343           0 :                 return timer_add_one_monotonic_spec(t, name, b, flags, usec, error);
     344             : 
     345           0 :         } else if (streq(name, "OnCalendar")) {
     346             : 
     347             :                 const char *str;
     348             : 
     349           0 :                 log_notice("Client is using obsolete %s= transient property, please use TimersCalendar= instead.", name);
     350             : 
     351           0 :                 r = sd_bus_message_read(message, "s", &str);
     352           0 :                 if (r < 0)
     353           0 :                         return r;
     354             : 
     355           0 :                 return timer_add_one_calendar_spec(t, name, TIMER_CALENDAR, flags, str, error);
     356             :         }
     357             : 
     358           0 :         return 0;
     359             : }
     360             : 
     361           0 : int bus_timer_set_property(
     362             :                 Unit *u,
     363             :                 const char *name,
     364             :                 sd_bus_message *message,
     365             :                 UnitWriteFlags mode,
     366             :                 sd_bus_error *error) {
     367             : 
     368           0 :         Timer *t = TIMER(u);
     369             : 
     370           0 :         assert(t);
     371           0 :         assert(name);
     372           0 :         assert(message);
     373             : 
     374           0 :         if (u->transient && u->load_state == UNIT_STUB)
     375           0 :                 return bus_timer_set_transient_property(t, name, message, mode, error);
     376             : 
     377           0 :         return 0;
     378             : }

Generated by: LCOV version 1.14