#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;
_cleanup_bus_close_unref_ sd_bus *container = NULL;
int k;
- r = sd_bus_open_system_container(&container, *i);
+ r = sd_bus_open_system_machine(&container, *i);
if (r < 0) {
log_error_errno(r, "Failed to connect to container %s: %m", *i);
continue;
assert(mi);
if (!bus) {
- r = sd_bus_open_system_container(&container, mi->name);
+ r = sd_bus_open_system_machine(&container, mi->name);
if (r < 0)
return r;
}
}
-static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
- const char *type, *path, *source;
- int r;
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
- if (!arg_quiet) {
- if (streq(type, "symlink"))
- log_info("Created symlink from %s to %s.", path, source);
- else
- log_info("Removed symlink %s.", path);
- }
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(m);
- if (r < 0)
- return bus_log_parse_error(r);
-
- return 0;
-}
-
static int set_default(sd_bus *bus, char **args) {
_cleanup_free_ char *unit = NULL;
UnitFileChange *changes = NULL;
return r;
}
- r = deserialize_and_dump_unit_file_changes(reply);
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
if (r < 0)
return r;
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)
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,
"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;
- }
-
- if (isempty(tmp_path)) {
- log_warning("%s ignored: not found", template);
- return 0;
- }
-
- *path = tmp_path;
- tmp_path = NULL;
-
- return 1;
- } else {
- r = unit_file_find_path(lp, template, path);
- if (r == 0)
- log_warning("%s ignored: not found", template);
- return r;
- }
-
- return 0;
-}
-
-typedef struct WaitData {
- Set *set;
-
- char *name;
- char *result;
-} WaitData;
-
-static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
- WaitData *d = data;
-
- assert(bus);
- assert(m);
- assert(d);
-
- log_debug("Got D-Bus request: %s.%s() on %s",
- sd_bus_message_get_interface(m),
- sd_bus_message_get_member(m),
- sd_bus_message_get_path(m));
-
- if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
- log_error("Warning! D-Bus connection terminated.");
- sd_bus_close(bus);
- } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
- uint32_t id;
- const char *path, *result, *unit;
- char *ret;
- int r;
-
- r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
- if (r >= 0) {
- ret = set_remove(d->set, (char*) path);
- if (!ret)
- return 0;
-
- free(ret);
-
- if (!isempty(result))
- d->result = strdup(result);
+ &path);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
- if (!isempty(unit))
- d->name = strdup(unit);
+ 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));
- return 0;
+ r = 0;
+ if (!isempty(path)) {
+ *fragment_path = path;
+ path = NULL;
+ r = 1;
}
-#ifndef NOLEGACY
- r = sd_bus_message_read(m, "uos", &id, &path, &result);
- if (r >= 0) {
- ret = set_remove(d->set, (char*) path);
- if (!ret)
- return 0;
-
- free(ret);
- if (*result)
- d->result = strdup(result);
-
- return 0;
+ if (dropin_paths && !strv_isempty(dropins)) {
+ *dropin_paths = dropins;
+ dropins = NULL;
+ r = 1;
}
-#endif
-
- bus_log_parse_error(r);
- }
-
- return 0;
-}
-
-static int enable_wait_for_jobs(sd_bus *bus) {
- int r;
-
- assert(bus);
-
- r = sd_bus_add_match(
- bus,
- NULL,
- "type='signal',"
- "sender='org.freedesktop.systemd1',"
- "interface='org.freedesktop.systemd1.Manager',"
- "member='JobRemoved',"
- "path='/org/freedesktop/systemd1'",
- NULL, NULL);
- if (r < 0) {
- log_error("Failed to add match");
- return -EIO;
- }
-
- /* This is slightly dirty, since we don't undo the match registrations. */
- return 0;
-}
+ } else {
+ _cleanup_set_free_ Set *names;
-static int bus_process_wait(sd_bus *bus) {
- int r;
+ names = set_new(NULL);
+ if (!names)
+ return -ENOMEM;
- for (;;) {
- r = sd_bus_process(bus, NULL);
+ r = set_put(names, unit_name);
if (r < 0)
return r;
- if (r > 0)
- return 0;
- r = sd_bus_wait(bus, (uint64_t) -1);
+
+ r = unit_file_find_path(lp, unit_name, fragment_path);
if (r < 0)
return r;
- }
-}
-
-static int check_wait_response(WaitData *d) {
- int r = 0;
- assert(d->result);
-
- if (!arg_quiet) {
- if (streq(d->result, "canceled"))
- log_error("Job for %s canceled.", strna(d->name));
- else if (streq(d->result, "timeout"))
- log_error("Job for %s timed out.", strna(d->name));
- else if (streq(d->result, "dependency"))
- log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
- else if (streq(d->result, "invalid"))
- log_error("Job for %s invalid.", strna(d->name));
- else if (streq(d->result, "assert"))
- log_error("Assertion failed on job for %s.", strna(d->name));
- else if (streq(d->result, "unsupported"))
- log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
- else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
- if (d->name) {
- bool quotes;
-
- quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
-
- log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
- d->name,
- quotes ? "'" : "", d->name, quotes ? "'" : "");
- } else
- log_error("Job failed. See \"journalctl -xe\" for details.");
- }
- }
+ if (r == 0) {
+ _cleanup_free_ char *template;
- if (streq(d->result, "canceled"))
- r = -ECANCELED;
- else if (streq(d->result, "timeout"))
- r = -ETIME;
- else if (streq(d->result, "dependency"))
- r = -EIO;
- else if (streq(d->result, "invalid"))
- r = -ENOEXEC;
- else if (streq(d->result, "assert"))
- r = -EPROTO;
- else if (streq(d->result, "unsupported"))
- r = -ENOTSUP;
- else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
- r = -EIO;
-
- return r;
-}
-
-static int wait_for_jobs(sd_bus *bus, Set *s) {
- _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
- WaitData d = { .set = s };
- int r = 0, q;
-
- assert(bus);
- assert(s);
-
- q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
- if (q < 0)
- return log_oom();
-
- while (!set_isempty(s)) {
- q = bus_process_wait(bus);
- if (q < 0)
- return log_error_errno(q, "Failed to wait for response: %m");
+ template = unit_name_template(unit_name);
+ if (!template)
+ return log_oom();
- if (d.result) {
- q = check_wait_response(&d);
- /* Return the first error as it is most likely to be
- * meaningful. */
- if (q < 0 && r == 0)
- r = q;
- log_debug("Got result %s/%s for job %s",
- strna(d.result), strerror(-q), strna(d.name));
+ if (!streq(template, unit_name)) {
+ r = unit_file_find_path(lp, template, fragment_path);
+ if (r < 0)
+ return r;
+ }
}
- free(d.name);
- d.name = NULL;
-
- free(d.result);
- d.result = NULL;
+ if (dropin_paths)
+ r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, dropin_paths);
}
return r;
const char *name,
const char *mode,
sd_bus_error *error,
- Set *s) {
+ BusWaitForJobs *w) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
const char *path;
if (need_daemon_reload(bus, name) > 0)
warn_unit_file_changed(name);
- if (s) {
- char *p;
-
- p = strdup(path);
- if (!p)
- return log_oom();
-
- log_debug("Adding %s to the set", p);
- r = set_consume(s, p);
+ if (w) {
+ log_debug("Adding %s to the set", path);
+ r = bus_wait_for_jobs_add(w, path);
if (r < 0)
return log_oom();
}
_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;
}
static int start_unit(sd_bus *bus, char **args) {
- _cleanup_set_free_free_ Set *s = NULL;
- _cleanup_strv_free_ char **names = NULL;
+ _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
const char *method, *mode, *one_name, *suffix = NULL;
+ _cleanup_strv_free_ char **names = NULL;
char **name;
int r = 0;
}
if (!arg_no_block) {
- r = enable_wait_for_jobs(bus);
+ r = bus_wait_for_jobs_new(bus, &w);
if (r < 0)
return log_error_errno(r, "Could not watch jobs: %m");
-
- s = set_new(&string_hash_ops);
- if (!s)
- return log_oom();
}
STRV_FOREACH(name, names) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int q;
- q = start_unit_one(bus, method, *name, mode, &error, s);
+ q = start_unit_one(bus, method, *name, mode, &error, w);
if (r >= 0 && q < 0)
r = translate_bus_error_to_exit_status(q, &error);
}
if (!arg_no_block) {
int q;
- q = wait_for_jobs(bus, s);
+ q = bus_wait_for_jobs(w, arg_quiet);
if (q < 0)
return q;
a == ACTION_HIBERNATE ||
a == ACTION_HYBRID_SLEEP)) {
r = reboot_with_logind(bus, a);
- if (r >= 0)
+ if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS))
return r;
}
if (i->control_group &&
(i->main_pid > 0 || i->control_pid > 0 ||
- ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
+ ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
unsigned c;
printf(" CGroup: %s\n", i->control_group);
- if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
+ if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
unsigned k = 0;
pid_t extra[2];
static const char prefix[] = " ";
format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
printf(" CGroup: %s\n", mi.control_group ?: "/");
- if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
+ if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
int flags =
arg_all * OUTPUT_SHOW_ALL |
(!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
}
- r = lookup_paths_init(lp,
- arg_scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
- arg_scope == UNIT_FILE_USER,
- arg_root,
- NULL, NULL, NULL);
+ r = lookup_paths_init_from_scope(lp, arg_scope, arg_root);
if (r < 0)
return log_error_errno(r, "Failed to lookup unit lookup paths: %m");
}
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;
}
else
puts("");
- if (!isempty(fragment_path)) {
+ if (fragment_path) {
printf("%s# %s%s\n",
ansi_highlight_blue(),
fragment_path,
return -EPROTO;
/* Remove this entry, so that we don't try enabling it as native unit */
- assert(f > 0 && streq(args[f-1], name));
- assert_se(strv_remove(args + f - 1, name));
+ assert(f > 0);
+ f--;
+ assert(args[f] == name);
+ strv_remove(args, name);
}
#endif
return bus_log_parse_error(r);
}
- r = deserialize_and_dump_unit_file_changes(reply);
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
if (r < 0)
return r;
return r;
}
- r = deserialize_and_dump_unit_file_changes(reply);
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
if (r < 0)
return r;
return r;
}
- r = deserialize_and_dump_unit_file_changes(reply);
+ r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
if (r < 0)
return r;
return 0;
}
-static int get_drop_in_to_edit(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_path) {
- char *tmp_new_path;
- char *tmp;
-
- assert(unit_name);
- assert(ret_path);
+static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
+ _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
switch (arg_scope) {
case UNIT_FILE_SYSTEM:
- tmp = strappenda(arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
+ path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
+ if (arg_runtime)
+ run = path_join(arg_root, "/run/systemd/system/", name);
break;
case UNIT_FILE_GLOBAL:
- tmp = strappenda(arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
+ path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
+ if (arg_runtime)
+ run = path_join(arg_root, "/run/systemd/user/", name);
break;
case UNIT_FILE_USER:
assert(user_home);
assert(user_runtime);
- tmp = strappenda(arg_runtime ? user_runtime : user_home, "/", unit_name, ".d/override.conf");
+ path = path_join(arg_root, user_home, name);
+ if (arg_runtime) {
+ path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
+ if (!path2)
+ return log_oom();
+ run = path_join(arg_root, user_runtime, name);
+ }
break;
default:
assert_not_reached("Invalid scope");
}
-
- tmp_new_path = path_join(arg_root, tmp, NULL);
- if (!tmp_new_path)
+ if (!path || (arg_runtime && !run))
return log_oom();
- *ret_path = tmp_new_path;
+ if (arg_runtime) {
+ if (access(path, F_OK) >= 0)
+ return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
+ run, path);
+ if (path2 && access(path2, F_OK) >= 0)
+ return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
+ run, path2);
+ *ret_path = run;
+ run = NULL;
+ } else {
+ *ret_path = path;
+ path = NULL;
+ }
return 0;
}
-static int unit_file_create_drop_in(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
- char *tmp_new_path;
+
+static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
+ char *tmp_new_path, *ending;
char *tmp_tmp_path;
int r;
assert(ret_new_path);
assert(ret_tmp_path);
- r = get_drop_in_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
+ ending = strappenda(unit_name, ".d/override.conf");
+ r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path);
if (r < 0)
return r;
return 0;
}
-static bool unit_is_editable(const char *unit_name, const char *fragment_path, const char *user_home) {
- bool editable = true;
- const char *invalid_path;
-
- assert(unit_name);
-
- if (!arg_runtime)
- return true;
-
- switch (arg_scope) {
- case UNIT_FILE_SYSTEM:
- if (path_startswith(fragment_path, "/etc/systemd/system")) {
- editable = false;
- invalid_path = "/etc/systemd/system";
- } else if (path_startswith(fragment_path, SYSTEM_CONFIG_UNIT_PATH)) {
- editable = false;
- invalid_path = SYSTEM_CONFIG_UNIT_PATH;
- }
- break;
- case UNIT_FILE_GLOBAL:
- if (path_startswith(fragment_path, "/etc/systemd/user")) {
- editable = false;
- invalid_path = "/etc/systemd/user";
- } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
- editable = false;
- invalid_path = USER_CONFIG_UNIT_PATH;
- }
- break;
- case UNIT_FILE_USER:
- assert(user_home);
-
- if (path_startswith(fragment_path, "/etc/systemd/user")) {
- editable = false;
- invalid_path = "/etc/systemd/user";
- } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
- editable = false;
- invalid_path = USER_CONFIG_UNIT_PATH;
- } else if (path_startswith(fragment_path, user_home)) {
- editable = false;
- invalid_path = user_home;
- }
- break;
- default:
- assert_not_reached("Invalid scope");
- }
-
- if (!editable)
- log_error("%s ignored: cannot temporarily edit units from %s", unit_name, invalid_path);
-
- return editable;
-}
-
-static int get_copy_to_edit(const char *unit_name, const char *fragment_path, const char *user_home, const char *user_runtime, char **ret_path) {
- char *tmp_new_path;
-
- assert(unit_name);
- assert(ret_path);
-
- if (!unit_is_editable(unit_name, fragment_path, user_home))
- return -EINVAL;
-
- switch (arg_scope) {
- case UNIT_FILE_SYSTEM:
- tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH, unit_name);
- break;
- case UNIT_FILE_GLOBAL:
- tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH, unit_name);
- break;
- case UNIT_FILE_USER:
- assert(user_home);
- assert(user_runtime);
-
- tmp_new_path = path_join(arg_root, arg_runtime ? user_runtime : user_home, unit_name);
- break;
- default:
- assert_not_reached("Invalid scope");
- }
- if (!tmp_new_path)
- return log_oom();
-
- *ret_path = tmp_new_path;
-
- return 0;
-}
-
static int unit_file_create_copy(const char *unit_name,
const char *fragment_path,
const char *user_home,
assert(ret_new_path);
assert(ret_tmp_path);
- r = get_copy_to_edit(unit_name, fragment_path, user_home, user_runtime, &tmp_new_path);
+ r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
if (r < 0)
return r;
}
}
- 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);
}
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_dropin(*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)
break;
case 'M':
- arg_transport = BUS_TRANSPORT_CONTAINER;
+ arg_transport = BUS_TRANSPORT_MACHINE;
arg_host = optarg;
break;
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0)
switch (c) {
case ARG_HELP:
case 't':
case 'a':
+ case 'f':
+ case 'F':
/* Compatibility nops */
break;
{ "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 },
goto finish;
}
+ /* Increase max number of open files to 16K if we can, we
+ * might needs this when browsing journal files, which might
+ * be split up into many files. */
+ setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
+
if (!avoid_bus())
r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);