mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-07 16:58:21 +03:00
unit: introduce 'banned' load state for units symlinked to /dev/null
This commit is contained in:
parent
c2b3f093d9
commit
00dc5d769a
4
TODO
4
TODO
@ -1,5 +1,3 @@
|
||||
* do not throw error when .service file is linked to /dev/null
|
||||
|
||||
* oneshot services which do not remain: 'exited' instead of 'dead'?
|
||||
it should be visible in 'systemctl' that they have been run
|
||||
|
||||
@ -9,8 +7,6 @@
|
||||
|
||||
* implicitly import "defaults" settings file into all types
|
||||
|
||||
* "disabled" load state?
|
||||
|
||||
* ability to kill services? i.e. in contrast to stopping them, go directly
|
||||
into killing mode?
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#define BUS_ERROR_ONLY_BY_DEPENDENCY "org.freedesktop.systemd1.OnlyByDependency"
|
||||
#define BUS_ERROR_NO_ISOLATION "org.freedesktop.systemd1.NoIsolation"
|
||||
#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
|
||||
#define BUS_ERROR_BANNED "org.freedesktop.systemd1.Banned"
|
||||
#define BUS_ERROR_JOB_TYPE_NOT_APPLICABLE "org.freedesktop.systemd1.JobTypeNotApplicable"
|
||||
#define BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE "org.freedesktop.systemd1.TransactionIsDestructive"
|
||||
#define BUS_ERROR_TRANSACTION_JOBS_CONFLICTING "org.freedesktop.systemd1.TransactionJobsConflicting"
|
||||
|
@ -1883,9 +1883,15 @@ static int load_from_path(Unit *u, const char *path) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Now, parse the file contents */
|
||||
if ((r = config_parse(filename, f, sections, items, false, u)) < 0)
|
||||
goto finish;
|
||||
if (null_or_empty(&st))
|
||||
u->meta.load_state = UNIT_BANNED;
|
||||
else {
|
||||
/* Now, parse the file contents */
|
||||
if ((r = config_parse(filename, f, sections, items, false, u)) < 0)
|
||||
goto finish;
|
||||
|
||||
u->meta.load_state = UNIT_LOADED;
|
||||
}
|
||||
|
||||
free(u->meta.fragment_path);
|
||||
u->meta.fragment_path = filename;
|
||||
@ -1893,7 +1899,6 @@ static int load_from_path(Unit *u, const char *path) {
|
||||
|
||||
u->meta.fragment_mtime = timespec_load(&st.st_mtim);
|
||||
|
||||
u->meta.load_state = UNIT_LOADED;
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
|
11
src/main.c
11
src/main.c
@ -1060,8 +1060,10 @@ int main(int argc, char *argv[]) {
|
||||
if ((r = manager_load_unit(m, arg_default_unit, NULL, &error, &target)) < 0) {
|
||||
log_error("Failed to load default target: %s", bus_error(&error, r));
|
||||
dbus_error_free(&error);
|
||||
} else if (target->meta.load_state != UNIT_LOADED)
|
||||
} else if (target->meta.load_state == UNIT_ERROR)
|
||||
log_error("Failed to load default target: %s", strerror(-target->meta.load_error));
|
||||
else if (target->meta.load_state == UNIT_BANNED)
|
||||
log_error("Default target banned.");
|
||||
|
||||
if (!target || target->meta.load_state != UNIT_LOADED) {
|
||||
log_info("Trying to load rescue target...");
|
||||
@ -1070,12 +1072,17 @@ int main(int argc, char *argv[]) {
|
||||
log_error("Failed to load rescue target: %s", bus_error(&error, r));
|
||||
dbus_error_free(&error);
|
||||
goto finish;
|
||||
} else if (target->meta.load_state != UNIT_LOADED) {
|
||||
} else if (target->meta.load_state == UNIT_ERROR) {
|
||||
log_error("Failed to load rescue target: %s", strerror(-target->meta.load_error));
|
||||
goto finish;
|
||||
} else if (target->meta.load_state == UNIT_BANNED) {
|
||||
log_error("Rescue target banned.");
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
assert(target->meta.load_state == UNIT_LOADED);
|
||||
|
||||
if (arg_action == ACTION_TEST) {
|
||||
printf("-> By units:\n");
|
||||
manager_dump_units(m, stdout, "\t");
|
||||
|
@ -1398,18 +1398,27 @@ static int transaction_add_job_and_dependencies(
|
||||
assert(type < _JOB_TYPE_MAX);
|
||||
assert(unit);
|
||||
|
||||
if (unit->meta.load_state != UNIT_LOADED && unit->meta.load_state != UNIT_ERROR) {
|
||||
if (unit->meta.load_state != UNIT_LOADED &&
|
||||
unit->meta.load_state != UNIT_ERROR &&
|
||||
unit->meta.load_state != UNIT_BANNED) {
|
||||
dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->meta.id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type != JOB_STOP && unit->meta.load_state == UNIT_ERROR) {
|
||||
dbus_set_error(e, BUS_ERROR_LOAD_FAILED, "Unit %s failed to load: %s. You might find more information in the system logs.",
|
||||
dbus_set_error(e, BUS_ERROR_LOAD_FAILED,
|
||||
"Unit %s failed to load: %s. "
|
||||
"You might find more information in the system logs.",
|
||||
unit->meta.id,
|
||||
strerror(-unit->meta.load_error));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type != JOB_STOP && unit->meta.load_state == UNIT_BANNED) {
|
||||
dbus_set_error(e, BUS_ERROR_BANNED, "Unit %s is banned.", unit->meta.id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!unit_job_is_applicable(unit, type)) {
|
||||
dbus_set_error(e, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE, "Job type %s is not applicable for unit %s.", job_type_to_string(type), unit->meta.id);
|
||||
return -EBADR;
|
||||
|
@ -389,7 +389,8 @@ static int path_start(Unit *u) {
|
||||
return -ENOENT;
|
||||
|
||||
p->failure = false;
|
||||
path_enter_waiting(p, true);
|
||||
path_enter_waiting(p, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -297,7 +297,8 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
|
||||
if (!output_show_job(u))
|
||||
continue;
|
||||
|
||||
if (!streq(u->load_state, "loaded")) {
|
||||
if (!streq(u->load_state, "loaded") &&
|
||||
!streq(u->load_state, "banned")) {
|
||||
on_loaded = ansi_highlight(true);
|
||||
off_loaded = ansi_highlight(false);
|
||||
} else
|
||||
@ -1628,7 +1629,8 @@ static void print_status_info(UnitStatusInfo *i) {
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (streq_ptr(i->load_state, "failed")) {
|
||||
if (streq_ptr(i->load_state, "failed") ||
|
||||
streq_ptr(i->load_state, "banned")) {
|
||||
on = ansi_highlight(true);
|
||||
off = ansi_highlight(false);
|
||||
} else
|
||||
|
@ -2236,7 +2236,8 @@ static const char* const unit_load_state_table[_UNIT_LOAD_STATE_MAX] = {
|
||||
[UNIT_STUB] = "stub",
|
||||
[UNIT_LOADED] = "loaded",
|
||||
[UNIT_ERROR] = "error",
|
||||
[UNIT_MERGED] = "merged"
|
||||
[UNIT_MERGED] = "merged",
|
||||
[UNIT_BANNED] = "banned"
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(unit_load_state, UnitLoadState);
|
||||
|
@ -62,6 +62,7 @@ enum UnitLoadState {
|
||||
UNIT_LOADED,
|
||||
UNIT_ERROR,
|
||||
UNIT_MERGED,
|
||||
UNIT_BANNED,
|
||||
_UNIT_LOAD_STATE_MAX,
|
||||
_UNIT_LOAD_STATE_INVALID = -1
|
||||
};
|
||||
|
15
src/util.c
15
src/util.c
@ -3313,6 +3313,21 @@ void freeze(void) {
|
||||
pause();
|
||||
}
|
||||
|
||||
bool null_or_empty(struct stat *st) {
|
||||
assert(st);
|
||||
|
||||
if (S_ISREG(st->st_mode) && st->st_size <= 0)
|
||||
return true;
|
||||
|
||||
/* /dev/null has major/minor of 1:3 */
|
||||
if (S_ISCHR(st->st_mode) &&
|
||||
major(st->st_rdev) == 1 &&
|
||||
minor(st->st_rdev) == 3)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char *const ioprio_class_table[] = {
|
||||
[IOPRIO_CLASS_NONE] = "none",
|
||||
[IOPRIO_CLASS_RT] = "realtime",
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
@ -358,6 +359,8 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid);
|
||||
|
||||
_noreturn_ void freeze(void);
|
||||
|
||||
bool null_or_empty(struct stat *st);
|
||||
|
||||
#define NULSTR_FOREACH(i, l) \
|
||||
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user