From c38b6200396f703917e4c66aca068f90cfbad325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?= Date: Mon, 19 Jun 2023 16:31:17 +0200 Subject: [PATCH] core: Support writing the sign/encrypt output directly to a file * src/engine-gpg.c (gpg_encrypt): Pass output file name to gpg if output has file name set. (gpg_encrypt_sign): Ditto. (gpg_sign): Ditto. * tests/run-encrypt.c (show_usage): New option --output. (main): Parse new option. Set file name on output if --output is given. Do not print output if --output is given. * tests/run-sign.c (show_usage): New option --output. (main): Parse new option. Set file name on output if --output is given. Do not print output if --output is given. -- This change makes it possible to tell gpg (and gpgtar) to write the output (i.e. the signed/encrypted data or the signature or the created archive) directly to a file with given file name instead of piping the output back to gpgme. GnuPG-bug-id: 6530 --- doc/gpgme.texi | 20 ++++++++++++-------- src/engine-gpg.c | 42 +++++++++++++++++++++++++++++++++++------- tests/run-encrypt.c | 24 +++++++++++++++++++++--- tests/run-sign.c | 24 +++++++++++++++++++++--- 4 files changed, 89 insertions(+), 21 deletions(-) diff --git a/doc/gpgme.texi b/doc/gpgme.texi index bc89792a..cf0525fc 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -6332,10 +6332,12 @@ GnuPG 2.4.1. @deftypefun gpgme_error_t gpgme_op_sign (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{sig}}, @w{gpgme_sig_mode_t @var{mode}}) The function @code{gpgme_op_sign} creates a signature for the text in the data object @var{plain} and returns it in the data object -@var{sig}. The type of the signature created is determined by the -@acronym{ASCII} armor (or, if that is not set, by the encoding -specified for @var{sig}), the text mode attributes set for the context -@var{ctx} and the requested signature mode @var{mode}. +@var{sig} or writes it directly to the file set with +@code{gpgme_data_set_file_name} for the data object @var{sig}. The type +of the signature created is determined by the @acronym{ASCII} armor (or, +if that is not set, by the encoding specified for @var{sig}), the text +mode attributes set for the context @var{ctx} and the requested signature +mode @var{mode}. If signature mode @code{GPGME_SIG_MODE_ARCHIVE} is requested, then a signed archive is created from the files and directories given as @@ -6510,10 +6512,12 @@ and then passed to the encryption operation. @deftypefun gpgme_error_t gpgme_op_encrypt (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{recp}[]}, @w{gpgme_encrypt_flags_t @var{flags}}, @w{gpgme_data_t @var{plain}}, @w{gpgme_data_t @var{cipher}}) The function @code{gpgme_op_encrypt} encrypts the plaintext in the data object @var{plain} for the recipients @var{recp} and stores the -ciphertext in the data object @var{cipher}. The type of the -ciphertext created is determined by the @acronym{ASCII} armor (or, if -that is not set, by the encoding specified for @var{cipher}) and the -text mode attributes set for the context @var{ctx}. +ciphertext in the data object @var{cipher} or writes it directly to the +file set with @code{gpgme_data_set_file_name} for the data object +@var{cipher}. The type of the ciphertext created is determined by the +@acronym{ASCII} armor (or, if that is not set, by the encoding specified +for @var{cipher}) and the text mode attributes set for the context +@var{ctx}. If the flag @code{GPGME_ENCRYPT_ARCHIVE} is set, then an encrypted archive is created from the files and directories given as NUL-separated diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 03e648f3..ba45e55a 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -2367,9 +2367,17 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring, if (!err) err = add_arg (gpg, "--output"); if (!err) - err = add_arg (gpg, "-"); - if (!err) - err = add_data (gpg, ciph, 1, 1); + { + const char *output = gpgme_data_get_file_name (ciph); + if (output) + err = add_arg (gpg, output); + else + { + err = add_arg (gpg, "-"); + if (!err) + err = add_data (gpg, ciph, 1, 1); + } + } if (gpg->flags.use_gpgtar) { const char *file_name = gpgme_data_get_file_name (plain); @@ -2479,9 +2487,17 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err) err = add_arg (gpg, "--output"); if (!err) - err = add_arg (gpg, "-"); - if (!err) - err = add_data (gpg, ciph, 1, 1); + { + const char *output = gpgme_data_get_file_name (ciph); + if (output) + err = add_arg (gpg, output); + else + { + err = add_arg (gpg, "-"); + if (!err) + err = add_data (gpg, ciph, 1, 1); + } + } if (gpg->flags.use_gpgtar) { const char *file_name = gpgme_data_get_file_name (plain); @@ -3559,6 +3575,7 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, { engine_gpg_t gpg = engine; gpgme_error_t err; + const char *output = NULL; (void)include_certs; @@ -3599,6 +3616,17 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, if (!err) err = append_args_from_sig_notations (gpg, ctx, NOTATION_FLAG_SIG); + if (!err) + { + output = gpgme_data_get_file_name (out); + if (output) + { + err = add_arg (gpg, "--output"); + if (!err) + err = add_arg (gpg, output); + } + } + /* Tell the gpg object about the data. */ if (gpg->flags.use_gpgtar) { @@ -3634,7 +3662,7 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out, err = add_data (gpg, in, -1, 0); } - if (!err) + if (!err && !output) err = add_data (gpg, out, 1, 1); if (!err) diff --git a/tests/run-encrypt.c b/tests/run-encrypt.c index 7266ba56..94a66283 100644 --- a/tests/run-encrypt.c +++ b/tests/run-encrypt.c @@ -152,6 +152,7 @@ show_usage (int ex) " --symmetric encrypt symmetric (OpenPGP only)\n" " --archive encrypt given file or directory into an archive\n" " --directory DIR switch to directory DIR before encrypting into an archive\n" + " --output FILE write output to FILE instead of stdout\n" " --diagnostics print diagnostics\n" " --cancel N cancel after N progress lines\n" , stderr); @@ -177,6 +178,7 @@ main (int argc, char **argv) int keycount = 0; char *keystring = NULL; const char *directory = NULL; + const char *output = NULL; int i; gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST; gpgme_off_t offset; @@ -294,6 +296,14 @@ main (int argc, char **argv) directory = *argv; argc--; argv++; } + else if (!strcmp (*argv, "--output")) + { + argc--; argv++; + if (!argc) + show_usage (1); + output = *argv; + argc--; argv++; + } else if (!strcmp (*argv, "--diagnostics")) { diagnostics = 1; @@ -410,6 +420,11 @@ main (int argc, char **argv) err = gpgme_data_new (&out); fail_if_err (err); + if (output) + { + err = gpgme_data_set_file_name (out, output); + fail_if_err (err); + } if (sign) err = gpgme_op_encrypt_sign_ext (ctx, keycount ? keys : NULL, keystring, @@ -451,9 +466,12 @@ main (int argc, char **argv) exit (1); } - fputs ("Begin Output:\n", stdout); - print_data (out); - fputs ("End Output.\n", stdout); + if (!output) + { + fputs ("Begin Output:\n", stdout); + print_data (out); + fputs ("End Output.\n", stdout); + } gpgme_data_release (out); gpgme_data_release (in); diff --git a/tests/run-sign.c b/tests/run-sign.c index 84d7c070..07482dd5 100644 --- a/tests/run-sign.c +++ b/tests/run-sign.c @@ -89,6 +89,7 @@ show_usage (int ex) " --clear create a clear text signature\n" " --archive create a signed archive with the given file or directory\n" " --directory DIR switch to directory DIR before creating the archive\n" + " --output FILE write output to FILE instead of stdout\n" " --diagnostics print diagnostics\n" , stderr); exit (ex); @@ -103,6 +104,7 @@ main (int argc, char **argv) gpgme_ctx_t ctx; const char *key_string = NULL; const char *directory = NULL; + const char *output = NULL; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; gpgme_sig_mode_t sigmode = GPGME_SIG_MODE_NORMAL; gpgme_data_t in, out; @@ -196,6 +198,14 @@ main (int argc, char **argv) directory = *argv; argc--; argv++; } + else if (!strcmp (*argv, "--output")) + { + argc--; argv++; + if (!argc) + show_usage (1); + output = *argv; + argc--; argv++; + } else if (!strcmp (*argv, "--diagnostics")) { diagnostics = 1; @@ -283,6 +293,11 @@ main (int argc, char **argv) err = gpgme_data_new (&out); fail_if_err (err); + if (output) + { + err = gpgme_data_set_file_name (out, output); + fail_if_err (err); + } err = gpgme_op_sign (ctx, in, out, sigmode); result = gpgme_op_sign_result (ctx); @@ -319,9 +334,12 @@ main (int argc, char **argv) if ((s = gpgme_get_ctx_flag (ctx, "redraw")) && *s) fputs ("Screen redraw suggested\n", stdout); - fputs ("Begin Output:\n", stdout); - print_data (out); - fputs ("End Output.\n", stdout); + if (!output) + { + fputs ("Begin Output:\n", stdout); + print_data (out); + fputs ("End Output.\n", stdout); + } gpgme_data_release (out); gpgme_data_release (in);