diff mbox series

[v2,2/2] hw compatibility check: add regexp support

Message ID 20190704100840.13013-3-mk@mkio.de
State Changes Requested
Headers show
Series [v2,1/2] swupdate: drop unnecessary strlen check | expand

Commit Message

Markus Klotzbuecher July 4, 2019, 10:08 a.m. UTC
From: Markus Klotzbuecher <markus.klotzbuecher@kistler.com>

This adds support for POSIX extended regular expressions for entries
of the sw-description hardware-compatibility list, which will be
matched against the actual hardware revision to determine
compatibility. To support simultaneous use of the existing literal
entries and regexp ones, the latter are identified using the prefix
"#RE:".

Signed-off-by: Markus Klotzbuecher <markus.klotzbuecher@kistler.com>
---
Changes for v2:
- Introduce "#RE:" prefix to distinguish literal from RE entries
- Drop CONFIG_HW_COMPATIBILITY_REGEXP
- Update docs

 core/util.c                   | 45 ++++++++++++++++++++++++++++++++++-
 doc/source/sw-description.rst | 37 ++++++++++++++++++----------
 include/util.h                |  3 +++
 3 files changed, 72 insertions(+), 13 deletions(-)

Comments

Stefan Herbrechtsmeier July 4, 2019, 6:10 p.m. UTC | #1
Hi Markus,


Am 04.07.19 um 12:08 schrieb Markus Klotzbuecher:
> From: Markus Klotzbuecher <markus.klotzbuecher@kistler.com>
> 
> This adds support for POSIX extended regular expressions for entries
> of the sw-description hardware-compatibility list, which will be
> matched against the actual hardware revision to determine
> compatibility. To support simultaneous use of the existing literal
> entries and regexp ones, the latter are identified using the prefix
> "#RE:".

Maybe we should enforce a stricter regex and detect a regex by a ^ as 
first and $ as last character.

> 
> Signed-off-by: Markus Klotzbuecher <markus.klotzbuecher@kistler.com>
> ---
> Changes for v2:
> - Introduce "#RE:" prefix to distinguish literal from RE entries
> - Drop CONFIG_HW_COMPATIBILITY_REGEXP
> - Update docs
> 
>   core/util.c                   | 45 ++++++++++++++++++++++++++++++++++-
>   doc/source/sw-description.rst | 37 ++++++++++++++++++----------
>   include/util.h                |  3 +++
>   3 files changed, 72 insertions(+), 13 deletions(-)
> 

[snip]

> --- a/doc/source/sw-description.rst
> +++ b/doc/source/sw-description.rst
> @@ -545,24 +545,37 @@ Each entry in sw-description can be redirect by a link as in the above example f
>   hardware-compatibility
>   ----------------------
>   
> -hardware-compatibility: [ "major.minor", "major.minor", ... ]
> +``hardware-compatibility: [ "major.minor", "major.minor", ... ]``
>   
> -It lists the hardware revisions that are compatible with this software image.
> +This entry lists the hardware revisions that are compatible with this
> +software image.
>   
>   Example:
>   
> +::
> +
>   	hardware-compatibility: [ "1.0", "1.2", "1.3"];
>   
> -This means that the software is compatible with HW-Revisions
> -1.0, 1.2 and 1.3, but not for 1.1 or other version not explicitly
> -listed here.
> -It is then duty of the single project to find which is the
> -revision of the board where SWUpdate is running. There is no
> -assumption how the revision can be obtained (GPIOs, EEPROM,..)
> -and each project is free to select the way most appropriate.
> -The result must be written in the file /etc/hwrevision (or in
> -another file if specified as configuration option) before
> -SWUpdate is started.
> +This defines that the software is compatible with HW-Revisions 1.0,
> +1.2 and 1.3, but not with 1.1 or any other version not explicitly
> +listed here. In the above example, compatibility is checked by means
> +of string comparision. If the software is compatible with a large
> +number of hardware revisions, it may get cumbersome to enumerate all
> +compatible versions. To allow more compact specifications, regular
> +expressions (POSIX extended) can be used by adding a prefix ``#RE:``
> +to the entry. Rewriting the above example would yield:
> +
> +::
> +
> +	hardware-compatibility: [ "#RE:1\.[023]" ];

Doesn't this also match 1.1.1 or 2.1.0?

> +
> +It is in the responsibility of the respective project to find the
> +revision of the board on which SWUpdate is running. No assumptions are
> +made about how the revision can be obtained (GPIOs, EEPROM,..) and
> +each project is free to select the most appropriate way. In the end
> +the result must be written to the file ``/etc/hwrevision`` (or in
> +another file if specified as configuration option) before SWUpdate is
> +started.
>   
>   .. _partitions-ubi-layout:
>   

Regards
   Stefan
Markus Klotzbuecher July 8, 2019, 5:11 a.m. UTC | #2
Hi Stefan

On Thu, Jul 04, 2019 at 08:10:12PM +0200, Stefan Herbrechtsmeier wrote:
>
>Am 04.07.19 um 12:08 schrieb Markus Klotzbuecher:
>> From: Markus Klotzbuecher <markus.klotzbuecher@kistler.com>
>> 
>> This adds support for POSIX extended regular expressions for entries
>> of the sw-description hardware-compatibility list, which will be
>> matched against the actual hardware revision to determine
>> compatibility. To support simultaneous use of the existing literal
>> entries and regexp ones, the latter are identified using the prefix
>> "#RE:".
>
>Maybe we should enforce a stricter regex and detect a regex by a ^ as first
>and $ as last character.

That would also be an option.

>> Signed-off-by: Markus Klotzbuecher <markus.klotzbuecher@kistler.com>
>> ---
>> Changes for v2:
>> - Introduce "#RE:" prefix to distinguish literal from RE entries
>> - Drop CONFIG_HW_COMPATIBILITY_REGEXP
>> - Update docs
>> 
>>   core/util.c                   | 45 ++++++++++++++++++++++++++++++++++-
>>   doc/source/sw-description.rst | 37 ++++++++++++++++++----------
>>   include/util.h                |  3 +++
>>   3 files changed, 72 insertions(+), 13 deletions(-)
>> 
>
>[snip]
>
>> --- a/doc/source/sw-description.rst
>> +++ b/doc/source/sw-description.rst
>> @@ -545,24 +545,37 @@ Each entry in sw-description can be redirect by a link as in the above example f
>>   hardware-compatibility
>>   ----------------------
>> -hardware-compatibility: [ "major.minor", "major.minor", ... ]
>> +``hardware-compatibility: [ "major.minor", "major.minor", ... ]``
>> -It lists the hardware revisions that are compatible with this software image.
>> +This entry lists the hardware revisions that are compatible with this
>> +software image.
>>   Example:
>> +::
>> +
>>   	hardware-compatibility: [ "1.0", "1.2", "1.3"];
>> -This means that the software is compatible with HW-Revisions
>> -1.0, 1.2 and 1.3, but not for 1.1 or other version not explicitly
>> -listed here.
>> -It is then duty of the single project to find which is the
>> -revision of the board where SWUpdate is running. There is no
>> -assumption how the revision can be obtained (GPIOs, EEPROM,..)
>> -and each project is free to select the way most appropriate.
>> -The result must be written in the file /etc/hwrevision (or in
>> -another file if specified as configuration option) before
>> -SWUpdate is started.
>> +This defines that the software is compatible with HW-Revisions 1.0,
>> +1.2 and 1.3, but not with 1.1 or any other version not explicitly
>> +listed here. In the above example, compatibility is checked by means
>> +of string comparision. If the software is compatible with a large
>> +number of hardware revisions, it may get cumbersome to enumerate all
>> +compatible versions. To allow more compact specifications, regular
>> +expressions (POSIX extended) can be used by adding a prefix ``#RE:``
>> +to the entry. Rewriting the above example would yield:
>> +
>> +::
>> +
>> +	hardware-compatibility: [ "#RE:1\.[023]" ];
>
>Doesn't this also match 1.1.1 or 2.1.0?

Yes, you are correct, to prevent that it shoud use ^ and $. I will
update this.

I've thought about the idea of using ^ and $ for detecting the regexp
itself. Indeed the majority of the cases should probably use these
symbols to prevent accidential mismatches. Still, I prefer the more
explicit '#RE:' since it doesn't exclude the possibility to use a
regexp without start and end detection. I also find it somewhat easier
to detect (visually) in the file.

>> +It is in the responsibility of the respective project to find the
>> +revision of the board on which SWUpdate is running. No assumptions are
>> +made about how the revision can be obtained (GPIOs, EEPROM,..) and
>> +each project is free to select the most appropriate way. In the end
>> +the result must be written to the file ``/etc/hwrevision`` (or in
>> +another file if specified as configuration option) before SWUpdate is
>> +started.
>>   .. _partitions-ubi-layout:
>

Thank you for your comments!

Best regards
Markus
diff mbox series

Patch

diff --git a/core/util.c b/core/util.c
index 5724b4c..dc4f4af 100644
--- a/core/util.c
+++ b/core/util.c
@@ -22,6 +22,7 @@ 
 #include <limits.h>
 #include <time.h>
 #include <libgen.h>
+#include <regex.h>
 
 #include "swupdate.h"
 #include "util.h"
@@ -281,6 +282,47 @@  int get_hw_revision(struct hw_type *hw)
 	return 0;
 }
 
+/**
+ * hwid_match - try to match a literal or RE hwid
+ * @rev: literal or RE specification
+ * @hwrev: current HW revision
+ *
+ * Return: 0 if match found, non-zero otherwise
+ */
+int hwid_match(const char* rev, const char* hwrev)
+{
+	int ret, prefix_len;
+	char errbuf[256];
+	regex_t re;
+	const char *re_str;
+
+	prefix_len = strlen(HWID_REGEXP_PREFIX);
+
+	/* literal revision */
+	if (strncmp(rev, HWID_REGEXP_PREFIX, prefix_len)) {
+		ret = strcmp(rev, hwrev);
+		goto out;
+	}
+
+	/* regexp revision */
+	re_str = rev+prefix_len;
+
+	if ((ret = regcomp(&re, re_str, REG_EXTENDED|REG_NOSUB)) != 0) {
+		regerror(ret, &re, errbuf, sizeof(errbuf));
+		ERROR("error in regexp %s: %s", re_str, errbuf);
+		goto out;
+	}
+
+	if ((ret = regexec(&re, hwrev, 0, NULL, 0)) == 0)
+		TRACE("hwrev %s matched by regexp %s", hwrev, re_str);
+	else
+		TRACE("no match of hwrev %s with regexp %s", hwrev, re_str);
+
+	regfree(&re);
+out:
+	return ret;
+}
+
 /*
  * The HW revision of the board *MUST* be inserted
  * in the sw-description file
@@ -297,7 +339,8 @@  int check_hw_compatibility(struct swupdate_cfg *cfg)
 
 	TRACE("Hardware %s Revision: %s", cfg->hw.boardname, cfg->hw.revision);
 	LIST_FOREACH(hw, &cfg->hardware, next) {
-		if (hw && (!strcmp(hw->revision, cfg->hw.revision))) {
+		if (hw &&
+		    (!hwid_match(hw->revision, cfg->hw.revision))) {
 			TRACE("Hardware compatibility verified");
 			return 0;
 		}
diff --git a/doc/source/sw-description.rst b/doc/source/sw-description.rst
index 0b25e50..77786e5 100644
--- a/doc/source/sw-description.rst
+++ b/doc/source/sw-description.rst
@@ -545,24 +545,37 @@  Each entry in sw-description can be redirect by a link as in the above example f
 hardware-compatibility
 ----------------------
 
-hardware-compatibility: [ "major.minor", "major.minor", ... ]
+``hardware-compatibility: [ "major.minor", "major.minor", ... ]``
 
-It lists the hardware revisions that are compatible with this software image.
+This entry lists the hardware revisions that are compatible with this
+software image.
 
 Example:
 
+::
+
 	hardware-compatibility: [ "1.0", "1.2", "1.3"];
 
-This means that the software is compatible with HW-Revisions
-1.0, 1.2 and 1.3, but not for 1.1 or other version not explicitly
-listed here.
-It is then duty of the single project to find which is the
-revision of the board where SWUpdate is running. There is no
-assumption how the revision can be obtained (GPIOs, EEPROM,..)
-and each project is free to select the way most appropriate.
-The result must be written in the file /etc/hwrevision (or in
-another file if specified as configuration option) before
-SWUpdate is started.
+This defines that the software is compatible with HW-Revisions 1.0,
+1.2 and 1.3, but not with 1.1 or any other version not explicitly
+listed here. In the above example, compatibility is checked by means
+of string comparision. If the software is compatible with a large
+number of hardware revisions, it may get cumbersome to enumerate all
+compatible versions. To allow more compact specifications, regular
+expressions (POSIX extended) can be used by adding a prefix ``#RE:``
+to the entry. Rewriting the above example would yield:
+
+::
+
+	hardware-compatibility: [ "#RE:1\.[023]" ];
+
+It is in the responsibility of the respective project to find the
+revision of the board on which SWUpdate is running. No assumptions are
+made about how the revision can be obtained (GPIOs, EEPROM,..) and
+each project is free to select the most appropriate way. In the end
+the result must be written to the file ``/etc/hwrevision`` (or in
+another file if specified as configuration option) before SWUpdate is
+started.
 
 .. _partitions-ubi-layout:
 
diff --git a/include/util.h b/include/util.h
index 4c261ed..a4edbef 100644
--- a/include/util.h
+++ b/include/util.h
@@ -23,6 +23,8 @@ 
 #define SWUPDATE_SHA_DIGEST_LENGTH	20
 #define AES_BLOCK_SIZE	16
 
+#define HWID_REGEXP_PREFIX	"#RE:"
+
 extern int loglevel;
 
 typedef enum {
@@ -186,6 +188,7 @@  void freeargs (char **argv);
 int get_hw_revision(struct hw_type *hw);
 void get_sw_versions(char *cfgfname, struct swupdate_cfg *sw);
 __u64 version_to_number(const char *version_string);
+int hwid_match(const char* rev, const char* hwrev);
 int check_hw_compatibility(struct swupdate_cfg *cfg);
 int count_elem_list(struct imglist *list);
 unsigned int count_string_array(const char **nodes);