Merge pull request #16344 from keszybz/update-utmp-erofs
Make update-utmp not fail if it only fails to write wtmp records
This commit is contained in:
commit
b3077c47a8
|
@ -13,8 +13,8 @@
|
|||
#include "signal-util.h"
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
int r;
|
||||
|
||||
log_setup_service();
|
||||
|
|
|
@ -14,12 +14,14 @@
|
|||
#include "alloc-util.h"
|
||||
#include "bus-error.h"
|
||||
#include "bus-util.h"
|
||||
#include "daemon-util.h"
|
||||
#include "def.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "initreq.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "memory-util.h"
|
||||
#include "process-util.h"
|
||||
#include "special.h"
|
||||
|
@ -68,11 +70,9 @@ static const char *translate_runlevel(int runlevel, bool *isolate) {
|
|||
{ '6', SPECIAL_REBOOT_TARGET, false },
|
||||
};
|
||||
|
||||
unsigned i;
|
||||
|
||||
assert(isolate);
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(table); i++)
|
||||
for (size_t i = 0; i < ELEMENTSOF(table); i++)
|
||||
if (table[i].runlevel == runlevel) {
|
||||
*isolate = table[i].isolate;
|
||||
if (runlevel == '6' && kexec_loaded())
|
||||
|
@ -228,6 +228,7 @@ static void fifo_free(Fifo *f) {
|
|||
|
||||
free(f);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Fifo*, fifo_free);
|
||||
|
||||
static void server_done(Server *s) {
|
||||
assert(s);
|
||||
|
@ -241,79 +242,49 @@ static void server_done(Server *s) {
|
|||
|
||||
static int server_init(Server *s, unsigned n_sockets) {
|
||||
int r;
|
||||
unsigned i;
|
||||
|
||||
/* This function will leave s partially initialized on failure. Caller needs to clean up. */
|
||||
|
||||
assert(s);
|
||||
assert(n_sockets > 0);
|
||||
|
||||
*s = (struct Server) {
|
||||
.epoll_fd = epoll_create1(EPOLL_CLOEXEC),
|
||||
};
|
||||
s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (s->epoll_fd < 0)
|
||||
return log_error_errno(errno, "Failed to create epoll object: %m");
|
||||
|
||||
if (s->epoll_fd < 0) {
|
||||
r = log_error_errno(errno,
|
||||
"Failed to create epoll object: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_sockets; i++) {
|
||||
Fifo *f;
|
||||
int fd;
|
||||
|
||||
fd = SD_LISTEN_FDS_START+i;
|
||||
for (unsigned i = 0; i < n_sockets; i++) {
|
||||
_cleanup_(fifo_freep) Fifo *f = NULL;
|
||||
int fd = SD_LISTEN_FDS_START + i;
|
||||
|
||||
r = sd_is_fifo(fd, NULL);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to determine file descriptor type: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
log_error("Wrong file descriptor type.");
|
||||
r = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine file descriptor type: %m");
|
||||
if (!r)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Wrong file descriptor type.");
|
||||
|
||||
f = new0(Fifo, 1);
|
||||
if (!f) {
|
||||
r = -ENOMEM;
|
||||
log_error_errno(errno, "Failed to create fifo object: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
f->fd = -1;
|
||||
if (!f)
|
||||
return log_oom();
|
||||
|
||||
struct epoll_event ev = {
|
||||
.events = EPOLLIN,
|
||||
.data.ptr = f,
|
||||
};
|
||||
|
||||
if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
|
||||
r = -errno;
|
||||
fifo_free(f);
|
||||
log_error_errno(errno, "Failed to add fifo fd to epoll object: %m");
|
||||
goto fail;
|
||||
}
|
||||
if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0)
|
||||
return log_error_errno(errno, "Failed to add fifo fd to epoll object: %m");
|
||||
|
||||
f->fd = fd;
|
||||
LIST_PREPEND(fifo, s->fifos, f);
|
||||
f->server = s;
|
||||
LIST_PREPEND(fifo, s->fifos, TAKE_PTR(f));
|
||||
s->n_fifos++;
|
||||
}
|
||||
|
||||
r = bus_connect_system_systemd(&s->bus);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to get D-Bus connection: %m");
|
||||
r = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get D-Bus connection: %m");
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
server_done(s);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int process_event(Server *s, struct epoll_event *ev) {
|
||||
|
@ -337,43 +308,33 @@ static int process_event(Server *s, struct epoll_event *ev) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Server server;
|
||||
int r = EXIT_FAILURE, n;
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(server_done) Server server = { .epoll_fd = -1 };
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
int r, n;
|
||||
|
||||
if (getppid() != 1) {
|
||||
log_error("This program should be invoked by init only.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
log_error("This program does not take arguments.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (argc > 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"This program does not take arguments.");
|
||||
|
||||
log_setup_service();
|
||||
|
||||
umask(0022);
|
||||
|
||||
n = sd_listen_fds(true);
|
||||
if (n < 0) {
|
||||
log_error_errno(r, "Failed to read listening file descriptors from environment: %m");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (n < 0)
|
||||
return log_error_errno(errno,
|
||||
"Failed to read listening file descriptors from environment: %m");
|
||||
|
||||
if (n <= 0 || n > SERVER_FD_MAX) {
|
||||
log_error("No or too many file descriptors passed.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (n <= 0 || n > SERVER_FD_MAX)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"No or too many file descriptors passed.");
|
||||
|
||||
if (server_init(&server, (unsigned) n) < 0)
|
||||
return EXIT_FAILURE;
|
||||
r = server_init(&server, (unsigned) n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_debug("systemd-initctl running as pid "PID_FMT, getpid_cached());
|
||||
|
||||
sd_notify(false,
|
||||
"READY=1\n"
|
||||
"STATUS=Processing requests...");
|
||||
notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
|
||||
|
||||
while (!server.quit) {
|
||||
struct epoll_event event;
|
||||
|
@ -383,27 +344,17 @@ int main(int argc, char *argv[]) {
|
|||
if (k < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
log_error_errno(errno, "epoll_wait() failed: %m");
|
||||
goto fail;
|
||||
return log_error_errno(errno, "epoll_wait() failed: %m");
|
||||
}
|
||||
|
||||
if (k <= 0)
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
if (process_event(&server, &event) < 0)
|
||||
goto fail;
|
||||
r = process_event(&server, &event);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = EXIT_SUCCESS;
|
||||
|
||||
log_debug("systemd-initctl stopped as pid "PID_FMT, getpid_cached());
|
||||
|
||||
fail:
|
||||
sd_notify(false,
|
||||
"STOPPING=1\n"
|
||||
"STATUS=Shutting down...");
|
||||
|
||||
server_done(&server);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_MAIN_FUNCTION(run);
|
||||
|
|
|
@ -1104,8 +1104,8 @@ static int load_certificates(char **key, char **cert, char **trust) {
|
|||
}
|
||||
|
||||
static int run(int argc, char **argv) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_cleanup_(journal_remote_server_destroy) RemoteServer s = {};
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_cleanup_free_ char *key = NULL, *cert = NULL, *trust = NULL;
|
||||
int r;
|
||||
|
||||
|
|
|
@ -815,8 +815,8 @@ static int open_journal(sd_journal **j) {
|
|||
}
|
||||
|
||||
static int run(int argc, char **argv) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_cleanup_(destroy_uploader) Uploader u = {};
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
bool use_journal;
|
||||
int r;
|
||||
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/vt.h>
|
||||
#if ENABLE_UTMP
|
||||
#include <utmpx.h>
|
||||
#endif
|
||||
|
||||
#include "sd-device.h"
|
||||
|
||||
|
@ -29,6 +26,7 @@
|
|||
#include "udev-util.h"
|
||||
#include "user-util.h"
|
||||
#include "userdb.h"
|
||||
#include "utmp-wtmp.h"
|
||||
|
||||
void manager_reset_config(Manager *m) {
|
||||
assert(m);
|
||||
|
@ -685,13 +683,14 @@ bool manager_all_buttons_ignored(Manager *m) {
|
|||
int manager_read_utmp(Manager *m) {
|
||||
#if ENABLE_UTMP
|
||||
int r;
|
||||
_cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (utmpxname(_PATH_UTMPX) < 0)
|
||||
return log_error_errno(errno, "Failed to set utmp path to " _PATH_UTMPX ": %m");
|
||||
|
||||
setutxent();
|
||||
utmpx = utxent_start();
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
|
@ -704,8 +703,7 @@ int manager_read_utmp(Manager *m) {
|
|||
if (!u) {
|
||||
if (errno != 0)
|
||||
log_warning_errno(errno, "Failed to read " _PATH_UTMPX ", ignoring: %m");
|
||||
r = 0;
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (u->ut_type != USER_PROCESS)
|
||||
|
@ -715,18 +713,14 @@ int manager_read_utmp(Manager *m) {
|
|||
continue;
|
||||
|
||||
t = strndup(u->ut_line, sizeof(u->ut_line));
|
||||
if (!t) {
|
||||
r = log_oom();
|
||||
break;
|
||||
}
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
c = path_startswith(t, "/dev/");
|
||||
if (c) {
|
||||
r = free_and_strdup(&t, c);
|
||||
if (r < 0) {
|
||||
log_oom();
|
||||
break;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (isempty(t))
|
||||
|
@ -756,8 +750,6 @@ int manager_read_utmp(Manager *m) {
|
|||
log_debug("Acquired TTY information '%s' from utmp for session '%s'.", s->tty, s->id);
|
||||
}
|
||||
|
||||
endutxent();
|
||||
return r;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include "user-util.h"
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
int r;
|
||||
|
||||
log_setup_service();
|
||||
|
|
|
@ -183,8 +183,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
int r;
|
||||
|
||||
log_setup_service();
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#include "user-util.h"
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
int r;
|
||||
|
||||
log_setup_service();
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#include "utmp-wtmp.h"
|
||||
|
||||
int utmp_get_runlevel(int *runlevel, int *previous) {
|
||||
_cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
struct utmpx *found, lookup = { .ut_type = RUN_LVL };
|
||||
int r;
|
||||
const char *e;
|
||||
|
||||
assert(runlevel);
|
||||
|
@ -35,8 +35,7 @@ int utmp_get_runlevel(int *runlevel, int *previous) {
|
|||
* precedence. Presumably, sysvinit does this to work around a
|
||||
* race condition that would otherwise exist where we'd always
|
||||
* go to disk and hence might read runlevel data that might be
|
||||
* very new and does not apply to the current script being
|
||||
* executed. */
|
||||
* very new and not apply to the current script being executed. */
|
||||
|
||||
e = getenv("RUNLEVEL");
|
||||
if (e && e[0] > 0) {
|
||||
|
@ -58,27 +57,17 @@ int utmp_get_runlevel(int *runlevel, int *previous) {
|
|||
if (utmpxname(_PATH_UTMPX) < 0)
|
||||
return -errno;
|
||||
|
||||
setutxent();
|
||||
utmpx = utxent_start();
|
||||
|
||||
found = getutxid(&lookup);
|
||||
if (!found)
|
||||
r = -errno;
|
||||
else {
|
||||
int a, b;
|
||||
return -errno;
|
||||
|
||||
a = found->ut_pid & 0xFF;
|
||||
b = (found->ut_pid >> 8) & 0xFF;
|
||||
*runlevel = found->ut_pid & 0xFF;
|
||||
if (previous)
|
||||
*previous = (found->ut_pid >> 8) & 0xFF;
|
||||
|
||||
*runlevel = a;
|
||||
if (previous)
|
||||
*previous = b;
|
||||
|
||||
r = 0;
|
||||
}
|
||||
|
||||
endutxent();
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init_timestamp(struct utmpx *store, usec_t t) {
|
||||
|
@ -106,7 +95,7 @@ static void init_entry(struct utmpx *store, usec_t t) {
|
|||
}
|
||||
|
||||
static int write_entry_utmp(const struct utmpx *store) {
|
||||
int r;
|
||||
_cleanup_(utxent_cleanup) bool utmpx = false;
|
||||
|
||||
assert(store);
|
||||
|
||||
|
@ -117,26 +106,35 @@ static int write_entry_utmp(const struct utmpx *store) {
|
|||
if (utmpxname(_PATH_UTMPX) < 0)
|
||||
return -errno;
|
||||
|
||||
setutxent();
|
||||
utmpx = utxent_start();
|
||||
|
||||
if (!pututxline(store))
|
||||
r = -errno;
|
||||
else
|
||||
r = 0;
|
||||
|
||||
endutxent();
|
||||
|
||||
return r;
|
||||
if (pututxline(store))
|
||||
return 0;
|
||||
if (errno == ENOENT) {
|
||||
/* If utmp/wtmp have been disabled, that's a good thing, hence ignore the error. */
|
||||
log_debug_errno(errno, "Not writing utmp: %m");
|
||||
return 0;
|
||||
}
|
||||
return -errno;
|
||||
}
|
||||
|
||||
static int write_entry_wtmp(const struct utmpx *store) {
|
||||
assert(store);
|
||||
|
||||
/* wtmp is a simple append-only file where each entry is
|
||||
simply appended to the end; i.e. basically a log. */
|
||||
* simply appended to the end; i.e. basically a log. */
|
||||
|
||||
errno = 0;
|
||||
updwtmpx(_PATH_WTMPX, store);
|
||||
if (errno == ENOENT) {
|
||||
/* If utmp/wtmp have been disabled, that's a good thing, hence ignore the error. */
|
||||
log_debug_errno(errno, "Not writing wtmp: %m");
|
||||
return 0;
|
||||
}
|
||||
if (errno == EROFS) {
|
||||
log_warning_errno(errno, "Failed to write wtmp record, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
@ -145,16 +143,7 @@ static int write_utmp_wtmp(const struct utmpx *store_utmp, const struct utmpx *s
|
|||
|
||||
r = write_entry_utmp(store_utmp);
|
||||
s = write_entry_wtmp(store_wtmp);
|
||||
|
||||
if (r >= 0)
|
||||
r = s;
|
||||
|
||||
/* If utmp/wtmp have been disabled, that's a good thing, hence
|
||||
* ignore the errors */
|
||||
if (r == -ENOENT)
|
||||
r = 0;
|
||||
|
||||
return r;
|
||||
return r < 0 ? r : s;
|
||||
}
|
||||
|
||||
static int write_entry_both(const struct utmpx *store) {
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "util.h"
|
||||
|
||||
#if ENABLE_UTMP
|
||||
#include <utmpx.h>
|
||||
|
||||
int utmp_get_runlevel(int *runlevel, int *previous);
|
||||
|
||||
int utmp_put_shutdown(void);
|
||||
|
@ -24,6 +26,15 @@ int utmp_wall(
|
|||
bool (*match_tty)(const char *tty, void *userdata),
|
||||
void *userdata);
|
||||
|
||||
static inline bool utxent_start(void) {
|
||||
setutxent();
|
||||
return true;
|
||||
}
|
||||
static inline void utxent_cleanup(bool *initialized) {
|
||||
if (initialized)
|
||||
endutxent();
|
||||
}
|
||||
|
||||
#else /* ENABLE_UTMP */
|
||||
|
||||
static inline int utmp_get_runlevel(int *runlevel, int *previous) {
|
||||
|
|
|
@ -89,8 +89,8 @@ settime:
|
|||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_message = NULL;
|
||||
const char *user = "systemd-timesync";
|
||||
uid_t uid, uid_current;
|
||||
gid_t gid;
|
||||
|
|
|
@ -84,11 +84,10 @@ static int get_current_runlevel(Context *c) {
|
|||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
unsigned i;
|
||||
|
||||
assert(c);
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(table); i++) {
|
||||
for (size_t i = 0; i < ELEMENTSOF(table); i++) {
|
||||
_cleanup_free_ char *state = NULL, *path = NULL;
|
||||
|
||||
path = unit_dbus_path_from_name(table[i].special);
|
||||
|
@ -223,9 +222,6 @@ static int run(int argc, char *argv[]) {
|
|||
};
|
||||
int r;
|
||||
|
||||
if (getppid() != 1)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"This program should be invoked by init only.");
|
||||
if (argc != 2)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"This program requires one argument.");
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
*/
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
_cleanup_(manager_freep) Manager *m = NULL;
|
||||
_cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
|
||||
int r;
|
||||
|
||||
log_setup_service();
|
||||
|
|
Loading…
Reference in a new issue