aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2022-03-21 12:06:00 +0000
committerWerner Koch <[email protected]>2022-03-21 12:21:20 +0000
commite5ef5e3b914d5c8f0b841b078b164500ea157804 (patch)
tree5a30d08231a5f9fae6598ec3bd434dcaa5793662
parentcommon: Fix another race condition, and address the other one. (diff)
downloadgnupg-e5ef5e3b914d5c8f0b841b078b164500ea157804.tar.gz
gnupg-e5ef5e3b914d5c8f0b841b078b164500ea157804.zip
gpgtar: Finally use a pipe for decryption.
* tools/gpgtar.h (opt): Add new flags. * tools/gpgtar.c: new options --batch, --yes, --no, --status-fd, and --require-compliance. (main): Init signals. * tools/gpgtar-create.c: Add new header files. (gpgtar_create): Rework to use a pipe for encryption and signing. * tools/gpgtar-list.c: Add new header files. (gpgtar_list): Rework to use a pipe for decryption. * tools/gpgtar-extract.c: Add new header files. (gpgtar_extract): Rework to use a pipe for decryption. -- Fixes-commit: 40dbee86f3043aff8a8c2055521e270318e33068
-rw-r--r--doc/tools.texi25
-rw-r--r--tools/gpgtar-create.c139
-rw-r--r--tools/gpgtar-extract.c104
-rw-r--r--tools/gpgtar-list.c104
-rw-r--r--tools/gpgtar.c26
-rw-r--r--tools/gpgtar.h5
6 files changed, 266 insertions, 137 deletions
diff --git a/doc/tools.texi b/doc/tools.texi
index 0acf4f49c..cff649752 100644
--- a/doc/tools.texi
+++ b/doc/tools.texi
@@ -2000,6 +2000,31 @@ This option is reserved and shall not be used. It will eventually be
used to encrypt or sign using the CMS protocol; but that is not yet
implemented.
+@item --batch
+@opindex batch
+Use batch mode. Never ask but use the default action. This option is
+passed directly to @command{gpg}.
+
+@item --yes
+@opindex yes
+Assume "yes" on most questions. Often used together with
+@option{--batch} to overwrite existing files. This option is passed
+directly to @command{gpg}.
+
+@item --no
+@opindex no
+Assume "no" on most questions. This option is passed directly to
+@command{gpg}.
+
+@item --require-compliance
+@opindex require-compliance
+This option is passed directly to @command{gpg}.
+
+@item --status-fd @var{n}
+@opindex status-fd
+Write special status strings to the file descriptor @var{n}.
+See the file DETAILS in the documentation for a listing of them.
+
@item --set-filename @var{file}
@opindex set-filename
diff --git a/tools/gpgtar-create.c b/tools/gpgtar-create.c
index d17467077..7d7844960 100644
--- a/tools/gpgtar-create.c
+++ b/tools/gpgtar-create.c
@@ -38,7 +38,8 @@
#endif /*!HAVE_W32_SYSTEM*/
#include "../common/i18n.h"
-#include "../common/exectool.h"
+#include <gpg-error.h>
+#include "../common/exechelp.h"
#include "../common/sysutils.h"
#include "../common/ccparray.h"
#include "../common/membuf.h"
@@ -992,8 +993,8 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
tar_header_t hdr, *start_tail;
estream_t files_from_stream = NULL;
estream_t outstream = NULL;
- estream_t cipher_stream = NULL;
int eof_seen = 0;
+ pid_t pid = (pid_t)(-1);
memset (scanctrl, 0, sizeof *scanctrl);
scanctrl->flist_tail = &scanctrl->flist;
@@ -1136,64 +1137,37 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
if (files_from_stream && files_from_stream != es_stdin)
es_fclose (files_from_stream);
- if (opt.outfile)
- {
- if (!strcmp (opt.outfile, "-"))
- outstream = es_stdout;
- else
- outstream = es_fopen (opt.outfile, "wb,sysopen");
- if (!outstream)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
- }
- else
- {
- outstream = es_stdout;
- }
-
- if (outstream == es_stdout)
- es_set_binary (es_stdout);
-
- if (encrypt || sign)
- {
- cipher_stream = outstream;
- outstream = es_fopenmem (0, "rwb");
- if (! outstream)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
- }
-
- for (hdr = scanctrl->flist; hdr; hdr = hdr->next)
- {
- err = write_file (outstream, hdr);
- if (err)
- goto leave;
- }
- err = write_eof_mark (outstream);
- if (err)
- goto leave;
-
if (encrypt || sign)
{
strlist_t arg;
ccparray_t ccp;
const char **argv;
- err = es_fseek (outstream, 0, SEEK_SET);
- if (err)
- goto leave;
-
/* '--encrypt' may be combined with '--symmetric', but 'encrypt'
- is set either way. Clear it if no recipients are specified.
- XXX: Fix command handling. */
+ * is set either way. Clear it if no recipients are specified.
+ */
if (opt.symmetric && opt.recipients == NULL)
encrypt = 0;
ccparray_init (&ccp, 0);
+ if (opt.batch)
+ ccparray_put (&ccp, "--batch");
+ if (opt.answer_yes)
+ ccparray_put (&ccp, "--yes");
+ if (opt.answer_no)
+ ccparray_put (&ccp, "--no");
+ if (opt.require_compliance)
+ ccparray_put (&ccp, "--require-compliance");
+ if (opt.status_fd != -1)
+ {
+ char tmpbuf[40];
+
+ snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd);
+ ccparray_put (&ccp, tmpbuf);
+ }
+
+ ccparray_put (&ccp, "--output");
+ ccparray_put (&ccp, opt.outfile? opt.outfile : "-");
if (encrypt)
ccparray_put (&ccp, "--encrypt");
if (sign)
@@ -1221,27 +1195,76 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
goto leave;
}
- err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- outstream, NULL, cipher_stream, NULL, NULL);
+ err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL,
+ (GNUPG_SPAWN_KEEP_STDOUT
+ | GNUPG_SPAWN_KEEP_STDERR),
+ &outstream, NULL, NULL, &pid);
xfree (argv);
if (err)
goto leave;
+ es_set_binary (outstream);
+ }
+ else if (opt.outfile) /* No crypto */
+ {
+ if (!strcmp (opt.outfile, "-"))
+ outstream = es_stdout;
+ else
+ outstream = es_fopen (opt.outfile, "wb,sysopen");
+ if (!outstream)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ if (outstream == es_stdout)
+ es_set_binary (es_stdout);
+
+ }
+ else /* Also no crypto. */
+ {
+ outstream = es_stdout;
+ es_set_binary (outstream);
+ }
+
+
+ for (hdr = scanctrl->flist; hdr; hdr = hdr->next)
+ {
+ err = write_file (outstream, hdr);
+ if (err)
+ goto leave;
+ }
+ err = write_eof_mark (outstream);
+ if (err)
+ goto leave;
+
+
+ if (pid != (pid_t)(-1))
+ {
+ int exitcode;
+
+ err = es_fclose (outstream);
+ outstream = NULL;
+ if (err)
+ log_error ("error closing pipe: %s\n", gpg_strerror (err));
+ else
+ {
+ err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode);
+ if (err)
+ log_error ("running %s failed (exitcode=%d): %s",
+ opt.gpg_program, exitcode, gpg_strerror (err));
+ gnupg_release_process (pid);
+ pid = (pid_t)(-1);
+ }
}
leave:
if (!err)
{
gpg_error_t first_err;
- if (outstream != es_stdout)
+ if (outstream != es_stdout || pid != (pid_t)(-1))
first_err = es_fclose (outstream);
else
first_err = es_fflush (outstream);
outstream = NULL;
- if (cipher_stream != es_stdout)
- err = es_fclose (cipher_stream);
- else
- err = es_fflush (cipher_stream);
- cipher_stream = NULL;
if (! err)
err = first_err;
}
@@ -1251,8 +1274,6 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
opt.outfile ? opt.outfile : "-", gpg_strerror (err));
if (outstream && outstream != es_stdout)
es_fclose (outstream);
- if (cipher_stream && cipher_stream != es_stdout)
- es_fclose (cipher_stream);
if (opt.outfile)
gnupg_remove (opt.outfile);
}
diff --git a/tools/gpgtar-extract.c b/tools/gpgtar-extract.c
index 5fad893c5..5f907733b 100644
--- a/tools/gpgtar-extract.c
+++ b/tools/gpgtar-extract.c
@@ -30,7 +30,8 @@
#include <unistd.h>
#include "../common/i18n.h"
-#include "../common/exectool.h"
+#include <gpg-error.h>
+#include "../common/exechelp.h"
#include "../common/sysutils.h"
#include "../common/ccparray.h"
#include "gpgtar.h"
@@ -316,55 +317,45 @@ gpg_error_t
gpgtar_extract (const char *filename, int decrypt)
{
gpg_error_t err;
- estream_t stream;
- estream_t cipher_stream = NULL;
+ estream_t stream = NULL;
tar_header_t header = NULL;
strlist_t extheader = NULL;
const char *dirprefix = NULL;
char *dirname = NULL;
struct tarinfo_s tarinfo_buffer;
tarinfo_t tarinfo = &tarinfo_buffer;
+ pid_t pid = (pid_t)(-1);
memset (&tarinfo_buffer, 0, sizeof tarinfo_buffer);
- if (filename)
- {
- if (!strcmp (filename, "-"))
- stream = es_stdin;
- else
- stream = es_fopen (filename, "rb,sysopen");
- if (!stream)
- {
- err = gpg_error_from_syserror ();
- log_error ("error opening '%s': %s\n", filename, gpg_strerror (err));
- return err;
- }
- }
- else
- stream = es_stdin;
-
- if (stream == es_stdin)
- es_set_binary (es_stdin);
-
if (decrypt)
{
strlist_t arg;
ccparray_t ccp;
const char **argv;
- cipher_stream = stream;
- stream = es_fopenmem (0, "rwb");
- if (! stream)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
-
ccparray_init (&ccp, 0);
+ if (opt.batch)
+ ccparray_put (&ccp, "--batch");
+ if (opt.require_compliance)
+ ccparray_put (&ccp, "--require-compliance");
+ if (opt.status_fd != -1)
+ {
+ char tmpbuf[40];
+ snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd);
+ ccparray_put (&ccp, tmpbuf);
+ }
+ ccparray_put (&ccp, "--output");
+ ccparray_put (&ccp, "-");
ccparray_put (&ccp, "--decrypt");
for (arg = opt.gpg_arguments; arg; arg = arg->next)
ccparray_put (&ccp, arg->d);
+ if (filename)
+ {
+ ccparray_put (&ccp, "--");
+ ccparray_put (&ccp, filename);
+ }
ccparray_put (&ccp, NULL);
argv = ccparray_get (&ccp, NULL);
@@ -374,17 +365,37 @@ gpgtar_extract (const char *filename, int decrypt)
goto leave;
}
- err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- cipher_stream, NULL, stream, NULL, NULL);
+ err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL,
+ ((filename? 0 : GNUPG_SPAWN_KEEP_STDIN)
+ | GNUPG_SPAWN_KEEP_STDERR),
+ NULL, &stream, NULL, &pid);
xfree (argv);
if (err)
goto leave;
-
- err = es_fseek (stream, 0, SEEK_SET);
- if (err)
- goto leave;
+ es_set_binary (stream);
+ }
+ else if (filename)
+ {
+ if (!strcmp (filename, "-"))
+ stream = es_stdin;
+ else
+ stream = es_fopen (filename, "rb,sysopen");
+ if (!stream)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error opening '%s': %s\n", filename, gpg_strerror (err));
+ return err;
+ }
+ if (stream == es_stdin)
+ es_set_binary (es_stdin);
+ }
+ else
+ {
+ stream = es_stdin;
+ es_set_binary (es_stdin);
}
+
if (opt.directory)
dirname = xtrystrdup (opt.directory);
else
@@ -435,6 +446,25 @@ gpgtar_extract (const char *filename, int decrypt)
header = NULL;
}
+ if (pid != (pid_t)(-1))
+ {
+ int exitcode;
+
+ err = es_fclose (stream);
+ stream = NULL;
+ if (err)
+ log_error ("error closing pipe: %s\n", gpg_strerror (err));
+ else
+ {
+ err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode);
+ if (err)
+ log_error ("running %s failed (exitcode=%d): %s",
+ opt.gpg_program, exitcode, gpg_strerror (err));
+ gnupg_release_process (pid);
+ pid = (pid_t)(-1);
+ }
+ }
+
leave:
free_strlist (extheader);
@@ -442,7 +472,5 @@ gpgtar_extract (const char *filename, int decrypt)
xfree (dirname);
if (stream != es_stdin)
es_fclose (stream);
- if (stream != cipher_stream)
- es_fclose (cipher_stream);
return err;
}
diff --git a/tools/gpgtar-list.c b/tools/gpgtar-list.c
index 413abeed3..9e175437b 100644
--- a/tools/gpgtar-list.c
+++ b/tools/gpgtar-list.c
@@ -27,8 +27,10 @@
#include <string.h>
#include "../common/i18n.h"
+#include <gpg-error.h>
#include "gpgtar.h"
-#include "../common/exectool.h"
+#include "../common/exechelp.h"
+#include "../common/sysutils.h"
#include "../common/ccparray.h"
@@ -453,53 +455,43 @@ gpg_error_t
gpgtar_list (const char *filename, int decrypt)
{
gpg_error_t err;
- estream_t stream;
- estream_t cipher_stream = NULL;
+ estream_t stream = NULL;
tar_header_t header = NULL;
strlist_t extheader = NULL;
struct tarinfo_s tarinfo_buffer;
tarinfo_t tarinfo = &tarinfo_buffer;
+ pid_t pid = (pid_t)(-1);
memset (&tarinfo_buffer, 0, sizeof tarinfo_buffer);
- if (filename)
- {
- if (!strcmp (filename, "-"))
- stream = es_stdin;
- else
- stream = es_fopen (filename, "rb");
- if (!stream)
- {
- err = gpg_error_from_syserror ();
- log_error ("error opening '%s': %s\n", filename, gpg_strerror (err));
- return err;
- }
- }
- else
- stream = es_stdin;
-
- if (stream == es_stdin)
- es_set_binary (es_stdin);
-
if (decrypt)
{
strlist_t arg;
ccparray_t ccp;
const char **argv;
- cipher_stream = stream;
- stream = es_fopenmem (0, "rwb");
- if (! stream)
- {
- err = gpg_error_from_syserror ();
- goto leave;
- }
-
ccparray_init (&ccp, 0);
+ if (opt.batch)
+ ccparray_put (&ccp, "--batch");
+ if (opt.require_compliance)
+ ccparray_put (&ccp, "--require-compliance");
+ if (opt.status_fd != -1)
+ {
+ char tmpbuf[40];
+ snprintf (tmpbuf, sizeof tmpbuf, "--status-fd=%d", opt.status_fd);
+ ccparray_put (&ccp, tmpbuf);
+ }
+ ccparray_put (&ccp, "--output");
+ ccparray_put (&ccp, "-");
ccparray_put (&ccp, "--decrypt");
for (arg = opt.gpg_arguments; arg; arg = arg->next)
ccparray_put (&ccp, arg->d);
+ if (filename)
+ {
+ ccparray_put (&ccp, "--");
+ ccparray_put (&ccp, filename);
+ }
ccparray_put (&ccp, NULL);
argv = ccparray_get (&ccp, NULL);
@@ -509,15 +501,34 @@ gpgtar_list (const char *filename, int decrypt)
goto leave;
}
- err = gnupg_exec_tool_stream (opt.gpg_program, argv,
- cipher_stream, NULL, stream, NULL, NULL);
+ err = gnupg_spawn_process (opt.gpg_program, argv, NULL, NULL,
+ ((filename? 0 : GNUPG_SPAWN_KEEP_STDIN)
+ | GNUPG_SPAWN_KEEP_STDERR),
+ NULL, &stream, NULL, &pid);
xfree (argv);
if (err)
goto leave;
-
- err = es_fseek (stream, 0, SEEK_SET);
- if (err)
- goto leave;
+ es_set_binary (stream);
+ }
+ else if (filename) /* No decryption requested. */
+ {
+ if (!strcmp (filename, "-"))
+ stream = es_stdin;
+ else
+ stream = es_fopen (filename, "rb,sysopen");
+ if (!stream)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("error opening '%s': %s\n", filename, gpg_strerror (err));
+ goto leave;
+ }
+ if (stream == es_stdin)
+ es_set_binary (es_stdin);
+ }
+ else
+ {
+ stream = es_stdin;
+ es_set_binary (es_stdin);
}
for (;;)
@@ -536,17 +547,34 @@ gpgtar_list (const char *filename, int decrypt)
header = NULL;
}
+ if (pid != (pid_t)(-1))
+ {
+ int exitcode;
+
+ err = es_fclose (stream);
+ stream = NULL;
+ if (err)
+ log_error ("error closing pipe: %s\n", gpg_strerror (err));
+ else
+ {
+ err = gnupg_wait_process (opt.gpg_program, pid, 1, &exitcode);
+ if (err)
+ log_error ("running %s failed (exitcode=%d): %s",
+ opt.gpg_program, exitcode, gpg_strerror (err));
+ gnupg_release_process (pid);
+ pid = (pid_t)(-1);
+ }
+ }
leave:
free_strlist (extheader);
xfree (header);
if (stream != es_stdin)
es_fclose (stream);
- if (stream != cipher_stream)
- es_fclose (cipher_stream);
return err;
}
+
gpg_error_t
gpgtar_read_header (estream_t stream, tarinfo_t info,
tar_header_t *r_header, strlist_t *r_extheader)
diff --git a/tools/gpgtar.c b/tools/gpgtar.c
index 57cac7c94..732a592fb 100644
--- a/tools/gpgtar.c
+++ b/tools/gpgtar.c
@@ -76,13 +76,19 @@ enum cmd_and_opt_values
oNull,
oUtf8Strings,
+ oBatch,
+ oAnswerYes,
+ oAnswerNo,
+ oStatusFD,
+ oRequireCompliance,
+
/* Compatibility with gpg-zip. */
oGpgArgs,
oTarArgs,
oTarProgram,
/* Debugging. */
- oDryRun,
+ oDryRun
};
@@ -113,6 +119,12 @@ static gpgrt_opt_t opts[] = {
ARGPARSE_s_n (oOpenPGP, "openpgp", "@"),
ARGPARSE_s_n (oCMS, "cms", "@"),
+ ARGPARSE_s_n (oBatch, "batch", "@"),
+ ARGPARSE_s_n (oAnswerYes, "yes", "@"),
+ ARGPARSE_s_n (oAnswerNo, "no", "@"),
+ ARGPARSE_s_i (oStatusFD, "status-fd", "@"),
+ ARGPARSE_s_n (oRequireCompliance, "require-compliance", "@"),
+
ARGPARSE_group (302, N_("@\nTar options:\n ")),
ARGPARSE_s_s (oDirectory, "directory",
@@ -374,6 +386,12 @@ parse_arguments (gpgrt_argparse_t *pargs, gpgrt_opt_t *popts)
case oOpenPGP: /* Dummy option for now. */ break;
case oCMS: /* Dummy option for now. */ break;
+ case oBatch: opt.batch = 1; break;
+ case oAnswerYes: opt.answer_yes = 1; break;
+ case oAnswerNo: opt.answer_no = 1; break;
+ case oStatusFD: opt.status_fd = pargs->r.ret_int; break;
+ case oRequireCompliance: opt.require_compliance = 1; break;
+
case oGpgArgs:;
{
strlist_t list;
@@ -443,9 +461,13 @@ main (int argc, char **argv)
/* Make sure that our subsystems are ready. */
i18n_init();
init_common_subsystems (&argc, &argv);
+ gnupg_init_signals (0, NULL);
log_assert (sizeof (struct ustar_raw_header) == 512);
+ /* Set default options */
+ opt.status_fd = -1;
+
/* Parse the command line. */
pargs.argc = &argc;
pargs.argv = &argv;
@@ -528,7 +550,7 @@ main (int argc, char **argv)
/* Read the next record from STREAM. RECORD is a buffer provided by
- the caller and must be at leadt of size RECORDSIZE. The function
+ the caller and must be at least of size RECORDSIZE. The function
return 0 on success and error code on failure; a diagnostic
printed as well. Note that there is no need for an EOF indicator
because a tarball has an explicit EOF record. */
diff --git a/tools/gpgtar.h b/tools/gpgtar.h
index 02b2d358c..c403835b5 100644
--- a/tools/gpgtar.h
+++ b/tools/gpgtar.h
@@ -41,6 +41,11 @@ struct
int symmetric;
const char *filename;
const char *directory;
+ int batch;
+ int answer_yes;
+ int answer_no;
+ int status_fd;
+ int require_compliance;
} opt;