[libvirt] [PATCH 21/23] src: replace strptime()/timegm()/mktime() with GDateTime APIs set

Daniel P. Berrangé berrange at redhat.com
Thu Jan 2 14:53:55 UTC 2020


All places where we use strptime/timegm()/mktime() are handling
conversion of dates in a format compatible with ISO 8601, so we
can use the GDateTime APIs to simplify code.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 src/conf/domain_conf.c | 32 +++++--------------
 src/esx/esx_vi_types.c | 71 +++++-------------------------------------
 src/vz/vz_sdk.c        | 10 +++---
 3 files changed, 20 insertions(+), 93 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index afa072e17d..ee33b7caf0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13673,33 +13673,17 @@ virDomainGraphicsAuthDefParseXML(xmlNodePtr node,
 
     validTo = virXMLPropString(node, "passwdValidTo");
     if (validTo) {
-        char *tmp;
-        struct tm tm;
-        memset(&tm, 0, sizeof(tm));
-        /* Expect: YYYY-MM-DDTHH:MM:SS (%d-%d-%dT%d:%d:%d)  eg 2010-11-28T14:29:01 */
-        if (/* year */
-            virStrToLong_i(validTo, &tmp, 10, &tm.tm_year) < 0 || *tmp != '-' ||
-            /* month */
-            virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_mon) < 0 || *tmp != '-' ||
-            /* day */
-            virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_mday) < 0 || *tmp != 'T' ||
-            /* hour */
-            virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_hour) < 0 || *tmp != ':' ||
-            /* minute */
-            virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_min) < 0 || *tmp != ':' ||
-            /* second */
-            virStrToLong_i(tmp+1, &tmp, 10, &tm.tm_sec) < 0 || *tmp != '\0') {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("cannot parse password validity time '%s', expect YYYY-MM-DDTHH:MM:SS"),
-                           validTo);
-            VIR_FREE(def->passwd);
+        g_autoptr(GDateTime) then = NULL;
+        g_autoptr(GTimeZone) tz = g_time_zone_new_utc();
+
+        then = g_date_time_new_from_iso8601(validTo, tz);
+        if (!then) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("password validity time '%s' values out of range"), validTo);
             return -1;
         }
 
-        tm.tm_year -= 1900; /* Human epoch starts at 0 BC, not 1900BC */
-        tm.tm_mon--; /* Humans start months at 1, computers at 0 */
-
-        def->validTo = timegm(&tm);
+        def->validTo = (int)g_date_time_to_unix(then);
         def->expires = true;
     }
 
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index 1deb5026b7..434313dfa4 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -1473,27 +1473,14 @@ int
 esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime,
                                      long long *secondsSinceEpoch)
 {
-    char value[64] = "";
-    char *tmp;
-    struct tm tm;
-    int milliseconds;
-    char sign;
-    int tz_hours;
-    int tz_minutes;
-    int tz_offset = 0;
+    g_autoptr(GDateTime) then = NULL;
+    g_autoptr(GTimeZone) tz = NULL;
 
     if (!dateTime || !secondsSinceEpoch) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
         return -1;
     }
 
-    if (virStrcpyStatic(value, dateTime->value) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("xsd:dateTime value '%s' too long for destination"),
-                       dateTime->value);
-        return -1;
-    }
-
     /*
      * expected format: [-]CCYY-MM-DDTHH:MM:SS[.ssssss][((+|-)HH:MM|Z)]
      * typical example: 2010-04-05T12:13:55.316789+02:00
@@ -1502,66 +1489,22 @@ esxVI_DateTime_ConvertToCalendarTime(esxVI_DateTime *dateTime,
      *
      * map negative years to 0, since the base for time_t is the year 1970.
      */
-    if (*value == '-') {
+    if (*(dateTime->value) == '-') {
         *secondsSinceEpoch = 0;
         return 0;
     }
 
-    tmp = strptime(value, "%Y-%m-%dT%H:%M:%S", &tm);
+    tz = g_time_zone_new_utc();
+    then = g_date_time_new_from_iso8601(dateTime->value, tz);
 
-    if (!tmp) {
+    if (!then) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("xsd:dateTime value '%s' has unexpected format"),
                        dateTime->value);
         return -1;
     }
 
-    if (*tmp != '\0') {
-        /* skip .ssssss part if present */
-        if (*tmp == '.' &&
-            virStrToLong_i(tmp + 1, &tmp, 10, &milliseconds) < 0) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("xsd:dateTime value '%s' has unexpected format"),
-                           dateTime->value);
-            return -1;
-        }
-
-        /* parse timezone offset if present. if missing assume UTC */
-        if (*tmp == '+' || *tmp == '-') {
-            sign = *tmp;
-
-            if (virStrToLong_i(tmp + 1, &tmp, 10, &tz_hours) < 0 ||
-                *tmp != ':' ||
-                virStrToLong_i(tmp + 1, NULL, 10, &tz_minutes) < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("xsd:dateTime value '%s' has unexpected format"),
-                               dateTime->value);
-                return -1;
-            }
-
-            tz_offset = tz_hours * 60 * 60 + tz_minutes * 60;
-
-            if (sign == '-')
-                tz_offset = -tz_offset;
-        } else if (STREQ(tmp, "Z")) {
-            /* Z refers to UTC. tz_offset is already initialized to zero */
-        } else {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("xsd:dateTime value '%s' has unexpected format"),
-                           dateTime->value);
-            return -1;
-        }
-    }
-
-    /*
-     * xsd:dateTime represents local time relative to the optional timezone
-     * given as offset. pretend the local time is in UTC and use timegm in
-     * order to avoid interference with the timezone to this computer.
-     * apply timezone correction afterwards, because it's simpler than
-     * handling all the possible over- and underflows when trying to apply
-     * it to the tm struct.
-     */
-    *secondsSinceEpoch = timegm(&tm) - tz_offset;
+    *secondsSinceEpoch = g_date_time_to_unix(then);
 
     return 0;
 }
diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c
index 59d7d31419..c98542c244 100644
--- a/src/vz/vz_sdk.c
+++ b/src/vz/vz_sdk.c
@@ -4607,17 +4607,17 @@ int prlsdkSetMemsize(virDomainObjPtr dom, unsigned int memsize)
 static long long
 prlsdkParseDateTime(const char *str)
 {
-    struct tm tm;
-    const char *tmp;
+    g_autoptr(GDateTime) then = NULL;
+    g_autoptr(GTimeZone) tz = g_time_zone_new_local();
 
-    tmp = strptime(str, "%Y-%m-%d %H:%M:%S", &tm);
-    if (!tmp || *tmp != '\0') {
+    then = g_date_time_new_from_iso8601(str, tz);
+    if (!then) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unexpected DateTime format: '%s'"), str);
         return -1;
     }
 
-    return mktime(&tm);
+    return g_date_time_to_unix(then);
 }
 
 static virDomainSnapshotObjListPtr
-- 
2.24.1




More information about the libvir-list mailing list