From fe1e8e71aa18b4ac6471292b2894b8859f42f7c8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 12 Aug 2016 15:24:46 +0200 Subject: [PATCH] core: Make use of the "size-hint" in engine-gpg. * 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 --- doc/gpgme.texi | 24 ++++++++++++++++ src/engine-gpg.c | 45 +++++++++++++++++++++++++++-- tests/run-encrypt.c | 69 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 134 insertions(+), 4 deletions(-) diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 2bbed285..8b0ec528 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -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 diff --git a/src/engine-gpg.c b/src/engine-gpg.c index efab80ac..3edac6ca 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -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) { @@ -1498,6 +1528,8 @@ gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain) err = add_arg (gpg, "-"); 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) @@ -1763,6 +1795,8 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, if (!err) 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) @@ -1836,6 +1870,8 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err) 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) @@ -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) @@ -2435,6 +2471,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) @@ -2481,10 +2519,11 @@ 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) @@ -2495,6 +2534,8 @@ gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, else { err = add_arg (gpg, "--verify"); + if (!err) + err = add_input_size_hint (gpg, signed_text); if (!err) err = add_arg (gpg, "--"); if (!err) diff --git a/tests/run-encrypt.c b/tests/run-encrypt.c index 210f88ab..b94b0288 100644 --- a/tests/run-encrypt.c +++ b/tests/run-encrypt.c @@ -36,15 +36,32 @@ 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) { @@ -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);