def->passwd);
if (def->expires) {
- char strbuf[100];
- struct tm tmbuf, *tm;
- tm = gmtime_r(&def->validTo, &tmbuf);
- strftime(strbuf, sizeof(strbuf), "%Y-%m-%dT%H:%M:%S", tm);
- virBufferAsprintf(buf, " passwdValidTo='%s'", strbuf);
+ g_autoptr(GDateTime) then = NULL;
+ g_autofree char *thenstr = NULL;
+
+ then = g_date_time_new_from_unix_utc(def->validTo);
+ thenstr = g_date_time_format(then, "%Y-%m-%dT%H:%M:%S");
+ virBufferAsprintf(buf, " passwdValidTo='%s'", thenstr);
}
if (def->connected)
virDomainObjPtr vm)
{
g_autoptr(libxlDriverConfig) cfg = libxlDriverConfigGet(driver);
- time_t curtime = time(NULL);
- char timestr[100];
- struct tm time_info;
+ g_autoptr(GDateTime) now = g_date_time_new_now_local();
+ g_autofree char *nowstr = NULL;
char *dumpfile = NULL;
- localtime_r(&curtime, &time_info);
- strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info);
+ nowstr = g_date_time_format(now, "%Y-%m-%d-%H:%M:%S");
dumpfile = g_strdup_printf("%s/%s-%s", cfg->autoDumpDir, vm->def->name,
- timestr);
+ nowstr);
/* Unlock virDomainObj while dumping core */
virObjectUnlock(vm);
break;
case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE: {
- time_t now = time(NULL);
- struct tm nowbits;
+ g_autoptr(GDateTime) now = g_date_time_new_now_utc();
+ g_autoptr(GDateTime) then = NULL;
+ g_autofree char *thenstr = NULL;
if (def->data.variable.basis == VIR_DOMAIN_CLOCK_BASIS_LOCALTIME) {
long localOffset;
def->data.variable.basis = VIR_DOMAIN_CLOCK_BASIS_UTC;
}
- now += def->data.variable.adjustment;
- gmtime_r(&now, &nowbits);
+ then = g_date_time_add_seconds(now, def->data.variable.adjustment);
+ thenstr = g_date_time_format(then, "%Y-%m-%dT%H:%M:%S");
/* when an RTC_CHANGE event is received from qemu, we need to
* have the adjustment used at domain start time available to
*/
def->data.variable.adjustment0 = def->data.variable.adjustment;
- virBufferAsprintf(&buf, "base=%d-%02d-%02dT%02d:%02d:%02d",
- nowbits.tm_year + 1900,
- nowbits.tm_mon + 1,
- nowbits.tm_mday,
- nowbits.tm_hour,
- nowbits.tm_min,
- nowbits.tm_sec);
+ virBufferAsprintf(&buf, "base=%s", thenstr);
} break;
default:
virDomainObjPtr vm)
{
g_autofree char *domname = virDomainDefGetShortName(vm->def);
- char timestr[100];
- struct tm time_info;
- time_t curtime = time(NULL);
+ g_autoptr(GDateTime) now = g_date_time_new_now_local();
+ g_autofree char *nowstr = NULL;
g_autoptr(virQEMUDriverConfig) cfg = NULL;
if (!domname)
cfg = virQEMUDriverGetConfig(driver);
- localtime_r(&curtime, &time_info);
- strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info);
+ nowstr = g_date_time_format(now, "%Y-%m-%d-%H:%M:%S");
- return g_strdup_printf("%s/%s-%s", cfg->autoDumpPath, domname, timestr);
+ return g_strdup_printf("%s/%s-%s", cfg->autoDumpPath, domname, nowstr);
}
static void
/**
* virTimeLocalOffsetFromUTC:
*
- * This function is threadsafe, but is *not* async signal safe (due to
- * gmtime_r() and mktime()).
+ * This function is threadsafe, but is *not* async signal safe
+ * due to use of GLib APIs.
*
* @offset: pointer to time_t that will be set to the difference
* between localtime and UTC in seconds (east of UTC is a
int
virTimeLocalOffsetFromUTC(long *offset)
{
- struct tm gmtimeinfo;
- time_t current, utc;
+ g_autoptr(GDateTime) now = g_date_time_new_now_local();
+ GTimeSpan diff = g_date_time_get_utc_offset(now);
- /* time() gives seconds since Epoch in current timezone */
- if ((current = time(NULL)) == (time_t)-1) {
- virReportSystemError(errno, "%s",
- _("failed to get current system time"));
- return -1;
- }
-
- /* treat current as if it were in UTC */
- if (!gmtime_r(¤t, &gmtimeinfo)) {
- virReportSystemError(errno, "%s",
- _("gmtime_r failed"));
- return -1;
- }
-
- /* tell mktime to figure out itself whether or not DST is in effect */
- gmtimeinfo.tm_isdst = -1;
-
- /* mktime() also obeys current timezone rules */
- if ((utc = mktime(&gmtimeinfo)) == (time_t)-1) {
- virReportSystemError(errno, "%s",
- _("mktime failed"));
- return -1;
- }
-
- *offset = current - utc;
+ /* GTimeSpan measures microseconds, we want seconds */
+ *offset = diff / 1000000;
return 0;
}
return 4096;
}
-time_t time(time_t *t)
+GDateTime *g_date_time_new_now_utc(void)
{
- const time_t ret = 1234567890;
- if (t)
- *t = ret;
- return ret;
+ return g_date_time_new_from_unix_utc(1234567890);
+}
+
+GDateTime *g_date_time_new_now_local(void)
+{
+ return g_date_time_new_from_unix_local(1234567890);
}
bool
static bool
isNearYearEnd(void)
{
- time_t current = time(NULL);
- struct tm timeinfo;
+ g_autoptr(GDateTime) now = g_date_time_new_now_local();
- if (current == (time_t)-1) {
- VIR_DEBUG("time() failed");
- return false;
- }
- if (!localtime_r(¤t, &timeinfo)) {
- VIR_DEBUG("localtime_r() failed");
- return false;
- }
-
- return (timeinfo.tm_mon == 0 && timeinfo.tm_mday == 1) ||
- (timeinfo.tm_mon == 11 && timeinfo.tm_mday == 31);
+ return ((g_date_time_get_month(now) == 1 &&
+ g_date_time_get_day_of_month(now) == 1) ||
+ (g_date_time_get_month(now) == 12 &&
+ g_date_time_get_day_of_month(now) == 31));
}
/* test DST processing with timezones that always
* have DST in effect; what's more, cover a zone with
* with an unusual DST different than a usual one hour
+ *
+ * These tests originally used '0' as the first day,
+ * but changed to '1' due to GLib GTimeZone parsing bug:
+ * https://gitlab.gnome.org/GNOME/glib/issues/1999
+ *
+ * Once we depend on a new enough GLib, we can put then
+ * back to 0 again.
*/
- TEST_LOCALOFFSET("VIR-00:30VID,0/00:00:00,365/23:59:59",
+ TEST_LOCALOFFSET("VIR-00:30VID,1/00:00:00,364/23:59:59",
((1 * 60) + 30) * 60);
- TEST_LOCALOFFSET("VIR-02:30VID,0/00:00:00,365/23:59:59",
+ TEST_LOCALOFFSET("VIR-02:30VID,1/00:00:00,364/23:59:59",
((3 * 60) + 30) * 60);
- TEST_LOCALOFFSET("VIR-02:30VID-04:30,0/00:00:00,365/23:59:59",
+ TEST_LOCALOFFSET("VIR-02:30VID-04:30,1/00:00:00,364/23:59:59",
((4 * 60) + 30) * 60);
- TEST_LOCALOFFSET("VIR-12:00VID-13:00,0/00:00:00,365/23:59:59",
+ TEST_LOCALOFFSET("VIR-12:00VID-13:00,1/00:00:00,364/23:59:59",
((13 * 60) + 0) * 60);
if (!isNearYearEnd()) {
* tests, except on Dec 31 and Jan 1.
*/
- TEST_LOCALOFFSET("VIR02:45VID00:45,0/00:00:00,365/23:59:59",
+ TEST_LOCALOFFSET("VIR02:45VID00:45,1/00:00:00,364/23:59:59",
-45 * 60);
- TEST_LOCALOFFSET("VIR05:00VID04:00,0/00:00:00,365/23:59:59",
+ TEST_LOCALOFFSET("VIR05:00VID04:00,1/00:00:00,364/23:59:59",
((-4 * 60) + 0) * 60);
- TEST_LOCALOFFSET("VIR11:00VID10:00,0/00:00:00,365/23:59:59",
+ TEST_LOCALOFFSET("VIR11:00VID10:00,1/00:00:00,364/23:59:59",
((-10 * 60) + 0) * 60);
}
char *doc = NULL;
virDomainCheckpointPtr checkpoint = NULL;
long long creation_longlong;
- time_t creation_time_t;
- char timestr[100];
- struct tm time_info;
+ g_autoptr(GDateTime) then = NULL;
+ g_autofree gchar *thenstr = NULL;
bool tree = vshCommandOptBool(cmd, "tree");
bool name = vshCommandOptBool(cmd, "name");
bool from = vshCommandOptBool(cmd, "from");
if (virXPathLongLong("string(/domaincheckpoint/creationTime)", ctxt,
&creation_longlong) < 0)
continue;
- creation_time_t = creation_longlong;
- if (creation_time_t != creation_longlong) {
- vshError(ctl, "%s", _("time_t overflow"));
- continue;
- }
- localtime_r(&creation_time_t, &time_info);
- strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z",
- &time_info);
+
+ then = g_date_time_new_from_unix_local(creation_longlong);
+ thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S %z");
if (parent) {
- if (vshTableRowAppend(table, chk_name, timestr,
+ if (vshTableRowAppend(table, chk_name, thenstr,
NULLSTR_EMPTY(parent_chk), NULL) < 0)
goto cleanup;
} else {
- if (vshTableRowAppend(table, chk_name, timestr, NULL) < 0)
+ if (vshTableRowAppend(table, chk_name, thenstr, NULL) < 0)
goto cleanup;
}
}
goto cleanup;
if (pretty) {
- char timestr[100];
- time_t cur_time = seconds;
- struct tm time_info;
+ g_autoptr(GDateTime) then = NULL;
+ g_autofree char *thenstr = NULL;
- if (!gmtime_r(&cur_time, &time_info)) {
- vshError(ctl, _("Unable to format time"));
- goto cleanup;
- }
- strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", &time_info);
+ then = g_date_time_new_from_unix_utc(seconds);
+ thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S");
- vshPrint(ctl, _("Time: %s"), timestr);
+ vshPrint(ctl, _("Time: %s"), thenstr);
} else {
vshPrint(ctl, _("Time: %lld"), seconds);
}
static char *
virshGenFileName(vshControl *ctl, virDomainPtr dom, const char *mime)
{
- char timestr[100];
- time_t cur_time;
- struct tm time_info;
+ g_autoptr(GDateTime) now = g_date_time_new_now_local();
+ g_autofree char *nowstr = NULL;
const char *ext = NULL;
char *ret = NULL;
ext = ".png";
/* add mime type here */
- time(&cur_time);
- localtime_r(&cur_time, &time_info);
- strftime(timestr, sizeof(timestr), "%Y-%m-%d-%H:%M:%S", &time_info);
+ nowstr = g_date_time_format(now, "%Y-%m-%d-%H:%M:%S");
- ret = g_strdup_printf("%s-%s%s", virDomainGetName(dom), timestr,
- NULLSTR_EMPTY(ext));
+ ret = g_strdup_printf("%s-%s%s", virDomainGetName(dom),
+ nowstr, NULLSTR_EMPTY(ext));
return ret;
}
const char *typestr = NULL;
g_autofree char *cidr_format = NULL;
virNetworkDHCPLeasePtr lease = leases[i];
- time_t expirytime_tmp = lease->expirytime;
- struct tm ts;
- char expirytime[32];
- localtime_r(&expirytime_tmp, &ts);
- strftime(expirytime, sizeof(expirytime), "%Y-%m-%d %H:%M:%S", &ts);
+ g_autoptr(GDateTime) then = g_date_time_new_from_unix_local(lease->expirytime);
+ g_autofree char *thenstr = NULL;
+
+ thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S");
if (lease->type == VIR_IP_ADDR_TYPE_IPV4)
typestr = "ipv4";
cidr_format = g_strdup_printf("%s/%d", lease->ipaddr, lease->prefix);
if (vshTableRowAppend(table,
- expirytime,
+ thenstr,
NULLSTR_MINUS(lease->mac),
NULLSTR_MINUS(typestr),
NULLSTR_MINUS(cidr_format),
virDomainSnapshotPtr snapshot = NULL;
char *state = NULL;
long long creation_longlong;
- time_t creation_time_t;
- char timestr[100];
- struct tm time_info;
+ g_autoptr(GDateTime) then = NULL;
+ g_autofree gchar *thenstr = NULL;
bool tree = vshCommandOptBool(cmd, "tree");
bool name = vshCommandOptBool(cmd, "name");
bool from = vshCommandOptBool(cmd, "from");
if (virXPathLongLong("string(/domainsnapshot/creationTime)", ctxt,
&creation_longlong) < 0)
continue;
- creation_time_t = creation_longlong;
- if (creation_time_t != creation_longlong) {
- vshError(ctl, "%s", _("time_t overflow"));
- continue;
- }
- localtime_r(&creation_time_t, &time_info);
- strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S %z",
- &time_info);
+ then = g_date_time_new_from_unix_local(creation_longlong);
+ thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S %z");
if (parent) {
- if (vshTableRowAppend(table, snap_name, timestr, state,
+ if (vshTableRowAppend(table, snap_name, thenstr, state,
NULLSTR_EMPTY(parent_snap),
NULL) < 0)
goto cleanup;
} else {
- if (vshTableRowAppend(table, snap_name, timestr, state,
+ if (vshTableRowAppend(table, snap_name, thenstr, state,
NULL) < 0)
goto cleanup;
}
return str ? _(str) : _("unknown");
}
-/*
- * vshAdmGetTimeStr:
- *
- * Produces string representation (local time) of @then
- * (seconds since epoch UTC) using format 'YYYY-MM-DD HH:MM:SS+ZZZZ'.
- *
- * Returns 0 if conversion finished successfully, -1 in case of an error.
- * Caller is responsible for freeing the string returned.
- */
-static int
-vshAdmGetTimeStr(vshControl *ctl, time_t then, char **result)
-{
- char *tmp = NULL;
- struct tm timeinfo;
-
- if (!localtime_r(&then, &timeinfo))
- goto error;
-
- if (VIR_ALLOC_N(tmp, VIRT_ADMIN_TIME_BUFLEN) < 0)
- goto error;
-
- if (strftime(tmp, VIRT_ADMIN_TIME_BUFLEN, "%Y-%m-%d %H:%M:%S%z",
- &timeinfo) == 0) {
- VIR_FREE(tmp);
- goto error;
- }
-
- *result = tmp;
- return 0;
-
- error:
- vshError(ctl, "%s", _("Timestamp string conversion failed"));
- return -1;
-}
/*
* vshAdmCatchDisconnect:
goto cleanup;
for (i = 0; i < nclts; i++) {
- g_autofree char *timestr = NULL;
+ g_autoptr(GDateTime) then = NULL;
+ g_autofree gchar *thenstr = NULL;
g_autofree char *idStr = NULL;
virAdmClientPtr client = clts[i];
id = virAdmClientGetID(client);
+ then = g_date_time_new_from_unix_local(virAdmClientGetTimestamp(client));
transport = virAdmClientGetTransport(client);
- if (vshAdmGetTimeStr(ctl, virAdmClientGetTimestamp(client),
- ×tr) < 0)
- goto cleanup;
+ thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S%z");
idStr = g_strdup_printf("%llu", id);
if (vshTableRowAppend(table, idStr,
vshAdmClientTransportToString(transport),
- timestr, NULL) < 0)
+ thenstr, NULL) < 0)
goto cleanup;
}
size_t i;
unsigned long long id;
const char *srvname = NULL;
- char *timestr = NULL;
+ g_autoptr(GDateTime) then = NULL;
+ g_autofree gchar *thenstr = NULL;
virAdmServerPtr srv = NULL;
virAdmClientPtr clnt = NULL;
virTypedParameterPtr params = NULL;
goto cleanup;
}
- if (vshAdmGetTimeStr(ctl, virAdmClientGetTimestamp(clnt), ×tr) < 0)
- goto cleanup;
+
+ then = g_date_time_new_from_unix_local(virAdmClientGetTimestamp(clnt));
+ thenstr = g_date_time_format(then, "%Y-%m-%d %H:%M:%S%z");
/* this info is provided by the client object itself */
vshPrint(ctl, "%-15s: %llu\n", "id", virAdmClientGetID(clnt));
- vshPrint(ctl, "%-15s: %s\n", "connection_time", timestr);
+ vshPrint(ctl, "%-15s: %s\n", "connection_time", thenstr);
vshPrint(ctl, "%-15s: %s\n", "transport",
vshAdmClientTransportToString(virAdmClientGetTransport(clnt)));
virTypedParamsFree(params, nparams);
virAdmServerFree(srv);
virAdmClientFree(clnt);
- VIR_FREE(timestr);
return ret;
}
char *str = NULL;
size_t len;
const char *lvl = "";
- time_t stTime;
- struct tm stTm;
+ g_autoptr(GDateTime) now = g_date_time_new_now_local();
+ g_autofree gchar *nowstr = NULL;
if (ctl->log_fd == -1)
return;
*
* [YYYY.MM.DD HH:MM:SS SIGNATURE PID] LOG_LEVEL message
*/
- time(&stTime);
- localtime_r(&stTime, &stTm);
- virBufferAsprintf(&buf, "[%d.%02d.%02d %02d:%02d:%02d %s %d] ",
- (1900 + stTm.tm_year),
- (1 + stTm.tm_mon),
- stTm.tm_mday,
- stTm.tm_hour,
- stTm.tm_min,
- stTm.tm_sec,
+ nowstr = g_date_time_format(now, "%Y.%m.%d %H:%M:%S");
+ virBufferAsprintf(&buf, "[%s %s %d] ",
+ nowstr,
ctl->progname,
(int) getpid());
switch (log_level) {