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.
This commit is contained in:
Marcus Brinkmann 2009-05-28 15:16:01 +00:00
parent 2c5d801fc4
commit bdb7bcf938
10 changed files with 101 additions and 5 deletions

6
NEWS
View File

@ -4,6 +4,10 @@ Noteworthy changes in version 1.1.9
* New encryption flag GPGME_ENCRYPT_NO_ENCRYPT_TO to disable default * New encryption flag GPGME_ENCRYPT_NO_ENCRYPT_TO to disable default
recipients. 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: * Interface changes relative to the 1.1.7 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_KEYLIST_MODE_EPHEMERAL NEW. GPGME_KEYLIST_MODE_EPHEMERAL NEW.
@ -16,6 +20,8 @@ Noteworthy changes in version 1.1.9
gpgme_op_assuan_result NEW. gpgme_op_assuan_result NEW.
gpgme_subkey_t EXTENDED: New fields is_cardkey, card_number. gpgme_subkey_t EXTENDED: New fields is_cardkey, card_number.
GPGME_ENCRYPT_NO_ENCRYPT_TO NEW. GPGME_ENCRYPT_NO_ENCRYPT_TO NEW.
gpgme_check_version CHANGED: Is now a macro.
gpgme_new EXTENDED: More failure codes.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View 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> 2009-05-18 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Encrypting a Plaintext): Document * gpgme.texi (Encrypting a Plaintext): Document

View File

@ -577,13 +577,13 @@ automatically by Libtool.
@cindex version check, of the library @cindex version check, of the library
@deftypefun {const char *} gpgme_check_version (@w{const char *@var{required_version}}) @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 used to retrieve the version number of the library. In addition it
can verify that the version number is higher than a certain required can verify that the version number is higher than a certain required
version number. In either case, the function initializes some version number. In either case, the function initializes some
sub-systems, and for this reason alone it must be invoked early in sub-systems, and for this reason alone it must be invoked early in
your program, before you make use of the other functions 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 As a side effect for W32 based systems, the socket layer will get
initialized. 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 older releases, but contains additional interfaces which your program
uses, this function provides a run-time check if the necessary uses, this function provides a run-time check if the necessary
features are provided by the installed version of the library. 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 @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 The function returns the error code @code{GPG_ERR_NO_ERROR} if the
context was successfully created, @code{GPG_ERR_INV_VALUE} if context was successfully created, @code{GPG_ERR_INV_VALUE} if
@var{ctx} is not a valid pointer, and @code{GPG_ERR_ENOMEM} if not @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 @end deftypefun

View 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> 2009-05-18 Marcus Brinkmann <marcus@g10code.de>
* gpgme.h.in (gpgme_encrypt_flags_t): Add * gpgme.h.in (gpgme_encrypt_flags_t): Add

View File

@ -28,6 +28,8 @@
#include "sema.h" #include "sema.h"
extern gpgme_error_t _gpgme_selftest;
/* Operations might require to remember arbitrary information and data /* Operations might require to remember arbitrary information and data
objects during invocations of the status handler. The objects during invocations of the status handler. The
ctx_op_data structure provides a generic framework to hook in ctx_op_data structure provides a generic framework to hook in

View File

@ -41,6 +41,9 @@ DEFINE_STATIC_LOCK (def_lc_lock);
static char *def_lc_ctype; static char *def_lc_ctype;
static char *def_lc_messages; static char *def_lc_messages;
gpgme_error_t _gpgme_selftest = GPG_ERR_NOT_OPERATIONAL;
/* Create a new context as an environment for GPGME crypto /* Create a new context as an environment for GPGME crypto
operations. */ operations. */
@ -50,6 +53,9 @@ gpgme_new (gpgme_ctx_t *r_ctx)
gpgme_ctx_t ctx; gpgme_ctx_t ctx;
TRACE_BEG (DEBUG_CTX, "gpgme_new", r_ctx); TRACE_BEG (DEBUG_CTX, "gpgme_new", r_ctx);
if (_gpgme_selftest)
return TRACE_ERR (gpgme_error (_gpgme_selftest));
ctx = calloc (1, sizeof *ctx); ctx = calloc (1, sizeof *ctx);
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error_from_errno (errno)); return TRACE_ERR (gpg_error_from_errno (errno));

View File

@ -171,5 +171,8 @@ EXPORTS
gpgme_op_assuan_result @132 gpgme_op_assuan_result @132
gpgme_op_assuan_transact_start @133 gpgme_op_assuan_transact_start @133
gpgme_op_assuan_transact @134 gpgme_op_assuan_transact @134
gpgme_check_version_internal @135
; END ; END

View File

@ -1894,9 +1894,21 @@ gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp);
/* Various functions. */ /* 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); 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 /* Get the information about the configured and installed engines. A
pointer to the first engine in the statically allocated linked list pointer to the first engine in the statically allocated linked list
is returned in *INFO. If an error occurs, it is returned. The is returned in *INFO. If an error occurs, it is returned. The

View File

@ -51,6 +51,8 @@ GPGME_1.1 {
gpgme_op_assuan_result; gpgme_op_assuan_result;
gpgme_op_assuan_transact; gpgme_op_assuan_transact;
gpgme_op_assuan_transact_start; gpgme_op_assuan_transact_start;
gpgme_check_version_internal;
}; };

View File

@ -32,6 +32,7 @@
#include "gpgme.h" #include "gpgme.h"
#include "priv-io.h" #include "priv-io.h"
#include "debug.h" #include "debug.h"
#include "context.h"
/* For _gpgme_sema_subsystem_init (). */ /* For _gpgme_sema_subsystem_init (). */
#include "sema.h" #include "sema.h"
@ -44,6 +45,10 @@
#include "windows.h" #include "windows.h"
#endif #endif
/* We implement this function, so we have to disable the overriding
macro. */
#undef gpgme_check_version
/* Bootstrap the subsystems needed for concurrent operation. This /* Bootstrap the subsystems needed for concurrent operation. This
must be done once at startup. We can not guarantee this using a 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 * const char *
gpgme_check_version (const char *req_version) gpgme_check_version (const char *req_version)
{ {
char *result;
do_subsystem_inits (); do_subsystem_inits ();
/* Catch-22: We need to get at least the debug subsystem ready /* 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=%s, VERSION=%s",
req_version? req_version:"(null)", VERSION); 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;
} }