[systemd-devel] [RFC PATCH] condition: add ConditionFileContains=
Dave Reisner
d at falconindy.com
Thu Jul 11 10:37:36 PDT 2013
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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
More information about the systemd-devel
mailing list