]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/calendarspec.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / basic / calendarspec.c
index 2fde3e107e0a81345cb39350290376554ec52eb3..a6a906f453d9310de6ac2519755aeb4c4862b13f 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+#include "alloc-util.h"
+#include "string-util.h"
 #include "calendarspec.h"
+#include "fileio.h"
 
 #define BITS_WEEKDAYS   127
 
@@ -253,6 +256,7 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
         char *buf = NULL;
         size_t sz = 0;
         FILE *f;
+        int r;
 
         assert(c);
         assert(p);
@@ -278,12 +282,14 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
         fputc(':', f);
         format_chain(f, 2, c->second);
 
-        fflush(f);
+        if (c->utc)
+                fputs(" UTC", f);
 
-        if (ferror(f)) {
+        r = fflush_and_check(f);
+        if (r < 0) {
                 free(buf);
                 fclose(f);
-                return -ENOMEM;
+                return r;
         }
 
         fclose(f);
@@ -646,6 +652,7 @@ fail:
 int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
         CalendarSpec *c;
         int r;
+        const char *utc;
 
         assert(p);
         assert(spec);
@@ -657,6 +664,12 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
         if (!c)
                 return -ENOMEM;
 
+        utc = endswith_no_case(p, " UTC");
+        if (utc) {
+                c->utc = true;
+                p = strndupa(p, utc - p);
+        }
+
         if (strcaseeq(p, "minutely")) {
                 r = const_chain(0, &c->second);
                 if (r < 0)
@@ -859,13 +872,13 @@ static int find_matching_component(const CalendarComponent *c, int *val) {
         return r;
 }
 
-static bool tm_out_of_bounds(const struct tm *tm) {
+static bool tm_out_of_bounds(const struct tm *tm, bool utc) {
         struct tm t;
         assert(tm);
 
         t = *tm;
 
-        if (mktime(&t) == (time_t) -1)
+        if (mktime_or_timegm(&t, utc) == (time_t) -1)
                 return true;
 
         /* Did any normalization take place? If so, it was out of bounds before */
@@ -878,7 +891,7 @@ static bool tm_out_of_bounds(const struct tm *tm) {
                 t.tm_sec != tm->tm_sec;
 }
 
-static bool matches_weekday(int weekdays_bits, const struct tm *tm) {
+static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
         struct tm t;
         int k;
 
@@ -886,7 +899,7 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm) {
                 return true;
 
         t = *tm;
-        if (mktime(&t) == (time_t) -1)
+        if (mktime_or_timegm(&t, utc) == (time_t) -1)
                 return false;
 
         k = t.tm_wday == 0 ? 6 : t.tm_wday - 1;
@@ -904,7 +917,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
 
         for (;;) {
                 /* Normalize the current date */
-                mktime(&c);
+                mktime_or_timegm(&c, spec->utc);
                 c.tm_isdst = -1;
 
                 c.tm_year += 1900;
@@ -916,7 +929,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                         c.tm_mday = 1;
                         c.tm_hour = c.tm_min = c.tm_sec = 0;
                 }
-                if (r < 0 || tm_out_of_bounds(&c))
+                if (r < 0 || tm_out_of_bounds(&c, spec->utc))
                         return r;
 
                 c.tm_mon += 1;
@@ -927,7 +940,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                         c.tm_mday = 1;
                         c.tm_hour = c.tm_min = c.tm_sec = 0;
                 }
-                if (r < 0 || tm_out_of_bounds(&c)) {
+                if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_year ++;
                         c.tm_mon = 0;
                         c.tm_mday = 1;
@@ -938,14 +951,14 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                 r = find_matching_component(spec->day, &c.tm_mday);
                 if (r > 0)
                         c.tm_hour = c.tm_min = c.tm_sec = 0;
-                if (r < 0 || tm_out_of_bounds(&c)) {
+                if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_mon ++;
                         c.tm_mday = 1;
                         c.tm_hour = c.tm_min = c.tm_sec = 0;
                         continue;
                 }
 
-                if (!matches_weekday(spec->weekdays_bits, &c)) {
+                if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) {
                         c.tm_mday++;
                         c.tm_hour = c.tm_min = c.tm_sec = 0;
                         continue;
@@ -954,7 +967,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                 r = find_matching_component(spec->hour, &c.tm_hour);
                 if (r > 0)
                         c.tm_min = c.tm_sec = 0;
-                if (r < 0 || tm_out_of_bounds(&c)) {
+                if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_mday ++;
                         c.tm_hour = c.tm_min = c.tm_sec = 0;
                         continue;
@@ -963,14 +976,14 @@ static int find_next(const CalendarSpec *spec, struct tm *tm) {
                 r = find_matching_component(spec->minute, &c.tm_min);
                 if (r > 0)
                         c.tm_sec = 0;
-                if (r < 0 || tm_out_of_bounds(&c)) {
+                if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_hour ++;
                         c.tm_min = c.tm_sec = 0;
                         continue;
                 }
 
                 r = find_matching_component(spec->second, &c.tm_sec);
-                if (r < 0 || tm_out_of_bounds(&c)) {
+                if (r < 0 || tm_out_of_bounds(&c, spec->utc)) {
                         c.tm_min ++;
                         c.tm_sec = 0;
                         continue;
@@ -991,13 +1004,13 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
         assert(next);
 
         t = (time_t) (usec / USEC_PER_SEC) + 1;
-        assert_se(localtime_r(&t, &tm));
+        assert_se(localtime_or_gmtime_r(&t, &tm, spec->utc));
 
         r = find_next(spec, &tm);
         if (r < 0)
                 return r;
 
-        t = mktime(&tm);
+        t = mktime_or_timegm(&tm, spec->utc);
         if (t == (time_t) -1)
                 return -EINVAL;