It similar with StartTransientUnit but the NewTransientUnit does not
start the unit immediately. Newly generated transient unit can be
activated by "systemctl start".
---
src/core/dbus-manager.c| 99 +-
src/core/org.freedesktop.systemd1.conf | 4 ++
src/core/service.c | 12 +
3 files changed, 103 insertions(+), 12 deletions(-)
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 533ce43..84c913b 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -615,10 +615,15 @@ static int method_set_unit_properties(sd_bus *bus,
sd_bus_message *message, void
return bus_unit_method_set_properties(bus, message, u, error);
}
-static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message,
void *userdata, sd_bus_error *error) {
+static int new_transient_unit_from_message(sd_bus *bus,
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error,
+ Unit **unit,
+ JobMode *mode,
+ bool keep) {
const char *name, *smode;
Manager *m = userdata;
-JobMode mode;
UnitType t;
Unit *u;
int r;
@@ -631,7 +636,9 @@ static int method_start_transient_unit(sd_bus *bus,
sd_bus_message *message, voi
if (r < 0)
return r;
if (r == 0)
-return 1; /* No authorization for now, but the async polkit
stuff will call us again when it has it */
+/* No authorization for now, but the async polkit
+ * stuff will call us again when it has it */
+return 1;
r = sd_bus_message_read(message, "ss", &name, &smode);
if (r < 0)
@@ -639,14 +646,22 @@ static int method_start_transient_unit(sd_bus *bus,
sd_bus_message *message, voi
t = unit_name_to_type(name);
if (t < 0)
-return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid unit type.");
+return sd_bus_error_setf(error,
+ SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid unit type.");
if (!unit_vtable[t]->can_transient)
-return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Unit type %s does not support transient units.", unit_type_to_string(t));
-
-mode = job_mode_from_string(smode);
-if (mode < 0)
-return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Job mode %s is invalid.", smode);
+return sd_bus_error_setf(error,
+ SD_BUS_ERROR_INVALID_ARGS,
+ "Unit type %s does not support
transient units.",
+ unit_type_to_string(t));
+
+*mode = job_mode_from_string(smode);
+if (*mode < 0)
+return sd_bus_error_setf(error,
+ SD_BUS_ERROR_INVALID_ARGS,
+ "Job mode %s is invalid.",
+ smode);
r = selinux_access_check(message, "start", error);
if (r < 0)
@@ -656,8 +671,12 @@ static int method_start_transient_unit(sd_bus *bus,
sd_bus_message *message, voi
if (r < 0)
return r;
-if (u->load_state != UNIT_NOT_FOUND ||
set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
-return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit
%s already exists.", name);
+if (u->load_state != UNIT_NOT_FOUND ||
+set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
+return sd_bus_error_setf(error,
+ BUS_ERROR_UNIT_EXISTS,
+ "Unit %s already exists.",
+ name);
/* OK, the unit failed to load and is unreferenced, now let's
* fill in the transient data instead */
@@ -675,10 +694,65 @@ static int method_start_transient_unit(sd_bus *bus,
sd_bus_message *message, voi
if (r < 0)
return r;
+*unit = u;
manager_dispatch_load_queue(m);
+return 0;
+}
+
+static int method_new_transient_unit(sd_bus *bus,
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+_cleanup_free_ char *path = NULL;
+JobMode mode;
+Unit *u = NULL;
+int r;
+
+r = new_transient_unit_from_message(bus,
+message,
+