On Thu, Jul 11, 2013 at 07:18:35PM +0200, Karol Lewandowski wrote: > 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, ':');
This is going to fail for a file:value pair such as /foo:/bar/baz:value. You could use strrchr(), but then you have to be concerned about matching values with a colon. > + 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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel