diff options
| author | Werner Koch <[email protected]> | 2014-12-08 10:19:16 +0000 | 
|---|---|---|
| committer | Werner Koch <[email protected]> | 2014-12-08 10:19:16 +0000 | 
| commit | 05258d427513a933f01d4df13aca834d797f91e7 (patch) | |
| tree | cc6375e4e4e24ef0231b7ded13956c99d92e7aee | |
| parent | Post release updates (diff) | |
| download | gpgme-05258d427513a933f01d4df13aca834d797f91e7.tar.gz gpgme-05258d427513a933f01d4df13aca834d797f91e7.zip | |
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.
| -rw-r--r-- | src/context.h | 2 | ||||
| -rw-r--r-- | src/export.c | 129 | 
2 files changed, 127 insertions, 4 deletions
| diff --git a/src/context.h b/src/context.h index e9214368..745ffa89 100644 --- a/src/context.h +++ b/src/context.h @@ -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; diff --git a/src/export.c b/src/export.c index 81a23b04..8930aa68 100644 --- a/src/export.c +++ b/src/export.c @@ -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); +    { +      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); +    { +      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);  } | 
