#include "cgroup-util.h"
#include "path-util.h"
#include "audit-fd.h"
+#include "efivars.h"
+#include "env-util.h"
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
#define GC_QUEUE_ENTRIES_MAX 16
/* Where clients shall send notification messages to */
#define NOTIFY_SOCKET "@/org/freedesktop/systemd1/notify"
+#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
+
static int manager_setup_notify(Manager *m) {
union {
struct sockaddr sa;
ev.data.ptr = &m->notify_watch;
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0) {
- log_error("Failed to add timer change fd to epoll: %m");
+ log_error("Failed to add notification socket fd to epoll: %m");
return -errno;
}
/* We only care for the cancellation event, hence we set the
* timeout to the latest possible value. */
- assert_cc(sizeof(time_t) == sizeof(long));
- its.it_value.tv_sec = LONG_MAX;
+ assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
+ its.it_value.tv_sec = TIME_T_MAX;
if (timerfd_settime(m->time_change_watch.fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
* the initrd interface:
* http://www.freedesktop.org/wiki/Software/systemd/InitrdInterface */
strv_remove_prefix(m->environment, "RD_");
+
+ /* Drop invalid entries */
+ strv_env_clean(m->environment);
}
int manager_new(SystemdRunningAs running_as, Manager **_m) {
return -ENOMEM;
dual_timestamp_get(&m->userspace_timestamp);
+ dual_timestamp_from_monotonic(&m->kernel_timestamp, 0);
+#ifdef ENABLE_EFI
+ efi_get_boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
+#endif
m->running_as = running_as;
m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
static void manager_build_unit_path_cache(Manager *m) {
char **i;
- DIR *d = NULL;
+ DIR _cleanup_free_ *d = NULL;
int r;
assert(m);
set_free_free(m->unit_path_cache);
- if (!(m->unit_path_cache = set_new(string_hash_func, string_compare_func))) {
+ m->unit_path_cache = set_new(string_hash_func, string_compare_func);
+ if (!m->unit_path_cache) {
log_error("Failed to allocate unit path cache.");
return;
}
d = opendir(*i);
if (!d) {
- log_error("Failed to open directory: %m");
+ if (errno != ENOENT)
+ log_error("Failed to open directory %s: %m", *i);
continue;
}
goto fail;
}
- if ((r = set_put(m->unit_path_cache, p)) < 0) {
+ r = set_put(m->unit_path_cache, p);
+ if (r < 0) {
free(p);
goto fail;
}
set_free_free(m->unit_path_cache);
m->unit_path_cache = NULL;
-
- if (d)
- closedir(d);
}
int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
job_type_collapse(&type, unit);
- tr = transaction_new();
+ tr = transaction_new(mode == JOB_REPLACE_IRREVERSIBLY);
if (!tr)
return -ENOMEM;
Iterator i;
Unit *u;
const char *t;
+ char **e;
int r;
assert(m);
dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
}
+ STRV_FOREACH(e, m->environment) {
+ _cleanup_free_ char *ce;
+
+ ce = cescape(*e);
+ if (ce)
+ fprintf(f, "env=%s\n", *e);
+ }
+
fputc('\n', f);
HASHMAP_FOREACH_KEY(u, t, m->units, i) {
dual_timestamp_deserialize(l+20, &m->userspace_timestamp);
else if (startswith(l, "finish-timestamp="))
dual_timestamp_deserialize(l+17, &m->finish_timestamp);
- else
+ else if (startswith(l, "env=")) {
+ _cleanup_free_ char *uce = NULL;
+ char **e;
+
+ uce = cunescape(l+4);
+ if (!uce) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ e = strv_env_set(m->environment, uce);
+ if (!e) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ strv_free(m->environment);
+ m->environment = e;
+ } else
log_debug("Unknown serialization item '%s'", l);
}
return r;
}
-bool manager_is_booting_or_shutting_down(Manager *m) {
+static bool manager_is_booting_or_shutting_down(Manager *m) {
Unit *u;
assert(m);
r = mkdir_p_label(p, 0755);
if (r < 0) {
- log_error("Failed to create generator directory: %s", strerror(-r));
+ log_error("Failed to create generator directory %s: %s",
+ p, strerror(-r));
free(p);
return r;
}
if (!mkdtemp(p)) {
free(p);
- log_error("Failed to create generator directory: %m");
+ log_error("Failed to create generator directory %s: %m",
+ p);
return -errno;
}
}
if (errno == ENOENT)
return;
- log_error("Failed to enumerate generator directory: %m");
+ log_error("Failed to enumerate generator directory %s: %m",
+ generator_path);
return;
}
unlink("/run/systemd/show-status");
}
-bool manager_get_show_status(Manager *m) {
+static bool manager_get_show_status(Manager *m) {
assert(m);
if (m->running_as != SYSTEMD_SYSTEM)
return plymouth_running();
}
+void manager_status_printf(Manager *m, bool ephemeral, const char *status, const char *format, ...) {
+ va_list ap;
+
+ if (!manager_get_show_status(m))
+ return;
+
+ if (!manager_is_booting_or_shutting_down(m))
+ return;
+
+ va_start(ap, format);
+ status_vprintf(status, true, ephemeral, format, ap);
+ va_end(ap);
+}
+
void watch_init(Watch *w) {
assert(w);