doc/
authorMarcus Brinkmann <mb@g10code.com>
Thu, 28 May 2009 15:16:01 +0000 (15:16 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Thu, 28 May 2009 15:16:01 +0000 (15:16 +0000)
2009-05-28  Marcus Brinkmann  <marcus@g10code.de>

* gpgme.texi (Library Version Check): Document selftest error.
(Creating Contexts): Likewise.

src/
2009-05-28  Marcus Brinkmann  <marcus@g10code.de>

* gpgme.h.in (gpgme_check_version_internal): New prototype.
(gpgme_check_version): New macro, overriding function of the same
name.
* libgpgme.vers, gpgme.def: Add gpgme_check_version_internal.o
* context.h (_gpgme_selftest): New variable declaration.
* version.c: Include "context.h".
(gpgme_check_version): Set _gpgme_selftest on success.
(gpgme_check_version_internal): New function.
* gpgme.c (_gpgme_selftest): Define it.
(gpgme_new): Check the selftest result.

trunk/NEWS
trunk/doc/ChangeLog
trunk/doc/gpgme.texi
trunk/src/ChangeLog
trunk/src/context.h
trunk/src/gpgme.c
trunk/src/gpgme.def
trunk/src/gpgme.h.in
trunk/src/libgpgme.vers
trunk/src/version.c

index f4c390988af971cb6f9a89d5a29320a2cd506af7..55288b4ef4d97456fd63f12dece0fda13ff2829d 100644 (file)
@@ -4,6 +4,10 @@ Noteworthy changes in version 1.1.9
  * New encryption flag GPGME_ENCRYPT_NO_ENCRYPT_TO to disable default
    recipients.
 
+ * gpgme_new will fail if gpgme_check_version was not called, or a
+   selftest failed (for example, if -mms-bitfields was not used on
+   MingW32 targets).
+
  * Interface changes relative to the 1.1.7 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  GPGME_KEYLIST_MODE_EPHEMERAL   NEW.
@@ -16,6 +20,8 @@ Noteworthy changes in version 1.1.9
  gpgme_op_assuan_result         NEW.
  gpgme_subkey_t                 EXTENDED: New fields is_cardkey, card_number.
  GPGME_ENCRYPT_NO_ENCRYPT_TO    NEW.
+ gpgme_check_version            CHANGED: Is now a macro.
+ gpgme_new                      EXTENDED: More failure codes.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
index e1f362252c9754e31870acf98675c3d2c463aa35..e1bb4a59bca7b3b08ff23d9354f512fd32110ac7 100644 (file)
@@ -1,3 +1,8 @@
+2009-05-28  Marcus Brinkmann  <marcus@g10code.de>
+
+       * gpgme.texi (Library Version Check): Document selftest error.
+       (Creating Contexts): Likewise.
+
 2009-05-18  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgme.texi (Encrypting a Plaintext): Document
index 0d5435f9614aa7fade2293a58cf59276f9799303..871575a29f17aa3934f2cd46afdb9b23ce2f5bc4 100644 (file)
@@ -577,13 +577,13 @@ automatically by Libtool.
 @cindex version check, of the library
 
 @deftypefun {const char *} gpgme_check_version (@w{const char *@var{required_version}})
-The function @code{gpgme_check_version} has three purposes.  It can be
+The function @code{gpgme_check_version} has four purposes.  It can be
 used to retrieve the version number of the library.  In addition it
 can verify that the version number is higher than a certain required
 version number.  In either case, the function initializes some
 sub-systems, and for this reason alone it must be invoked early in
 your program, before you make use of the other functions in
-@acronym{GPGME}. 
+@acronym{GPGME}.  The last purpose is to run selftests.
 
 As a side effect for W32 based systems, the socket layer will get
 initialized.
@@ -606,6 +606,11 @@ If you use a version of a library that is backwards compatible with
 older releases, but contains additional interfaces which your program
 uses, this function provides a run-time check if the necessary
 features are provided by the installed version of the library.
+
+If a selftest fails, the function may still succeed.  Selftest errors
+are returned later when invoking @code{gpgme_new}, so that a detailed
+error code can be returned (historically, @code{gpgme_check_version}
+does not return a detailed error code).
 @end deftypefun
 
 
@@ -1985,7 +1990,11 @@ and returns a handle for it in @var{ctx}.
 The function returns the error code @code{GPG_ERR_NO_ERROR} if the
 context was successfully created, @code{GPG_ERR_INV_VALUE} if
 @var{ctx} is not a valid pointer, and @code{GPG_ERR_ENOMEM} if not
-enough memory is available.
+enough memory is available.  Also, it returns
+@code{GPG_ERR_NOT_OPERATIONAL} if @code{gpgme_check_version} was not
+called to initialize GPGME, and @code{GPG_ERR_SELFTEST_FAILED} if a
+selftest failed.  Currently, the only selftest is for Windows MingW32
+targets to see if @code{-mms-bitfields} was used (as required).
 @end deftypefun
 
 
index 434c68024a8b794940e52e789bd1c0b614929396..7ee34395bc57598cf74b4a5bec37aa246f3967de 100644 (file)
@@ -1,3 +1,16 @@
+2009-05-28  Marcus Brinkmann  <marcus@g10code.de>
+
+       * gpgme.h.in (gpgme_check_version_internal): New prototype.
+       (gpgme_check_version): New macro, overriding function of the same
+       name.
+       * libgpgme.vers, gpgme.def: Add gpgme_check_version_internal.o
+       * context.h (_gpgme_selftest): New variable declaration.
+       * version.c: Include "context.h".
+       (gpgme_check_version): Set _gpgme_selftest on success.
+       (gpgme_check_version_internal): New function.
+       * gpgme.c (_gpgme_selftest): Define it.
+       (gpgme_new): Check the selftest result.
+
 2009-05-18  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgme.h.in (gpgme_encrypt_flags_t): Add
index 76aeb337f444abfe9635d94dd6897169ed9f3f27..472b8bebf14000f679b96b06f932b7b56f0130cc 100644 (file)
@@ -28,6 +28,8 @@
 #include "sema.h"
 
 \f
+extern gpgme_error_t _gpgme_selftest;
+
 /* Operations might require to remember arbitrary information and data
    objects during invocations of the status handler.  The
    ctx_op_data structure provides a generic framework to hook in
index 99d27ce6a5a3d9f175a0e5de4f8ee2d2f9e99a6c..b76b3991a417c83f025c6561ff5393453ed3cb23 100644 (file)
@@ -41,6 +41,9 @@ DEFINE_STATIC_LOCK (def_lc_lock);
 static char *def_lc_ctype;
 static char *def_lc_messages;
 
+\f
+gpgme_error_t _gpgme_selftest = GPG_ERR_NOT_OPERATIONAL;
+
 \f
 /* Create a new context as an environment for GPGME crypto
    operations.  */
@@ -50,6 +53,9 @@ gpgme_new (gpgme_ctx_t *r_ctx)
   gpgme_ctx_t ctx;
   TRACE_BEG (DEBUG_CTX, "gpgme_new", r_ctx);
 
+  if (_gpgme_selftest)
+    return TRACE_ERR (gpgme_error (_gpgme_selftest));
+
   ctx = calloc (1, sizeof *ctx);
   if (!ctx)
     return TRACE_ERR (gpg_error_from_errno (errno));
index 835177efcacb7a1ae0af7c2653859a0f54fa8286..14636d64adadb738d4cfb486eeae70708c82b303 100644 (file)
@@ -171,5 +171,8 @@ EXPORTS
     gpgme_op_assuan_result                @132
     gpgme_op_assuan_transact_start        @133
     gpgme_op_assuan_transact              @134
+
+    gpgme_check_version_internal         @135
+
 ; END
 
index fb2b7363a6db21f1755e153322c204b9615d5b6d..a9a4a3f7d48df465ae0063a689fc81d9fd17f0d3 100644 (file)
@@ -1894,9 +1894,21 @@ gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp);
 \f
 /* Various functions.  */
 
-/* Check that the library fulfills the version requirement.  */
+/* Check that the library fulfills the version requirement.  Note:
+   This is here only for the case where a user takes a pointer from
+   the old version of this function.  The new version and macro for
+   run-time checks are below.  */
 const char *gpgme_check_version (const char *req_version);
 
+/* Check that the library fulfills the version requirement and check
+   for struct layout mismatch involving bitfields.  */
+const char *gpgme_check_version_internal (const char *req_version,
+                                         size_t offset_sig_validity);
+
+#define gpgme_check_version(req_version)                               \
+  gpgme_check_version_internal (req_version,                           \
+                               offsetof (struct _gpgme_signature, validity))
+
 /* Get the information about the configured and installed engines.  A
    pointer to the first engine in the statically allocated linked list
    is returned in *INFO.  If an error occurs, it is returned.  The
index 1653a63c00eed859d9925d235eb9fade0d5d3463..bc6eb7cdfee4b101037bf9c307726eb63a72b6a3 100644 (file)
@@ -51,6 +51,8 @@ GPGME_1.1 {
     gpgme_op_assuan_result;    
     gpgme_op_assuan_transact;    
     gpgme_op_assuan_transact_start;    
+
+    gpgme_check_version_internal;
 };
 
 
index c6fb52b97990aec96977938eaea586c0e07f5efe..213df6de7e7283b2bfa21179c4aee73a374d0118 100644 (file)
@@ -32,6 +32,7 @@
 #include "gpgme.h"
 #include "priv-io.h"
 #include "debug.h"
+#include "context.h"
 
 /* For _gpgme_sema_subsystem_init ().  */
 #include "sema.h"
 #include "windows.h"
 #endif
 
+/* We implement this function, so we have to disable the overriding
+   macro.  */
+#undef gpgme_check_version
+
 \f
 /* Bootstrap the subsystems needed for concurrent operation.  This
    must be done once at startup.  We can not guarantee this using a
@@ -183,6 +188,7 @@ _gpgme_compare_versions (const char *my_version,
 const char *
 gpgme_check_version (const char *req_version)
 {
+  char *result;
   do_subsystem_inits ();
 
   /* Catch-22: We need to get at least the debug subsystem ready
@@ -193,7 +199,39 @@ gpgme_check_version (const char *req_version)
          "req_version=%s, VERSION=%s",
           req_version? req_version:"(null)", VERSION);
  
-  return _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL;
+  result = _gpgme_compare_versions (VERSION, req_version) ? VERSION : NULL;
+  if (result != NULL)
+    _gpgme_selftest = 0;
+
+  return result;
+}
+
+/* Check the version and also at runtime if the struct layout of the
+   library matches the one of the user.  This is particular useful for
+   Windows targets (-mms-bitfields).  */
+const char *
+gpgme_check_version_internal (const char *req_version,
+                             size_t offset_sig_validity)
+{
+  char *result;
+
+  TRACE2 (DEBUG_INIT, "gpgme_check_version_internal: ", 0,
+         "req_version=%s, offset_sig_validity=%i",
+         req_version ? req_version : "(null)", offset_sig_validity);
+
+  result = gpgme_check_version (req_version);
+  if (result == NULL)
+    return result;
+
+  if (offset_sig_validity != offsetof (struct _gpgme_signature, validity))
+    {
+      TRACE1 (DEBUG_INIT, "gpgme_check_version_internal: ", 0,
+             "offset_sig_validity mismatch: expected %i",
+             offsetof (struct _gpgme_signature, validity));
+      _gpgme_selftest = GPG_ERR_SELFTEST_FAILED;
+    }
+
+  return result;
 }
 
 \f