chiark / gitweb /
unit: introduce 'banned' load state for units symlinked to /dev/null
authorLennart Poettering <lennart@poettering.net>
Fri, 8 Oct 2010 00:31:36 +0000 (02:31 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 8 Oct 2010 00:31:36 +0000 (02:31 +0200)
TODO
src/bus-errors.h
src/load-fragment.c
src/main.c
src/manager.c
src/path.c
src/systemctl.c
src/unit.c
src/unit.h
src/util.c
src/util.h

diff --git a/TODO b/TODO
index 47f060b..cdb4cc5 100644 (file)
--- a/TODO
+++ b/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?
 
index 2db1b77..8f5c4eb 100644 (file)
@@ -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"
index 1685c4a..54b1af0 100644 (file)
@@ -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:
index 6c65e64..d6f5c56 100644 (file)
@@ -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");
index 4ee04e1..26a631e 100644 (file)
@@ -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;
index 7a87124..92f9938 100644 (file)
@@ -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;
 }
 
index 918dcbe..4beec0f 100644 (file)
@@ -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
index 2f8b92d..d2652ba 100644 (file)
@@ -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);
index afae580..a020bd8 100644 (file)
@@ -62,6 +62,7 @@ enum UnitLoadState {
         UNIT_LOADED,
         UNIT_ERROR,
         UNIT_MERGED,
+        UNIT_BANNED,
         _UNIT_LOAD_STATE_MAX,
         _UNIT_LOAD_STATE_INVALID = -1
 };
index 85ee09d..12c19b3 100644 (file)
@@ -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",
index 8a510ae..2bf86d9 100644 (file)
@@ -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)