[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