#endif
#include "virhostuptime.h"
+#include "viralloc.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virstring.h"
+#include "virtime.h"
#include "virthread.h"
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.virhostuptime");
+
static unsigned long long bootTime;
static int bootTimeErrno;
static virOnceControl virHostGetBootTimeOnce = VIR_ONCE_CONTROL_INITIALIZER;
-#ifdef HAVE_GETUTXID
+#if defined(__linux__)
+# define UPTIME_FILE "/proc/uptime"
+static int
+virHostGetBootTimeProcfs(unsigned long long *btime)
+{
+ unsigned long long now;
+ double up;
+ g_autofree char *buf = NULL;
+ char *tmp;
+
+ if (virTimeMillisNow(&now) < 0)
+ return -errno;
+
+ /* 1KiB limit is more than enough. */
+ if (virFileReadAll(UPTIME_FILE, 1024, &buf) < 0)
+ return -errno;
+
+ /* buf contains two doubles now:
+ * $uptime $idle_time
+ * We're interested only in the first one */
+ if (!(tmp = strchr(buf, ' '))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("uptime file has unexpected format '%s'"),
+ buf);
+ return -EINVAL;
+ }
+
+ *tmp = '\0';
+
+ if (virStrToDouble(buf, NULL, &up) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to parse uptime value '%s'"),
+ buf);
+ return -EINVAL;
+ }
+
+ *btime = now / 1000 - up + 0.5;
+
+ return 0;
+}
+#endif /* defined(__linux__) */
+
+#if defined(HAVE_GETUTXID) || defined(__linux__)
static void
virHostGetBootTimeOnceInit(void)
{
+# ifdef HAVE_GETUTXID
struct utmpx id = {.ut_type = BOOT_TIME};
struct utmpx *res = NULL;
}
endutxent();
+# endif /* HAVE_GETUTXID */
+
+ if (bootTimeErrno != 0 || bootTime == 0)
+ bootTimeErrno = -virHostGetBootTimeProcfs(&bootTime);
}
-#else /* !HAVE_GETUTXID */
+#else /* !defined(HAVE_GETUTXID) && !defined(__linux__) */
static void
virHostGetBootTimeOnceInit(void)
{
bootTimeErrno = ENOSYS;
}
-#endif /* HAVE_GETUTXID */
+#endif /* !defined(HAVE_GETUTXID) && !defined(__linux__) */
/**
* virHostGetBootTime: