summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2020-08-21 21:28:28 +0200
committerWerner Koch <wk@gnupg.org>2020-08-21 21:28:28 +0200
commit34e7703a962809921e83770f20f3eb66599265d1 (patch)
tree2d5f0418759d91c779add74bd2e865c8bef518dc /tools
parentcommon: Use gpgrt functions for mkdir and chdir. (diff)
downloadgnupg2-34e7703a962809921e83770f20f3eb66599265d1.tar.xz
gnupg2-34e7703a962809921e83770f20f3eb66599265d1.zip
gpgtar,w32: Handle Unicode file names.
* tools/gpgtar.c (oUtf8Strings): New. (opts): Add option --utf8-strings. (parse_arguments): Set option. * tools/gpgtar.h (opt): Add field utf8strings. * tools/gpgtar-create.c (name_to_utf8): New. (fillup_entry_w32): Use that. (scan_directory): Ditto. (scan_directory) [W32]: Convert file name to utf8. (gpgtar_create): Convert pattern. -- Note that this works only with file names read from a file or if the specified files on the command line are plain ascii. When recursing into a directory Unicode file names work again. This limitation is due to main(int, char**) which can't get the wchar version. We could fix that but is needs a bit more work in our init code. GnuPG-bug-id: 4083 Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/gpgtar-create.c61
-rw-r--r--tools/gpgtar.c8
-rw-r--r--tools/gpgtar.h3
3 files changed, 62 insertions, 10 deletions
diff --git a/tools/gpgtar-create.c b/tools/gpgtar-create.c
index 9921074a3..8a54c70ee 100644
--- a/tools/gpgtar-create.c
+++ b/tools/gpgtar-create.c
@@ -58,6 +58,38 @@ struct scanctrl_s
+/* On Windows convert name to UTF8 and return it; caller must release
+ * the result. On Unix or if ALREADY_UTF8 is set, this function is a
+ * mere xtrystrcopy. On failure NULL is returned and ERRNO set. */
+static char *
+name_to_utf8 (const char *name, int already_utf8)
+{
+#ifdef HAVE_W32_SYSTEM
+ wchar_t *wstring;
+ char *result;
+
+ if (already_utf8)
+ result = xtrystrdup (name);
+ else
+ {
+ wstring = native_to_wchar (name);
+ if (!wstring)
+ return NULL;
+ result = wchar_to_utf8 (wstring);
+ xfree (wstring);
+ }
+ return result;
+
+#else /*!HAVE_W32_SYSTEM */
+
+ (void)already_utf8;
+ return xtrystrdup (name);
+
+#endif /*!HAVE_W32_SYSTEM */
+}
+
+
+
/* Given a fresh header object HDR with only the name field set, try
to gather all available info. This is the W32 version. */
@@ -73,7 +105,7 @@ fillup_entry_w32 (tar_header_t hdr)
for (p=hdr->name; *p; p++)
if (*p == '/')
*p = '\\';
- wfname = native_to_wchar (hdr->name);
+ wfname = utf8_to_wchar (hdr->name);
for (p=hdr->name; *p; p++)
if (*p == '\\')
*p = '/';
@@ -213,7 +245,7 @@ fillup_entry_posix (tar_header_t hdr)
#endif /*!HAVE_W32_SYSTEM*/
-/* Add a new entry. The name of a director entry is ENTRYNAME; if
+/* Add a new entry. The name of a directory entry is ENTRYNAME; if
that is NULL, DNAME is the name of the directory itself. Under
Windows ENTRYNAME shall have backslashes replaced by standard
slashes. */
@@ -225,7 +257,7 @@ add_entry (const char *dname, const char *entryname, scanctrl_t scanctrl)
char *p;
size_t dnamelen = strlen (dname);
- assert (dnamelen);
+ log_assert (dnamelen);
hdr = xtrycalloc (1, sizeof *hdr + dnamelen + 1
+ (entryname? strlen (entryname) : 0) + 1);
@@ -300,7 +332,7 @@ scan_directory (const char *dname, scanctrl_t scanctrl)
for (p=fname; *p; p++)
if (*p == '/')
*p = '\\';
- wfname = native_to_wchar (fname);
+ wfname = utf8_to_wchar (fname);
xfree (fname);
if (!wfname)
{
@@ -323,7 +355,7 @@ scan_directory (const char *dname, scanctrl_t scanctrl)
do
{
- char *fname = wchar_to_native (fi.cFileName);
+ char *fname = wchar_to_utf8 (fi.cFileName);
if (!fname)
{
err = gpg_error_from_syserror ();
@@ -760,6 +792,19 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
estream_t cipher_stream = NULL;
int eof_seen = 0;
+ memset (scanctrl, 0, sizeof *scanctrl);
+ scanctrl->flist_tail = &scanctrl->flist;
+
+ /* { unsigned int cpno, cpno2, cpno3; */
+
+ /* cpno = GetConsoleOutputCP (); */
+ /* cpno2 = GetACP (); */
+ /* cpno3 = GetOEMCP (); */
+ /* log_debug ("Codepages: Console: %u ANSI: %u OEM: %u\n", */
+ /* cpno, cpno2, cpno3); */
+ /* } */
+
+
if (!inpattern)
{
if (!files_from || !strcmp (files_from, "-"))
@@ -778,8 +823,6 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
}
}
- memset (scanctrl, 0, sizeof *scanctrl);
- scanctrl->flist_tail = &scanctrl->flist;
if (opt.directory && gnupg_chdir (opt.directory))
{
@@ -805,7 +848,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
if (!*pattern)
continue;
- pat = xtrystrdup (pattern);
+ pat = name_to_utf8 (pattern, 0);
}
else /* Read Nul or LF delimited pattern from files_from_stream. */
{
@@ -871,7 +914,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
if (skip_this || n < 2)
continue;
- pat = xtrystrdup (namebuf);
+ pat = name_to_utf8 (namebuf, opt.utf8strings);
}
if (!pat)
diff --git a/tools/gpgtar.c b/tools/gpgtar.c
index 4a5a00a1f..a06e870ad 100644
--- a/tools/gpgtar.c
+++ b/tools/gpgtar.c
@@ -75,6 +75,7 @@ enum cmd_and_opt_values
oCMS,
oSetFilename,
oNull,
+ oUtf8Strings,
/* Compatibility with gpg-zip. */
oGpgArgs,
@@ -120,6 +121,12 @@ static gpgrt_opt_t opts[] = {
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")),
+#ifdef HAVE_W32_SYSTEM
+ ARGPARSE_s_n (oUtf8Strings, "utf8-strings",
+ N_("-T reads UTF-8 encoded names")),
+#else
+ ARGPARSE_s_n (oUtf8Strings, "utf8-strings", "@"),
+#endif
ARGPARSE_s_s (oGpgArgs, "gpg-args", "@"),
ARGPARSE_s_s (oTarArgs, "tar-args", "@"),
@@ -325,6 +332,7 @@ parse_arguments (gpgrt_argparse_t *pargs, gpgrt_opt_t *popts)
case oNoVerbose: opt.verbose = 0; break;
case oFilesFrom: files_from = pargs->r.ret_str; break;
case oNull: null_names = 1; break;
+ case oUtf8Strings: opt.utf8strings = 1; break;
case aList:
case aDecrypt:
diff --git a/tools/gpgtar.h b/tools/gpgtar.h
index 3e7aa5ed6..c931b8247 100644
--- a/tools/gpgtar.h
+++ b/tools/gpgtar.h
@@ -32,6 +32,7 @@ struct
unsigned int debug_level;
int quiet;
int dry_run;
+ int utf8strings;
const char *gpg_program;
strlist_t gpg_arguments;
const char *outfile;
@@ -121,7 +122,7 @@ struct tar_header_s
unsigned long long nrecords; /* Number of data records. */
- char name[1]; /* Filename (dynamically extended). */
+ char name[1]; /* Filename (UTF-8, dynamically extended). */
};