]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/manager.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[thirdparty/systemd.git] / src / core / manager.c
index ede2a9910dae5e71e611c552efa8fa68706db2eb..9ad8a136abb326c1bf3861e0af126e193949e3a2 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <dirent.h>
 #include <errno.h>
-#include <string.h>
+#include <fcntl.h>
+#include <linux/kd.h>
 #include <signal.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <sys/inotify.h>
+#include <string.h>
 #include <sys/epoll.h>
-#include <sys/reboot.h>
+#include <sys/inotify.h>
 #include <sys/ioctl.h>
-#include <linux/kd.h>
-#include <fcntl.h>
-#include <dirent.h>
+#include <sys/reboot.h>
 #include <sys/timerfd.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
 #ifdef HAVE_AUDIT
 #include <libaudit.h>
 #include "sd-daemon.h"
 #include "sd-messages.h"
 
-#include "hashmap.h"
-#include "macro.h"
-#include "strv.h"
-#include "log.h"
-#include "util.h"
-#include "mkdir.h"
-#include "ratelimit.h"
-#include "locale-setup.h"
-#include "unit-name.h"
-#include "missing.h"
-#include "rm-rf.h"
-#include "path-lookup.h"
-#include "special.h"
-#include "exit-status.h"
-#include "virt.h"
-#include "watchdog.h"
-#include "path-util.h"
 #include "audit-fd.h"
 #include "boot-timestamps.h"
-#include "env-util.h"
 #include "bus-common-errors.h"
 #include "bus-error.h"
-#include "bus-util.h"
 #include "bus-kernel.h"
-#include "time-util.h"
-#include "process-util.h"
-#include "terminal-util.h"
-#include "signal-util.h"
-#include "dbus.h"
-#include "dbus-unit.h"
+#include "bus-util.h"
 #include "dbus-job.h"
 #include "dbus-manager.h"
+#include "dbus-unit.h"
+#include "dbus.h"
+#include "env-util.h"
+#include "escape.h"
+#include "exit-status.h"
+#include "fd-util.h"
+#include "hashmap.h"
+#include "io-util.h"
+#include "locale-setup.h"
+#include "log.h"
+#include "macro.h"
 #include "manager.h"
+#include "missing.h"
+#include "mkdir.h"
+#include "parse-util.h"
+#include "path-lookup.h"
+#include "path-util.h"
+#include "process-util.h"
+#include "ratelimit.h"
+#include "rm-rf.h"
+#include "signal-util.h"
+#include "special.h"
+#include "string-util.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "time-util.h"
 #include "transaction.h"
+#include "unit-name.h"
+#include "util.h"
+#include "virt.h"
+#include "watchdog.h"
 
 /* Initial delay and the interval for printing status messages about running jobs */
 #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC)
@@ -111,7 +116,7 @@ static void manager_watch_jobs_in_progress(Manager *m) {
         (void) sd_event_source_set_description(m->jobs_in_progress_event_source, "manager-jobs-in-progress");
 }
 
-#define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1))
+#define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED)-1) + sizeof(ANSI_HIGHLIGHT_RED)-1 + 2*(sizeof(ANSI_NORMAL)-1))
 
 static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
         char *p = buffer;
@@ -122,23 +127,23 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po
         if (pos > 1) {
                 if (pos > 2)
                         p = mempset(p, ' ', pos-2);
-                p = stpcpy(p, ANSI_RED_ON);
+                p = stpcpy(p, ANSI_RED);
                 *p++ = '*';
         }
 
         if (pos > 0 && pos <= width) {
-                p = stpcpy(p, ANSI_HIGHLIGHT_RED_ON);
+                p = stpcpy(p, ANSI_HIGHLIGHT_RED);
                 *p++ = '*';
         }
 
-        p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
+        p = stpcpy(p, ANSI_NORMAL);
 
         if (pos < width) {
-                p = stpcpy(p, ANSI_RED_ON);
+                p = stpcpy(p, ANSI_RED);
                 *p++ = '*';
                 if (pos < width-1)
                         p = mempset(p, ' ', width-1-pos);
-                strcpy(p, ANSI_HIGHLIGHT_OFF);
+                strcpy(p, ANSI_NORMAL);
         }
 }
 
@@ -317,6 +322,8 @@ static int manager_watch_idle_pipe(Manager *m) {
 static void manager_close_idle_pipe(Manager *m) {
         assert(m);
 
+        m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
+
         safe_close_pair(m->idle_pipe);
         safe_close_pair(m->idle_pipe + 2);
 }
@@ -493,6 +500,7 @@ static void manager_clean_environment(Manager *m) {
                         "MANAGERPID",
                         "LISTEN_PID",
                         "LISTEN_FDS",
+                        "LISTEN_FDNAMES",
                         "WATCHDOG_PID",
                         "WATCHDOG_USEC",
                         NULL);
@@ -554,7 +562,7 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
                 return -ENOMEM;
 
 #ifdef ENABLE_EFI
-        if (running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0)
+        if (running_as == MANAGER_SYSTEM && detect_container() <= 0)
                 boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
 #endif
 
@@ -568,11 +576,16 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
 
         m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
 
-        m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd = m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->utab_inotify_fd = -1;
+        m->pin_cgroupfs_fd = m->notify_fd = m->signal_fd = m->time_change_fd =
+                m->dev_autofs_fd = m->private_listen_fd = m->kdbus_fd = m->cgroup_inotify_fd = -1;
+
         m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
 
         m->ask_password_inotify_fd = -1;
         m->have_ask_password = -EINVAL; /* we don't know */
+        m->first_boot = -1;
+
+        m->cgroup_netclass_registry_last = CGROUP_NETCLASS_FIXED_MAX;
 
         m->test_run = test_run;
 
@@ -599,14 +612,6 @@ int manager_new(ManagerRunningAs running_as, bool test_run, Manager **_m) {
         if (r < 0)
                 goto fail;
 
-        r = set_ensure_allocated(&m->startup_units, NULL);
-        if (r < 0)
-                goto fail;
-
-        r = set_ensure_allocated(&m->failed_units, NULL);
-        if (r < 0)
-                goto fail;
-
         r = sd_event_default(&m->event);
         if (r < 0)
                 goto fail;
@@ -671,8 +676,7 @@ static int manager_setup_notify(Manager *m) {
                 static const int one = 1;
 
                 /* First free all secondary fields */
-                free(m->notify_socket);
-                m->notify_socket = NULL;
+                m->notify_socket = mfree(m->notify_socket);
                 m->notify_event_source = sd_event_source_unref(m->notify_event_source);
 
                 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
@@ -942,7 +946,6 @@ Manager* manager_free(Manager *m) {
         sd_event_source_unref(m->notify_event_source);
         sd_event_source_unref(m->time_change_event_source);
         sd_event_source_unref(m->jobs_in_progress_event_source);
-        sd_event_source_unref(m->idle_pipe_event_source);
         sd_event_source_unref(m->run_queue_event_source);
 
         safe_close(m->signal_fd);
@@ -965,6 +968,8 @@ Manager* manager_free(Manager *m) {
         hashmap_free(m->cgroup_unit);
         set_free_free(m->unit_path_cache);
 
+        hashmap_free(m->cgroup_netclass_registry);
+
         free(m->switch_root);
         free(m->switch_root_init);
 
@@ -1072,8 +1077,7 @@ static void manager_build_unit_path_cache(Manager *m) {
                                 goto fail;
                 }
 
-                closedir(d);
-                d = NULL;
+                d = safe_closedir(d);
         }
 
         return;
@@ -1582,19 +1586,19 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
 
                 /* Notify every unit that might be interested, but try
                  * to avoid notifying the same one multiple times. */
-                u1 = manager_get_unit_by_pid(m, ucred->pid);
+                u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid);
                 if (u1) {
                         manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds);
                         found = true;
                 }
 
-                u2 = hashmap_get(m->watch_pids1, LONG_TO_PTR(ucred->pid));
+                u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid));
                 if (u2 && u2 != u1) {
                         manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds);
                         found = true;
                 }
 
-                u3 = hashmap_get(m->watch_pids2, LONG_TO_PTR(ucred->pid));
+                u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid));
                 if (u3 && u3 != u2 && u3 != u1) {
                         manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds);
                         found = true;
@@ -1660,13 +1664,13 @@ static int manager_dispatch_sigchld(Manager *m) {
 
                         /* And now figure out the unit this belongs
                          * to, it might be multiple... */
-                        u1 = manager_get_unit_by_pid(m, si.si_pid);
+                        u1 = manager_get_unit_by_pid_cgroup(m, si.si_pid);
                         if (u1)
                                 invoke_sigchld_event(m, u1, &si);
-                        u2 = hashmap_get(m->watch_pids1, LONG_TO_PTR(si.si_pid));
+                        u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(si.si_pid));
                         if (u2 && u2 != u1)
                                 invoke_sigchld_event(m, u2, &si);
-                        u3 = hashmap_get(m->watch_pids2, LONG_TO_PTR(si.si_pid));
+                        u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(si.si_pid));
                         if (u3 && u3 != u2 && u3 != u1)
                                 invoke_sigchld_event(m, u3, &si);
                 }
@@ -1960,7 +1964,6 @@ static int manager_dispatch_idle_pipe_fd(sd_event_source *source, int fd, uint32
 
         m->no_console_output = m->n_on_console > 0;
 
-        m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
         manager_close_idle_pipe(m);
 
         return 0;
@@ -2153,7 +2156,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u) {
         if (m->running_as != MANAGER_SYSTEM)
                 return;
 
-        if (detect_container(NULL) > 0)
+        if (detect_container() > 0)
                 return;
 
         if (u->type != UNIT_SERVICE &&
@@ -2610,7 +2613,7 @@ static void manager_notify_finished(Manager *m) {
         if (m->test_run)
                 return;
 
-        if (m->running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0) {
+        if (m->running_as == MANAGER_SYSTEM && detect_container() <= 0) {
 
                 /* Note that m->kernel_usec.monotonic is always at 0,
                  * and m->firmware_usec.monotonic and
@@ -2673,9 +2676,6 @@ static void manager_notify_finished(Manager *m) {
 }
 
 void manager_check_finished(Manager *m) {
-        Unit *u = NULL;
-        Iterator i;
-
         assert(m);
 
         if (m->n_reloading > 0)
@@ -2688,11 +2688,9 @@ void manager_check_finished(Manager *m) {
                 return;
 
         if (hashmap_size(m->jobs) > 0) {
-
                 if (m->jobs_in_progress_event_source)
                         /* Ignore any failure, this is only for feedback */
-                        (void) sd_event_source_set_time(m->jobs_in_progress_event_source,
-                                                        now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
+                        (void) sd_event_source_set_time(m->jobs_in_progress_event_source, now(CLOCK_MONOTONIC) + JOBS_IN_PROGRESS_WAIT_USEC);
 
                 return;
         }
@@ -2700,7 +2698,6 @@ void manager_check_finished(Manager *m) {
         manager_flip_auto_status(m, false);
 
         /* Notify Type=idle units that we are done now */
-        m->idle_pipe_event_source = sd_event_source_unref(m->idle_pipe_event_source);
         manager_close_idle_pipe(m);
 
         /* Turn off confirm spawn now */
@@ -2719,9 +2716,7 @@ void manager_check_finished(Manager *m) {
 
         manager_notify_finished(m);
 
-        SET_FOREACH(u, m->startup_units, i)
-                if (u->cgroup_path)
-                        cgroup_context_apply(unit_get_cgroup_context(u), unit_get_cgroup_mask(u), u->cgroup_path, manager_state(m));
+        manager_invalidate_startup_units(m);
 }
 
 static int create_generator_dir(Manager *m, char **generator, const char *name) {
@@ -2790,10 +2785,8 @@ static void trim_generator_dir(Manager *m, char **generator) {
         if (!*generator)
                 return;
 
-        if (rmdir(*generator) >= 0) {
-                free(*generator);
-                *generator = NULL;
-        }
+        if (rmdir(*generator) >= 0)
+                *generator = mfree(*generator);
 
         return;
 }
@@ -2863,8 +2856,7 @@ static void remove_generator_dir(Manager *m, char **generator) {
         strv_remove(m->lookup_paths.unit_path, *generator);
         (void) rm_rf(*generator, REMOVE_ROOT);
 
-        free(*generator);
-        *generator = NULL;
+        *generator = mfree(*generator);
 }
 
 static void manager_undo_generators(Manager *m) {
@@ -2965,9 +2957,9 @@ void manager_set_show_status(Manager *m, ShowStatus mode) {
         m->show_status = mode;
 
         if (mode > 0)
-                touch("/run/systemd/show-status");
+                (void) touch("/run/systemd/show-status");
         else
-                unlink("/run/systemd/show-status");
+                (void) unlink("/run/systemd/show-status");
 }
 
 static bool manager_get_show_status(Manager *m, StatusType type) {
@@ -2998,12 +2990,14 @@ void manager_set_first_boot(Manager *m, bool b) {
         if (m->running_as != MANAGER_SYSTEM)
                 return;
 
-        m->first_boot = b;
+        if (m->first_boot != (int) b) {
+                if (b)
+                        (void) touch("/run/systemd/first-boot");
+                else
+                        (void) unlink("/run/systemd/first-boot");
+        }
 
-        if (m->first_boot)
-                touch("/run/systemd/first-boot");
-        else
-                unlink("/run/systemd/first-boot");
+        m->first_boot = b;
 }
 
 void manager_status_printf(Manager *m, StatusType type, const char *status, const char *format, ...) {
@@ -3024,30 +3018,6 @@ void manager_status_printf(Manager *m, StatusType type, const char *status, cons
         va_end(ap);
 }
 
-int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) {
-        _cleanup_free_ char *p = NULL;
-        Unit *found;
-        int r;
-
-        assert(m);
-        assert(path);
-        assert(suffix);
-        assert(_found);
-
-        r = unit_name_from_path(path, suffix, &p);
-        if (r < 0)
-                return r;
-
-        found = manager_get_unit(m, p);
-        if (!found) {
-                *_found = NULL;
-                return 0;
-        }
-
-        *_found = found;
-        return 1;
-}
-
 Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) {
         char p[strlen(path)+1];
 
@@ -3068,8 +3038,9 @@ const char *manager_get_runtime_prefix(Manager *m) {
                getenv("XDG_RUNTIME_DIR");
 }
 
-void manager_update_failed_units(Manager *m, Unit *u, bool failed) {
+int manager_update_failed_units(Manager *m, Unit *u, bool failed) {
         unsigned size;
+        int r;
 
         assert(m);
         assert(u->manager == m);
@@ -3077,13 +3048,19 @@ void manager_update_failed_units(Manager *m, Unit *u, bool failed) {
         size = set_size(m->failed_units);
 
         if (failed) {
+                r = set_ensure_allocated(&m->failed_units, NULL);
+                if (r < 0)
+                        return log_oom();
+
                 if (set_put(m->failed_units, u) < 0)
-                        log_oom();
+                        return log_oom();
         } else
-                set_remove(m->failed_units, u);
+                (void) set_remove(m->failed_units, u);
 
         if (set_size(m->failed_units) != size)
                 bus_manager_send_change_signal(m);
+
+        return 0;
 }
 
 ManagerState manager_state(Manager *m) {