After the efforts we've made to get a stable boot time out of read_utmp(),
it's worth to export this facility through a simpler API. The new module
'boot-time' does this.

It has a link dependency on libsystemd, if --enable-systemd was used.
Since libsystemd does not contribute to producing the boot time, it would
be possible to refactor the readutmp module in such a way that this link
dependency would be avoided. But that is not high priority, IMO.


2023-08-10  Bruno Haible  <br...@clisp.org>

        boot-time: Add tests.
        * tests/test-boot-time.c: New file.
        * modules/boot-time-tests: New file.

        boot-time: New module.
        * lib/boot-time.h: New file.
        * lib/boot-time.c: New file.
        * modules/boot-time: New file.

>From 4dcef2572018d4e8965a0c54a0b6040c0a5233f4 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Thu, 10 Aug 2023 13:08:19 +0200
Subject: [PATCH 1/2] boot-time: New module.

* lib/boot-time.h: New file.
* lib/boot-time.c: New file.
* modules/boot-time: New file.
---
 ChangeLog         |  7 +++++++
 lib/boot-time.c   | 43 +++++++++++++++++++++++++++++++++++++++++++
 lib/boot-time.h   | 38 ++++++++++++++++++++++++++++++++++++++
 modules/boot-time | 27 +++++++++++++++++++++++++++
 4 files changed, 115 insertions(+)
 create mode 100644 lib/boot-time.c
 create mode 100644 lib/boot-time.h
 create mode 100644 modules/boot-time

diff --git a/ChangeLog b/ChangeLog
index b167189c03..cb3c937797 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2023-08-10  Bruno Haible  <br...@clisp.org>
+
+	boot-time: New module.
+	* lib/boot-time.h: New file.
+	* lib/boot-time.c: New file.
+	* modules/boot-time: New file.
+
 2023-08-10  Bruno Haible  <br...@clisp.org>
 
 	readutmp: Return a boot time also on Android.
diff --git a/lib/boot-time.c b/lib/boot-time.c
new file mode 100644
index 0000000000..fe1e13eccb
--- /dev/null
+++ b/lib/boot-time.c
@@ -0,0 +1,43 @@
+/* Determine the time when the machine last booted.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "boot-time.h"
+
+#include <stddef.h>
+
+#include "idx.h"
+#include "readutmp.h"
+
+int
+get_boot_time (struct timespec *p_boot_time)
+{
+  idx_t n_entries = 0;
+  STRUCT_UTMP *utmp = NULL;
+  read_utmp (UTMP_FILE, &n_entries, &utmp, READ_UTMP_BOOT_TIME);
+  if (n_entries > 0)
+    {
+      *p_boot_time = utmp[0].ut_ts;
+      free (utmp);
+      return 0;
+    }
+  free (utmp);
+  return -1;
+}
diff --git a/lib/boot-time.h b/lib/boot-time.h
new file mode 100644
index 0000000000..159a0056f9
--- /dev/null
+++ b/lib/boot-time.h
@@ -0,0 +1,38 @@
+/* Determine the time when the machine last booted.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>.  */
+
+#ifndef _BOOT_TIME_H
+#define _BOOT_TIME_H
+
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Store the approximate time when the machine last booted in *P_BOOT_TIME,
+   and return 0.  If it cannot be determined, return -1.  */
+extern int get_boot_time (struct timespec *p_boot_time);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BOOT_TIME_H */
diff --git a/modules/boot-time b/modules/boot-time
new file mode 100644
index 0000000000..99ae5c9fe7
--- /dev/null
+++ b/modules/boot-time
@@ -0,0 +1,27 @@
+Description:
+Determine the time when the machine last booted.
+
+Files:
+lib/boot-time.h
+lib/boot-time.c
+
+Depends-on:
+idx
+readutmp
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += boot-time.c
+
+Include:
+"boot-time.h"
+
+Link:
+$(READUTMP_LIB)
+
+License:
+GPL
+
+Maintainer:
+all
-- 
2.34.1

>From c1a4224957f8bfc6ad38224398a79dabf6e981c6 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Thu, 10 Aug 2023 13:08:48 +0200
Subject: [PATCH 2/2] boot-time: Add tests.

* tests/test-boot-time.c: New file.
* modules/boot-time-tests: New file.
---
 ChangeLog               |  4 ++++
 modules/boot-time-tests | 11 +++++++++
 tests/test-boot-time.c  | 50 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+)
 create mode 100644 modules/boot-time-tests
 create mode 100644 tests/test-boot-time.c

diff --git a/ChangeLog b/ChangeLog
index cb3c937797..c2a67df01f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2023-08-10  Bruno Haible  <br...@clisp.org>
 
+	boot-time: Add tests.
+	* tests/test-boot-time.c: New file.
+	* modules/boot-time-tests: New file.
+
 	boot-time: New module.
 	* lib/boot-time.h: New file.
 	* lib/boot-time.c: New file.
diff --git a/modules/boot-time-tests b/modules/boot-time-tests
new file mode 100644
index 0000000000..0ba9d467ca
--- /dev/null
+++ b/modules/boot-time-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-boot-time.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-boot-time
+check_PROGRAMS += test-boot-time
+test_boot_time_LDADD = $(LDADD) $(READUTMP_LIB)
diff --git a/tests/test-boot-time.c b/tests/test-boot-time.c
new file mode 100644
index 0000000000..291514019a
--- /dev/null
+++ b/tests/test-boot-time.c
@@ -0,0 +1,50 @@
+/* Test of getting the boot time.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2023.  */
+
+#include <config.h>
+
+#include "boot-time.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "macros.h"
+
+int
+main (int argc, char *argv[])
+{
+  struct timespec boot_time;
+  ASSERT (get_boot_time (&boot_time) == 0);
+
+  time_t tim = boot_time.tv_sec;
+  struct tm *gmt = gmtime (&tim);
+  ASSERT (gmt != NULL);
+  char timbuf[100];
+  ASSERT (strftime (timbuf, sizeof (timbuf), "%Y-%m-%d %H:%M:%S", gmt) > 0);
+
+  printf ("Boot time (UTC): %s.%09ld\n", timbuf, (long) boot_time.tv_nsec);
+
+  /* If the boot time is more than 5 years in the past or more than a week
+     in the future, the value must be wrong.  */
+  time_t now = time (NULL);
+  ASSERT (tim >= now - 157680000);
+  ASSERT (tim <= now + 604800);
+
+  return 0;
+}
-- 
2.34.1

Reply via email to