mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-07 17:33:02 +01:00
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:
parent
35c0c8b211
commit
2eb3248058
@ -42,12 +42,8 @@ do
|
|||||||
grep -qe "\\b${F}\\b" "$FILELIST"
|
grep -qe "\\b${F}\\b" "$FILELIST"
|
||||||
done
|
done
|
||||||
|
|
||||||
EXTRACT_FLAGS="--directory=${TESTDIR}"
|
$TOOL --gpg "$GPG" --tar-args --directory="${TESTDIR}" \
|
||||||
if [ "$TOOL" = "$GPGZIP" ]
|
--decrypt "${TESTDIR}/test.tar.pgp"
|
||||||
then
|
|
||||||
EXTRACT_FLAGS="--tar-args $EXTRACT_FLAGS"
|
|
||||||
fi
|
|
||||||
$TOOL --gpg "$GPG" $EXTRACT_FLAGS --decrypt "${TESTDIR}/test.tar.pgp"
|
|
||||||
for F in $TESTFILES
|
for F in $TESTFILES
|
||||||
do
|
do
|
||||||
diff -q "$F" "${TESTDIR}/$F"
|
diff -q "$F" "${TESTDIR}/$F"
|
||||||
|
158
tools/gpgtar.c
158
tools/gpgtar.c
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <assuan.h>
|
#include <assuan.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <npth.h>
|
#include <npth.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -41,6 +42,7 @@
|
|||||||
#include "../common/asshelp.h"
|
#include "../common/asshelp.h"
|
||||||
#include "../common/openpgpdefs.h"
|
#include "../common/openpgpdefs.h"
|
||||||
#include "../common/init.h"
|
#include "../common/init.h"
|
||||||
|
#include "../common/strlist.h"
|
||||||
|
|
||||||
#include "gpgtar.h"
|
#include "gpgtar.h"
|
||||||
|
|
||||||
@ -70,7 +72,10 @@ enum cmd_and_opt_values
|
|||||||
oOpenPGP,
|
oOpenPGP,
|
||||||
oCMS,
|
oCMS,
|
||||||
oSetFilename,
|
oSetFilename,
|
||||||
oNull
|
oNull,
|
||||||
|
|
||||||
|
/* Compatibility with gpg-zip. */
|
||||||
|
oTarArgs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -90,18 +95,35 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
ARGPARSE_s_s (oUser, "local-user",
|
ARGPARSE_s_s (oUser, "local-user",
|
||||||
N_("|USER-ID|use USER-ID to sign or decrypt")),
|
N_("|USER-ID|use USER-ID to sign or decrypt")),
|
||||||
ARGPARSE_s_s (oOutput, "output", N_("|FILE|write output to FILE")),
|
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 (oVerbose, "verbose", N_("verbose")),
|
||||||
ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
|
ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
|
||||||
ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
|
ARGPARSE_s_s (oGpgProgram, "gpg", "@"),
|
||||||
ARGPARSE_s_n (oSkipCrypto, "skip-crypto", N_("skip the crypto processing")),
|
ARGPARSE_s_n (oSkipCrypto, "skip-crypto", N_("skip the crypto processing")),
|
||||||
ARGPARSE_s_s (oSetFilename, "set-filename", "@"),
|
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",
|
ARGPARSE_s_s (oFilesFrom, "files-from",
|
||||||
N_("|FILE|get names to create from FILE")),
|
N_("|FILE|get names to create from FILE")),
|
||||||
ARGPARSE_s_n (oNull, "null", N_("-T reads null-terminated names")),
|
ARGPARSE_s_n (oNull, "null", N_("-T reads null-terminated names")),
|
||||||
ARGPARSE_s_n (oOpenPGP, "openpgp", "@"),
|
|
||||||
ARGPARSE_s_n (oCMS, "cms", "@"),
|
|
||||||
|
|
||||||
ARGPARSE_end ()
|
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;
|
*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;
|
ASSUAN_SYSTEM_NPTH_IMPL;
|
||||||
|
|
||||||
@ -169,11 +290,11 @@ int null_names = 0;
|
|||||||
|
|
||||||
/* Command line parsing. */
|
/* Command line parsing. */
|
||||||
static void
|
static void
|
||||||
parse_arguments (ARGPARSE_ARGS *pargs)
|
parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
|
||||||
{
|
{
|
||||||
int no_more_options = 0;
|
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)
|
switch (pargs->r_opt)
|
||||||
{
|
{
|
||||||
@ -219,6 +340,27 @@ parse_arguments (ARGPARSE_ARGS *pargs)
|
|||||||
case oOpenPGP: /* Dummy option for now. */ break;
|
case oOpenPGP: /* Dummy option for now. */ break;
|
||||||
case oCMS: /* 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;
|
default: pargs->err = 2; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,7 +394,7 @@ main (int argc, char **argv)
|
|||||||
pargs.argc = &argc;
|
pargs.argc = &argc;
|
||||||
pargs.argv = &argv;
|
pargs.argv = &argv;
|
||||||
pargs.flags = ARGPARSE_FLAG_KEEP;
|
pargs.flags = ARGPARSE_FLAG_KEEP;
|
||||||
parse_arguments (&pargs);
|
parse_arguments (&pargs, opts);
|
||||||
|
|
||||||
if ((files_from && !null_names) || (!files_from && null_names))
|
if ((files_from && !null_names) || (!files_from && null_names))
|
||||||
log_error ("--files-from and --null may only be used in conjunction\n");
|
log_error ("--files-from and --null may only be used in conjunction\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user