Add ability to test if given file contains specified value.
File and expected value are given as one argument separated
by colon (":"), i.e.

  ConditionFileContains=/sys/module/sn/parameters/enabled:1

---
As above example suggests we use it to conditionally
start service based on kernel module parameter value.
This can be (ab)used for other/regular files too.

RFC

Thanks!
---
 man/systemd.unit.xml                  |    8 ++++++++
 src/core/condition.c                  |   34 +++++++++++++++++++++++++++++++++
 src/core/condition.h                  |    1 +
 src/core/load-fragment-gperf.gperf.m4 |    1 +
 4 files changed, 44 insertions(+)

diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 4f0bd64..d26bd23 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -841,6 +841,7 @@
                                 
<term><varname>ConditionDirectoryNotEmpty=</varname></term>
                                 
<term><varname>ConditionFileNotEmpty=</varname></term>
                                 
<term><varname>ConditionFileIsExecutable=</varname></term>
+                                
<term><varname>ConditionFileContains=</varname></term>
                                 
<term><varname>ConditionKernelCommandLine=</varname></term>
                                 
<term><varname>ConditionVirtualization=</varname></term>
                                 
<term><varname>ConditionSecurity=</varname></term>
@@ -932,6 +933,13 @@
                                 exists, is a regular file and marked
                                 executable.</para>
 
+                                <para><varname>ConditionFileContains=</varname>
+                                may be used to check whether a given
+                                file contains specified value.  The
+                                argument consists of file path to be
+                                tested, separator (":"), and the
+                                expected value.</para>
+
                                 <para>Similar,
                                 <varname>ConditionKernelCommandLine=</varname>
                                 may be used to check whether a
diff --git a/src/core/condition.c b/src/core/condition.c
index 427aa08..7c62d11 100644
--- a/src/core/condition.c
+++ b/src/core/condition.c
@@ -124,6 +124,36 @@ static bool test_kernel_command_line(const char 
*parameter) {
         return found;
 }
 
+static bool test_file_contains(const char *parameter) {
+        int r;
+        char *p;
+        _cleanup_free_ char *path = NULL;
+        _cleanup_free_ char *line = NULL;
+
+        assert(parameter);
+
+        path = strdup(parameter);
+        if (!path) {
+                log_oom();
+                return false;
+        }
+
+        p = strchr(path, ':');
+        if (!p)
+                return false;
+
+        *(p++) = '\0';
+
+        r = read_one_line_file(path, &line);
+
+        if (r < 0) {
+                log_warning("Failed to read %s, ignoring: %s", path, 
strerror(-r));
+                return false;
+        }
+
+        return !!streq(line, p);
+}
+
 static bool test_virtualization(const char *parameter) {
         int b;
         Virtualization v;
@@ -307,6 +337,9 @@ bool condition_test(Condition *c) {
                 return (S_ISREG(st.st_mode) && (st.st_mode & 0111)) == 
!c->negate;
         }
 
+        case CONDITION_FILE_CONTAINS:
+                return test_file_contains(c->parameter) == !c->negate;
+
         case CONDITION_KERNEL_COMMAND_LINE:
                 return test_kernel_command_line(c->parameter) == !c->negate;
 
@@ -392,6 +425,7 @@ static const char* const 
condition_type_table[_CONDITION_TYPE_MAX] = {
         [CONDITION_DIRECTORY_NOT_EMPTY] = "ConditionDirectoryNotEmpty",
         [CONDITION_FILE_NOT_EMPTY] = "ConditionFileNotEmpty",
         [CONDITION_FILE_IS_EXECUTABLE] = "ConditionFileIsExecutable",
+        [CONDITION_FILE_CONTAINS] = "ConditionFileContains",
         [CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
         [CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
         [CONDITION_SECURITY] = "ConditionSecurity",
diff --git a/src/core/condition.h b/src/core/condition.h
index 50ed955..2bf26bd 100644
--- a/src/core/condition.h
+++ b/src/core/condition.h
@@ -35,6 +35,7 @@ typedef enum ConditionType {
         CONDITION_DIRECTORY_NOT_EMPTY,
         CONDITION_FILE_NOT_EMPTY,
         CONDITION_FILE_IS_EXECUTABLE,
+        CONDITION_FILE_CONTAINS,
         CONDITION_KERNEL_COMMAND_LINE,
         CONDITION_VIRTUALIZATION,
         CONDITION_SECURITY,
diff --git a/src/core/load-fragment-gperf.gperf.m4 
b/src/core/load-fragment-gperf.gperf.m4
index 2325d6a..310e1c5 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -134,6 +134,7 @@ Unit.ConditionPathIsReadWrite,   
config_parse_unit_condition_path,   CONDITION_P
 Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path,   
CONDITION_DIRECTORY_NOT_EMPTY, 0
 Unit.ConditionFileNotEmpty,      config_parse_unit_condition_path,   
CONDITION_FILE_NOT_EMPTY,      0
 Unit.ConditionFileIsExecutable,  config_parse_unit_condition_path,   
CONDITION_FILE_IS_EXECUTABLE,  0
+Unit.ConditionFileContains,      config_parse_unit_condition_string, 
CONDITION_FILE_CONTAINS,       0
 Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, 
CONDITION_KERNEL_COMMAND_LINE, 0
 Unit.ConditionVirtualization,    config_parse_unit_condition_string, 
CONDITION_VIRTUALIZATION,      0
 Unit.ConditionSecurity,          config_parse_unit_condition_string, 
CONDITION_SECURITY,            0
-- 
1.7.10.4

_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to