core: Add gpgme_op_query_swdb and helper.
* src/gpgme.h.in (gpgme_query_swdb_result_t): New. (gpgme_op_query_swdb): New. (gpgme_op_query_swdb_result): New. * src/libgpgme.vers, src/gpgme.def: Add the two new functions. * src/queryswdb.c: New. * src/Makefile.am (main_sources): Add new file. * src/context.h (OPDATA_QUERY_SWDB): New. * src/engine-backend.h (struct engine_ops): Add field 'query_swdb'. Adjust all initializer. * src/engine.c (_gpgme_engine_op_query_swdb): New. * src/engine-gpgconf.c (parse_swdb_line): New. (gpgconf_query_swdb): New. (_gpgme_engine_ops_gpgconf): Register that function. * src/util.h (GPG_ERR_TOO_OLD): Define for older libgpg-error. (GPG_ERR_ENGINE_TOO_OLD): Ditto. * tests/run-swdb.c: New. * tests/Makefile.am (noinst_PROGRAMS): Add new debug tool. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
34a4e8017b
commit
aad94cb7c3
3
NEWS
3
NEWS
@ -9,6 +9,9 @@ Noteworthy changes in version 1.7.2 (unreleased)
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
gpgme_set_sender NEW.
|
gpgme_set_sender NEW.
|
||||||
gpgme_get_sender NEW.
|
gpgme_get_sender NEW.
|
||||||
|
gpgme_op_query_swdb NEW.
|
||||||
|
gpgme_op_query_swdb_result NEW.
|
||||||
|
gpgme_query_swdb_result_t NEW.
|
||||||
qt: DN NEW.
|
qt: DN NEW.
|
||||||
qt: DN::Attribute NEW.
|
qt: DN::Attribute NEW.
|
||||||
|
|
||||||
|
141
doc/gpgme.texi
141
doc/gpgme.texi
@ -237,7 +237,9 @@ Encrypt
|
|||||||
|
|
||||||
Miscellaneous
|
Miscellaneous
|
||||||
|
|
||||||
* Running other Programs:: Running other Programs
|
* Running other Programs:: Running other Programs.
|
||||||
|
* Using the Assuan protocol:: Using the Assuan protocol.
|
||||||
|
* Checking for updates:: How to check for software updates.
|
||||||
|
|
||||||
Run Control
|
Run Control
|
||||||
|
|
||||||
@ -5561,6 +5563,7 @@ Here are some support functions which are sometimes useful.
|
|||||||
@menu
|
@menu
|
||||||
* Running other Programs:: Running other Programs
|
* Running other Programs:: Running other Programs
|
||||||
* Using the Assuan protocol:: Using the Assuan protocol
|
* Using the Assuan protocol:: Using the Assuan protocol
|
||||||
|
* Checking for updates:: How to check for software updates
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
@ -5692,6 +5695,142 @@ Synchronous variant.
|
|||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
|
|
||||||
|
@node Checking for updates
|
||||||
|
@subsection How to check for software updates
|
||||||
|
|
||||||
|
The GnuPG Project operates a server to query the current versions of
|
||||||
|
software packages related to GnuPG. GPGME can be used to
|
||||||
|
access this online database and check whether a new version of a
|
||||||
|
software package is available.
|
||||||
|
|
||||||
|
@deftp {Data type} {gpgme_query_swdb_result_t}
|
||||||
|
This is a pointer to a structure used to store the result of a
|
||||||
|
@code{gpgme_op_query_swdb} operation. After success full call to that
|
||||||
|
function, you can retrieve the pointer to the result with
|
||||||
|
@code{gpgme_op_query_swdb_result}. The structure contains the
|
||||||
|
following member:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item name
|
||||||
|
This is the name of the package.
|
||||||
|
|
||||||
|
@item iversion
|
||||||
|
The currently installed version or an empty string. This value is
|
||||||
|
either a copy of the argument given to @code{gpgme_op_query_swdb} or
|
||||||
|
the version of the installed software as figured out by GPGME or GnuPG.
|
||||||
|
|
||||||
|
@item created
|
||||||
|
This gives the date the file with the list of version numbers has
|
||||||
|
originally be created by the GnuPG project.
|
||||||
|
|
||||||
|
@item retrieved
|
||||||
|
This gives the date the file was downloaded.
|
||||||
|
|
||||||
|
@item warning
|
||||||
|
If this flag is set either an error has occurred or some of the
|
||||||
|
information in this structure are not properly set. For example if
|
||||||
|
the version number of the installed software could not be figured out,
|
||||||
|
the @code{update} flag may not reflect a required update status.
|
||||||
|
|
||||||
|
@item update
|
||||||
|
If this flag is set an update of the software is available.
|
||||||
|
|
||||||
|
@item urgent
|
||||||
|
If this flag is set an available update is important.
|
||||||
|
|
||||||
|
@item noinfo
|
||||||
|
If this flag is set, no valid information could be retrieved.
|
||||||
|
|
||||||
|
@item unknown
|
||||||
|
If this flag is set the given @code{name} is not known.
|
||||||
|
|
||||||
|
@item tooold
|
||||||
|
If this flag is set the available information is not fresh enough.
|
||||||
|
|
||||||
|
@item error
|
||||||
|
If this flag is set some other error has occured.
|
||||||
|
|
||||||
|
@item version
|
||||||
|
The version string of the latest released version.
|
||||||
|
|
||||||
|
@item reldate
|
||||||
|
The release date of the latest released version.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
@deftypefun gpgme_error_t gpgme_op_query_swdb @
|
||||||
|
(@w{gpgme_ctx_t @var{ctx}}, @
|
||||||
|
@w{const char *@var{name}}, @
|
||||||
|
@w{const char *@var{iversion}}, @
|
||||||
|
@w{gpgme_data_t @var{reserved}})
|
||||||
|
|
||||||
|
Query the software version database for software package @var{name}
|
||||||
|
and check against the installed version given by @var{iversion}. If
|
||||||
|
@var{iversion} is given as @code{NULL} a check is only done if GPGME
|
||||||
|
can figure out the version by itself (for example when using
|
||||||
|
"gpgme" or "gnupg"). If @code{NULL} is used for @var{name} the
|
||||||
|
current gpgme version is checked. @var{reserved} must be set to 0.
|
||||||
|
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@deftypefun gpgme_query_swdb_result_t gpgme_op_query_swdb_result @
|
||||||
|
(@w{gpgme_ctx_t @var{ctx}})
|
||||||
|
|
||||||
|
The function @code{gpgme_op_query_swdb_result} returns a
|
||||||
|
@code{gpgme_query_swdb_result_t} pointer to a structure holding the
|
||||||
|
result of a @code{gpgme_op_query_swdb} operation. The pointer is only
|
||||||
|
valid if the last operation on the context was a sucessful call to
|
||||||
|
@code{gpgme_op_query_swdb}. If that call failed, the result might
|
||||||
|
be a @code{NULL} pointer. The returned pointer is only valid until
|
||||||
|
the next operation is started on the context @var{ctx}.
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
Here is an example on how to check whether GnuPG is current:
|
||||||
|
|
||||||
|
@example
|
||||||
|
#include <gpgme.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
@{
|
||||||
|
gpg_error_t err;
|
||||||
|
gpgme_ctx_t ctx;
|
||||||
|
gpgme_query_swdb_result_t result;
|
||||||
|
|
||||||
|
gpgme_check_version (NULL);
|
||||||
|
err = gpgme_new (&ctx);
|
||||||
|
if (err)
|
||||||
|
fprintf (stderr, "error creating context: %s\n", gpg_strerror (err));
|
||||||
|
else
|
||||||
|
@{
|
||||||
|
gpgme_set_protocol (ctx, GPGME_PROTOCOL_GPGCONF);
|
||||||
|
|
||||||
|
err = gpgme_op_query_swdb (ctx, "gnupg", NULL, 0);
|
||||||
|
if (err)
|
||||||
|
fprintf (stderr, "error querying swdb: %s\n", gpg_strerror (err));
|
||||||
|
else
|
||||||
|
@{
|
||||||
|
result = gpgme_op_query_swdb_result (ctx);
|
||||||
|
if (!result)
|
||||||
|
fprintf (stderr, "error querying swdb\n");
|
||||||
|
if (!result->warning && !result->update)
|
||||||
|
printf ("GnuPG version %s is current\n",
|
||||||
|
result->iversion);
|
||||||
|
else if (!result->warning && result->update)
|
||||||
|
printf ("GnuPG version %s can be updated to %s\n",
|
||||||
|
result->iversion, result->version);
|
||||||
|
else
|
||||||
|
fprintf (stderr, "error finding the update status\n");
|
||||||
|
@}
|
||||||
|
gpgme_release (ctx);
|
||||||
|
@}
|
||||||
|
return 0;
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
|
||||||
@node Run Control
|
@node Run Control
|
||||||
@section Run Control
|
@section Run Control
|
||||||
@cindex run control
|
@cindex run control
|
||||||
|
@ -91,7 +91,7 @@ main_sources = \
|
|||||||
$(uiserver_components) \
|
$(uiserver_components) \
|
||||||
engine-g13.c vfs-mount.c vfs-create.c \
|
engine-g13.c vfs-mount.c vfs-create.c \
|
||||||
engine-spawn.c \
|
engine-spawn.c \
|
||||||
gpgconf.c \
|
gpgconf.c queryswdb.c \
|
||||||
sema.h priv-io.h $(system_components) sys-util.h dirinfo.c \
|
sema.h priv-io.h $(system_components) sys-util.h dirinfo.c \
|
||||||
debug.c debug.h gpgme.c version.c error.c
|
debug.c debug.h gpgme.c version.c error.c
|
||||||
|
|
||||||
|
@ -38,7 +38,8 @@ typedef enum
|
|||||||
OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
|
OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
|
||||||
OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
|
OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
|
||||||
OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT,
|
OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT,
|
||||||
OPDATA_PASSWD, OPDATA_EXPORT, OPDATA_KEYSIGN, OPDATA_TOFU_POLICY
|
OPDATA_PASSWD, OPDATA_EXPORT, OPDATA_KEYSIGN, OPDATA_TOFU_POLICY,
|
||||||
|
OPDATA_QUERY_SWDB
|
||||||
} ctx_op_data_id_t;
|
} ctx_op_data_id_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -796,6 +796,7 @@ struct engine_ops _gpgme_engine_ops_assuan =
|
|||||||
llass_transact, /* opassuan_transact */
|
llass_transact, /* opassuan_transact */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
|
NULL, /* query_swdb */
|
||||||
llass_set_io_cbs,
|
llass_set_io_cbs,
|
||||||
llass_io_event,
|
llass_io_event,
|
||||||
llass_cancel,
|
llass_cancel,
|
||||||
|
@ -127,6 +127,10 @@ struct engine_ops
|
|||||||
gpgme_error_t (*conf_load) (void *engine, gpgme_conf_comp_t *conf_p);
|
gpgme_error_t (*conf_load) (void *engine, gpgme_conf_comp_t *conf_p);
|
||||||
gpgme_error_t (*conf_save) (void *engine, gpgme_conf_comp_t conf);
|
gpgme_error_t (*conf_save) (void *engine, gpgme_conf_comp_t conf);
|
||||||
|
|
||||||
|
gpgme_error_t (*query_swdb) (void *engine,
|
||||||
|
const char *name, const char *iversion,
|
||||||
|
gpgme_query_swdb_result_t result);
|
||||||
|
|
||||||
void (*set_io_cbs) (void *engine, gpgme_io_cbs_t io_cbs);
|
void (*set_io_cbs) (void *engine, gpgme_io_cbs_t io_cbs);
|
||||||
void (*io_event) (void *engine, gpgme_event_io_t type, void *type_data);
|
void (*io_event) (void *engine, gpgme_event_io_t type, void *type_data);
|
||||||
|
|
||||||
|
@ -811,6 +811,7 @@ struct engine_ops _gpgme_engine_ops_g13 =
|
|||||||
g13_transact,
|
g13_transact,
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
|
NULL, /* query_swdb */
|
||||||
g13_set_io_cbs,
|
g13_set_io_cbs,
|
||||||
g13_io_event,
|
g13_io_event,
|
||||||
g13_cancel,
|
g13_cancel,
|
||||||
|
@ -2969,6 +2969,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
|
|||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
|
NULL, /* query_swdb */
|
||||||
gpg_set_io_cbs,
|
gpg_set_io_cbs,
|
||||||
gpg_io_event,
|
gpg_io_event,
|
||||||
gpg_cancel,
|
gpg_cancel,
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
#include "engine-backend.h"
|
#include "engine-backend.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct engine_gpgconf
|
struct engine_gpgconf
|
||||||
{
|
{
|
||||||
@ -941,6 +942,217 @@ gpgconf_conf_save (void *engine, gpgme_conf_comp_t comp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse a line received from gpgconf --query-swdb. This function may
|
||||||
|
* modify LINE. The result is stored at RESUL. */
|
||||||
|
static gpg_error_t
|
||||||
|
parse_swdb_line (char *line, gpgme_query_swdb_result_t result)
|
||||||
|
{
|
||||||
|
char *field[9];
|
||||||
|
int fields = 0;
|
||||||
|
gpg_err_code_t ec;
|
||||||
|
|
||||||
|
while (line && fields < DIM (field))
|
||||||
|
{
|
||||||
|
field[fields++] = line;
|
||||||
|
line = strchr (line, ':');
|
||||||
|
if (line)
|
||||||
|
*line++ = 0;
|
||||||
|
}
|
||||||
|
/* We require that all fields exists - gpgme emits all these fields
|
||||||
|
* even on error. They might be empty, though. */
|
||||||
|
if (fields < 9)
|
||||||
|
return gpg_error (GPG_ERR_INV_ENGINE);
|
||||||
|
|
||||||
|
free (result->name);
|
||||||
|
result->name = strdup (field[0]);
|
||||||
|
if (!result->name)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
free (result->iversion);
|
||||||
|
result->iversion = strdup (field[1]);
|
||||||
|
if (!result->iversion)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
result->urgent = (strtol (field[3], NULL, 10) > 0);
|
||||||
|
|
||||||
|
ec = gpg_err_code (strtoul (field[4], NULL, 10));
|
||||||
|
|
||||||
|
result->created = _gpgme_parse_timestamp (field[5], NULL);
|
||||||
|
result->retrieved= _gpgme_parse_timestamp (field[6], NULL);
|
||||||
|
|
||||||
|
free (result->version);
|
||||||
|
result->version = strdup (field[7]);
|
||||||
|
if (!result->version)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
result->reldate = _gpgme_parse_timestamp (field[8], NULL);
|
||||||
|
|
||||||
|
/* Set other flags. */
|
||||||
|
result->warning = !!ec;
|
||||||
|
result->update = 0;
|
||||||
|
result->noinfo = 0;
|
||||||
|
result->unknown = 0;
|
||||||
|
result->tooold = 0;
|
||||||
|
result->error = 0;
|
||||||
|
|
||||||
|
switch (*field[2])
|
||||||
|
{
|
||||||
|
case '-': result->warning = 1; break;
|
||||||
|
case '?': result->unknown = result->warning = 1; break;
|
||||||
|
case 'u': result->update = 1; break;
|
||||||
|
case 'c': break;
|
||||||
|
case 'n': break;
|
||||||
|
default:
|
||||||
|
result->warning = 1;
|
||||||
|
if (!ec)
|
||||||
|
ec = GPG_ERR_INV_ENGINE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec == GPG_ERR_TOO_OLD)
|
||||||
|
result->tooold = 1;
|
||||||
|
else if (ec == GPG_ERR_ENOENT)
|
||||||
|
result->noinfo = 1;
|
||||||
|
else if (ec)
|
||||||
|
result->error = 1;
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
gpgconf_query_swdb (void *engine,
|
||||||
|
const char *name, const char *iversion,
|
||||||
|
gpgme_query_swdb_result_t result)
|
||||||
|
{
|
||||||
|
struct engine_gpgconf *gpgconf = engine;
|
||||||
|
gpgme_error_t err = 0;
|
||||||
|
char *linebuf;
|
||||||
|
size_t linebufsize;
|
||||||
|
int linelen;
|
||||||
|
char *argv[7];
|
||||||
|
int argc = 0;
|
||||||
|
int rp[2];
|
||||||
|
struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0},
|
||||||
|
{-1, -1} };
|
||||||
|
int status;
|
||||||
|
int nread;
|
||||||
|
char *mark = NULL;
|
||||||
|
|
||||||
|
if (!have_gpgconf_version (gpgconf, "2.1.16"))
|
||||||
|
return gpg_error (GPG_ERR_ENGINE_TOO_OLD);
|
||||||
|
|
||||||
|
/* _gpgme_engine_new guarantees that this is not NULL. */
|
||||||
|
argv[argc++] = gpgconf->file_name;
|
||||||
|
|
||||||
|
if (gpgconf->home_dir)
|
||||||
|
{
|
||||||
|
argv[argc++] = (char*)"--homedir";
|
||||||
|
argv[argc++] = gpgconf->home_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[argc++] = (char*)"--query-swdb";
|
||||||
|
argv[argc++] = (char*)name;
|
||||||
|
argv[argc++] = (char*)iversion;
|
||||||
|
argv[argc] = NULL;
|
||||||
|
assert (argc < DIM (argv));
|
||||||
|
|
||||||
|
if (_gpgme_io_pipe (rp, 1) < 0)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
cfd[0].fd = rp[1];
|
||||||
|
|
||||||
|
status = _gpgme_io_spawn (gpgconf->file_name, argv,
|
||||||
|
IOSPAWN_FLAG_DETACHED, cfd, NULL, NULL, NULL);
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
_gpgme_io_close (rp[0]);
|
||||||
|
_gpgme_io_close (rp[1]);
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
}
|
||||||
|
|
||||||
|
linebufsize = 2048; /* Same as used by gpgconf. */
|
||||||
|
linebuf = malloc (linebufsize);
|
||||||
|
if (!linebuf)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
linelen = 0;
|
||||||
|
|
||||||
|
while ((nread = _gpgme_io_read (rp[0], linebuf + linelen,
|
||||||
|
linebufsize - linelen - 1)))
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
const char *lastmark = NULL;
|
||||||
|
size_t nused;
|
||||||
|
|
||||||
|
if (nread < 0)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
linelen += nread;
|
||||||
|
linebuf[linelen] = '\0';
|
||||||
|
|
||||||
|
for (line=linebuf; (mark = strchr (line, '\n')); line = mark+1 )
|
||||||
|
{
|
||||||
|
lastmark = mark;
|
||||||
|
if (mark > line && mark[-1] == '\r')
|
||||||
|
mark[-1] = '\0';
|
||||||
|
else
|
||||||
|
mark[0] = '\0';
|
||||||
|
|
||||||
|
/* Got a full line. Due to the CR removal code (which
|
||||||
|
occurs only on Windows) we might be one-off and thus
|
||||||
|
would see empty lines. */
|
||||||
|
if (*line)
|
||||||
|
{
|
||||||
|
err = parse_swdb_line (line, result);
|
||||||
|
goto leave; /* Ready. */
|
||||||
|
}
|
||||||
|
else /* empty line. */
|
||||||
|
err = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nused = lastmark? (lastmark + 1 - linebuf) : 0;
|
||||||
|
memmove (linebuf, linebuf + nused, linelen - nused);
|
||||||
|
linelen -= nused;
|
||||||
|
|
||||||
|
if (!(linelen < linebufsize - 1))
|
||||||
|
{
|
||||||
|
char *newlinebuf;
|
||||||
|
|
||||||
|
if (linelen < 8 * 1024 - 1)
|
||||||
|
linebufsize = 8 * 1024;
|
||||||
|
else if (linelen < 64 * 1024 - 1)
|
||||||
|
linebufsize = 64 * 1024;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We reached our limit - give up. */
|
||||||
|
err = gpg_error (GPG_ERR_LINE_TOO_LONG);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
newlinebuf = realloc (linebuf, linebufsize);
|
||||||
|
if (!newlinebuf)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
linebuf = newlinebuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
free (linebuf);
|
||||||
|
_gpgme_io_close (rp[0]);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gpgconf_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
|
gpgconf_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
|
||||||
{
|
{
|
||||||
@ -998,6 +1210,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
|
|||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
gpgconf_conf_load,
|
gpgconf_conf_load,
|
||||||
gpgconf_conf_save,
|
gpgconf_conf_save,
|
||||||
|
gpgconf_query_swdb,
|
||||||
gpgconf_set_io_cbs,
|
gpgconf_set_io_cbs,
|
||||||
NULL, /* io_event */
|
NULL, /* io_event */
|
||||||
NULL, /* cancel */
|
NULL, /* cancel */
|
||||||
|
@ -2101,6 +2101,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
|
|||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
|
NULL, /* query_swdb */
|
||||||
gpgsm_set_io_cbs,
|
gpgsm_set_io_cbs,
|
||||||
gpgsm_io_event,
|
gpgsm_io_event,
|
||||||
gpgsm_cancel,
|
gpgsm_cancel,
|
||||||
|
@ -469,6 +469,7 @@ struct engine_ops _gpgme_engine_ops_spawn =
|
|||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
|
NULL, /* query_swdb */
|
||||||
engspawn_set_io_cbs,
|
engspawn_set_io_cbs,
|
||||||
engspawn_io_event, /* io_event */
|
engspawn_io_event, /* io_event */
|
||||||
engspawn_cancel, /* cancel */
|
engspawn_cancel, /* cancel */
|
||||||
|
@ -1393,6 +1393,7 @@ struct engine_ops _gpgme_engine_ops_uiserver =
|
|||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
|
NULL, /* query_swdb */
|
||||||
uiserver_set_io_cbs,
|
uiserver_set_io_cbs,
|
||||||
uiserver_io_event,
|
uiserver_io_event,
|
||||||
uiserver_cancel,
|
uiserver_cancel,
|
||||||
|
15
src/engine.c
15
src/engine.c
@ -980,6 +980,21 @@ _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpgme_error_t
|
||||||
|
_gpgme_engine_op_query_swdb (engine_t engine,
|
||||||
|
const char *name, const char *iversion,
|
||||||
|
gpgme_query_swdb_result_t result)
|
||||||
|
{
|
||||||
|
if (!engine)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
if (!engine->ops->query_swdb)
|
||||||
|
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
|
return (*engine->ops->query_swdb) (engine->engine, name, iversion, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
|
_gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
|
||||||
{
|
{
|
||||||
|
@ -173,6 +173,12 @@ gpgme_error_t _gpgme_engine_op_conf_load (engine_t engine,
|
|||||||
gpgme_error_t _gpgme_engine_op_conf_save (engine_t engine,
|
gpgme_error_t _gpgme_engine_op_conf_save (engine_t engine,
|
||||||
gpgme_conf_comp_t conf);
|
gpgme_conf_comp_t conf);
|
||||||
|
|
||||||
|
gpgme_error_t _gpgme_engine_op_query_swdb (engine_t engine,
|
||||||
|
const char *name,
|
||||||
|
const char *iversion,
|
||||||
|
gpgme_query_swdb_result_t result);
|
||||||
|
|
||||||
|
|
||||||
void _gpgme_engine_set_io_cbs (engine_t engine,
|
void _gpgme_engine_set_io_cbs (engine_t engine,
|
||||||
gpgme_io_cbs_t io_cbs);
|
gpgme_io_cbs_t io_cbs);
|
||||||
void _gpgme_engine_io_event (engine_t engine,
|
void _gpgme_engine_io_event (engine_t engine,
|
||||||
|
@ -65,7 +65,7 @@ gpgme_conf_release (gpgme_conf_comp_t conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Public function to release load a configuration list. No
|
/* Public function to load a configuration list. No
|
||||||
asynchronous interface for now. */
|
asynchronous interface for now. */
|
||||||
gpgme_error_t
|
gpgme_error_t
|
||||||
gpgme_op_conf_load (gpgme_ctx_t ctx, gpgme_conf_comp_t *conf_p)
|
gpgme_op_conf_load (gpgme_ctx_t ctx, gpgme_conf_comp_t *conf_p)
|
||||||
@ -108,5 +108,3 @@ gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp)
|
|||||||
ctx->protocol = proto;
|
ctx->protocol = proto;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -249,5 +249,8 @@ EXPORTS
|
|||||||
gpgme_set_sender @187
|
gpgme_set_sender @187
|
||||||
gpgme_get_sender @188
|
gpgme_get_sender @188
|
||||||
|
|
||||||
|
gpgme_op_query_swdb @189
|
||||||
|
gpgme_op_query_swdb_result @190
|
||||||
|
|
||||||
; END
|
; END
|
||||||
|
|
||||||
|
@ -2418,6 +2418,67 @@ gpgme_error_t gpgme_op_conf_load (gpgme_ctx_t ctx, gpgme_conf_comp_t *conf_p);
|
|||||||
gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp);
|
gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp);
|
||||||
|
|
||||||
|
|
||||||
|
/* Information about software versions. */
|
||||||
|
typedef struct _gpgme_op_query_swdb_result
|
||||||
|
{
|
||||||
|
/* RFU */
|
||||||
|
struct _gpgme_op_query_swdb_result *next;
|
||||||
|
|
||||||
|
/* The name of the package (e.g. "gpgme", "gnupg") */
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
/* The version number of the installed version. */
|
||||||
|
char *iversion;
|
||||||
|
|
||||||
|
/* The time the online info was created. */
|
||||||
|
unsigned long created;
|
||||||
|
|
||||||
|
/* The time the online info was retrieved. */
|
||||||
|
unsigned long retrieved;
|
||||||
|
|
||||||
|
/* This bit is set if an error occured or some of the information
|
||||||
|
* in this structure may not be set. */
|
||||||
|
unsigned int warning : 1;
|
||||||
|
|
||||||
|
/* An update is available. */
|
||||||
|
unsigned int update : 1;
|
||||||
|
|
||||||
|
/* The update is important. */
|
||||||
|
unsigned int urgent : 1;
|
||||||
|
|
||||||
|
/* No information at all available. */
|
||||||
|
unsigned int noinfo : 1;
|
||||||
|
|
||||||
|
/* The package name is not known. */
|
||||||
|
unsigned int unknown : 1;
|
||||||
|
|
||||||
|
/* The information here is too old. */
|
||||||
|
unsigned int tooold : 1;
|
||||||
|
|
||||||
|
/* Other error. */
|
||||||
|
unsigned int error : 1;
|
||||||
|
|
||||||
|
unsigned int _reserved : 25;
|
||||||
|
|
||||||
|
/* The version number of the latest released version. */
|
||||||
|
char *version;
|
||||||
|
|
||||||
|
/* The release date of that version. */
|
||||||
|
unsigned long reldate;
|
||||||
|
|
||||||
|
} *gpgme_query_swdb_result_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* Run the gpgconf --query-swdb command. */
|
||||||
|
gpgme_error_t gpgme_op_query_swdb (gpgme_ctx_t ctx,
|
||||||
|
const char *name, const char *iversion,
|
||||||
|
unsigned int reserved);
|
||||||
|
|
||||||
|
/* Return the result from the last query_swdb operation. */
|
||||||
|
gpgme_query_swdb_result_t gpgme_op_query_swdb_result (gpgme_ctx_t ctx);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Various functions.
|
* Various functions.
|
||||||
|
@ -122,6 +122,9 @@ GPGME_1.1 {
|
|||||||
|
|
||||||
gpgme_set_sender;
|
gpgme_set_sender;
|
||||||
gpgme_get_sender;
|
gpgme_get_sender;
|
||||||
|
|
||||||
|
gpgme_op_query_swdb;
|
||||||
|
gpgme_op_query_swdb_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
121
src/queryswdb.c
Normal file
121
src/queryswdb.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/* queryswdb.c - Access to the SWDB file
|
||||||
|
* Copyright (C) 2016 g10 Code GmbH
|
||||||
|
*
|
||||||
|
* This file is part of GPGME.
|
||||||
|
*
|
||||||
|
* GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GPGME is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "gpgme.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "ops.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct _gpgme_op_query_swdb_result result;
|
||||||
|
|
||||||
|
} *op_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
release_op_data (void *hook)
|
||||||
|
{
|
||||||
|
op_data_t opd = (op_data_t) hook;
|
||||||
|
gpgme_query_swdb_result_t result = &opd->result;
|
||||||
|
|
||||||
|
assert (!result->next);
|
||||||
|
free (result->name);
|
||||||
|
free (result->iversion);
|
||||||
|
free (result->version);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpgme_query_swdb_result_t
|
||||||
|
gpgme_op_query_swdb_result (gpgme_ctx_t ctx)
|
||||||
|
{
|
||||||
|
void *hook;
|
||||||
|
op_data_t opd;
|
||||||
|
gpgme_error_t err;
|
||||||
|
|
||||||
|
TRACE_BEG (DEBUG_CTX, "gpgme_op_query_swdb_result", ctx);
|
||||||
|
|
||||||
|
err = _gpgme_op_data_lookup (ctx, OPDATA_QUERY_SWDB, &hook, -1, NULL);
|
||||||
|
opd = hook;
|
||||||
|
|
||||||
|
if (err || !opd)
|
||||||
|
{
|
||||||
|
TRACE_SUC0 ("result=(null)");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_SUC1 ("result=%p", &opd->result);
|
||||||
|
return &opd->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Query the swdb for software package NAME and check against the
|
||||||
|
* installed version given by IVERSION. If IVERSION is NULL a check
|
||||||
|
* is only done if GPGME can figure out the version by itself
|
||||||
|
* (e.g. for "gpgme" or "gnupg"). RESERVED should be 0.
|
||||||
|
*
|
||||||
|
* Note that we only implemented the synchronous variant of this
|
||||||
|
* function but the API is prepared for an asynchronous variant.
|
||||||
|
*/
|
||||||
|
gpgme_error_t
|
||||||
|
gpgme_op_query_swdb (gpgme_ctx_t ctx, const char *name, const char *iversion,
|
||||||
|
unsigned int reserved)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
void *hook;
|
||||||
|
op_data_t opd;
|
||||||
|
|
||||||
|
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_query_swdb", ctx,
|
||||||
|
"name=%s, iversion=%a", name, iversion);
|
||||||
|
|
||||||
|
if (!ctx || reserved)
|
||||||
|
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||||
|
|
||||||
|
if (ctx->protocol != GPGME_PROTOCOL_GPGCONF)
|
||||||
|
return TRACE_ERR (gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL));
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
name = "gpgme";
|
||||||
|
|
||||||
|
if (!iversion && !strcmp (name, "gpgme"))
|
||||||
|
iversion = VERSION;
|
||||||
|
|
||||||
|
err = _gpgme_op_reset (ctx, 1);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = _gpgme_op_data_lookup (ctx, OPDATA_QUERY_SWDB, &hook,
|
||||||
|
sizeof (*opd), release_op_data);
|
||||||
|
opd = hook;
|
||||||
|
if (err)
|
||||||
|
return TRACE_ERR (err);
|
||||||
|
|
||||||
|
err = _gpgme_engine_op_query_swdb (ctx->engine, name, iversion,
|
||||||
|
&opd->result);
|
||||||
|
return TRACE_ERR (err);
|
||||||
|
}
|
@ -49,6 +49,11 @@
|
|||||||
# define GPG_ERR_FALSE 256
|
# define GPG_ERR_FALSE 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if GPG_ERROR_VERSION_NUMBER < 0x011900 /* 1.25 */
|
||||||
|
# define GPG_ERR_ENGINE_TOO_OLD 300
|
||||||
|
# define GPG_ERR_TOO_OLD 308
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef GPGRT_ATTR_SENTINEL
|
#ifndef GPGRT_ATTR_SENTINEL
|
||||||
# define GPGRT_ATTR_SENTINEL(a) /* */
|
# define GPGRT_ATTR_SENTINEL(a) /* */
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,7 +33,7 @@ noinst_HEADERS = run-support.h
|
|||||||
|
|
||||||
noinst_PROGRAMS = $(TESTS) run-keylist run-export run-import run-sign \
|
noinst_PROGRAMS = $(TESTS) run-keylist run-export run-import run-sign \
|
||||||
run-verify run-encrypt run-identify run-decrypt run-genkey \
|
run-verify run-encrypt run-identify run-decrypt run-genkey \
|
||||||
run-keysign run-tofu
|
run-keysign run-tofu run-swdb
|
||||||
|
|
||||||
|
|
||||||
if RUN_GPG_TESTS
|
if RUN_GPG_TESTS
|
||||||
|
151
tests/run-swdb.c
Normal file
151
tests/run-swdb.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/* run-swdb.c - Test tool for SWDB function
|
||||||
|
* Copyright (C) 2016 g10 Code GmbH
|
||||||
|
*
|
||||||
|
* This file is part of GPGME.
|
||||||
|
*
|
||||||
|
* GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GPGME is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We need to include config.h so that we know whether we are building
|
||||||
|
with large file system (LFS) support. */
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <gpgme.h>
|
||||||
|
|
||||||
|
#define PGM "run-swdb"
|
||||||
|
|
||||||
|
#include "run-support.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int verbose;
|
||||||
|
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
isotimestr (unsigned long value)
|
||||||
|
{
|
||||||
|
time_t t;
|
||||||
|
static char buffer[25+5];
|
||||||
|
struct tm *tp;
|
||||||
|
|
||||||
|
if (!value)
|
||||||
|
return "none";
|
||||||
|
t = value;
|
||||||
|
|
||||||
|
tp = gmtime (&t);
|
||||||
|
snprintf (buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||||
|
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
|
||||||
|
tp->tm_hour, tp->tm_min, tp->tm_sec);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
show_usage (int ex)
|
||||||
|
{
|
||||||
|
fputs ("usage: " PGM " [options] NAME [VERSION]\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" --verbose run in verbose mode\n"
|
||||||
|
" --status print status lines from the backend\n"
|
||||||
|
, stderr);
|
||||||
|
exit (ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int last_argc = -1;
|
||||||
|
gpgme_error_t err;
|
||||||
|
gpgme_ctx_t ctx;
|
||||||
|
gpgme_protocol_t protocol = GPGME_PROTOCOL_GPGCONF;
|
||||||
|
const char *name;
|
||||||
|
const char *iversion;
|
||||||
|
gpgme_query_swdb_result_t result;
|
||||||
|
|
||||||
|
if (argc)
|
||||||
|
{ argc--; argv++; }
|
||||||
|
|
||||||
|
while (argc && last_argc != argc )
|
||||||
|
{
|
||||||
|
last_argc = argc;
|
||||||
|
if (!strcmp (*argv, "--"))
|
||||||
|
{
|
||||||
|
argc--; argv++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!strcmp (*argv, "--help"))
|
||||||
|
show_usage (0);
|
||||||
|
else if (!strcmp (*argv, "--verbose"))
|
||||||
|
{
|
||||||
|
verbose = 1;
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
|
else if (!strncmp (*argv, "--", 2))
|
||||||
|
show_usage (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc < 1 || argc > 2)
|
||||||
|
show_usage (1);
|
||||||
|
name = argv[0];
|
||||||
|
iversion = argc > 1? argv[1] : NULL;
|
||||||
|
|
||||||
|
init_gpgme (protocol);
|
||||||
|
|
||||||
|
err = gpgme_new (&ctx);
|
||||||
|
fail_if_err (err);
|
||||||
|
gpgme_set_protocol (ctx, protocol);
|
||||||
|
|
||||||
|
err = gpgme_op_query_swdb (ctx, name, iversion, 0);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
fprintf (stderr, PGM ": error querying swdb: %s\n", gpg_strerror (err));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = gpgme_op_query_swdb_result (ctx);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
fprintf (stderr, PGM ": error querying swdb: %s\n", "no result");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("package ...: %s\n"
|
||||||
|
"iversion ..: %s\n"
|
||||||
|
"version ...: %s\n",
|
||||||
|
nonnull (result->name),
|
||||||
|
nonnull (result->iversion),
|
||||||
|
nonnull (result->version));
|
||||||
|
printf ("reldate ...: %s\n", isotimestr (result->reldate));
|
||||||
|
printf ("created ...: %s\n", isotimestr (result->created));
|
||||||
|
printf ("retrieved .: %s\n", isotimestr (result->retrieved));
|
||||||
|
printf ("flags .....:%s%s%s%s%s%s%s\n",
|
||||||
|
result->warning? " warning" : "",
|
||||||
|
result->update? " update" : "",
|
||||||
|
result->urgent? " urgent" : "",
|
||||||
|
result->unknown? " unknown" : "",
|
||||||
|
result->tooold? " tooold" : "",
|
||||||
|
result->noinfo? " noinfo" : "",
|
||||||
|
result->error? " error" : "" );
|
||||||
|
|
||||||
|
|
||||||
|
gpgme_release (ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user