calendarspec: allow ranges in date and time specifications

Resolves #3042
This commit is contained in:
Douglas Christman
2016-07-01 23:13:58 -04:00
parent 563a69f480
commit 32b5236916
4 changed files with 54 additions and 21 deletions
+45 -19
View File
@@ -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) {
@@ -448,8 +450,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 +491,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 +539,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;