From 92a6fbdeccc6373e554d014ba9465b8d1d9cd150 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 12 Aug 2023 19:40:28 +0200 Subject: [PATCH] readutmp, boot-time: On Haiku, return the boot time. * m4/readutmp.m4 (gl_PREREQ_READUTMP_H): Test whether exists. * lib/boot-time-aux.h (get_haiku_boot_time, get_haiku_boot_time_final_fallback): New functions. * lib/readutmp.c: Include . (read_utmp_from_file): If opening UTMP_FILE fails, continue processing instead of failing. Invoke get_haiku_boot_time and get_haiku_boot_time_final_fallback. * lib/boot-time.c: Include . (get_boot_time_uncached): Invoke get_haiku_boot_time and get_haiku_boot_time_final_fallback. --- ChangeLog | 14 +++++ lib/boot-time-aux.h | 45 ++++++++++++++ lib/boot-time.c | 20 +++++- lib/readutmp.c | 148 +++++++++++++++++++++++++++++--------------- m4/readutmp.m4 | 4 +- 5 files changed, 178 insertions(+), 53 deletions(-) diff --git a/ChangeLog b/ChangeLog index f1db83be86..30bf3bef82 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2023-08-12 Bruno Haible + + readutmp, boot-time: On Haiku, return the boot time. + * m4/readutmp.m4 (gl_PREREQ_READUTMP_H): Test whether exists. + * lib/boot-time-aux.h (get_haiku_boot_time, + get_haiku_boot_time_final_fallback): New functions. + * lib/readutmp.c: Include . + (read_utmp_from_file): If opening UTMP_FILE fails, continue processing + instead of failing. Invoke get_haiku_boot_time and + get_haiku_boot_time_final_fallback. + * lib/boot-time.c: Include . + (get_boot_time_uncached): Invoke get_haiku_boot_time and + get_haiku_boot_time_final_fallback. + 2023-08-12 Bruno Haible readutmp: Reduce code duplication. diff --git a/lib/boot-time-aux.h b/lib/boot-time-aux.h index 8de834efd7..8006b72134 100644 --- a/lib/boot-time-aux.h +++ b/lib/boot-time-aux.h @@ -227,6 +227,51 @@ get_bsd_boot_time_final_fallback (struct timespec *p_boot_time) #endif +#if defined __HAIKU__ + +static int +get_haiku_boot_time (struct timespec *p_boot_time) +{ + /* On Haiku, /etc/utmp does not exist. During boot, + 1. the current time is restored, but possibly with a wrong time zone, + that is, with an offset of a few hours, + 2. some symlinks and files get created, + 3. the various devices are brought up, in particular the network device, + 4. the correct date and time is set, + 5. some more device nodes get created. + The boot time can be retrieved by looking at a directory created during + phase 5, such as /dev/input. */ + const char * const boot_touched_file = "/dev/input"; + struct stat statbuf; + if (stat (boot_touched_file, &statbuf) >= 0) + { + *p_boot_time = get_stat_mtime (&statbuf); + return 0; + } + return -1; +} + +#endif + +#if HAVE_OS_H /* BeOS, Haiku */ + +/* The following approach is only usable as a fallback, because it produces + wrong values after the date has been bumped in the running system, which + happens frequently if the system is running in a virtual machine and this + VM has been put into "saved" or "sleep" state and then resumed. */ +static int +get_haiku_boot_time_final_fallback (struct timespec *p_boot_time) +{ + system_info si; + + get_system_info (&si); + p_boot_time->tv_sec = si.boot_time / 1000000; + p_boot_time->tv_nsec = (si.boot_time % 1000000) * 1000; + return 0; +} + +#endif + #if defined __CYGWIN__ || defined _WIN32 static int diff --git a/lib/boot-time.c b/lib/boot-time.c index b27cb6c6b6..53bd8b148b 100644 --- a/lib/boot-time.c +++ b/lib/boot-time.c @@ -39,6 +39,10 @@ # include #endif +#if HAVE_OS_H +# include +#endif + #include "idx.h" #include "readutmp.h" #include "stat-time.h" @@ -162,7 +166,7 @@ get_boot_time_uncached (struct timespec *p_boot_time) found_boot_time = runlevel_ts; # endif -# else /* HP-UX */ +# else /* HP-UX, Haiku */ FILE *f = fopen (UTMP_FILE, "re"); @@ -216,6 +220,20 @@ get_boot_time_uncached (struct timespec *p_boot_time) } # endif +# if defined __HAIKU__ + if (found_boot_time.tv_sec == 0) + { + get_haiku_boot_time (&found_boot_time); + } +# endif + +# if HAVE_OS_H + if (found_boot_time.tv_sec == 0) + { + get_haiku_boot_time_final_fallback (&found_boot_time); + } +# endif + # if defined __CYGWIN__ || defined _WIN32 if (found_boot_time.tv_sec == 0) { diff --git a/lib/readutmp.c b/lib/readutmp.c index d3ed04e242..d0c6303466 100644 --- a/lib/readutmp.c +++ b/lib/readutmp.c @@ -47,6 +47,10 @@ # include #endif +#if HAVE_OS_H +# include +#endif + #include "stat-time.h" #include "xalloc.h" @@ -495,64 +499,74 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf, } # endif -# else /* old FreeBSD, OpenBSD, HP-UX */ +# else /* old FreeBSD, OpenBSD, HP-UX, Haiku */ FILE *f = fopen (file, "re"); - if (! f) - return -1; - - for (;;) + if (f != NULL) { - struct UTMP_STRUCT_NAME ut; + for (;;) + { + struct UTMP_STRUCT_NAME ut; - if (fread (&ut, sizeof ut, 1, f) == 0) - break; - a = add_utmp (a, options, - UT_USER (&ut), strnlen (UT_USER (&ut), UT_USER_SIZE), - #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_ID : HAVE_STRUCT_UTMP_UT_ID) - ut.ut_id, strnlen (ut.ut_id, UT_ID_SIZE), - #else - "", 0, - #endif - ut.ut_line, strnlen (ut.ut_line, UT_LINE_SIZE), - #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_HOST : HAVE_STRUCT_UTMP_UT_HOST) - ut.ut_host, strnlen (ut.ut_host, UT_HOST_SIZE), - #else - "", 0, - #endif - #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_PID : HAVE_STRUCT_UTMP_UT_PID) - ut.ut_pid, - #else - 0, - #endif - #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_TYPE : HAVE_STRUCT_UTMP_UT_TYPE) - ut.ut_type, - #else - 0, - #endif - #if (HAVE_UTMPX_H ? 1 : HAVE_STRUCT_UTMP_UT_TV) - (struct timespec) { .tv_sec = ut.ut_tv.tv_sec, .tv_nsec = ut.ut_tv.tv_usec * 1000 }, - #else - (struct timespec) { .tv_sec = ut.ut_time, .tv_nsec = 0 }, - #endif - #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_SESSION : HAVE_STRUCT_UTMP_UT_SESSION) - ut.ut_session, - #else - 0, - #endif - UT_EXIT_E_TERMINATION (&ut), UT_EXIT_E_EXIT (&ut) - ); - } + if (fread (&ut, sizeof ut, 1, f) == 0) + break; + a = add_utmp (a, options, + UT_USER (&ut), strnlen (UT_USER (&ut), UT_USER_SIZE), + #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_ID : HAVE_STRUCT_UTMP_UT_ID) + ut.ut_id, strnlen (ut.ut_id, UT_ID_SIZE), + #else + "", 0, + #endif + ut.ut_line, strnlen (ut.ut_line, UT_LINE_SIZE), + #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_HOST : HAVE_STRUCT_UTMP_UT_HOST) + ut.ut_host, strnlen (ut.ut_host, UT_HOST_SIZE), + #else + "", 0, + #endif + #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_PID : HAVE_STRUCT_UTMP_UT_PID) + ut.ut_pid, + #else + 0, + #endif + #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_TYPE : HAVE_STRUCT_UTMP_UT_TYPE) + ut.ut_type, + #else + 0, + #endif + #if (HAVE_UTMPX_H ? 1 : HAVE_STRUCT_UTMP_UT_TV) + (struct timespec) { .tv_sec = ut.ut_tv.tv_sec, .tv_nsec = ut.ut_tv.tv_usec * 1000 }, + #else + (struct timespec) { .tv_sec = ut.ut_time, .tv_nsec = 0 }, + #endif + #if (HAVE_UTMPX_H ? HAVE_STRUCT_UTMPX_UT_SESSION : HAVE_STRUCT_UTMP_UT_SESSION) + ut.ut_session, + #else + 0, + #endif + UT_EXIT_E_TERMINATION (&ut), UT_EXIT_E_EXIT (&ut) + ); + } - int saved_errno = ferror (f) ? errno : 0; - if (fclose (f) != 0) - saved_errno = errno; - if (saved_errno != 0) + int saved_errno = ferror (f) ? errno : 0; + if (fclose (f) != 0) + saved_errno = errno; + if (saved_errno != 0) + { + free (a.utmp); + errno = saved_errno; + return -1; + } + } + else { - free (a.utmp); - errno = saved_errno; - return -1; + if (strcmp (file, UTMP_FILE) != 0) + { + int saved_errno = errno; + free (a.utmp); + errno = saved_errno; + return -1; + } } # if defined __OpenBSD__ @@ -591,6 +605,38 @@ read_utmp_from_file (char const *file, idx_t *n_entries, STRUCT_UTMP **utmp_buf, } # endif +# if defined __HAIKU__ + if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0 + && strcmp (file, UTMP_FILE) == 0 + && !have_boot_time (a)) + { + struct timespec boot_time; + if (get_haiku_boot_time (&boot_time) >= 0) + a = add_utmp (a, options, + "reboot", strlen ("reboot"), + "", 0, + "", 0, + "", 0, + 0, BOOT_TIME, boot_time, 0, 0, 0); + } +# endif + +# if HAVE_OS_H /* BeOS, Haiku */ + if ((options & (READ_UTMP_USER_PROCESS | READ_UTMP_NO_BOOT_TIME)) == 0 + && strcmp (file, UTMP_FILE) == 0 + && !have_boot_time (a)) + { + struct timespec boot_time; + if (get_haiku_boot_time_final_fallback (&boot_time) >= 0) + a = add_utmp (a, options, + "reboot", strlen ("reboot"), + "", 0, + "", 0, + "", 0, + 0, BOOT_TIME, boot_time, 0, 0, 0); + } +# endif + # endif # if defined __CYGWIN__ || defined _WIN32 diff --git a/m4/readutmp.m4 b/m4/readutmp.m4 index 357bb8b3c8..827b573f46 100644 --- a/m4/readutmp.m4 +++ b/m4/readutmp.m4 @@ -1,4 +1,4 @@ -# readutmp.m4 serial 25 +# readutmp.m4 serial 26 dnl Copyright (C) 2002-2023 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -112,4 +112,6 @@ AC_INCLUDES_DEFAULT #endif ]) AC_CHECK_FUNCS([sysctl]) + + AC_CHECK_HEADERS_ONCE([OS.h]) ]) -- 2.39.5