]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/update-utmp/update-utmp.c
5a999806bd5d2070a45d6878baa457065384a2cb
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "bus-locator.h"
10 #include "libaudit-util.h"
12 #include "main-func.h"
13 #include "time-util.h"
14 #include "utmp-wtmp.h"
17 typedef struct Context
{
22 static void context_clear(Context
*c
) {
25 c
->bus
= sd_bus_flush_close_unref(c
->bus
);
26 c
->audit_fd
= close_audit_fd(c
->audit_fd
);
29 static int get_startup_monotonic_time(Context
*c
, usec_t
*ret
) {
30 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
37 r
= bus_connect_system_systemd(&c
->bus
);
39 return log_warning_errno(r
, "Failed to get D-Bus connection, ignoring: %m");
42 r
= bus_get_property_trivial(
45 "UserspaceTimestampMonotonic",
49 return log_warning_errno(r
, "Failed to get timestamp, ignoring: %s", bus_error_message(&error
, r
));
54 static int on_reboot(int argc
, char *argv
[], void *userdata
) {
55 Context
*c
= ASSERT_PTR(userdata
);
56 usec_t t
= 0, boottime
;
59 /* We finished start-up, so let's write the utmp record and send the audit msg. */
63 if (sym_audit_log_user_comm_message(c
->audit_fd
, AUDIT_SYSTEM_BOOT
, "", "systemd-update-utmp", NULL
, NULL
, NULL
, 1) < 0 &&
65 q
= log_error_errno(errno
, "Failed to send audit message: %m");
68 /* If this call fails, then utmp_put_reboot() will fix to the current time. */
69 (void) get_startup_monotonic_time(c
, &t
);
70 boottime
= map_clock_usec(t
, CLOCK_MONOTONIC
, CLOCK_REALTIME
);
71 /* We query the recorded monotonic time here (instead of the system clock CLOCK_REALTIME), even
72 * though we actually want the system clock time. That's because there's a likely chance that the
73 * system clock wasn't set right during early boot. By manually converting the monotonic clock to the
74 * system clock here we can compensate for incorrectly set clocks during early boot. */
76 r
= utmp_put_reboot(boottime
);
78 return log_error_errno(r
, "Failed to write utmp record: %m");
83 static int on_shutdown(int argc
, char *argv
[], void *userdata
) {
86 /* We started shut-down, so let's write the utmp record and send the audit msg. */
89 Context
*c
= ASSERT_PTR(userdata
);
92 if (sym_audit_log_user_comm_message(c
->audit_fd
, AUDIT_SYSTEM_SHUTDOWN
, "", "systemd-update-utmp", NULL
, NULL
, NULL
, 1) < 0 &&
94 q
= log_error_errno(errno
, "Failed to send audit message: %m");
97 r
= utmp_put_shutdown();
99 return log_error_errno(r
, "Failed to write utmp record: %m");
104 static int run(int argc
, char *argv
[]) {
105 static const Verb verbs
[] = {
106 { "reboot", 1, 1, 0, on_reboot
},
107 { "shutdown", 1, 1, 0, on_shutdown
},
111 _cleanup_(context_clear
) Context c
= {
119 c
.audit_fd
= open_audit_fd_or_warn();
121 return dispatch_verb(argc
, argv
, verbs
, &c
);
124 DEFINE_MAIN_FUNCTION(run
);