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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list