summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-07-02 09:03:20 -0700
committerGitHub <noreply@github.com>2016-07-02 09:03:20 -0700
commite71af7931616601159f50c9029efc07ec347d73b (patch)
treef4f52580575f641dffad52224d3a5477c74e530b /src/basic
parent3a1707fff139e957b915e392ac3b5a293c8dc17b (diff)
parente638d0504fa4861896f47c19e22b48c7f8ca3478 (diff)
Merge pull request #3637 from dobyrch/calendar-ranges
Allow date and time ranges in OnCalendar
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/calendarspec.c88
1 files changed, 63 insertions, 25 deletions
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 6e0bab9b94..e4cfab364e 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -32,6 +32,8 @@
#include "parse-util.h"
#include "string-util.h"
+/* Longest valid date/time range is 1970..2199 */
+#define MAX_RANGE_LEN 230
#define BITS_WEEKDAYS 127
static void free_chain(CalendarComponent *c) {
@@ -200,7 +202,7 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) {
};
int l, x;
- bool need_colon = false;
+ bool need_comma = false;
assert(f);
assert(c);
@@ -211,10 +213,10 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) {
if (c->weekdays_bits & (1 << x)) {
if (l < 0) {
- if (need_colon)
+ if (need_comma)
fputc(',', f);
else
- need_colon = true;
+ need_comma = true;
fputs(days[x], f);
l = x;
@@ -223,7 +225,7 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) {
} else if (l >= 0) {
if (x > l + 1) {
- fputc(x > l + 2 ? '-' : ',', f);
+ fputs(x > l + 2 ? ".." : ",", f);
fputs(days[x-1], f);
}
@@ -232,7 +234,7 @@ static void format_weekdays(FILE *f, const CalendarSpec *c) {
}
if (l >= 0 && x > l + 1) {
- fputc(x > l + 2 ? '-' : ',', f);
+ fputs(x > l + 2 ? ".." : ",", f);
fputs(days[x-1], f);
}
}
@@ -357,6 +359,7 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
skip = strlen(day_nr[i].name);
if ((*p)[skip] != '-' &&
+ (*p)[skip] != '.' &&
(*p)[skip] != ',' &&
(*p)[skip] != ' ' &&
(*p)[skip] != 0)
@@ -394,7 +397,18 @@ static int parse_weekdays(const char **p, CalendarSpec *c) {
return 0;
}
- if (**p == '-') {
+ if (**p == '.') {
+ if (l >= 0)
+ return -EINVAL;
+
+ if ((*p)[1] != '.')
+ return -EINVAL;
+
+ l = day_nr[i].nr;
+ *p += 1;
+
+ /* Support ranges with "-" for backwards compatibility */
+ } else if (**p == '-') {
if (l >= 0)
return -EINVAL;
@@ -448,8 +462,26 @@ static int parse_component_decimal(const char **p, bool usec, unsigned long *res
return 0;
}
+static int const_chain(int value, CalendarComponent **c) {
+ CalendarComponent *cc = NULL;
+
+ assert(c);
+
+ cc = new0(CalendarComponent, 1);
+ if (!cc)
+ return -ENOMEM;
+
+ cc->value = value;
+ cc->repeat = 0;
+ cc->next = *c;
+
+ *c = cc;
+
+ return 0;
+}
+
static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
- unsigned long value, repeat = 0;
+ unsigned long i, value, range_end, range_inc, repeat = 0;
CalendarComponent *cc;
int r;
const char *e;
@@ -471,6 +503,30 @@ static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
if (repeat == 0)
return -ERANGE;
+ } else if (e[0] == '.' && e[1] == '.') {
+ e += 2;
+ r = parse_component_decimal(&e, usec, &range_end);
+ if (r < 0)
+ return r;
+
+ if (value >= range_end)
+ return -EINVAL;
+
+ range_inc = usec ? USEC_PER_SEC : 1;
+
+ /* Don't allow impossibly large ranges... */
+ if (range_end - value >= MAX_RANGE_LEN * range_inc)
+ return -EINVAL;
+
+ /* ...or ranges with only a single element */
+ if (range_end - value < range_inc)
+ return -EINVAL;
+
+ for (i = value; i <= range_end; i += range_inc) {
+ r = const_chain(i, c);
+ if (r < 0)
+ return r;
+ }
}
if (*e != 0 && *e != ' ' && *e != ',' && *e != '-' && *e != ':')
@@ -495,24 +551,6 @@ static int prepend_component(const char **p, bool usec, CalendarComponent **c) {
return 0;
}
-static int const_chain(int value, CalendarComponent **c) {
- CalendarComponent *cc = NULL;
-
- assert(c);
-
- cc = new0(CalendarComponent, 1);
- if (!cc)
- return -ENOMEM;
-
- cc->value = value;
- cc->repeat = 0;
- cc->next = *c;
-
- *c = cc;
-
- return 0;
-}
-
static int parse_chain(const char **p, bool usec, CalendarComponent **c) {
const char *t;
CalendarComponent *cc = NULL;