summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2014-12-13 16:38:35 -0500
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2014-12-16 00:30:34 -0500
commitad2a035820e0fca29e49816f735bec1fcdabf82a (patch)
tree6be0dfe9332ade06d230956bbd8e63f33c6bf2bd /src
parent8df1850740f2b78407b856e32ba649a7037227d4 (diff)
systemctl: share path lookup between 'cat' and 'edit'
'systemctl cat' now works for templates too. 'systemctl edit' does not refuse to edit units that have changed on disk. That restriction didn't seem useful, actually editing units that have changed on disk before they are started is very reasonable. 'edit' with instances and templates works again: Now: $ build/systemctl edit getty@ Failed to copy /etc/systemd/system/getty@.service.d/override.conf to /etc/systemd/system/getty@.service.d/.override.confdff6290408c86369: Permission denied $ build/systemctl edit getty@tty3 Failed to create directories for /etc/systemd/system/getty@tty3.service.d/override.conf: Permission denied $ build/systemctl edit --full getty@tty3 Failed to copy /usr/lib/systemd/system/getty@.service to /etc/systemd/system/.getty@tty3.serviced3d175087e7e439b: Permission denied Failed to create temporary file for /etc/systemd/system/getty@tty3.service: Permission denied $ build/systemctl edit --full getty@ Failed to copy /usr/lib/systemd/system/getty@.service to /etc/systemd/system/.getty@.servicea3caad491c0f2f3d: Permission denied Failed to create temporary file for /etc/systemd/system/getty@.service: Permission denied
Diffstat (limited to 'src')
-rw-r--r--src/systemctl/systemctl.c179
1 files changed, 104 insertions, 75 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 68cb71c58..51ba33079 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -74,6 +74,7 @@
#include "bus-error.h"
#include "bus-common-errors.h"
#include "mkdir.h"
+#include "dropin.h"
static char **arg_types = NULL;
static char **arg_states = NULL;
@@ -2286,7 +2287,7 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un
assert(unit_path);
STRV_FOREACH(p, lp->unit_path) {
- char *path;
+ _cleanup_free_ char *path;
path = path_join(arg_root, *p, unit_name);
if (!path)
@@ -2294,35 +2295,46 @@ static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **un
if (access(path, F_OK) == 0) {
*unit_path = path;
+ path = NULL;
return 1;
}
-
- free(path);
}
return 0;
}
-static int unit_find_path(sd_bus *bus, const char *unit_name, const char *template, bool avoid_bus_cache, LookupPaths *lp, char **path) {
+static int unit_find_paths(sd_bus *bus,
+ const char *unit_name,
+ bool avoid_bus_cache,
+ LookupPaths *lp,
+ char **fragment_path,
+ char ***dropin_paths) {
int r;
+ /**
+ * Finds where the unit is defined on disk. Returns 0 if the unit
+ * is not found. Returns 1 if it is found, and sets
+ * - the path to the unit in *path, if it exists on disk,
+ * - and a strv of existing drop-ins in *dropins,
+ * if the arg is not NULL and any dropins were found.
+ */
+
assert(unit_name);
- assert(path);
+ assert(fragment_path);
assert(lp);
if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *unit = NULL;
- _cleanup_free_ char *tmp_path = NULL;
+ _cleanup_free_ char *path = NULL;
+ _cleanup_strv_free_ char **dropins = NULL;
unit = unit_dbus_path_from_name(unit_name);
if (!unit)
return log_oom();
- if (need_daemon_reload(bus, unit_name) > 0) {
+ if (need_daemon_reload(bus, unit_name) > 0)
warn_unit_file_changed(unit_name);
- return 0;
- }
r = sd_bus_get_property_string(
bus,
@@ -2331,29 +2343,67 @@ static int unit_find_path(sd_bus *bus, const char *unit_name, const char *templa
"org.freedesktop.systemd1.Unit",
"FragmentPath",
&error,
- &tmp_path);
- if (r < 0) {
- log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
- return 0;
+ &path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
+
+ r = sd_bus_get_property_strv(
+ bus,
+ "org.freedesktop.systemd1",
+ unit,
+ "org.freedesktop.systemd1.Unit",
+ "DropInPaths",
+ &error,
+ &dropins);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
+
+ r = 0;
+ if (!isempty(path)) {
+ *fragment_path = path;
+ path = NULL;
+ r = 1;
}
- if (isempty(tmp_path)) {
- log_warning("%s ignored: not found", template);
- return 0;
+ if (dropin_paths && !strv_isempty(dropins)) {
+ *dropin_paths = dropins;
+ dropins = NULL;
+ r = 1;
}
+ } else {
+ _cleanup_set_free_ Set *names;
- *path = tmp_path;
- tmp_path = NULL;
+ names = set_new(NULL);
+ if (!names)
+ return -ENOMEM;
- return 1;
- } else {
- r = unit_file_find_path(lp, template, path);
- if (r == 0)
- log_warning("%s ignored: not found", template);
- return r;
+ r = set_put(names, unit_name);
+ if (r < 0)
+ return r;
+
+ r = unit_file_find_path(lp, unit_name, fragment_path);
+ if (r < 0)
+ return r;
+
+ if (r == 0) {
+ _cleanup_free_ char *template;
+
+ template = unit_name_template(unit_name);
+ if (!template)
+ return log_oom();
+
+ if (!streq(template, unit_name)) {
+ r = unit_file_find_path(lp, template, fragment_path);
+ if (r < 0)
+ return r;
+ }
+ }
+
+ if (dropin_paths)
+ r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, dropin_paths);
}
- return 0;
+ return r;
}
typedef struct WaitData {
@@ -2810,6 +2860,9 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_free_ UnitInfo *unit_infos = NULL;
+ if (!bus)
+ return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
+
r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
if (r < 0)
return r;
@@ -4701,56 +4754,38 @@ static int init_home_and_lookup_paths(char **user_home, char **user_runtime, Loo
}
static int cat(sd_bus *bus, char **args) {
+ _cleanup_free_ char *user_home = NULL;
+ _cleanup_free_ char *user_runtime = NULL;
+ _cleanup_lookup_paths_free_ LookupPaths lp = {};
_cleanup_strv_free_ char **names = NULL;
char **name;
- bool first = true;
+ bool first = true, avoid_bus_cache;
int r = 0;
- assert(bus);
assert(args);
+ r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
+ if (r < 0)
+ return r;
+
r = expand_names(bus, args + 1, NULL, &names);
if (r < 0)
log_error_errno(r, "Failed to expand names: %m");
+ avoid_bus_cache = !bus || avoid_bus();
+
pager_open_if_enabled();
STRV_FOREACH(name, names) {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_free_ char *fragment_path = NULL;
_cleanup_strv_free_ char **dropin_paths = NULL;
- _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
char **path;
- unit = unit_dbus_path_from_name(*name);
- if (!unit)
- return log_oom();
-
- if (need_daemon_reload(bus, *name) > 0)
- warn_unit_file_changed(*name);
-
- r = sd_bus_get_property_string(
- bus,
- "org.freedesktop.systemd1",
- unit,
- "org.freedesktop.systemd1.Unit",
- "FragmentPath",
- &error,
- &fragment_path);
- if (r < 0) {
- log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
- continue;
- }
-
- r = sd_bus_get_property_strv(
- bus,
- "org.freedesktop.systemd1",
- unit,
- "org.freedesktop.systemd1.Unit",
- "DropInPaths",
- &error,
- &dropin_paths);
- if (r < 0) {
- log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
+ r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &fragment_path, &dropin_paths);
+ if (r < 0)
+ return r;
+ else if (r == 0) {
+ log_warning("Unit %s does not have any files on disk", *name);
continue;
}
@@ -4759,7 +4794,7 @@ static int cat(sd_bus *bus, char **args) {
else
puts("");
- if (!isempty(fragment_path)) {
+ if (fragment_path) {
printf("%s# %s%s\n",
ansi_highlight_blue(),
fragment_path,
@@ -6115,7 +6150,7 @@ static int run_editor(char **paths) {
}
}
- log_error("Cannot edit unit(s): No editor available. Please set either SYSTEMD_EDITOR or EDITOR or VISUAL environment variable");
+ log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR or $EDITOR or $VISUAL.");
_exit(EXIT_FAILURE);
}
@@ -6145,27 +6180,21 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
STRV_FOREACH(name, names) {
_cleanup_free_ char *path = NULL;
- _cleanup_free_ char *template = NULL;
char *new_path, *tmp_path;
- template = unit_name_template(*name);
- if (!template)
- return log_oom();
-
- r = unit_find_path(bus, *name, template, avoid_bus_cache, &lp, &path);
+ r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &path, NULL);
if (r < 0)
return r;
- else if (r == 0) {
- continue;
- }
+ else if (r == 0 || !path)
+ // FIXME: support units with path==NULL (no FragmentPath)
+ return log_error_errno(ENOENT, "Unit %s not found, cannot edit.", *name);
if (arg_full)
- r = unit_file_create_copy(template, path, user_home, user_runtime, &new_path, &tmp_path);
+ r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
else
- r = unit_file_create_drop_in(template, user_home, user_runtime, &new_path, &tmp_path);
-
+ r = unit_file_create_drop_in(*name, user_home, user_runtime, &new_path, &tmp_path);
if (r < 0)
- continue;
+ return r;
r = strv_push_pair(paths, new_path, tmp_path);
if (r < 0)
@@ -7307,7 +7336,7 @@ static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
{ "check", MORE, 2, check_unit_active },
{ "is-failed", MORE, 2, check_unit_failed },
{ "show", MORE, 1, show },
- { "cat", MORE, 2, cat },
+ { "cat", MORE, 2, cat, NOBUS },
{ "status", MORE, 1, show },
{ "help", MORE, 2, show },
{ "snapshot", LESS, 2, snapshot },