[git] GPG-ERROR - branch, master, updated. libgpg-error-1.32-55-ga5d4a4b

by Werner Koch cvs at cvs.gnupg.org
Thu Nov 15 19:30:10 CET 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Error codes used by GnuPG et al.".

The branch, master has been updated
       via  a5d4a4b32b11814d673241d62624ecec1d577571 (commit)
      from  4a92763a6e529824f1c6043b75ac1346af41a926 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a5d4a4b32b11814d673241d62624ecec1d577571
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Nov 15 19:18:53 2018 +0100

    core: New API gpgrt_cmp_version
    
    * src/gpg-error.h.in: New API gpgrt_cmp_version.
    * src/visibility.c (gpgrt_cmp_version): New wrapper.
    * src/version.c (parse_version_string): Revamped.
    (do_cmp_version): New.
    (_gpgrt_cmp_version): New.
    (_gpg_error_check_version): Re-implemented using the new func.
    * tests/t-version.c: Include t-common.h.
    (t_gpgrt_cmp_version): New test.
    (main): Run new test.  Change test for new version number to require a
    2 level number.
    --
    
    We have implementations of very similar functions in all out libs.
    Thus it makes sense to provide a generic version.  This version is
    actually derived from the ftp-indexer.c we use for the gnupg
    website (see the gnupg-doc repo).
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/Makefile.am b/Makefile.am
index b602c7f..4991911 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,6 +15,7 @@
 #
 # You should have received a copy of the GNU Lesser General Public
 # License along with this program; if not, see <https://www.gnu.org/licenses/>.
+# SPDX-License-Identifier: LGPL-2.1-or-later
 
 # Location of the released tarball archives.  Note that this is an
 # internal archive and before uploading this to the public server,
diff --git a/NEWS b/NEWS
index 8c605b2..f1facf4 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,11 @@ Noteworthy changes in version 1.33 (unreleased) [C24/A24/R_]
 -----------------------------------------------
 
 
+ * Interface changes relative to the 1.28 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ gpgrt_cmp_version               New.
+
+
 Noteworthy changes in version 1.32 (2018-07-12) [C24/A24/R3]
 -----------------------------------------------
 
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in
index 67bb12e..c2fabb0 100644
--- a/src/gpg-error.def.in
+++ b/src/gpg-error.def.in
@@ -218,5 +218,7 @@ EXPORTS
  gpgrt_b64enc_write           @167
  gpgrt_b64enc_finish          @168
 
+ gpgrt_cmp_version            @169
+
 
 ;; end of file with public symbols for Windows.
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index 8bcafcc..2bf6a6f 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -1271,6 +1271,15 @@ void gpgrt_set_strusage (const char *(*f)(int));
 void gpgrt_set_usage_outfnc (int (*f)(int, const char *));
 void gpgrt_set_fixed_string_mapper (const char *(*f)(const char*));
 
+

+/*
+ * Various helper functions
+ */
+
+/* Compare arbitrary version strings.  For the standard m.n.o version
+ * numbering scheme a LEVEL of 3 is suitable; see the manual.  */
+int gpgrt_cmp_version (const char *a, const char *b, int level);
+
 
 
 #ifdef __cplusplus
diff --git a/src/gpg-error.vers b/src/gpg-error.vers
index 201b784..8c50a15 100644
--- a/src/gpg-error.vers
+++ b/src/gpg-error.vers
@@ -190,6 +190,7 @@ GPG_ERROR_1.0 {
     gpgrt_b64enc_write;
     gpgrt_b64enc_finish;
 
+    gpgrt_cmp_version;
 
   local:
     *;
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index 34e494c..b5a4dd1 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -742,6 +742,12 @@ void _gpgrt_set_usage_outfnc (int (*fnc)(int, const char *));
 void _gpgrt_set_fixed_string_mapper (const char *(*f)(const char*));
 
 
+/*
+ * Various helper functions
+ */
+int _gpgrt_cmp_version (const char *a, const char *b, int level);
+
+
 

 /*
  * Internal platform abstraction functions (sysutils.c)
diff --git a/src/version.c b/src/version.c
index 94b75af..ac2f057 100644
--- a/src/version.c
+++ b/src/version.c
@@ -47,6 +47,10 @@ cright_blurb (void)
 }
 
 
+/* This function parses the first portion of the version number S and
+ * stores it at NUMBER.  On success, this function returns a pointer
+ * into S starting with the first character, which is not part of the
+ * initial number portion; on failure, NULL is returned.  */
 static const char*
 parse_version_number (const char *s, int *number)
 {
@@ -64,45 +68,161 @@ parse_version_number (const char *s, int *number)
 }
 
 
+/* This function breaks up the complete string-representation of the
+ * version number S, which is of the following struture: <major
+ * number>.<minor number>.<micro number><patch level>.  The major,
+ * minor and micro number components will be stored in *MAJOR, *MINOR
+ * and *MICRO.  If MINOR or MICRO is NULL the version number is
+ * assumed to have just 1 respective 2 parts.
+ *
+ * On success, the last component, the patch level, will be returned;
+ * in failure, NULL will be returned.  */
 static const char *
-parse_version_string (const char *s, int *major, int *minor)
+parse_version_string (const char *s, int *major, int *minor, int *micro)
 {
   s = parse_version_number (s, major);
-  if (!s || *s != '.')
-    return NULL;
-  s++;
-  s = parse_version_number (s, minor);
   if (!s)
     return NULL;
-  return s;  /* Patchlevel.  */
+  if (!minor)
+    {
+      if (*s == '.')
+        s++;
+    }
+  else
+    {
+      if (*s != '.')
+        return NULL;
+      s++;
+      s = parse_version_number (s, minor);
+      if (!s)
+        return NULL;
+      if (!micro)
+        {
+          if (*s == '.')
+            s++;
+        }
+      else
+        {
+          if (*s != '.')
+            return NULL;
+          s++;
+          s = parse_version_number (s, micro);
+          if (!s)
+            return NULL;
+        }
+    }
+  return s; /* patchlevel */
 }
 
 
-static const char *
-compare_versions (const char *my_version, const char *req_version)
+/* Helper for _gpgrt_cmp_version.  */
+static int
+do_cmp_version (const char *a, const char *b, int level)
 {
-  int my_major, my_minor;
-  int rq_major, rq_minor;
-  const char *my_plvl, *rq_plvl;
+  int a_major, a_minor, a_micro;
+  int b_major, b_minor, b_micro;
+  const char *a_plvl, *b_plvl;
+  int r;
+  int ignore_plvl;
+  int positive, negative;
+
+  if (level < 0)
+    {
+      positive = -1;
+      negative = 1;
+      level = 0 - level;
+    }
+  else
+    {
+      positive = 1;
+      negative = -1;
+    }
+  if ((ignore_plvl = (level > 9)))
+    level %= 10;
+
+  a_major = a_minor = a_micro = 0;
+  a_plvl = parse_version_string (a, &a_major,
+                                 level > 1? &a_minor : NULL,
+                                 level > 2? &a_micro : NULL);
+  if (!a_plvl)
+    a_major = a_minor = a_micro = 0; /* Error.  */
+
+  b_major = b_minor = b_micro = 0;
+  b_plvl = parse_version_string (b, &b_major,
+                                 level > 1? &b_minor : NULL,
+                                 level > 2? &b_micro : NULL);
+  if (!b_plvl)
+    b_major = b_minor = b_micro = 0;
+
+  if (!ignore_plvl)
+    {
+      if (!a_plvl && !b_plvl)
+        return negative;  /* Put invalid strings at the end.  */
+      if (a_plvl && !b_plvl)
+        return positive;
+      if (!a_plvl && b_plvl)
+        return negative;
+    }
 
-  if (!req_version)
-    return my_version;
-  if (!my_version)
-    return NULL;
+  if (a_major > b_major)
+    return positive;
+  if (a_major < b_major)
+    return negative;
+
+  if (a_minor > b_minor)
+    return positive;
+  if (a_minor < b_minor)
+    return negative;
+
+  if (a_micro > b_micro)
+    return positive;
+  if (a_micro < b_micro)
+    return negative;
 
-  my_plvl = parse_version_string (my_version, &my_major, &my_minor);
-  if (!my_plvl)
-    return NULL;	/* Very strange: our own version is bogus.  */
-  rq_plvl = parse_version_string(req_version, &rq_major, &rq_minor);
-  if (!rq_plvl)
-    return NULL;	/* Requested version string is invalid.  */
+  if (ignore_plvl)
+    return 0;
 
-  if (my_major > rq_major
-      || (my_major == rq_major && my_minor >= rq_minor))
+  for (; *a_plvl && *b_plvl; a_plvl++, b_plvl++)
     {
-      return my_version;
-    }
-  return NULL;
+      if (*a_plvl == '.' && *b_plvl == '.')
+        {
+          r = strcmp (a_plvl, b_plvl);
+          if (!r)
+            return 0;
+          else if ( r > 0 )
+            return positive;
+          else
+            return negative;
+        }
+      else if (*a_plvl == '.')
+        return negative; /* B is larger. */
+      else if (*b_plvl == '.')
+        return positive; /* A is larger. */
+      else if (*a_plvl != *b_plvl)
+        break;
+        }
+  if (*a_plvl == *b_plvl)
+    return 0;
+  else if ((*(signed char *)a_plvl - *(signed char *)b_plvl) > 0)
+    return positive;
+  else
+    return negative;
+}
+
+
+/* Compare function for version strings.  The return value is
+ * like strcmp().  LEVEL may be
+ *   0 - reserved
+ *   1 - format is "<major><patchlevel>".
+ *   2 - format is "<major>.<minor><patchlevel>".
+ *   3 - format is "<major>.<minor>.<micro><patchlevel>".
+ * To ignore the patchlevel in the comparison add 10 to LEVEL.  To get
+ * a reverse sorting order use a negative number.
+ */
+int
+_gpgrt_cmp_version (const char *a, const char *b, int level)
+{
+  return do_cmp_version (a, b, level);
 }
 
 
@@ -115,7 +235,12 @@ compare_versions (const char *my_version, const char *req_version)
 const char *
 _gpg_error_check_version (const char *req_version)
 {
+  const char *my_version = PACKAGE_VERSION;
+
   if (req_version && req_version[0] == 1 && req_version[1] == 1)
     return cright_blurb ();
-  return compare_versions (PACKAGE_VERSION, req_version);
+  if (!req_version)
+    return my_version;
+  return _gpgrt_cmp_version
+    (my_version, req_version, 12) >= 0 ? my_version : NULL;
 }
diff --git a/src/visibility.c b/src/visibility.c
index 6f8bb24..ab5e383 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1123,6 +1123,15 @@ gpgrt_set_fixed_string_mapper (const char *(*f)(const char*))
 
 
 

+/* Compare program versions.  */
+int
+gpgrt_cmp_version (const char *a, const char *b, int level)
+{
+  return _gpgrt_cmp_version (a, b, level);
+}
+
+
+

 /* For consistency reasons we use function wrappers also for Windows
  * specific function despite that they are technically not needed.  */
 #ifdef HAVE_W32_SYSTEM
diff --git a/src/visibility.h b/src/visibility.h
index cfa32e5..d6933df 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -209,6 +209,8 @@ MARK_VISIBLE (gpgrt_set_strusage)
 MARK_VISIBLE (gpgrt_set_fixed_string_mapper);
 MARK_VISIBLE (gpgrt_set_usage_outfnc);
 
+MARK_VISIBLE (gpgrt_cmp_version);
+
 #undef MARK_VISIBLE
 
 #else /*!_GPGRT_INCL_BY_VISIBILITY_C*/
@@ -379,6 +381,8 @@ MARK_VISIBLE (gpgrt_set_usage_outfnc);
 #define gpgrt_set_usage_outfnc        _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_set_fixed_string_mapper _gpgrt_USE_UNDERSCORED_FUNCTION
 
+#define gpgrt_cmp_version           _gpgrt_USE_UNDERSCORED_FUNCTION
+
 /* Windows specific functions.  */
 #define gpgrt_w32_reg_query_string  _gpgrt_USE_UNDERSCORED_FUNCTION
 
diff --git a/tests/t-version.c b/tests/t-version.c
index 4606dbc..240d4b4 100644
--- a/tests/t-version.c
+++ b/tests/t-version.c
@@ -26,12 +26,90 @@
 #include <string.h>
 #include <assert.h>
 
-#include "../src/gpg-error.h"
+#define PGM "t-version"
+#include "t-common.h"
+
+static const char *logpfx = PGM;
+
+
+static void
+t_gpgrt_cmp_version (void)
+{
+  struct { int result; int level; const char *a; const char *b; } t[] = {
+    {  0, 1, "0", "0" },
+    { -1, 1, "0", "1" },
+    {  1, 1, "1", "0" },
+    { -1, 1, "0.0", "0.1" },
+    { -1, 1, "0.1", "1.2" },
+    {  1, 1, "1.0", "0.9" },
+    { -1, 1, "-1.0", "0.9" }, /* A is invalid */
+    {  0, 1, "0rc0", "0rc0" },
+    {  1, 1, "0rc1", "0rc0" },
+    { -1, 1, "0rc1", "0rc2" },
+    {  0, 1, "0.rc0", "0.rc0" },
+    {  1, 1, "0.rc1", "0.rc0" },
+    { -1, 1, "0.rc1", "0.rc2" },
+    {  0, 1, "0.rc1", "0.rc1" },
+    { -1, 1, "0qc1",  "0rc0" },
+    { -1, 1, "0.qc1", "0.rc0" },
+    {  0, 2, "0.0", "0.0" },
+    { -1, 2, "0.1", "0.2" },
+    { -1, 2, "3.1", "3.2" },
+    { -1, 2, "3.1", "4.0" },
+    {  0, 2, "1.1rc0", "1.1rc0" },
+    {  1, 2, "1.1rc1", "1.1rc0" },
+    { -1, 2, "1.1rc0", "1.1rc1" },
+    {  0, 3, "7.0.0", "7.0.0" },
+    { -1, 3, "7.0.1", "7.0.2" },
+    { -1, 3, "7.3.1", "7.3.2" },
+    { -1, 3, "7.3.1", "7.4.0" },
+    {  0, 3, "7.1.1rc0", "7.1.1rc0" },
+    {  1, 3, "7.1.1rc1", "7.1.1rc0" },
+    { -1, 3, "7.1.1rc0", "7.1.1rc1" },
+    {  1, 3, "6.0.0", "5.0.0" },
+    {  0, 3, "6.0.0", "6.0.0" },
+    {  1, 3, "6.0.1", "6.0.0" },
+    {  1, 3, "6.1.0", "6.0.0" },
+    {  1, 3, "6.2.1", "6.2.0" },
+    { -1, 3, "6.2.1", "6.2.2" },
+    { -1, 3, "6.0.0", "6.0.2" },
+    { -1, 3, "6.0.0", "6.1.0" },
+    { -1, 3, "6.2.0", "6.2.1" },
+    {  1, 3, "6.0.0-beta1", "6.0.0-beta0" },
+    {  0, 3, "6.0.0-beta2", "6.0.0-beta2" },
+    {  1, 3, "6.0.0-beta20", "6.0.0-beta19" },
+    { -1, 3, "6.0.0-beta1", "6.0.0-beta2" },
+    {  1, 3, "6.0.0-beta2", "6.0.0-beta1" },
+    { -1, 3, "6.0.0-beta20", "6.0.0-beta21" },
+    {  0,13, "6.0.0-beta1", "6.0.0-beta0" },
+    {  0,13, "6.0.0-beta2", "6.0.0-beta2" },
+    {  0,13, "6.0.0-beta20", "6.0.0-beta19" },
+    {  0,13, "6.0.0-beta1", "6.0.0-beta2" },
+    {  0,13, "6.0.0-beta2", "6.0.0-beta1" },
+    {  0,13, "6.0.0-beta20", "6.0.0-beta21" }
+  };
+  int i;
+  int result, expected;
+
+  for (i=0; i < DIM (t); i++)
+    {
+      expected = t[i].result;
+      result = gpgrt_cmp_version (t[i].a, t[i].b, t[i].level);
+      if (result != expected)
+        fail ("test %d failed: cmp('%s','%s',%d) = %d expected %d",
+              i, t[i].a, t[i].b, t[i].level, result, expected);
+    }
+  for (i=0; i < DIM (t); i++)
+    {
+      expected = 0 - t[i].result;
+      result = gpgrt_cmp_version (t[i].a, t[i].b, -t[i].level);
+      if (result != expected)
+        fail ("test %d-rev failed: cmp('%s','%s',%d) = %d expected %d",
+              i, t[i].a, t[i].b, -t[i].level, result, expected);
+    }
+}
+
 
-static const char *logpfx = "";
-static int verbose;
-static int debug;
-static int errorcount;
 
 int
 main (int argc, char **argv)
@@ -40,7 +118,6 @@ main (int argc, char **argv)
 
   if (argc)
     {
-      logpfx = *argv;
       argc--; argv++;
     }
   while (argc && last_argc != argc )
@@ -68,6 +145,8 @@ main (int argc, char **argv)
         }
     }
 
+  t_gpgrt_cmp_version ();
+
   if (!gpg_error_check_version (GPG_ERROR_VERSION))
     {
       fprintf (stderr, "%s: gpg_error_check_version returned an error\n",
@@ -80,7 +159,7 @@ main (int argc, char **argv)
                "error for an old version\n", logpfx);
       errorcount++;
     }
-  if (gpg_error_check_version ("15"))
+  if (gpg_error_check_version ("15.0"))
     {
       fprintf (stderr, "%s: gpg_error_check_version did not return an error"
                " for a newer version\n", logpfx);

-----------------------------------------------------------------------

Summary of changes:
 Makefile.am          |   1 +
 NEWS                 |   5 ++
 src/gpg-error.def.in |   2 +
 src/gpg-error.h.in   |   9 +++
 src/gpg-error.vers   |   1 +
 src/gpgrt-int.h      |   6 ++
 src/version.c        | 179 +++++++++++++++++++++++++++++++++++++++++++--------
 src/visibility.c     |   9 +++
 src/visibility.h     |   4 ++
 tests/t-version.c    |  93 ++++++++++++++++++++++++--
 10 files changed, 275 insertions(+), 34 deletions(-)


hooks/post-receive
-- 
Error codes used by GnuPG et al.
http://git.gnupg.org




More information about the Gnupg-commits mailing list