tools/gpgtar: Handle '--tar-args' for compatibility with gpg-zip.

* tools/gpgtar.c (enum cmd_and_opt_values): New value.
(opts): Add new group for tar options, rearrange a little, add
'--tar-args'.
(tar_opts): New variable.
(shell_parse_stringlist): New function.
(shell_parse_argv): Likewise.
(parse_arguments): Add option argument, handle '--tar-args'.
(main): Fix invokation of 'parse_arguments'.
* tests/openpgp/gpgtar.test: Simplify decryption.

Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
Justus Winter 2015-11-26 14:08:48 +01:00
parent 35c0c8b211
commit 2eb3248058
2 changed files with 152 additions and 14 deletions

View File

@ -42,12 +42,8 @@ do
grep -qe "\\b${F}\\b" "$FILELIST"
done
EXTRACT_FLAGS="--directory=${TESTDIR}"
if [ "$TOOL" = "$GPGZIP" ]
then
EXTRACT_FLAGS="--tar-args $EXTRACT_FLAGS"
fi
$TOOL --gpg "$GPG" $EXTRACT_FLAGS --decrypt "${TESTDIR}/test.tar.pgp"
$TOOL --gpg "$GPG" --tar-args --directory="${TESTDIR}" \
--decrypt "${TESTDIR}/test.tar.pgp"
for F in $TESTFILES
do
diff -q "$F" "${TESTDIR}/$F"

View File

@ -28,6 +28,7 @@
#include <config.h>
#include <assuan.h>
#include <ctype.h>
#include <errno.h>
#include <npth.h>
#include <stdio.h>
@ -41,6 +42,7 @@
#include "../common/asshelp.h"
#include "../common/openpgpdefs.h"
#include "../common/init.h"
#include "../common/strlist.h"
#include "gpgtar.h"
@ -70,7 +72,10 @@ enum cmd_and_opt_values
oOpenPGP,
oCMS,
oSetFilename,
oNull
oNull,
/* Compatibility with gpg-zip. */
oTarArgs,
};
@ -90,18 +95,35 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_s (oUser, "local-user",
N_("|USER-ID|use USER-ID to sign or decrypt")),
ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
ARGPARSE_s_s (oDirectory, "directory",
N_("|DIRECTORY|extract files into DIRECTORY")),
ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
ARGPARSE_s_n (oSkipCrypto, "skip-crypto", N_("skip the crypto processing")),
ARGPARSE_s_s (oSetFilename, "set-filename", "@"),
ARGPARSE_s_n (oOpenPGP, "openpgp", "@"),
ARGPARSE_s_n (oCMS, "cms", "@"),
ARGPARSE_group (302, N_("@\nTar options:\n ")),
ARGPARSE_s_s (oDirectory, "directory",
N_("|DIRECTORY|extract files into DIRECTORY")),
ARGPARSE_s_s (oFilesFrom, "files-from",
N_("|FILE|get names to create from FILE")),
ARGPARSE_s_n (oNull, "null", N_("-T reads null-terminated names")),
ARGPARSE_s_s (oTarArgs, "tar-args", "@"),
ARGPARSE_end ()
};
/* The list of commands and options for tar that we understand. */
static ARGPARSE_OPTS tar_opts[] = {
ARGPARSE_s_s (oDirectory, "directory",
N_("|DIRECTORY|extract files into DIRECTORY")),
ARGPARSE_s_s (oFilesFrom, "files-from",
N_("|FILE|get names to create from FILE")),
ARGPARSE_s_n (oNull, "null", N_("-T reads null-terminated names")),
ARGPARSE_s_n (oOpenPGP, "openpgp", "@"),
ARGPARSE_s_n (oCMS, "cms", "@"),
ARGPARSE_end ()
};
@ -156,6 +178,105 @@ set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
*ret_cmd = cmd;
}
/* Shell-like argument splitting.
For compatibility with gpg-zip we accept arguments for GnuPG and
tar given as a string argument to '--gpg-args' and '--tar-args'.
gpg-zip was implemented as a Bourne Shell script, and therefore, we
need to split the string the same way the shell would. */
static int
shell_parse_stringlist (const char *str, strlist_t *r_list)
{
strlist_t list = NULL;
const char *s = str;
char quoted = 0;
char arg[1024];
char *p = arg;
#define addchar(c) \
do { if (p - arg + 2 < sizeof arg) *p++ = (c); else return 1; } while (0)
#define addargument() \
do { \
if (p > arg) \
{ \
*p = 0; \
append_to_strlist (&list, arg); \
p = arg; \
} \
} while (0)
#define unquoted 0
#define singlequote '\''
#define doublequote '"'
for (; *s; s++)
{
switch (quoted)
{
case unquoted:
if (isspace (*s))
addargument ();
else if (*s == singlequote || *s == doublequote)
quoted = *s;
else
addchar (*s);
break;
case singlequote:
if (*s == singlequote)
quoted = unquoted;
else
addchar (*s);
break;
case doublequote:
assert (s > str || !"cannot be quoted at first char");
if (*s == doublequote && *(s - 1) != '\\')
quoted = unquoted;
else
addchar (*s);
break;
default:
assert (! "reached");
}
}
/* Append the last argument. */
addargument ();
#undef doublequote
#undef singlequote
#undef unquoted
#undef addargument
#undef addchar
*r_list = list;
return 0;
}
/* Like shell_parse_stringlist, but returns an argv vector
instead of a strlist. */
static int
shell_parse_argv (const char *s, int *r_argc, char ***r_argv)
{
int i;
strlist_t list;
if (shell_parse_stringlist (s, &list))
return 1;
*r_argc = strlist_length (list);
*r_argv = xtrycalloc (*r_argc, sizeof **r_argv);
if (*r_argv == NULL)
return 1;
for (i = 0; list; i++)
(*r_argv)[i] = list->d, list = list->next;
return 0;
}
/* Define Assuan hooks for NPTH. */
ASSUAN_SYSTEM_NPTH_IMPL;
@ -169,11 +290,11 @@ int null_names = 0;
/* Command line parsing. */
static void
parse_arguments (ARGPARSE_ARGS *pargs)
parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
{
int no_more_options = 0;
while (!no_more_options && optfile_parse (NULL, NULL, NULL, pargs, opts))
while (!no_more_options && optfile_parse (NULL, NULL, NULL, pargs, popts))
{
switch (pargs->r_opt)
{
@ -219,6 +340,27 @@ parse_arguments (ARGPARSE_ARGS *pargs)
case oOpenPGP: /* Dummy option for now. */ break;
case oCMS: /* Dummy option for now. */ break;
case oTarArgs:;
int tar_argc;
char **tar_argv;
if (shell_parse_argv (pargs->r.ret_str, &tar_argc, &tar_argv))
log_error ("failed to parse tar arguments '%s'\n",
pargs->r.ret_str);
else
{
ARGPARSE_ARGS tar_args;
tar_args.argc = &tar_argc;
tar_args.argv = &tar_argv;
tar_args.flags = ARGPARSE_FLAG_ARG0;
parse_arguments (&tar_args, tar_opts);
if (tar_args.err)
log_error ("unsupported tar arguments '%s'\n",
pargs->r.ret_str);
pargs->err = tar_args.err;
}
break;
default: pargs->err = 2; break;
}
}
@ -252,7 +394,7 @@ main (int argc, char **argv)
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags = ARGPARSE_FLAG_KEEP;
parse_arguments (&pargs);
parse_arguments (&pargs, opts);
if ((files_from && !null_names) || (!files_from && null_names))
log_error ("--files-from and --null may only be used in conjunction\n");