summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-05-05 16:07:11 +0200
committerGitHub <noreply@github.com>2020-05-05 16:07:11 +0200
commiteaf7ac4929d2d83704aff0a2e874320f13735751 (patch)
tree9a30f6ee8edc057b7207677a9508cd8d031e9155
parent05c7d9bf5bcc4b3a450f3fa208ba13b121d42dd5 (diff)
parent2edc7aea7a95dc0dc0fb3e9ef5ffbe413a477593 (diff)
downloadsystemd-eaf7ac4929d2d83704aff0a2e874320f13735751.tar.gz
Merge pull request #15645 from poettering/calender-expression-doc-fix
some calendar expression fixes and documentation updates
-rw-r--r--man/systemd.time.xml17
-rw-r--r--src/shared/calendarspec.c26
-rw-r--r--src/shared/calendarspec.h6
-rw-r--r--src/test/test-calendarspec.c4
4 files changed, 35 insertions, 18 deletions
diff --git a/man/systemd.time.xml b/man/systemd.time.xml
index dc1e78a187..b4656b05d1 100644
--- a/man/systemd.time.xml
+++ b/man/systemd.time.xml
@@ -199,15 +199,14 @@ tomorrow Pacific/Auckland → Thu 2012-11-23 19:00:00
continuous weekdays. <literal>,</literal> and <literal>..</literal>
may be combined freely.</para>
- <para>In the date and time specifications, any component may be
- specified as <literal>*</literal> in which case any value will
- match. Alternatively, each component can be specified as a list of
- values separated by commas. Values may be suffixed with
- <literal>/</literal> and a repetition value, which indicates that
- the value itself and the value plus all multiples of the repetition value
- are matched. Two values separated by <literal>..</literal> may be used
- to indicate a range of values; ranges may also be followed with
- <literal>/</literal> and a repetition value.</para>
+ <para>In the date and time specifications, any component may be specified as <literal>*</literal> in
+ which case any value will match. Alternatively, each component can be specified as a list of values
+ separated by commas. Values may be suffixed with <literal>/</literal> and a repetition value, which
+ indicates that the value itself and the value plus all multiples of the repetition value are matched.
+ Two values separated by <literal>..</literal> may be used to indicate a range of values; ranges may also
+ be followed with <literal>/</literal> and a repetition value, in which case the expression matches all
+ times starting with the start value, and continuing with all multiples of the repetition value relative
+ to the start value, ending at the end value the latest.</para>
<para>A date specification may use <literal>~</literal> to indicate the
last day(s) in a month. For example, <literal>*-02~03</literal> means
diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
index 4103cf3ef0..b162224d9d 100644
--- a/src/shared/calendarspec.c
+++ b/src/shared/calendarspec.c
@@ -30,6 +30,9 @@
* linked compenents anyway. */
#define CALENDARSPEC_COMPONENTS_MAX 240
+/* Let's make sure that the microsecond component is safe to be stored in an 'int' */
+assert_cc(INT_MAX >= USEC_PER_SEC);
+
static void chain_free(CalendarComponent *c) {
CalendarComponent *n;
@@ -88,6 +91,16 @@ static void normalize_chain(CalendarComponent **c) {
if (i->stop > i->start && i->repeat > 0)
i->stop -= (i->stop - i->start) % i->repeat;
+ /* If a repeat value is specified, but it cannot even be triggered once, let's suppress
+ * it.
+ *
+ * Similar, if the stop value is the same as the start value, then let's just make this a
+ * non-repeating chain element */
+ if ((i->stop > i->start && i->repeat > 0 && i->start + i->repeat > i->stop) ||
+ i->start == i->stop) {
+ i->repeat = 0;
+ i->stop = -1;
+ }
}
if (n <= 1)
@@ -162,7 +175,7 @@ int calendar_spec_normalize(CalendarSpec *c) {
return 0;
}
-_pure_ static bool chain_valid(CalendarComponent *c, int from, int to, bool end_of_month) {
+static bool chain_valid(CalendarComponent *c, int from, int to, bool end_of_month) {
assert(to >= from);
if (!c)
@@ -366,14 +379,13 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
}
r = fflush_and_check(f);
+ fclose(f);
+
if (r < 0) {
free(buf);
- fclose(f);
return r;
}
- fclose(f);
-
*p = buf;
return 0;
}
@@ -643,6 +655,12 @@ static int prepend_component(const char **p, bool usec, unsigned nesting, Calend
if (repeat == 0)
return -ERANGE;
+ } else {
+ /* If no repeat value is specified for the µs component, then let's explicitly refuse ranges
+ * below 1s because our default repeat granularity is beyond that. */
+
+ if (usec && stop >= 0 && start + repeat > stop)
+ return -EINVAL;
}
if (!IN_SET(*e, 0, ' ', ',', '-', '~', ':'))
diff --git a/src/shared/calendarspec.h b/src/shared/calendarspec.h
index 3bf8a39e1a..0a5d95b4b1 100644
--- a/src/shared/calendarspec.h
+++ b/src/shared/calendarspec.h
@@ -19,9 +19,9 @@ typedef struct CalendarComponent {
typedef struct CalendarSpec {
int weekdays_bits;
- bool end_of_month;
- bool utc;
- int dst;
+ bool end_of_month:1;
+ bool utc:1;
+ signed int dst:2;
char *timezone;
CalendarComponent *year;
diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
index 9c2be7f445..9e2ae55ab6 100644
--- a/src/test/test-calendarspec.c
+++ b/src/test/test-calendarspec.c
@@ -185,6 +185,8 @@ int main(int argc, char* argv[]) {
test_one("@1493187147 UTC", "2017-04-26 06:12:27 UTC");
test_one("@0", "1970-01-01 00:00:00 UTC");
test_one("@0 UTC", "1970-01-01 00:00:00 UTC");
+ test_one("*:05..05", "*-*-* *:05:00");
+ test_one("*:05..10/6", "*-*-* *:05:00");
test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000);
test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000);
@@ -237,8 +239,6 @@ int main(int argc, char* argv[]) {
assert_se(calendar_spec_from_string("*~29", &c) < 0);
assert_se(calendar_spec_from_string("*~16..31", &c) < 0);
assert_se(calendar_spec_from_string("12..1/2-*", &c) < 0);
- assert_se(calendar_spec_from_string("*:05..05", &c) < 0);
- assert_se(calendar_spec_from_string("*:05..10/6", &c) < 0);
assert_se(calendar_spec_from_string("20/4:00", &c) < 0);
assert_se(calendar_spec_from_string("00:00/60", &c) < 0);
assert_se(calendar_spec_from_string("00:00:2300", &c) < 0);