summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/providers/ipa/ipa_timerules.c1187
-rw-r--r--src/providers/ipa/ipa_timerules.h56
-rw-r--r--src/tests/ipa_timerules-tests.c582
3 files changed, 0 insertions, 1825 deletions
diff --git a/src/providers/ipa/ipa_timerules.c b/src/providers/ipa/ipa_timerules.c
deleted file mode 100644
index 857107dfa..000000000
--- a/src/providers/ipa/ipa_timerules.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/*
- SSSD
-
- IPA Provider Time Rules Parsing
-
- Authors:
- Jakub Hrozek <jhrozek@redhat.com>
-
- Copyright (C) Red Hat, Inc 2009
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define _XOPEN_SOURCE /* strptime() needs this */
-
-#include <pcre.h>
-#include <talloc.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <time.h>
-#include <stdbool.h>
-#include <limits.h>
-
-#include "providers/ipa/ipa_timerules.h"
-#include "util/util.h"
-
-#define JMP_NEOK(variable) do { \
- if (variable != EOK) goto done; \
-} while (0)
-
-#define JMP_NEOK_LABEL(variable, label) do { \
- if (variable != EOK) goto label; \
-} while (0)
-
-#define CHECK_PTR(ptr) do { \
- if (ptr == NULL) { \
- return ENOMEM; \
- } \
-} while (0)
-
-#define CHECK_PTR_JMP(ptr) do { \
- if (ptr == NULL) { \
- ret = ENOMEM; \
- goto done; \
- } \
-} while (0)
-
-#define BUFFER_OR_JUMP(ctx, ptr, count) do { \
- ptr = talloc_array(ctx, unsigned char, count); \
- if (ptr == NULL) { \
- return ENOMEM; \
- } \
- memset(ptr, 0, sizeof(unsigned char)*count); \
-} while (0)
-
-#define TEST_BIT_RANGE(bitfield, index, resptr) do { \
- if (bitfield) { \
- if (test_bit(&bitfield, index) == 0) { \
- *resptr = false; \
- return EOK; \
- } \
- } \
-} while (0)
-
-#define TEST_BIT_RANGE_PTR(bitfield, index, resptr) do { \
- if (bitfield) { \
- if (test_bit(bitfield, index) == 0) { \
- *resptr = false; \
- return EOK; \
- } \
- } \
-} while (0)
-
-/* number of match offsets when matching pcre regexes */
-#define OVEC_SIZE 30
-
-/* regular expressions describing syntax of our HBAC grammar */
-#define RGX_WEEKLY "day (?P<day_of_week>(0|1|2|3|4|5|6|7|Mon|Tue|Wed|Thu|Fri|Sat|Sun|,|-)+)"
-
-#define RGX_MDAY "(?P<mperspec_day>day) (?P<interval_day>[0-9,-]+) "
-#define RGX_MWEEK "(?P<mperspec_week>week) (?P<interval_week>[0-9,-]+) "RGX_WEEKLY
-#define RGX_MONTHLY RGX_MDAY"|"RGX_MWEEK
-
-#define RGX_YDAY "(?P<yperspec_day>day) (?P<day_of_year>[0-9,-]+) "
-#define RGX_YWEEK "(?P<yperspec_week>week) (?P<week_of_year>[0-9,-]+) "RGX_WEEKLY
-#define RGX_YMONTH "(?P<yperspec_month>month) (?P<month_number>[0-9,-]+) (?P<m_period>.*?)$"
-#define RGX_YEARLY RGX_YMONTH"|"RGX_YWEEK"|"RGX_YDAY
-
-#define RGX_TIMESPEC "(?P<timeFrom>[0-9]{4}) ~ (?P<timeTo>[0-9]{4})"
-
-#define RGX_GENERALIZED "(?P<year>[0-9]{4})(?P<month>[0-9]{2})(?P<day>[0-9]{2})(?P<hour>[0-9]{2})?(?P<minute>[0-9]{2})?(?P<second>[0-9]{2})?"
-
-#define RGX_PERIODIC "^periodic (?P<perspec>daily|weekly|monthly|yearly) (?P<period>.*?)"RGX_TIMESPEC"$"
-#define RGX_ABSOLUTE "^absolute (?P<from>\\S+) ~ (?P<to>\\S+)$"
-
-/* limits on various parameters */
-#define DAY_OF_WEEK_MAX 7
-#define DAY_OF_MONTH_MAX 31
-#define WEEK_OF_MONTH_MAX 5
-#define WEEK_OF_YEAR_MAX 54
-#define DAY_OF_YEAR_MAX 366
-#define MONTH_MAX 12
-#define HOUR_MAX 23
-#define MINUTE_MAX 59
-
-/* limits on sizes of buffers for bit arrays */
-#define DAY_OF_MONTH_BUFSIZE 8
-#define DAY_OF_YEAR_BUFSIZE 44
-#define WEEK_OF_YEAR_BUFSIZE 13
-#define MONTH_BUFSIZE 2
-#define HOUR_BUFSIZE 4
-#define MINUTE_BUFSIZE 8
-
-/* Lookup tables for translating names of days and months */
-static const char *names_day_of_week[] =
- { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", NULL };
-static const char *names_months[] =
- { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Nov", "Dec", NULL };
-
-/*
- * Timelib knows two types of ranges - periodic and absolute
- */
-enum rangetypes {
- TYPE_ABSOLUTE,
- TYPE_PERIODIC
-};
-
-struct absolute_range {
- time_t time_from;
- time_t time_to;
-};
-
-struct periodic_range {
- unsigned char day_of_week;
- unsigned char *day_of_month;
- unsigned char *day_of_year;
- unsigned char week_of_month;
- unsigned char *week_of_year;
- unsigned char *month;
- unsigned char *hour;
- unsigned char *minute;
-};
-
-/*
- * Context of one time rule being analyzed
- */
-struct range_ctx {
- /* main context with precompiled patterns */
- struct time_rules_ctx *trctx;
- /* enum rangetypes */
- enum rangetypes type;
-
- struct absolute_range *abs;
- struct periodic_range *per;
-};
-
-
-/*
- * The context of one regular expression
- */
-struct parse_ctx {
- /* the regular expression used for one parsing */
- pcre *re;
- /* number of matches */
- int matches;
- /* vector of matches */
- int *ovec;
-};
-
-/* indexes to the array of precompiled regexes */
-enum timelib_rgx {
- LP_RGX_GENERALIZED,
- LP_RGX_MDAY,
- LP_RGX_MWEEK,
- LP_RGX_YEARLY,
- LP_RGX_WEEKLY,
- LP_RGX_ABSOLUTE,
- LP_RGX_PERIODIC,
- LP_RGX_MAX,
-};
-
-/* matches the indexes */
-static const char *lookup_table[] = {
- RGX_GENERALIZED,
- RGX_MDAY,
- RGX_MWEEK,
- RGX_YEARLY,
- RGX_WEEKLY,
- RGX_ABSOLUTE,
- RGX_PERIODIC,
- NULL,
-};
-
-/*
- * Main struct passed outside
- * holds precompiled regular expressions
- */
-struct time_rules_ctx {
- pcre *re[LP_RGX_MAX];
-};
-
-/*******************************************************************
- * helper function - bit arrays *
- *******************************************************************/
-
-/* set a single bit in a bitmap */
-static void set_bit(unsigned char *bitmap, unsigned int bit)
-{
- bitmap[bit/CHAR_BIT] |= 1 << (bit%CHAR_BIT);
-}
-
-/*
- * This function is based on bit_nset macro written originally by Paul Vixie,
- * copyrighted by The Regents of the University of California, as found
- * in tarball of fcron, file bitstring.h
- */
-static void set_bit_range(unsigned char *bitmap, unsigned int start,
- unsigned int stop)
-{
- int startbyte = start/CHAR_BIT;
- int stopbyte = stop/CHAR_BIT;
-
- if (startbyte == stopbyte) {
- bitmap[startbyte] |= ((0xff << (start & 0x7)) &
- (0xff >> (CHAR_BIT- 1 - (stop & 0x7))));
- } else {
- bitmap[startbyte] |= 0xff << (start & 0x7);
- while (++startbyte < stopbyte) {
- bitmap[startbyte] |= 0xff;
- }
- bitmap[stopbyte] |= 0xff >> (CHAR_BIT- 1 - (stop & 0x7));
- }
-}
-
-static int test_bit(unsigned char *bitmap, unsigned int bit)
-{
- return (int)(bitmap[bit/CHAR_BIT] >> (bit%CHAR_BIT)) & 1;
-}
-
-/*******************************************************************
- * parsing intervals *
- *******************************************************************/
-
-/*
- * Some ranges allow symbolic names, like Mon..Sun for names of day.
- * This routine takes a list of symbolic names as NAME_ARRAY and the
- * one we're looking for as KEY and returns its index or -1 when not
- * found. The last member of NAME_ARRAY must be NULL.
- */
-static int name_index(const char **name_array, const char *key, int min)
-{
- int idx = 0;
- const char *one;
-
- if (name_array == NULL) {
- return -1;
- }
-
- while ((one = name_array[idx]) != NULL) {
- if (strcmp(key,one) == 0) {
- return idx+min;
- }
- idx++;
- }
-
- return -1;
-}
-
-/*
- * Sets appropriate bits given by an interval in STR (in form of 1,5-7,10) to
- * a bitfield given in OUT. Does no boundary checking. STR can also contain
- * symbolic names, these would be given in TRANSLATE.
- */
-static int interval2bitfield(TALLOC_CTX *mem_ctx,
- unsigned char *out,
- const char *str,
- int min, int max,
- const char **translate)
-{
- char *copy;
- char *next, *token;
- int tokval, tokmax;
- char *end_ptr;
- int ret;
- char *dash;
-
- DEBUG(9, ("Converting '%s' to interval\n", str));
-
- copy = talloc_strdup(mem_ctx, str);
- CHECK_PTR(copy);
-
- next = copy;
- while (next) {
- token = next;
- next = strchr(next, ',');
- if (next) {
- *next = '\0';
- next++;
- }
-
- errno = 0;
- tokval = strtol(token, &end_ptr, 10);
- if (*end_ptr == '\0' && errno == 0) {
- if (tokval <= max && tokval >= 0) {
- set_bit(out, tokval);
- continue;
- } else {
- ret = ERANGE;
- goto done;
- }
- } else if ((dash = strchr(token, '-')) != NULL){
- *dash = '\0';
- ++dash;
-
- errno = 0;
- tokval = strtol(token, &end_ptr, 10);
- if (*end_ptr != '\0' || errno != 0) {
- tokval = name_index(translate, token, min);
- if (tokval == -1) {
- ret = ERANGE;
- goto done;
- }
- }
- errno = 0;
- tokmax = strtol(dash, &end_ptr, 10);
- if (*end_ptr != '\0' || errno != 0) {
- tokmax = name_index(translate, dash, min);
- if (tokmax == -1) {
- ret = ERANGE;
- goto done;
- }
- }
-
- if (tokval <= max && tokmax <= max &&
- tokval >= min && tokmax >= min) {
- if (tokmax > tokval) {
- DEBUG(7, ("Setting interval %d-%d\n", tokval, tokmax));
- DEBUG(9, ("interval: %p\n", out));
- set_bit_range(out, tokval, tokmax);
- } else {
- /* Interval wraps around - i.e. from 18.00 to 06.00 */
- DEBUG(7, ("Setting inverted interval %d-%d\n", tokval, tokmax));
- DEBUG(9, ("interval: %p\n", out));
- set_bit_range(out, min, tokmax);
- set_bit_range(out, tokval, max);
- }
- continue;
- } else {
- /* tokval or tokmax are not between <min, max> */
- ret = ERANGE;
- goto done;
- }
- } else if ((tokval = name_index(translate, token, min)) != -1) {
- /* Try to translate one token by name */
- if (tokval <= max) {
- set_bit(out, tokval);
- continue;
- } else {
- ret = ERANGE;
- goto done;
- }
- } else {
- ret = EINVAL;
- goto done;
- }
- }
-
- ret = EOK;
-done:
- talloc_free(copy);
- return ret;
-}
-
-/*******************************************************************
- * wrappers around regexp handling *
- *******************************************************************/
-
-/*
- * Copies a named substring SUBSTR_NAME from string STR using the parsing
- * information from PCTX. The context PCTX is also used as a talloc context.
- *
- * The resulting string is stored in OUT.
- * Return value is EOK on no error or ENOENT on error capturing the substring
- */
-static int copy_substring(struct parse_ctx *pctx,
- const char *str,
- const char *substr_name,
- char **out)
-{
- const char *result = NULL;
- int ret;
- char *o = NULL;
-
- result = NULL;
-
- ret = pcre_get_named_substring(pctx->re, str, pctx->ovec,
- pctx->matches, substr_name, &result);
- if (ret < 0 || result == NULL) {
- DEBUG(5, ("named substring '%s' does not exist in '%s'\n",
- substr_name, str));
- return ENOENT;
- }
-
- o = talloc_strdup(pctx, result);
- pcre_free_substring(result);
- if (o == NULL) {
- return ENOMEM;
- }
-
- DEBUG(9, ("Copied substring named '%s' value '%s'\n", substr_name, o));
-
- *out = o;
- return EOK;
-}
-
-/*
- * Copies a named substring SUBSTR_NAME from string STR using the parsing
- * information from PCTX and converts it to an integer.
- * The context PCTX is also used as a talloc context.
- *
- * The resulting string is stored in OUT.
- * Return value is EOK on no error or ENOENT on error capturing the substring
- */
-static int substring_strtol(struct parse_ctx *pctx,
- const char *str,
- const char *substr_name,
- int *out)
-{
- char *substr = NULL;
- int ret;
- int val;
- char *err_ptr;
-
- ret = copy_substring(pctx, str, substr_name, &substr);
- if (ret != EOK) {
- DEBUG(5, ("substring '%s' does not exist\n", substr_name));
- return ret;
- }
-
- errno = 0;
- val = strtol(substr, &err_ptr, 10);
- if (substr == '\0' || *err_ptr != '\0' || errno != 0) {
- DEBUG(5, ("substring '%s' does not contain an integerexist\n",
- substr));
- talloc_free(substr);
- return EINVAL;
- }
-
- *out = val;
- talloc_free(substr);
- return EOK;
-}
-
-/*
- * Compiles a regular expression REGEXP and tries to match it against the
- * string STR. Fills in structure _PCTX with info about matching.
- *
- * Returns EOK on no error, EFAULT on bad regexp, EINVAL when it cannot
- * match the regexp.
- */
-static int matches_regexp(TALLOC_CTX *ctx,
- struct time_rules_ctx *trctx,
- const char *str,
- enum timelib_rgx regex,
- struct parse_ctx **_pctx)
-{
- int ret;
- struct parse_ctx *pctx = NULL;
-
- pctx = talloc_zero(ctx, struct parse_ctx);
- CHECK_PTR(pctx);
- pctx->ovec = talloc_array(pctx, int, OVEC_SIZE);
- CHECK_PTR_JMP(pctx->ovec);
- pctx->re = trctx->re[regex];
-
- ret = pcre_exec(pctx->re, NULL, str, strlen(str), 0, PCRE_NOTEMPTY, pctx->ovec, OVEC_SIZE);
- if (ret <= 0) {
- DEBUG(8, ("string '%s' did *NOT* match regexp '%s'\n", str, lookup_table[regex]));
- ret = EINVAL;
- goto done;
- }
- DEBUG(8, ("string '%s' matched regexp '%s'\n", str, lookup_table[regex]));
-
- pctx->matches = ret;
- *_pctx = pctx;
- return EOK;
-
-done:
- talloc_free(pctx);
- return ret;
-}
-
-/*******************************************************************
- * date/time helper functions *
- *******************************************************************/
-
-/*
- * Returns week number as an integer
- * This may seem ugly, but I think it's actually less error prone
- * than writing my own routine
- */
-static int weeknum(const struct tm *t)
-{
- char buf[3];
-
- if (!strftime(buf, 3, "%U", t)) {
- return -1;
- }
-
- /* %U returns 0-53, we want 1-54 */
- return atoi(buf)+1;
-}
-
-/*
- * Return the week of the month
- * Range is 1 to 5
- */
-static int get_week_of_month(const struct tm *t)
-{
- int fs; /* first sunday */
-
- fs = (t->tm_mday % 7) - t->tm_wday;
- if (fs <= 0) {
- fs += 7;
- }
-
- return (t->tm_mday <= fs) ? 1 : (2 + (t->tm_mday - fs - 1) / 7);
-}
-
-/*
- * Normalize differencies between our HBAC definition and semantics of
- * struct tm
- */
-static void abs2tm(struct tm *t)
-{
- /* tm defines tm_year as num of yrs since 1900, we have absolute number */
- t->tm_year %= 1900;
- /* struct tm defines tm_mon as number of month since January */
- t->tm_mon--;
-}
-
-/*
- * Normalize differencies between our HBAC definition and semantics of
- * struct tm
- */
-static void tm2abs(struct tm *t)
-{
- /* tm defines tm_year as num of yrs since 1900, we have absolute number */
- t->tm_year += 1900;
- /* struct tm defines tm_mon as number of month since January */
- t->tm_mon++;
-}
-
-/*******************************************************************
- * parsing of HBAC rules themselves *
- *******************************************************************/
-
-/*
- * Parses generalized time string given in STR and fills the
- * information into OUT.
- */
-static int parse_generalized_time(struct parse_ctx *pctx,
- struct time_rules_ctx *trctx,
- const char *str,
- time_t *out)
-{
- int ret;
- struct parse_ctx *gctx = NULL;
- struct tm tm;
-
- memset(&tm, 0, sizeof(tm));
- tm.tm_isdst = -1;
-
- ret = matches_regexp(pctx, trctx, str, LP_RGX_GENERALIZED, &gctx);
- JMP_NEOK(ret);
-
- /* compulsory */
- ret = substring_strtol(gctx, str, "year", &tm.tm_year);
- JMP_NEOK(ret);
- ret = substring_strtol(gctx, str, "month", &tm.tm_mon);
- JMP_NEOK(ret);
- ret = substring_strtol(gctx, str, "day", &tm.tm_mday);
- JMP_NEOK(ret);
- /* optional */
- ret = substring_strtol(gctx, str, "hour", &tm.tm_hour);
- JMP_NEOK_LABEL(ret, enoent);
- ret = substring_strtol(gctx, str, "minute", &tm.tm_min);
- JMP_NEOK_LABEL(ret, enoent);
- ret = substring_strtol(gctx, str, "second", &tm.tm_sec);
- JMP_NEOK_LABEL(ret, enoent);
-
-enoent:
- if (ret == ENOENT) {
- ret = EOK;
- }
-
- abs2tm(&tm);
-
- *out = mktime(&tm);
- DEBUG(3, ("converted to time: '%s'\n", ctime(out)));
- if (*out == -1) {
- ret = EINVAL;
- }
-done:
- talloc_free(gctx);
- return ret;
-}
-
-/*
- * Parses absolute timerange string given in STR and fills the
- * information into ABS.
- */
-static int parse_absolute(struct absolute_range *absr,
- struct time_rules_ctx *trctx,
- struct parse_ctx *pctx,
- const char *str)
-{
- char *from = NULL, *to = NULL;
- int ret;
-
- ret = copy_substring(pctx, str, "from", &from);
- if (ret != EOK) {
- DEBUG(1, ("Missing required part 'from' in absolute timespec\n"));
- ret = EINVAL;
- goto done;
- }
- ret = copy_substring(pctx, str, "to", &to);
- if (ret != EOK) {
- DEBUG(1, ("Missing required part 'to' in absolute timespec\n"));
- ret = EINVAL;
- goto done;
- }
-
- ret = parse_generalized_time(pctx, trctx, from, &absr->time_from);
- if (ret != EOK) {
- DEBUG(1, ("Cannot parse generalized time - first part\n"));
- goto done;
- }
-
- ret = parse_generalized_time(pctx, trctx, to, &absr->time_to);
- if (ret != EOK) {
- DEBUG(1, ("Cannot parse generalized time - second part\n"));
- goto done;
- }
-
- if (difftime(absr->time_to, absr->time_from) < 0) {
- DEBUG(1, ("Not a valid interval\n"));
- ret = EINVAL;
- goto done;
- }
-
- ret = EOK;
-done:
- talloc_free(from);
- talloc_free(to);
- return ret;
-}
-
-static int parse_hhmm(const char *str, int *hour, int *min)
-{
- struct tm t;
- char *err;
-
- err = strptime(str, "%H%M", &t);
- if (*err != '\0') {
- return EINVAL;
- }
-
- *hour = t.tm_hour;
- *min = t.tm_min;
-
- return EOK;
-}
-
-/*
- * Parses monthly periodic timerange given in STR.
- * Fills the information into PER.
- */
-static int parse_periodic_monthly(TALLOC_CTX *ctx,
- struct time_rules_ctx *trctx,
- struct periodic_range *per,
- const char *str)
-{
- int ret;
- struct parse_ctx *mpctx = NULL;
- char *match = NULL;
- char *mperspec = NULL;
-
- /* This code would be much less ugly if RHEL5 PCRE knew about PCRE_DUPNAMES */
- ret = matches_regexp(ctx, trctx, str, LP_RGX_MDAY, &mpctx);
- if (ret == EOK) {
- ret = copy_substring(mpctx, str, "mperspec_day", &mperspec);
- JMP_NEOK(ret);
- ret = copy_substring(mpctx, str, "interval_day", &match);
- JMP_NEOK(ret);
- BUFFER_OR_JUMP(per, per->day_of_month, DAY_OF_MONTH_BUFSIZE);
- ret = interval2bitfield(mpctx, per->day_of_month, match,
- 1, DAY_OF_MONTH_MAX, NULL);
- JMP_NEOK(ret);
- } else {
- ret = matches_regexp(ctx, trctx, str, LP_RGX_MWEEK, &mpctx);
- JMP_NEOK(ret);
- ret = copy_substring(mpctx, str, "mperspec_week", &mperspec);
- JMP_NEOK(ret);
-
- ret = copy_substring(mpctx, str, "interval_week", &match);
- JMP_NEOK(ret);
- ret = interval2bitfield(mpctx, &per->week_of_month, match,
- 1, WEEK_OF_MONTH_MAX, NULL);
- JMP_NEOK(ret);
-
- ret = copy_substring(mpctx, str, "day_of_week", &match);
- JMP_NEOK(ret);
- ret = interval2bitfield(mpctx, &per->day_of_week, match,
- 1, DAY_OF_WEEK_MAX, names_day_of_week);
- JMP_NEOK(ret);
- }
-
-done:
- talloc_free(mpctx);
- return ret;
-}
-
-/*
- * Parses yearly periodic timerange given in STR.
- * Fills the information into PER.
- */
-static int parse_periodic_yearly(TALLOC_CTX *ctx,
- struct time_rules_ctx *trctx,
- struct periodic_range *per,
- const char *str)
-{
- int ret;
- struct parse_ctx *ypctx = NULL;
- char *match = NULL;
- char *yperspec = NULL;
-
- ret = matches_regexp(ctx, trctx, str, LP_RGX_YEARLY, &ypctx);
- JMP_NEOK(ret);
- ret = copy_substring(ypctx, str, "yperspec_day", &yperspec);
- if (ret == EOK) {
- ret = copy_substring(ypctx, str, "day_of_year", &match);
- JMP_NEOK(ret);
- BUFFER_OR_JUMP(per, per->day_of_year, DAY_OF_YEAR_BUFSIZE);
- ret = interval2bitfield(ypctx, per->day_of_year, match,
- 1, DAY_OF_YEAR_MAX, NULL);
- JMP_NEOK(ret);
- }
-
- if (ret != ENOENT) goto done;
-
- ret = copy_substring(ypctx, str, "yperspec_week", &yperspec);
- if (ret == EOK) {
- ret = copy_substring(ypctx, str, "week_of_year", &match);
- JMP_NEOK(ret);
- BUFFER_OR_JUMP(per, per->week_of_year, WEEK_OF_YEAR_BUFSIZE);
- ret = interval2bitfield(ypctx, per->week_of_year, match,
- 1, WEEK_OF_YEAR_MAX, NULL);
- JMP_NEOK(ret);
-
- talloc_free(match);
- ret = copy_substring(ypctx, str, "day_of_week", &match);
- JMP_NEOK(ret);
- ret = interval2bitfield(ypctx, &per->day_of_week, match,
- 1, DAY_OF_WEEK_MAX, names_day_of_week);
- JMP_NEOK(ret);
- }
-
- if (ret != ENOENT) goto done;
-
- ret = copy_substring(ypctx, str, "yperspec_month", &yperspec);
- JMP_NEOK(ret);
-
- talloc_free(match);
- ret = copy_substring(ypctx, str, "month_number", &match);
- JMP_NEOK(ret);
- BUFFER_OR_JUMP(per, per->month, MONTH_BUFSIZE);
- ret = interval2bitfield(ypctx, per->month, match,
- 1, MONTH_MAX, names_months);
- JMP_NEOK(ret);
-
- talloc_free(match);
- ret = copy_substring(ypctx, str, "m_period", &match);
- JMP_NEOK(ret);
- DEBUG(7, ("Monthly year period - calling parse_periodic_monthly()\n"));
- ret = parse_periodic_monthly(ypctx, trctx, per, match);
- JMP_NEOK(ret);
-
-done:
- talloc_free(ypctx);
- return ret;
-}
-
-/*
- * Parses weekly periodic timerange given in STR.
- * Fills the information into PER.
- */
-static int parse_periodic_weekly(TALLOC_CTX *ctx,
- struct time_rules_ctx *trctx,
- struct periodic_range *per,
- const char *str)
-{
- int ret;
- struct parse_ctx *wpctx = NULL;
- char *dow = NULL;
-
- ret = matches_regexp(ctx, trctx, str, LP_RGX_WEEKLY, &wpctx);
- JMP_NEOK(ret);
-
- ret = copy_substring(wpctx, str, "day_of_week", &dow);
- JMP_NEOK(ret);
- DEBUG(8, ("day_of_week = '%s'\n", dow));
-
- ret = interval2bitfield(wpctx, &per->day_of_week, dow,
- 1, DAY_OF_WEEK_MAX, names_day_of_week);
-
-done:
- talloc_free(wpctx);
- return ret;
-}
-
-static int parse_periodic_time(struct periodic_range *per,
- struct parse_ctx *pctx,
- const char *str)
-{
- char *substr = NULL;
- int ret;
-
- int hour_from;
- int hour_to;
- int min_from;
- int min_to;
-
- /* parse out the time */
- ret = copy_substring(pctx, str, "timeFrom", &substr);
- JMP_NEOK(ret);
- parse_hhmm(substr, &hour_from, &min_from);
- DEBUG(7, ("Parsed timeFrom: %d:%d\n", hour_from, min_from));
- JMP_NEOK(ret);
-
- talloc_free(substr);
- ret = copy_substring(pctx, str, "timeTo", &substr);
- JMP_NEOK(ret);
- parse_hhmm(substr, &hour_to, &min_to);
- DEBUG(7, ("Parsed timeTo: %d:%d\n", hour_to, min_to));
- JMP_NEOK(ret);
-
- /* set the interval */
- if (hour_from > hour_to ) {
- set_bit_range(per->hour, 0, hour_to);
- set_bit_range(per->hour, hour_from, HOUR_MAX);
- } else {
- set_bit_range(per->hour, hour_from, hour_to);
- }
-
- if (min_from > min_to) {
- set_bit_range(per->minute, 0, min_to);
- set_bit_range(per->minute, min_from, MINUTE_MAX);
- } else {
- set_bit_range(per->minute, min_from, min_to);
- }
-
-
- ret = EOK;
-done:
- talloc_free(substr);
- return ret;
-}
-
-/*
- * Parses periodic timerange given in STR.
- * Fills the information into PER.
- */
-static int parse_periodic(struct periodic_range *per,
- struct time_rules_ctx *trctx,
- struct parse_ctx *pctx,
- const char *str)
-{
- char *substr = NULL;
- char *period = NULL;
- int ret;
-
- /* These are mandatory */
- BUFFER_OR_JUMP(per, per->hour, HOUR_BUFSIZE);
- BUFFER_OR_JUMP(per, per->minute, MINUTE_BUFSIZE);
-
- ret = copy_substring(pctx, str, "perspec", &substr);
- JMP_NEOK(ret);
- ret = copy_substring(pctx, str, "period", &period);
- JMP_NEOK(ret);
-
- if (strcmp(substr, "yearly") == 0) {
- DEBUG(5, ("periodic yearly\n"));
- ret = parse_periodic_yearly(pctx, trctx, per, period);
- JMP_NEOK(ret);
- } else if (strcmp(substr, "monthly") == 0) {
- DEBUG(5, ("periodic monthly\n"));
- ret = parse_periodic_monthly(pctx, trctx, per, period);
- JMP_NEOK(ret);
- } else if (strcmp(substr, "weekly") == 0) {
- DEBUG(5, ("periodic weekly\n"));
- ret = parse_periodic_weekly(pctx, trctx, per, period);
- JMP_NEOK(ret);
- } else if (strcmp(substr, "daily") == 0) {
- DEBUG(5, ("periodic daily\n"));
- } else {
- DEBUG(1, ("Cannot determine periodic rule type"
- "(perspec = '%s', period = '%s')\n", substr, period));
- ret = EINVAL;
- goto done;
- }
-
- talloc_free(period);
-
- ret = parse_periodic_time(per, pctx, str);
- JMP_NEOK(ret);
-
- ret = EOK;
-done:
- talloc_free(substr);
- return ret;
-}
-
-/*
- * Parses time specification given in string RULE into range_ctx
- * context CTX.
- */
-static int parse_timespec(struct range_ctx *ctx, const char *rule)
-{
- int ret;
- struct parse_ctx *pctx = NULL;
-
- if (matches_regexp(ctx, ctx->trctx, rule, LP_RGX_ABSOLUTE, &pctx) == EOK) {
- DEBUG(5, ("Matched absolute range\n"));
- ctx->type = TYPE_ABSOLUTE;
- ctx->abs = talloc_zero(ctx, struct absolute_range);
- CHECK_PTR_JMP(ctx->abs);
-
- ret = parse_absolute(ctx->abs, ctx->trctx, pctx, rule);
- JMP_NEOK(ret);
- } else if (matches_regexp(ctx, ctx->trctx, rule, LP_RGX_PERIODIC, &pctx) == EOK) {
- DEBUG(5, ("Matched periodic range\n"));
- ctx->type = TYPE_PERIODIC;
- ctx->per = talloc_zero(ctx, struct periodic_range);
- CHECK_PTR_JMP(ctx->per);
-
- ret = parse_periodic(ctx->per, ctx->trctx, pctx, rule);
- JMP_NEOK(ret);
- } else {
- DEBUG(1, ("Cannot determine rule type\n"));
- ret = EINVAL;
- goto done;
- }
-
- ret = EOK;
-done:
- talloc_free(pctx);
- return ret;
-}
-
-/*******************************************************************
- * validation of rules against time_t *
- *******************************************************************/
-
-static int absolute_timerange_valid(struct absolute_range *absr,
- const time_t now,
- bool *result)
-{
- if (difftime(absr->time_from, now) > 0) {
- DEBUG(3, ("Absolute timerange invalid (before interval)\n"));
- *result = false;
- return EOK;
- }
-
- if (difftime(absr->time_to, now) < 0) {
- DEBUG(3, ("Absolute timerange invalid (after interval)\n"));
- *result = false;
- return EOK;
- }
-
- DEBUG(3, ("Absolute timerange valid\n"));
- *result = true;
- return EOK;
-}
-
-static int periodic_timerange_valid(struct periodic_range *per,
- const time_t now,
- bool *result)
-{
- struct tm tm_now;
- int wnum;
- int wom;
-
- memset(&tm_now, 0, sizeof(struct tm));
- if (localtime_r(&now, &tm_now) == NULL) {
- DEBUG(0, ("Cannot convert time_t to struct tm\n"));
- return EFAULT;
- }
- DEBUG(9, ("Got struct tm value %s", asctime(&tm_now)));
- tm2abs(&tm_now);
-
- wnum = weeknum(&tm_now);
- if (wnum == -1) {
- DEBUG(7, ("Cannot get week number"));
- return EINVAL;
- }
- DEBUG(9, ("Week number is %d\n", wnum));
-
- wom = get_week_of_month(&tm_now);
- if (wnum == -1) {
- DEBUG(7, ("Cannot get week of number"));
- return EINVAL;
- }
- DEBUG(9, ("Week of month number is %d\n", wom));
-
- /* The validation itself */
- TEST_BIT_RANGE(per->day_of_week, tm_now.tm_wday, result);
- DEBUG(9, ("day of week OK\n"));
- TEST_BIT_RANGE_PTR(per->day_of_month, tm_now.tm_mday, result);
- DEBUG(9, ("day of month OK\n"));
- TEST_BIT_RANGE(per->week_of_month, wom, result);
- DEBUG(9, ("week of month OK\n"));
- TEST_BIT_RANGE_PTR(per->week_of_year, wnum, result);
- DEBUG(9, ("week of year OK\n"));
- TEST_BIT_RANGE_PTR(per->month, tm_now.tm_mon, result);
- DEBUG(9, ("month OK\n"));
- TEST_BIT_RANGE_PTR(per->day_of_year, tm_now.tm_yday, result);
- DEBUG(9, ("day of year OK\n"));
- TEST_BIT_RANGE_PTR(per->hour, tm_now.tm_hour, result);
- DEBUG(9, ("hour OK\n"));
- TEST_BIT_RANGE_PTR(per->minute, tm_now.tm_min, result);
- DEBUG(9, ("minute OK\n"));
-
- DEBUG(3, ("Periodic timerange valid\n"));
- *result = true;
- return EOK;
-}
-
-/*
- * Returns EOK if the timerange in range_ctx context is valid compared against a
- * given time_t value in NOW, returns ERANGE if the time value is outside the
- * specified range.
- */
-static int timerange_valid(struct range_ctx *ctx,
- const time_t now,
- bool *result)
-{
- int ret;
-
- switch(ctx->type) {
- case TYPE_ABSOLUTE:
- DEBUG(7, ("Checking absolute range\n"));
- ret = absolute_timerange_valid(ctx->abs, now, result);
- break;
-
- case TYPE_PERIODIC:
- DEBUG(7, ("Checking periodic range\n"));
- ret = periodic_timerange_valid(ctx->per, now, result);
- break;
-
- default:
- DEBUG(1, ("Unknown range type (%d)\n", ctx->type));
- ret = EINVAL;
- break;
- }
-
- return ret;
-}
-
-/*******************************************************************
- * public interface *
- *******************************************************************/
-
-/*
- * This is actually the meat of the library. The function takes a string
- * representation of a time rule in STR and time to check against (usually that
- * would be current time) in NOW.
- *
- * It returns EOK if the rule is valid in the current time, ERANGE if not and
- * EINVAL if the rule cannot be parsed
- */
-int check_time_rule(TALLOC_CTX *mem_ctx,
- struct time_rules_ctx *trctx,
- const char *str,
- const time_t now,
- bool *result)
-{
- int ret;
- struct range_ctx *ctx;
-
- ctx = talloc_zero(mem_ctx, struct range_ctx);
- CHECK_PTR_JMP(ctx);
- ctx->trctx = trctx;
-
- DEBUG(9, ("Got time_t value %s", ctime(&now)));
-
- ret = parse_timespec(ctx, str);
- if (ret != EOK) {
- DEBUG(1, ("Cannot parse the time specification (%d)\n", ret));
- goto done;
- }
-
- ret = timerange_valid(ctx, now, result);
- if (ret != EOK) {
- DEBUG(1, ("Cannot check the time range (%d)\n", ret));
- goto done;
- }
-
- ret = EOK;
-done:
- talloc_free(ctx);
- return ret;
-}
-
-/*
- * Frees the resources taken by the precompiled rules
- */
-static int time_rules_parser_destructor(struct time_rules_ctx *ctx)
-{
- int i;
-
- for (i = 0; i< LP_RGX_MAX; ++i) {
- pcre_free(ctx->re[i]);
- ctx->re[i] = NULL;
- }
-
- return 0;
-}
-
-/*
- * Initializes the parser by precompiling the regular expressions
- * for later use
- */
-int init_time_rules_parser(TALLOC_CTX *mem_ctx,
- struct time_rules_ctx **_out)
-{
- const char *errstr;
- int errval;
- int errpos;
- int ret;
- int i;
- struct time_rules_ctx *ctx = NULL;
-
- ctx = talloc_zero(mem_ctx, struct time_rules_ctx);
- CHECK_PTR(ctx);
- talloc_set_destructor(ctx, time_rules_parser_destructor);
-
- /* Precompile regular expressions */
- for (i = LP_RGX_GENERALIZED; i< LP_RGX_MAX; ++i) {
- ctx->re[i] = pcre_compile2(lookup_table[i],
- 0,
- &errval,
- &errstr,
- &errpos,
- NULL);
-
- if (ctx->re[i] == NULL) {
- DEBUG(0, ("Invalid Regular Expression pattern '%s' at position %d"
- " (Error: %d [%s])\n", lookup_table[i],
- errpos, errval, errstr));
- ret = EFAULT;
- goto done;
- }
-
- }
-
- *_out = ctx;
- return EOK;
-done:
- talloc_free(ctx);
- return ret;
-}
-
diff --git a/src/providers/ipa/ipa_timerules.h b/src/providers/ipa/ipa_timerules.h
deleted file mode 100644
index e1beaa22e..000000000
--- a/src/providers/ipa/ipa_timerules.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- SSSD
-
- IPA Provider Time Rules Parsing
-
- Authors:
- Jakub Hrozek <jhrozek@redhat.com>
-
- Copyright (C) Red Hat, Inc 2009
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __IPA_TIMERULES_H_
-#define __IPA_TIMERULES_H_
-
-#include <stdbool.h>
-#include <talloc.h>
-
-/* Opaque structure given after init */
-struct time_rules_ctx;
-
-/*
- * Init the parser. Destroy the allocated resources by simply
- * talloc_free()-ing the time_rules_ctx
- */
-int init_time_rules_parser(TALLOC_CTX *mem_ctx,
- struct time_rules_ctx **_out);
-
-/*
- * This is actually the meat of the library. The function takes a string
- * representation of a time rule in STR and time to check against (usually that
- * would be current time) in NOW.
- *
- * It returns EOK if the rule can be parsed, error code if not. If the time
- * given in the NOW parameter would be accepted by the rule, it stores true in
- * RESULT, false otherwise.
- */
-int check_time_rule(TALLOC_CTX *mem_ctx,
- struct time_rules_ctx *trctx,
- const char *str,
- const time_t now,
- bool *result);
-
-#endif /* __IPA_TIMERULES_H_ */
diff --git a/src/tests/ipa_timerules-tests.c b/src/tests/ipa_timerules-tests.c
deleted file mode 100644
index f9e22fc85..000000000
--- a/src/tests/ipa_timerules-tests.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- Timelib
-
- test_timelib.c
-
- Copyright (C) Jakub Hrozek <jhrozek@redhat.com> 2009
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define _XOPEN_SOURCE /* strptime */
-
-#include <check.h>
-#include <popt.h>
-#include <time.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include "providers/ipa/ipa_timerules.h"
-#include "util/util.h"
-#include "tests/common.h"
-
-#define CHECK_TIME_RULE_LEAK(ctx, tctx, str, now, result) do { \
- check_leaks_push(ctx); \
- ret = check_time_rule(ctx, tctx, str, now, result); \
- check_leaks_pop(ctx); \
-} while (0)
-
-static TALLOC_CTX *ctx;
-
-static void usage(poptContext pc, const char *error)
-{
- poptPrintUsage(pc, stderr, 0);
- if (error) fprintf(stderr, "%s", error);
-}
-
-int str2time_t(const char *fmt, const char *str, time_t *out)
-{
- char *err;
- struct tm stm;
- memset(&stm, 0, sizeof(struct tm));
-
- err = strptime(str, fmt, &stm);
- if(!err || err[0] != '\0')
- return EINVAL;
-
- DEBUG(9, ("after strptime: %s\n", asctime(&stm)));
- stm.tm_isdst = -1;
- *out = mktime(&stm);
- DEBUG(9, ("after mktime: %s\n", ctime(out)));
- return (*out == -1) ? EINVAL : EOK;
-}
-
-/* Fixtures - open the time library before every test, close it afterwards */
-void setup(void)
-{
- leak_check_setup();
-
- ctx = talloc_new(NULL);
- fail_if(ctx == NULL);
-}
-
-void teardown(void)
-{
- leak_check_teardown();
-}
-
-/* Test that timelib detects a time rule inside the absolute range */
-START_TEST(test_timelib_absolute_in_range)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%F", "2000-1-1", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "absolute 199412161032.5 ~ 200512161032,5", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error");
-
- talloc_free(tctx);
-}
-END_TEST
-
-/* Test that timelib detects a time rule outside the absolute range */
-START_TEST(test_timelib_absolute_out_of_range)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%F", "2007-1-1", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "absolute 199412161032.5 ~ 200512161032,5", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error");
-
- talloc_free(tctx);
-}
-END_TEST
-
-/* Test that absolute timeranges work OK with only minimal data supplied */
-START_TEST(test_timelib_absolute_minimal)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%F", "2000-1-1", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "absolute 19941216 ~ 20051216", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error");
-
- talloc_free(tctx);
-}
-END_TEST
-
-/* Test a time value "right off the edge" of the time specifier */
-START_TEST(test_timelib_absolute_one_off)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M-%S", "1994-12-16-10-32-29", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "absolute 19941216103230 ~ 19941216103231", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M-%S", "1994-12-16-10-32-32", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "absolute 19941216103230 ~ 19941216103231", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error");
-
- talloc_free(tctx);
-}
-END_TEST
-
-
-/* Test a time value "right on the edge" of the time specifier */
-START_TEST(test_timelib_absolute_one_on)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M-%S", "1994-12-16-10-32-30", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "absolute 19941216103230 ~ 19941216103231", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M-%S", "1994-12-16-10-32-31", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "absolute 19941216103230 ~ 19941216103231", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error");
-
- talloc_free(tctx);
-}
-END_TEST
-
-START_TEST(test_timelib_periodic_daily_in)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error");
-
- /* test edges */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-09-30", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 0930 ~ 1830", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (edge1)");
- fail_unless(result == true, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-18-30", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 0930 ~ 1830", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (edge2)");
- fail_unless(result == true, "Range check error");
-
- /* test wrap around */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-16-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 1500 ~ 0600", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (edge1)");
- fail_unless(result == true, "Range check error1");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-15-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 1500 ~ 0600", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (edge1)");
- fail_unless(result == true, "Range check error1");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-06-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 1500 ~ 0600", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (edge1)");
- fail_unless(result == true, "Range check error1");
-
- talloc_free(tctx);
-}
-END_TEST
-
-START_TEST(test_timelib_periodic_daily_out)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-21-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error");
-
- /* test one-off errors */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-09-29", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 0930 ~ 1830", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (one-off 1)");
- fail_unless(result == false, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-18-31", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 0930 ~ 1830", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (one-off 2)");
- fail_unless(result == false, "Range check error");
-
- /* test wrap around */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-10-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 1500 ~ 0600", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (edge1)");
- fail_unless(result == false, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-14-59", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 1500 ~ 0600", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (edge1)");
- fail_unless(result == false, "Range check error1");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-03-30-06-01", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic daily 1500 ~ 0600", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (edge1)");
- fail_unless(result == false, "Range check error2");
-
- talloc_free(tctx);
-}
-END_TEST
-
-START_TEST(test_timelib_periodic_weekly_in)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-04-02-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Mon-Fri 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error1");
-
- /* test edges - monday */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-22-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Mon-Fri 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error2");
-
- /* test edges - friday */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-26-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Mon-Fri 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error3");
-
- /* test wrap around */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-11-03-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Fri-Tue 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error2");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-11-06-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Fri-Tue 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == true, "Range check error3");
-
- talloc_free(tctx);
-}
-END_TEST
-
-START_TEST(test_timelib_periodic_weekly_out)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-04-04-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Mon-Fri 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error");
-
- /* test one-off error - monday */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-22-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Tue-Thu 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error");
-
- /* test one-off error - friday */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-26-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Tue-Thu 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error");
-
- /* test wrap around */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-11-04-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Fri-Tue 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error2");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-11-05-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic weekly day Fri-Tue 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule");
- fail_unless(result == false, "Range check error3");
-
- talloc_free(tctx);
-}
-END_TEST
-
-START_TEST(test_timelib_periodic_monthly_in)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-04-07-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly week 1,2 day Mon,Tue 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule1 (ret = %d: %s)", ret, strerror(ret));
- fail_unless(result == true, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-04-05-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly day 1-5,10,15,20-25 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule2 (ret = %d: %s)", ret, strerror(ret));
- fail_unless(result == true, "Range check error");
-
- /* edges - week in */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-13-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly week 1,2 day Sat 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (week edge 1)");
- fail_unless(result == true, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-29-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly week 5 day Mon,Tue 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (week edge 2)");
- fail_unless(result == true, "Range check error");
-
- /* edges - day in */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-04-01-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (day edge 1)");
- fail_unless(result == true, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-04-10-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (day edge 2)");
- fail_unless(result == true, "Range check error");
-
- talloc_free(tctx);
-}
-END_TEST
-
-START_TEST(test_timelib_periodic_monthly_out)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-03-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly week 1,2 day Mon,Tue 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (ret = %d)", ret);
- fail_unless(result == false, "Range check error");
-
- /* one-off error - week out */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-15-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly week 1 day Sun-Sat 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (week edge 1)");
- fail_unless(result == false, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-28-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly week 5 day Mon,Tue 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (week edge 2)");
- fail_unless(result == false, "Range check error");
-
- /* one-off error - day out */
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-04-01-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly day 2-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (day edge 1)");
- fail_unless(result == false, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-04-11-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic monthly day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (day edge 2)");
- fail_unless(result == false, "Range check error");
-
- talloc_free(tctx);
-}
-END_TEST
-
-START_TEST(test_timelib_periodic_yearly_in)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-08-03-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic yearly month 1,7-8 day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (ret = %d)", ret);
- fail_unless(result == true, "Range check error1");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-01-01-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic yearly month 1,7-8 day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (ret = %d)", ret);
- fail_unless(result == true, "Range check error2");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-01-01-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic yearly week 1 day 1-7 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (ret = %d)", ret);
- fail_unless(result == true, "Range check error3");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-07-10-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic yearly month 1,7-8 day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule (ret = %d)", ret);
- fail_unless(result == true, "Range check error4");
-
- talloc_free(tctx);
-}
-END_TEST
-
-START_TEST(test_timelib_periodic_yearly_out)
-{
- time_t now;
- int ret;
- bool result;
- static struct time_rules_ctx *tctx = NULL;
-
- ret = init_time_rules_parser(ctx, &tctx);
- fail_if(ret != EOK);
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-06-13-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic yearly month 7-8 day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule1 (ret = %d)", ret);
- fail_unless(result == false, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-09-13-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic yearly month 7-8 day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule2 (ret = %d)", ret);
- fail_unless(result == false, "Range check error");
-
- fail_unless(str2time_t("%Y-%m-%d-%H-%M", "2009-01-11-12-00", &now) == 0, "Cannot parse time spec");
- CHECK_TIME_RULE_LEAK(ctx, tctx, "periodic yearly month 1,7-8 day 1-10 0900 ~ 1800", now, &result);
- fail_unless(ret == EOK, "Fail to check the time rule3 (ret = %d)", ret);
- fail_unless(result == false, "Range check error");
-
- talloc_free(tctx);
-}
-END_TEST
-
-Suite *create_timelib_suite(void)
-{
- Suite *s = suite_create("timelib");
-
- TCase *tc_timelib = tcase_create("Timelib Tests");
-
-
- /* Add setup() and teardown() methods */
- tcase_add_checked_fixture(tc_timelib, setup, teardown);
-
- /* Do some testing */
- tcase_add_test(tc_timelib, test_timelib_absolute_in_range);
- tcase_add_test(tc_timelib, test_timelib_absolute_out_of_range);
- tcase_add_test(tc_timelib, test_timelib_absolute_minimal);
- tcase_add_test(tc_timelib, test_timelib_absolute_one_off);
- tcase_add_test(tc_timelib, test_timelib_absolute_one_on);
-
- tcase_add_test(tc_timelib, test_timelib_periodic_daily_in);
- tcase_add_test(tc_timelib, test_timelib_periodic_daily_out);
- tcase_add_test(tc_timelib, test_timelib_periodic_weekly_in);
- tcase_add_test(tc_timelib, test_timelib_periodic_weekly_out);
- tcase_add_test(tc_timelib, test_timelib_periodic_monthly_in);
- tcase_add_test(tc_timelib, test_timelib_periodic_monthly_out);
- tcase_add_test(tc_timelib, test_timelib_periodic_yearly_in);
- tcase_add_test(tc_timelib, test_timelib_periodic_yearly_out);
-
- /* Add all test cases to the test suite */
- suite_add_tcase(s, tc_timelib);
-
- return s;
-}
-
-int main(int argc, const char *argv[])
-{
- int ret;
- poptContext pc;
- int failure_count;
- Suite *timelib_suite;
- SRunner *sr;
- int debug = 0;
-
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- { "debug-level", 'd', POPT_ARG_INT, &debug, 0, "Set debug level", NULL },
- POPT_TABLEEND
- };
-
- pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 0);
- if((ret = poptGetNextOpt(pc)) < -1) {
- usage(pc, poptStrerror(ret));
- return EXIT_FAILURE;
- }
- debug_level = debug;
-
- tests_set_cwd();
-
- timelib_suite = create_timelib_suite();
- sr = srunner_create(timelib_suite);
- /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
- srunner_run_all(sr, CK_ENV);
- failure_count = srunner_ntests_failed(sr);
- srunner_free(sr);
- return (failure_count==0 ? EXIT_SUCCESS : EXIT_FAILURE);
-}
-