chiark / gitweb /
core: Refuse mount on symlink
[elogind.git] / src / core / dbus-manager.c
index 58e484df804b2e6f054827c8d5b5fa69104063a9..ffef0c7d05813b5c058eba116a3a92953c9df06f 100644 (file)
@@ -28,7 +28,7 @@
 #include "install.h"
 #include "selinux-access.h"
 #include "watchdog.h"
-#include "hwclock.h"
+#include "clock-util.h"
 #include "path-util.h"
 #include "virt.h"
 #include "architecture.h"
@@ -130,7 +130,7 @@ static int property_get_tainted(
         if (access("/proc/cgroups", F_OK) < 0)
                 e = stpcpy(e, "cgroups-missing:");
 
-        if (hwclock_is_localtime() > 0)
+        if (clock_is_localtime() > 0)
                 e = stpcpy(e, "local-hwclock:");
 
         /* remove the last ':' */
@@ -728,7 +728,7 @@ static int method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userd
         return sd_bus_reply_method_return(message, NULL);
 }
 
-static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int list_units_filtered(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error, char **states) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         Manager *m = userdata;
         const char *k;
@@ -761,6 +761,12 @@ static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdat
 
                 following = unit_following(u);
 
+                if (!strv_isempty(states) &&
+                    !strv_contains(states, unit_load_state_to_string(u->load_state)) &&
+                    !strv_contains(states, unit_active_state_to_string(unit_active_state(u))) &&
+                    !strv_contains(states, unit_sub_state_to_string(u)))
+                        continue;
+
                 unit_path = unit_dbus_path(u);
                 if (!unit_path)
                         return -ENOMEM;
@@ -794,6 +800,21 @@ static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdat
         return sd_bus_send(bus, reply, NULL);
 }
 
+static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        return list_units_filtered(bus, message, userdata, error, NULL);
+}
+
+static int method_list_units_filtered(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        _cleanup_strv_free_ char **states = NULL;
+        int r;
+
+        r = sd_bus_message_read_strv(message, &states);
+        if (r < 0)
+                return r;
+
+        return list_units_filtered(bus, message, userdata, error, states);
+}
+
 static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         Manager *m = userdata;
@@ -1170,7 +1191,7 @@ static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userda
         /* Safety check */
         if (isempty(init)) {
                 if (! path_is_os_tree(root))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. /etc/os-release is missing.", root);
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. os-release file is missing.", root);
         } else {
                 _cleanup_free_ char *p = NULL;
 
@@ -1466,8 +1487,8 @@ fail:
 static int method_enable_unit_files_generic(
                 sd_bus *bus,
                 sd_bus_message *message,
-                Manager *m, const
-                char *verb,
+                Manager *m,
+                const char *verb,
                 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
                 bool carries_install_info,
                 sd_bus_error *error) {
@@ -1489,6 +1510,10 @@ static int method_enable_unit_files_generic(
         if (r < 0)
                 return r;
 
+        r = sd_bus_message_read(message, "bb", &runtime, &force);
+        if (r < 0)
+                return r;
+
 #ifdef HAVE_SELINUX
         STRV_FOREACH(i, l) {
                 Unit *u;
@@ -1502,10 +1527,6 @@ static int method_enable_unit_files_generic(
         }
 #endif
 
-        r = sd_bus_message_read(message, "bb", &runtime, &force);
-        if (r < 0)
-                return r;
-
         scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
 
         r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
@@ -1527,14 +1548,74 @@ static int method_link_unit_files(sd_bus *bus, sd_bus_message *message, void *us
         return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_link, false, error);
 }
 
+static int unit_file_preset_without_mode(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) {
+        return unit_file_preset(scope, runtime, root_dir, files, UNIT_FILE_PRESET_FULL, force, changes, n_changes);
+}
+
 static int method_preset_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
-        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset, true, error);
+        return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset_without_mode, true, error);
 }
 
 static int method_mask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
         return method_enable_unit_files_generic(bus, message, userdata, "disable", unit_file_mask, false, error);
 }
 
+static int method_preset_unit_files_with_mode(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+
+        _cleanup_strv_free_ char **l = NULL;
+#ifdef HAVE_SELINUX
+        char **i;
+#endif
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        Manager *m = userdata;
+        UnitFilePresetMode mm;
+        UnitFileScope scope;
+        int runtime, force, r;
+        const char *mode;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read_strv(message, &l);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
+        if (r < 0)
+                return r;
+
+        if (isempty(mode))
+                mm = UNIT_FILE_PRESET_FULL;
+        else {
+                mm = unit_file_preset_mode_from_string(mode);
+                if (mm < 0)
+                        return -EINVAL;
+        }
+
+#ifdef HAVE_SELINUX
+        STRV_FOREACH(i, l) {
+                Unit *u;
+
+                u = manager_get_unit(m, *i);
+                if (u) {
+                        r = selinux_unit_access_check(u, message, "enable", error);
+                        if (r < 0)
+                                return r;
+                }
+        }
+#endif
+
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+
+        r = unit_file_preset(scope, runtime, NULL, l, mm, force, &changes, &n_changes);
+        if (r < 0)
+                return r;
+
+        return reply_unit_file_changes_and_free(m, bus, message, r, changes, n_changes);
+}
+
 static int method_disable_unit_files_generic(
                 sd_bus *bus,
                 sd_bus_message *message,
@@ -1611,6 +1692,44 @@ static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void
         return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
 }
 
+static int method_preset_all_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+        UnitFileChange *changes = NULL;
+        unsigned n_changes = 0;
+        Manager *m = userdata;
+        UnitFilePresetMode mm;
+        UnitFileScope scope;
+        const char *mode;
+        int force, runtime, r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = selinux_access_check(message, "enable", error);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
+        if (r < 0)
+                return r;
+
+        if (isempty(mode))
+                mm = UNIT_FILE_PRESET_FULL;
+        else {
+                mm = unit_file_preset_mode_from_string(mode);
+                if (mm < 0)
+                        return -EINVAL;
+        }
+
+        scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+
+        r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes);
+        if (r < 0)
+                return r;
+
+        return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
+}
+
 const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_VTABLE_START(0),
 
@@ -1670,6 +1789,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
         SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
         SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -1694,10 +1814,12 @@ const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
         SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
         SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
+        SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, 0),
         SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
         SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
         SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
         SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, 0),
 
         SD_BUS_SIGNAL("UnitNew", "so", 0),
         SD_BUS_SIGNAL("UnitRemoved", "so", 0),