core: Make use of the "size-hint" in engine-gpg.
authorWerner Koch <wk@gnupg.org>
Fri, 12 Aug 2016 13:24:46 +0000 (15:24 +0200)
committerWerner Koch <wk@gnupg.org>
Fri, 12 Aug 2016 13:32:31 +0000 (15:32 +0200)
* src/engine-gpg.c: Include data.h.
(add_input_size_hint): New.
(gpg_decrypt, gpg_encrypt, gpg_encrypt_sign, gpg_sign)
(gpg_verify): Call new function,

* tests/run-encrypt.c (status_cb): Print to stderr.
(progress_cb): New.o
(main): Add option --progress.  Print full-status lines.  Provide a
size for the input data.

Signed-off-by: Werner Koch <wk@gnupg.org>
doc/gpgme.texi
src/engine-gpg.c
tests/run-encrypt.c

index 2bbed28..8b0ec52 100644 (file)
@@ -2177,6 +2177,30 @@ The function @code{gpgme_data_set_encoding} changes the encoding of
 the data object with the handle @var{dh} to @var{enc}.
 @end deftypefun
 
+@deftypefun {gpgme_error_t} gpgme_data_set_flag  @
+            (@w{gpgme_data_t @var{dh}}, @
+            @w{const char *@var{name}}, @
+            @w{const char *@var{value}})
+
+Some minor properties of the data object can be controlled with flags
+set by this function.  The properties are identified by the following
+values for @var{name}:
+
+@table @code
+@item size-hint
+The value is a decimal number with the length gpgme shall assume for
+this data object.  This is useful if the data is provided by callbacks
+or via file descriptors but the applications knows the total size of
+the data.  If this is set the OpenPGP engine may use this to decide on
+buffer allocation strategies and to provide a total value for its
+progress information.
+
+@end table
+
+This function returns @code{0} on success.
+@end deftypefun
+
+
 @node Data Buffer Convenience
 @subsection Data Buffer Convenience Functions
 @cindex data buffer, convenience
index efab80a..3edac6c 100644 (file)
@@ -42,6 +42,7 @@
 #include "priv-io.h"
 #include "sema.h"
 #include "debug.h"
+#include "data.h"
 
 #include "engine-backend.h"
 
@@ -1483,6 +1484,35 @@ start (engine_gpg_t gpg)
 }
 
 
+/* Add the --input-size-hint option if requested.  */
+static gpgme_error_t
+add_input_size_hint (engine_gpg_t gpg, gpgme_data_t data)
+{
+  gpgme_error_t err;
+  gpgme_off_t value = _gpgme_data_get_size_hint (data);
+  char numbuf[50];  /* Large enough for even 2^128 in base-10.  */
+  char *p;
+
+  if (!value || !have_gpg_version (gpg, "2.1.15"))
+    return 0;
+
+  err = add_arg (gpg, "--input-size-hint");
+  if (!err)
+    {
+      p = numbuf + sizeof numbuf;
+      *--p = 0;
+      do
+        {
+          *--p = '0' + (value % 10);
+          value /= 10;
+        }
+      while (value);
+      err = add_arg (gpg, p);
+    }
+  return err;
+}
+
+
 static gpgme_error_t
 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
 {
@@ -1499,6 +1529,8 @@ gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
   if (!err)
     err = add_data (gpg, plain, 1, 1);
   if (!err)
+    err = add_input_size_hint (gpg, ciph);
+  if (!err)
     err = add_arg (gpg, "--");
   if (!err)
     err = add_data (gpg, ciph, -1, 0);
@@ -1764,6 +1796,8 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
        err = add_arg (gpg, gpgme_data_get_file_name (plain));
     }
   if (!err)
+    err = add_input_size_hint (gpg, plain);
+  if (!err)
     err = add_arg (gpg, "--");
   if (!err)
     err = add_data (gpg, plain, -1, 0);
@@ -1837,6 +1871,8 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
        err = add_arg (gpg, gpgme_data_get_file_name (plain));
     }
   if (!err)
+    err = add_input_size_hint (gpg, plain);
+  if (!err)
     err = add_arg (gpg, "--");
   if (!err)
     err = add_data (gpg, plain, -1, 0);
@@ -2291,7 +2327,7 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
   err = add_arg (gpg, "--with-colons");
 
   /* Since gpg 2.1.15 fingerprints are always printed, thus there is
-   * no more need to explictly reqeust them.  */
+   * no more need to explictly request them.  */
   if (!have_gpg_version (gpg, "2.1.15"))
     {
       if (!err)
@@ -2436,6 +2472,8 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
 
   /* Tell the gpg object about the data.  */
   if (!err)
+    err = add_input_size_hint (gpg, in);
+  if (!err)
     err = add_arg (gpg, "--");
   if (!err)
     err = add_data (gpg, in, -1, 0);
@@ -2481,11 +2519,12 @@ gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
   if (plaintext)
     {
       /* Normal or cleartext signature.  */
-
       err = add_arg (gpg, "--output");
       if (!err)
        err = add_arg (gpg, "-");
       if (!err)
+        err = add_input_size_hint (gpg, sig);
+      if (!err)
        err = add_arg (gpg, "--");
       if (!err)
        err = add_data (gpg, sig, -1, 0);
@@ -2496,6 +2535,8 @@ gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
     {
       err = add_arg (gpg, "--verify");
       if (!err)
+        err = add_input_size_hint (gpg, signed_text);
+      if (!err)
        err = add_arg (gpg, "--");
       if (!err)
        err = add_data (gpg, sig, -1, 0);
index 210f88a..b94b028 100644 (file)
 
 static int verbose;
 
+
 static gpg_error_t
 status_cb (void *opaque, const char *keyword, const char *value)
 {
   (void)opaque;
-  printf ("status_cb: %s %s\n", keyword, value);
+  fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
   return 0;
 }
 
 
 static void
+progress_cb (void *opaque, const char *what, int type, int current, int total)
+{
+  (void)opaque;
+  (void)type;
+
+  if (total)
+    fprintf (stderr, "progress for '%s' %u%% (%d of %d)\n",
+             nonnull (what),
+             (unsigned)(((double)current / total) * 100), current, total);
+  else
+    fprintf (stderr, "progress for '%s' %d\n", nonnull(what), current);
+  fflush (stderr);
+}
+
+
+static void
 print_result (gpgme_encrypt_result_t result)
 {
   gpgme_invalid_key_t invkey;
@@ -65,6 +82,7 @@ show_usage (int ex)
          "Options:\n"
          "  --verbose        run in verbose mode\n"
          "  --status         print status lines from the backend\n"
+         "  --progress       print progress info\n"
          "  --openpgp        use the OpenPGP protocol (default)\n"
          "  --cms            use the CMS protocol\n"
          "  --uiserver       use the UI server\n"
@@ -87,12 +105,14 @@ main (int argc, char **argv)
   gpgme_data_t in, out;
   gpgme_encrypt_result_t result;
   int print_status = 0;
+  int print_progress = 0;
   int use_loopback = 0;
   char *keyargs[10];
   gpgme_key_t keys[10+1];
   int keycount = 0;
   int i;
   gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;
+  gpgme_off_t offset;
 
   if (argc)
     { argc--; argv++; }
@@ -120,6 +140,11 @@ main (int argc, char **argv)
           print_status = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--progress"))
+        {
+          print_progress = 1;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--openpgp"))
         {
           protocol = GPGME_PROTOCOL_OpenPGP;
@@ -179,7 +204,12 @@ main (int argc, char **argv)
   gpgme_set_protocol (ctx, protocol);
   gpgme_set_armor (ctx, 1);
   if (print_status)
-    gpgme_set_status_cb (ctx, status_cb, NULL);
+    {
+      gpgme_set_status_cb (ctx, status_cb, NULL);
+      gpgme_set_ctx_flag (ctx, "full-status", "1");
+    }
+  if (print_progress)
+    gpgme_set_progress_cb (ctx, progress_cb, NULL);
   if (use_loopback)
     {
       gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
@@ -200,6 +230,41 @@ main (int argc, char **argv)
                *argv, gpg_strerror (err));
       exit (1);
     }
+  offset = gpgme_data_seek (in, 0, SEEK_END);
+  if (offset == (gpgme_off_t)(-1))
+    {
+      err = gpg_error_from_syserror ();
+      fprintf (stderr, PGM ": error seeking `%s': %s\n",
+               *argv, gpg_strerror (err));
+      exit (1);
+    }
+  if (gpgme_data_seek (in, 0, SEEK_SET) == (gpgme_off_t)(-1))
+    {
+      err = gpg_error_from_syserror ();
+      fprintf (stderr, PGM ": error seeking `%s': %s\n",
+               *argv, gpg_strerror (err));
+      exit (1);
+    }
+  {
+    char numbuf[50];
+    char *p;
+
+    p = numbuf + sizeof numbuf;
+    *--p = 0;
+    do
+      {
+        *--p = '0' + (offset % 10);
+        offset /= 10;
+      }
+    while (offset);
+    err = gpgme_data_set_flag (in, "size-hint", p);
+    if (err)
+      {
+        fprintf (stderr, PGM ": error setting size-hint for `%s': %s\n",
+                 *argv, gpg_strerror (err));
+        exit (1);
+      }
+  }
 
   err = gpgme_data_new (&out);
   fail_if_err (err);