#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
# include <sys/sysctl.h>
#endif
+#if HAVE_OS_H
+# include <OS.h>
+#endif
+
#include "stat-time.h"
#include "xalloc.h"
}
# 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__
}
# 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