]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #16344 from keszybz/update-utmp-erofs
authorLennart Poettering <lennart@poettering.net>
Mon, 6 Jul 2020 15:52:17 +0000 (17:52 +0200)
committerGitHub <noreply@github.com>
Mon, 6 Jul 2020 15:52:17 +0000 (17:52 +0200)
Make update-utmp not fail if it only fails to write wtmp records

13 files changed:
src/home/homed.c
src/initctl/initctl.c
src/journal-remote/journal-remote-main.c
src/journal-remote/journal-upload.c
src/login/logind-core.c
src/network/networkd.c
src/network/wait-online/wait-online.c
src/resolve/resolved.c
src/shared/utmp-wtmp.c
src/shared/utmp-wtmp.h
src/timesync/timesyncd.c
src/update-utmp/update-utmp.c
src/userdb/userdbd.c

index 2fd3b65d8983d255c26c98b21fbcb9805f3d0a8b..ed8404d7e3da2585921877df3bea812185a99b16 100644 (file)
@@ -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();
index 7505512fe7e4f5a5f1185545d2f7005ebab2b88f..7eee197665f2eef51b657b269404b3b911611ae5 100644 (file)
 #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),
-        };
-
-        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;
+        s->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
+        if (s->epoll_fd < 0)
+                return log_error_errno(errno, "Failed to create epoll object: %m");
 
-                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;
-
-        if (getppid() != 1) {
-                log_error("This program should be invoked by init only.");
-                return EXIT_FAILURE;
-        }
+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 (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 || n > SERVER_FD_MAX) {
-                log_error("No or too many file descriptors passed.");
-                return EXIT_FAILURE;
-        }
+        if (n < 0)
+                return log_error_errno(errno,
+                                       "Failed to read listening file descriptors from environment: %m");
 
-        if (server_init(&server, (unsigned) n) < 0)
-                return EXIT_FAILURE;
+        if (n <= 0 || n > SERVER_FD_MAX)
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "No or too many file descriptors passed.");
 
-        log_debug("systemd-initctl running as pid "PID_FMT, getpid_cached());
+        r = server_init(&server, (unsigned) n);
+        if (r < 0)
+                return r;
 
-        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);
index f82d188a8c64767c7bfce68e576fc74d5e61efa3..273fdf9196ec0417e77e4ed7c0fed3ec9c3636cd 100644 (file)
@@ -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;
 
index e169a27eb3c7df8440c0a48507510cfbb3a383f5..13ca90f957f6c4eb3812a423aaf1866a6a5a27e9 100644 (file)
@@ -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;
 
index 475759c79b514b3879246d9831c7ae6b84b08b7f..480ec1927b03cc5b513815b26686fb9306823ad9 100644 (file)
@@ -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
index 35f22fea8014338d6a860a21277427330244b378..445aee16ad0435b4f7361cb6098dac5d859837dc 100644 (file)
@@ -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();
index 17ed5d38cfe3de6bd53344cc7f391f90e9f61c13..cfd9093f1a3e954b609736ab85adf9994855214f 100644 (file)
@@ -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();
index 566b950a637a1f486bdc7f7f0a610d28fb5d37ae..16477f28d69e73d30638689a81a76f254ab6c639 100644 (file)
@@ -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();
index 9debb54390e6d80b5d09ab2da12b689726f4b4e4..9edcd8302ac79d204693a7600130d16af7491760 100644 (file)
@@ -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;
-
-                a = found->ut_pid & 0xFF;
-                b = (found->ut_pid >> 8) & 0xFF;
-
-                *runlevel = a;
-                if (previous)
-                        *previous = b;
-
-                r = 0;
-        }
+                return -errno;
 
-        endutxent();
+        *runlevel = found->ut_pid & 0xFF;
+        if (previous)
+                *previous = (found->ut_pid >> 8) & 0xFF;
 
-        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();
-
-        if (!pututxline(store))
-                r = -errno;
-        else
-                r = 0;
-
-        endutxent();
+        utmpx = utxent_start();
 
-        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) {
index 9e433cf73ec5a968ad5149b3768b3b1369c1f4c4..fe55bad12d632bd85b11938eca87a0fba780bbf2 100644 (file)
@@ -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) {
index e56e09ca8cec5255a83a9531530b53a8654ab4e6..4f514d536d0b73a00e6eecbd359711f394d46ff5 100644 (file)
@@ -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;
index fd24cdc789a9cb4aa97237b5bdf21008b3a0d143..47354d50129090875b799341f0a361dd25df1806 100644 (file)
@@ -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.");
index 978fd1d7886223763e1aba953aae128633b08b53..dbc285e61aac1b0224968c208836e39e2d769069 100644 (file)
@@ -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();