Return an error for some export key operations.

* src/context.h (OPDATA_EXPORT): New.
* src/export.c (op_data_t): New.
(release_op_data): New.
(parse_error): New.
(export_status_handler): New.
(export_start, export_ext_start): Prepare op_data.
(gpgme_op_export_ext, gpgme_op_export_keys): Return an error from the
status handler.
--

To support an error return also for the async functions we need to
extend the API.  Until we have done that this new features helps at
least in some cases; in particular for --send-keys.
This commit is contained in:
Werner Koch 2014-12-08 11:19:16 +01:00
parent 162c87f069
commit 05258d4275
2 changed files with 127 additions and 4 deletions

View File

@ -38,7 +38,7 @@ typedef enum
OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT,
OPDATA_PASSWD
OPDATA_PASSWD, OPDATA_EXPORT
} ctx_op_data_id_t;

View File

@ -1,6 +1,6 @@
/* export.c - Export a key.
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2010 g10 Code GmbH
Copyright (C) 2001-2004, 2010, 2014 g10 Code GmbH
This file is part of GPGME.
@ -31,9 +31,82 @@
#include "ops.h"
/* Local operation data. */
typedef struct
{
gpg_error_t err; /* Error encountred during the export. */
} *op_data_t;
static void
release_op_data (void *hook)
{
op_data_t opd = (op_data_t) hook;
(void)opd; /* Nothing to release here. */
}
/* Parse an error status line. Return the error location and the
error code. The function may modify ARGS. */
static char *
parse_error (char *args, gpg_error_t *r_err)
{
char *where = strchr (args, ' ');
char *which;
if (where)
{
*where = '\0';
which = where + 1;
where = strchr (which, ' ');
if (where)
*where = '\0';
where = args;
}
else
{
*r_err = trace_gpg_error (GPG_ERR_INV_ENGINE);
return NULL;
}
*r_err = atoi (which);
return where;
}
static gpgme_error_t
export_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
gpgme_error_t err;
void *hook;
op_data_t opd;
const char *loc;
err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
opd = hook;
if (err)
return err;
switch (code)
{
case GPGME_STATUS_ERROR:
loc = parse_error (args, &err);
if (!loc)
return err;
else if (opd->err)
; /* We only want to report the first error. */
else if (!strcmp (loc, "keyserver_send"))
opd->err = err;
break;
default:
break;
}
return 0;
}
@ -43,6 +116,8 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
gpgme_export_mode_t mode, gpgme_data_t keydata)
{
gpgme_error_t err;
void *hook;
op_data_t opd;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL)))
@ -64,6 +139,12 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
if (err)
return err;
err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook,
sizeof (*opd), release_op_data);
opd = hook;
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
return _gpgme_engine_op_export (ctx->engine, pattern, mode, keydata,
@ -114,6 +195,8 @@ export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
gpgme_export_mode_t mode, gpgme_data_t keydata)
{
gpgme_error_t err;
void *hook;
op_data_t opd;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL)))
@ -134,6 +217,12 @@ export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
if (err)
return err;
err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook,
sizeof (*opd), release_op_data);
opd = hook;
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
return _gpgme_engine_op_export_ext (ctx->engine, pattern, mode, keydata,
@ -196,7 +285,24 @@ gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
err = export_ext_start (ctx, 1, pattern, mode, keydata);
if (!err)
{
err = _gpgme_wait_one (ctx);
if (!err)
{
/* For this synchronous operation we check for operational
errors and return them. For asynchronous operations
there is currently no way to do this - we need to add a
gpgme_op_export_result function to fix that. */
void *hook;
op_data_t opd;
err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
opd = hook;
if (!err)
err = opd->err;
}
}
return TRACE_ERR (err);
}
@ -319,7 +425,24 @@ gpgme_op_export_keys (gpgme_ctx_t ctx,
err = export_keys_start (ctx, 1, keys, mode, keydata);
if (!err)
{
err = _gpgme_wait_one (ctx);
if (!err)
{
/* For this synchronous operation we check for operational
errors and return them. For asynchronous operations
there is currently no way to do this - we need to add a
gpgme_op_export_result function to fix that. */
void *hook;
op_data_t opd;
err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
opd = hook;
if (!err)
err = opd->err;
}
}
return TRACE_ERR (err);
}