diff options
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | docs/TRANSIENT-SETTINGS.md | 4 | ||||
-rw-r--r-- | man/systemd-run.xml | 12 | ||||
-rw-r--r-- | man/systemd.timer.xml | 11 | ||||
-rw-r--r-- | src/core/dbus-timer.c | 40 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 2 | ||||
-rw-r--r-- | src/core/timer.c | 30 | ||||
-rw-r--r-- | src/core/timer.h | 2 | ||||
-rw-r--r-- | src/journal-remote/journal-remote-parse.c | 6 | ||||
-rw-r--r-- | src/journal-remote/journal-remote-write.c | 5 | ||||
-rw-r--r-- | src/journal-remote/journal-remote-write.h | 1 | ||||
-rw-r--r-- | src/journal/journal-file.c | 4 | ||||
-rw-r--r-- | src/journal/journal-verify.c | 2 | ||||
-rw-r--r-- | src/libsystemd-network/sd-ipv4ll.c | 32 | ||||
-rw-r--r-- | src/run/run.c | 46 | ||||
-rw-r--r-- | src/shared/bus-unit-util.c | 3 | ||||
l--------- | test/TEST-30-ONCLOCKCHANGE/Makefile | 1 | ||||
-rwxr-xr-x | test/TEST-30-ONCLOCKCHANGE/test.sh | 53 | ||||
-rwxr-xr-x | test/TEST-30-ONCLOCKCHANGE/testsuite.sh | 33 |
19 files changed, 233 insertions, 59 deletions
@@ -144,9 +144,6 @@ Features: * When reloading configuration PID 1 should reset all its properties to the original defaults before calling parse_config() -* Add OnTimezoneChange= and OnTimeChange= stanzas to .timer units in order to - schedule events based on time and timezone changes. - * nspawn: greater control over selinux label? * hibernate/s2h: make this robust and safe to enable in Fedora by default. @@ -828,9 +825,7 @@ Features: * timer units: - timer units should get the ability to trigger when: - o CLOCK_REALTIME makes jumps (TFD_TIMER_CANCEL_ON_SET) o DST changes - o timezone changes - Modulate timer frequency based on battery state * add libsystemd-password or so to query passwords during boot using the password agent logic diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md index ac89fb174f..343df66754 100644 --- a/docs/TRANSIENT-SETTINGS.md +++ b/docs/TRANSIENT-SETTINGS.md @@ -335,10 +335,12 @@ All automount unit setting is available to transient units: Most timer unit settings are available to transient units. ``` -✓ OnCalendar= ✓ OnActiveSec= ✓ OnBootSec= +✓ OnCalendar= +✓ OnClockChange= ✓ OnStartupSec= +✓ OnTimezoneChange ✓ OnUnitActiveSec= ✓ OnUnitInactiveSec= ✓ Persistent= diff --git a/man/systemd-run.xml b/man/systemd-run.xml index 4dd81395cd..8f7a6229cc 100644 --- a/man/systemd-run.xml +++ b/man/systemd-run.xml @@ -317,6 +317,18 @@ </varlistentry> <varlistentry> + <term><option>--on-clock-change</option></term> + <term><option>--on-timezone-change</option></term> + + <listitem><para>Defines a trigger based on system clock jumps or timezone changes for starting the + specified command. See <varname>OnClockChange=</varname> and <varname>OnTimezoneChange=</varname> in + <citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>. These + options are shortcuts for <command>--timer-property=OnClockChange=yes</command> and + <command>--timer-property=OnTimezoneChange=yes</command>. These options may not be combined with + <option>--scope</option> or <option>--pty</option>.</para></listitem> + </varlistentry> + + <varlistentry> <term><option>--path-property=</option></term> <term><option>--socket-property=</option></term> <term><option>--timer-property=</option></term> diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml index f1afcf6b7e..6a13e52ccf 100644 --- a/man/systemd.timer.xml +++ b/man/systemd.timer.xml @@ -260,6 +260,17 @@ </varlistentry> <varlistentry> + <term><varname>OnClockChange=</varname></term> + <term><varname>OnTimezoneChange=</varname></term> + + <listitem><para>These options take boolean arguments. When true, the service unit will be triggered + when the system clock (<constant>CLOCK_REALTIME</constant>) jumps relative to the monotonic clock + (<constant>CLOCK_MONOTONIC</constant>), or when the local system timezone is modified. These options + can be used alone or in combination with other timer expressions (see above) within the same timer + unit. These options default to false.</para></listitem> + </varlistentry> + + <varlistentry> <term><varname>Unit=</varname></term> <listitem><para>The unit to activate when this timer elapses. diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c index b9d2f3d07e..807ca8022a 100644 --- a/src/core/dbus-timer.c +++ b/src/core/dbus-timer.c @@ -123,6 +123,8 @@ const sd_bus_vtable bus_timer_vtable[] = { SD_BUS_PROPERTY("Unit", "s", bus_property_get_triggered_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimersMonotonic", "a(stt)", property_get_monotonic_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), SD_BUS_PROPERTY("TimersCalendar", "a(sst)", property_get_calendar_timers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + SD_BUS_PROPERTY("OnClockChange", "b", bus_property_get_bool, offsetof(Timer, on_clock_change), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("OnTimezoneChange", "b", bus_property_get_bool, offsetof(Timer, on_timezone_change), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NextElapseUSecRealtime", "t", bus_property_get_usec, offsetof(Timer, next_elapse_realtime), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("NextElapseUSecMonotonic", "t", property_get_next_elapse_monotonic, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), @@ -171,6 +173,12 @@ static int bus_timer_set_transient_property( if (streq(name, "RemainAfterElapse")) return bus_set_transient_bool(u, name, &t->remain_after_elapse, message, flags, error); + if (streq(name, "OnTimezoneChange")) + return bus_set_transient_bool(u, name, &t->on_timezone_change, message, flags, error); + + if (streq(name, "OnClockChange")) + return bus_set_transient_bool(u, name, &t->on_clock_change, message, flags, error); + if (streq(name, "TimersMonotonic")) { const char *base_name; usec_t usec = 0; @@ -194,12 +202,14 @@ static int bus_timer_set_transient_property( unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", base_name, format_timespan(ts, sizeof(ts), usec, USEC_PER_MSEC)); - v = new0(TimerValue, 1); + v = new(TimerValue, 1); if (!v) return -ENOMEM; - v->base = b; - v->value = usec; + *v = (TimerValue) { + .base = b, + .value = usec, + }; LIST_PREPEND(value, t->values, v); } @@ -247,12 +257,14 @@ static int bus_timer_set_transient_property( unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", base_name, str); - v = new0(TimerValue, 1); + v = new(TimerValue, 1); if (!v) return -ENOMEM; - v->base = b; - v->calendar_spec = TAKE_PTR(c); + *v = (TimerValue) { + .base = b, + .calendar_spec = TAKE_PTR(c), + }; LIST_PREPEND(value, t->values, v); } @@ -300,12 +312,14 @@ static int bus_timer_set_transient_property( unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, format_timespan(time, sizeof(time), usec, USEC_PER_MSEC)); - v = new0(TimerValue, 1); + v = new(TimerValue, 1); if (!v) return -ENOMEM; - v->base = b; - v->value = usec; + *v = (TimerValue) { + .base = b, + .value = usec, + }; LIST_PREPEND(value, t->values, v); } @@ -333,12 +347,14 @@ static int bus_timer_set_transient_property( unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, str); - v = new0(TimerValue, 1); + v = new(TimerValue, 1); if (!v) return -ENOMEM; - v->base = TIMER_CALENDAR; - v->calendar_spec = TAKE_PTR(c); + *v = (TimerValue) { + .base = TIMER_CALENDAR, + .calendar_spec = TAKE_PTR(c), + }; LIST_PREPEND(value, t->values, v); } diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index ca0cf5894d..a2ed7f2abe 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -433,6 +433,8 @@ Timer.OnBootSec, config_parse_timer, TIMER_BOOT, Timer.OnStartupSec, config_parse_timer, TIMER_STARTUP, 0 Timer.OnUnitActiveSec, config_parse_timer, TIMER_UNIT_ACTIVE, 0 Timer.OnUnitInactiveSec, config_parse_timer, TIMER_UNIT_INACTIVE, 0 +Timer.OnClockChange, config_parse_bool, 0, offsetof(Timer, on_clock_change) +Timer.OnTimezoneChange, config_parse_bool, 0, offsetof(Timer, on_timezone_change) Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent) Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system) Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse) diff --git a/src/core/timer.c b/src/core/timer.c index 0e5214afe8..8440bb27ba 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -77,7 +77,7 @@ static int timer_verify(Timer *t) { if (UNIT(t)->load_state != UNIT_LOADED) return 0; - if (!t->values) { + if (!t->values && !t->on_clock_change && !t->on_timezone_change) { log_unit_error(UNIT(t), "Timer unit lacks value setting. Refusing."); return -ENOEXEC; } @@ -215,14 +215,18 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) { "%sPersistent: %s\n" "%sWakeSystem: %s\n" "%sAccuracy: %s\n" - "%sRemainAfterElapse: %s\n", + "%sRemainAfterElapse: %s\n" + "%sOnClockChange: %s\n" + "%sOnTimeZoneChange %s\n", prefix, timer_state_to_string(t->state), prefix, timer_result_to_string(t->result), prefix, trigger ? trigger->id : "n/a", prefix, yes_no(t->persistent), prefix, yes_no(t->wake_system), prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1), - prefix, yes_no(t->remain_after_elapse)); + prefix, yes_no(t->remain_after_elapse), + prefix, yes_no(t->on_clock_change), + prefix, yes_no(t->on_timezone_change)); LIST_FOREACH(value, v, t->values) { @@ -474,7 +478,7 @@ static void timer_enter_waiting(Timer *t, bool time_change) { } } - if (!found_monotonic && !found_realtime) { + if (!found_monotonic && !found_realtime && !t->on_timezone_change && !t->on_clock_change) { log_unit_debug(UNIT(t), "Timer is elapsed."); timer_enter_elapsed(t, leave_around); return; @@ -815,8 +819,13 @@ static void timer_time_change(Unit *u) { if (t->last_trigger.realtime > ts) t->last_trigger.realtime = ts; - log_unit_debug(u, "Time change, recalculating next elapse."); - timer_enter_waiting(t, true); + if (t->on_clock_change) { + log_unit_debug(u, "Time change, triggering activation."); + timer_enter_running(t); + } else { + log_unit_debug(u, "Time change, recalculating next elapse."); + timer_enter_waiting(t, true); + } } static void timer_timezone_change(Unit *u) { @@ -827,8 +836,13 @@ static void timer_timezone_change(Unit *u) { if (t->state != TIMER_WAITING) return; - log_unit_debug(u, "Timezone change, recalculating next elapse."); - timer_enter_waiting(t, false); + if (t->on_timezone_change) { + log_unit_debug(u, "Timezone change, triggering activation."); + timer_enter_running(t); + } else { + log_unit_debug(u, "Timezone change, recalculating next elapse."); + timer_enter_waiting(t, false); + } } static const char* const timer_base_table[_TIMER_BASE_MAX] = { diff --git a/src/core/timer.h b/src/core/timer.h index 833aadb0b8..ab66a201ad 100644 --- a/src/core/timer.h +++ b/src/core/timer.h @@ -57,6 +57,8 @@ struct Timer { bool persistent; bool wake_system; bool remain_after_elapse; + bool on_clock_change; + bool on_timezone_change; char *stamp_path; }; diff --git a/src/journal-remote/journal-remote-parse.c b/src/journal-remote/journal-remote-parse.c index 535d06ac76..ebcae2fcaa 100644 --- a/src/journal-remote/journal-remote-parse.c +++ b/src/journal-remote/journal-remote-parse.c @@ -68,7 +68,11 @@ int process_source(RemoteSource *source, bool compress, bool seal) { assert(source->importer.iovw.iovec); - r = writer_write(source->writer, &source->importer.iovw, &source->importer.ts, compress, seal); + r = writer_write(source->writer, + &source->importer.iovw, + &source->importer.ts, + &source->importer.boot_id, + compress, seal); if (r == -EBADMSG) { log_error_errno(r, "Entry is invalid, ignoring."); r = 0; diff --git a/src/journal-remote/journal-remote-write.c b/src/journal-remote/journal-remote-write.c index 188ff3582d..ab5e03ab5a 100644 --- a/src/journal-remote/journal-remote-write.c +++ b/src/journal-remote/journal-remote-write.c @@ -59,6 +59,7 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(Writer, writer, writer_free); int writer_write(Writer *w, struct iovec_wrapper *iovw, dual_timestamp *ts, + sd_id128_t *boot_id, bool compress, bool seal) { int r; @@ -75,7 +76,7 @@ int writer_write(Writer *w, return r; } - r = journal_file_append_entry(w->journal, ts, NULL, + r = journal_file_append_entry(w->journal, ts, boot_id, iovw->iovec, iovw->count, &w->seqnum, NULL, NULL); if (r >= 0) { @@ -93,7 +94,7 @@ int writer_write(Writer *w, log_debug("%s: Successfully rotated journal", w->journal->path); log_debug("Retrying write."); - r = journal_file_append_entry(w->journal, ts, NULL, + r = journal_file_append_entry(w->journal, ts, boot_id, iovw->iovec, iovw->count, &w->seqnum, NULL, NULL); if (r < 0) diff --git a/src/journal-remote/journal-remote-write.h b/src/journal-remote/journal-remote-write.h index e445859ecf..d42256e673 100644 --- a/src/journal-remote/journal-remote-write.h +++ b/src/journal-remote/journal-remote-write.h @@ -28,6 +28,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Writer*, writer_unref); int writer_write(Writer *s, struct iovec_wrapper *iovw, dual_timestamp *ts, + sd_id128_t *boot_id, bool compress, bool seal); diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 6a2e80e3c8..91d1c2921a 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -1796,7 +1796,9 @@ static int journal_file_append_entry_internal( o->entry.realtime = htole64(ts->realtime); o->entry.monotonic = htole64(ts->monotonic); o->entry.xor_hash = htole64(xor_hash); - o->entry.boot_id = boot_id ? *boot_id : f->header->boot_id; + if (boot_id) + f->header->boot_id = *boot_id; + o->entry.boot_id = f->header->boot_id; #if HAVE_GCRYPT r = journal_file_hmac_put_object(f, OBJECT_ENTRY, o, np); diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 5eff80a99f..0a06ce7b84 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -65,7 +65,7 @@ static uint64_t scale_progress(uint64_t scale, uint64_t p, uint64_t m) { * Currently all callers use m >= 1, but we keep the check to be defensive. */ - if (p >= m || m == 0) /* lgtm [cpp/constant-comparison] */ + if (p >= m || m == 0) // lgtm[cpp/constant-comparison] return scale; return scale * p / m; diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c index e451dff744..a59a952326 100644 --- a/src/libsystemd-network/sd-ipv4ll.c +++ b/src/libsystemd-network/sd-ipv4ll.c @@ -218,28 +218,21 @@ static int ipv4ll_pick_address(sd_ipv4ll *ll) { return sd_ipv4ll_set_address(ll, &(struct in_addr) { addr }); } -int sd_ipv4ll_restart(sd_ipv4ll *ll) { - ll->address = 0; - - return sd_ipv4ll_start(ll); -} - #define MAC_HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) -int sd_ipv4ll_start(sd_ipv4ll *ll) { +static int ipv4ll_start_internal(sd_ipv4ll *ll, bool reset_generation) { int r; bool picked_address = false; assert_return(ll, -EINVAL); assert_return(!ether_addr_is_null(&ll->mac), -EINVAL); - assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); /* If no random seed is set, generate some from the MAC address */ if (!ll->seed_set) ll->seed.value = htole64(siphash24(ll->mac.ether_addr_octet, ETH_ALEN, MAC_HASH_KEY.bytes)); - /* Restart the generation counter. */ - ll->seed.generation = 0; + if (reset_generation) + ll->seed.generation = 0; if (ll->address == 0) { r = ipv4ll_pick_address(ll); @@ -263,6 +256,19 @@ int sd_ipv4ll_start(sd_ipv4ll *ll) { return 0; } +int sd_ipv4ll_start(sd_ipv4ll *ll) { + assert_return(ll, -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); + + return ipv4ll_start_internal(ll, true); +} + +int sd_ipv4ll_restart(sd_ipv4ll *ll) { + ll->address = 0; + + return ipv4ll_start_internal(ll, false); +} + static void ipv4ll_client_notify(sd_ipv4ll *ll, int event) { assert(ll); @@ -298,11 +304,7 @@ void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { ll->claimed_address = 0; } else { - r = ipv4ll_pick_address(ll); - if (r < 0) - goto error; - - r = sd_ipv4acd_start(ll->acd); + r = sd_ipv4ll_restart(ll); if (r < 0) goto error; } diff --git a/src/run/run.c b/src/run/run.c index 0d05fab345..56aa9aaee6 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -60,7 +60,7 @@ static enum { static char **arg_path_property = NULL; static char **arg_socket_property = NULL; static char **arg_timer_property = NULL; -static bool with_timer = false; +static bool arg_with_timer = false; static bool arg_quiet = false; static bool arg_aggressive_gc = false; static char *arg_working_directory = NULL; @@ -124,6 +124,8 @@ static int help(void) { " --on-unit-active=SECONDS Run SECONDS after the last activation\n" " --on-unit-inactive=SECONDS Run SECONDS after the last deactivation\n" " --on-calendar=SPEC Realtime timer\n" + " --on-timezone-change Run when the timezone changes\n" + " --on-clock-change Run when the realtime clock jumps\n" " --timer-property=NAME=VALUE Set timer unit property\n" "\nSee the %s for details.\n" , program_invocation_short_name @@ -170,6 +172,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_ON_UNIT_ACTIVE, ARG_ON_UNIT_INACTIVE, ARG_ON_CALENDAR, + ARG_ON_TIMEZONE_CHANGE, + ARG_ON_CLOCK_CHANGE, ARG_TIMER_PROPERTY, ARG_PATH_PROPERTY, ARG_SOCKET_PROPERTY, @@ -210,6 +214,8 @@ static int parse_argv(int argc, char *argv[]) { { "on-unit-active", required_argument, NULL, ARG_ON_UNIT_ACTIVE }, { "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE }, { "on-calendar", required_argument, NULL, ARG_ON_CALENDAR }, + { "on-timezone-change",no_argument, NULL, ARG_ON_TIMEZONE_CHANGE}, + { "on-clock-change", no_argument, NULL, ARG_ON_CLOCK_CHANGE }, { "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY }, { "path-property", required_argument, NULL, ARG_PATH_PROPERTY }, { "socket-property", required_argument, NULL, ARG_SOCKET_PROPERTY }, @@ -339,7 +345,7 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return r; - with_timer = true; + arg_with_timer = true; break; case ARG_ON_BOOT: @@ -347,7 +353,7 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return r; - with_timer = true; + arg_with_timer = true; break; case ARG_ON_STARTUP: @@ -355,7 +361,7 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return r; - with_timer = true; + arg_with_timer = true; break; case ARG_ON_UNIT_ACTIVE: @@ -363,7 +369,7 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return r; - with_timer = true; + arg_with_timer = true; break; case ARG_ON_UNIT_INACTIVE: @@ -371,7 +377,7 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return r; - with_timer = true; + arg_with_timer = true; break; case ARG_ON_CALENDAR: @@ -379,7 +385,23 @@ static int parse_argv(int argc, char *argv[]) { if (r < 0) return r; - with_timer = true; + arg_with_timer = true; + break; + + case ARG_ON_TIMEZONE_CHANGE: + r = add_timer_property("OnTimezoneChange", "yes"); + if (r < 0) + return r; + + arg_with_timer = true; + break; + + case ARG_ON_CLOCK_CHANGE: + r = add_timer_property("OnClockChange", "yes"); + if (r < 0) + return r; + + arg_with_timer = true; break; case ARG_TIMER_PROPERTY: @@ -387,7 +409,7 @@ static int parse_argv(int argc, char *argv[]) { if (strv_extend(&arg_timer_property, optarg) < 0) return log_oom(); - with_timer = with_timer || + arg_with_timer = arg_with_timer || STARTSWITH_SET(optarg, "OnActiveSec=", "OnBootSec=", @@ -455,10 +477,10 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } - with_trigger = !!arg_path_property || !!arg_socket_property || with_timer; + with_trigger = !!arg_path_property || !!arg_socket_property || arg_with_timer; /* currently, only single trigger (path, socket, timer) unit can be created simultaneously */ - if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) with_timer > 1) + if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) arg_with_timer > 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Only single trigger (path, socket, timer) unit can be created."); @@ -554,7 +576,7 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Path, socket or timer options are not supported in --scope mode."); - if (arg_timer_property && !with_timer) + if (arg_timer_property && !arg_with_timer) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--timer-property= has no effect without any other timer options."); @@ -1646,7 +1668,7 @@ static int run(int argc, char* argv[]) { r = start_transient_trigger(bus, ".path"); else if (arg_socket_property) r = start_transient_trigger(bus, ".socket"); - else if (with_timer) + else if (arg_with_timer) r = start_transient_trigger(bus, ".timer"); else r = start_transient_service(bus, &retval); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 968f91b28c..b27227aeb6 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -1499,7 +1499,8 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons static int bus_append_timer_property(sd_bus_message *m, const char *field, const char *eq) { int r; - if (STR_IN_SET(field, "WakeSystem", "RemainAfterElapse", "Persistent")) + if (STR_IN_SET(field, "WakeSystem", "RemainAfterElapse", "Persistent", + "OnTimezoneChange", "OnClockChange")) return bus_append_parse_boolean(m, field, eq); diff --git a/test/TEST-30-ONCLOCKCHANGE/Makefile b/test/TEST-30-ONCLOCKCHANGE/Makefile new file mode 120000 index 0000000000..e9f93b1104 --- /dev/null +++ b/test/TEST-30-ONCLOCKCHANGE/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile
\ No newline at end of file diff --git a/test/TEST-30-ONCLOCKCHANGE/test.sh b/test/TEST-30-ONCLOCKCHANGE/test.sh new file mode 100755 index 0000000000..25709410b9 --- /dev/null +++ b/test/TEST-30-ONCLOCKCHANGE/test.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +set -e +TEST_DESCRIPTION="test OnClockChange= + OnTimezoneChange=" +TEST_NO_NSPAWN=1 + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image + mkdir -p $TESTDIR/root + mount ${LOOPDEV}p1 $TESTDIR/root + + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + inst_any /usr/share/zoneinfo/Europe/Kiev + inst_any /usr/share/zoneinfo/Europe/Berlin + + setup_basic_environment + + # mask some services that we do not want to run in these tests + ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service + ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service + ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service + ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket + ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service + ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service + + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <<EOF +[Unit] +Description=Testsuite service + +[Service] +ExecStart=/testsuite.sh +Type=oneshot +StandardOutput=tty +StandardError=tty +NotifyAccess=all +EOF + cp testsuite.sh $initdir/ + + setup_testsuite + ) || return 1 + + ddebug "umount $TESTDIR/root" + umount $TESTDIR/root +} + +do_test "$@" diff --git a/test/TEST-30-ONCLOCKCHANGE/testsuite.sh b/test/TEST-30-ONCLOCKCHANGE/testsuite.sh new file mode 100755 index 0000000000..8ded85633a --- /dev/null +++ b/test/TEST-30-ONCLOCKCHANGE/testsuite.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +set -ex +set -o pipefail + +systemd-analyze set-log-level debug +systemd-analyze set-log-target console + +systemctl disable --now systemd-timesyncd.service + +timedatectl set-timezone Europe/Berlin +timedatectl set-time 1980-10-15 + +systemd-run --on-timezone-change touch /tmp/timezone-changed +systemd-run --on-clock-change touch /tmp/clock-changed + +! test -f /tmp/timezone-changed +! test -f /tmp/clock-changed + +timedatectl set-timezone Europe/Kiev + +while ! test -f /tmp/timezone-changed ; do sleep .5 ; done + +timedatectl set-time 2018-1-1 + +while ! test -f /tmp/clock-changed ; do sleep .5 ; done + +systemd-analyze set-log-level info + +echo OK > /testok + +exit 0 |