mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-31 11:41:32 +01:00
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>
This commit is contained in:
parent
364cef997c
commit
843890663b
@ -2033,6 +2033,12 @@ line.
|
|||||||
Modify option @option{--files-from} to use a binary nul instead of a
|
Modify option @option{--files-from} to use a binary nul instead of a
|
||||||
linefeed to separate file names.
|
linefeed to separate file names.
|
||||||
|
|
||||||
|
@item --utf8-strings
|
||||||
|
@opindex utf8-strings
|
||||||
|
Assume that the file names read by @option{--files-from} are UTF-8
|
||||||
|
encoded. This option has an effect only on Windows where the active
|
||||||
|
code page is otherwise assumed.
|
||||||
|
|
||||||
@item --openpgp
|
@item --openpgp
|
||||||
@opindex openpgp
|
@opindex openpgp
|
||||||
This option has no effect because OpenPGP encryption and signing is
|
This option has no effect because OpenPGP encryption and signing is
|
||||||
|
@ -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
|
/* Given a fresh header object HDR with only the name field set, try
|
||||||
to gather all available info. This is the W32 version. */
|
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++)
|
for (p=hdr->name; *p; p++)
|
||||||
if (*p == '/')
|
if (*p == '/')
|
||||||
*p = '\\';
|
*p = '\\';
|
||||||
wfname = native_to_wchar (hdr->name);
|
wfname = utf8_to_wchar (hdr->name);
|
||||||
for (p=hdr->name; *p; p++)
|
for (p=hdr->name; *p; p++)
|
||||||
if (*p == '\\')
|
if (*p == '\\')
|
||||||
*p = '/';
|
*p = '/';
|
||||||
@ -213,7 +245,7 @@ fillup_entry_posix (tar_header_t hdr)
|
|||||||
#endif /*!HAVE_W32_SYSTEM*/
|
#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
|
that is NULL, DNAME is the name of the directory itself. Under
|
||||||
Windows ENTRYNAME shall have backslashes replaced by standard
|
Windows ENTRYNAME shall have backslashes replaced by standard
|
||||||
slashes. */
|
slashes. */
|
||||||
@ -225,7 +257,7 @@ add_entry (const char *dname, const char *entryname, scanctrl_t scanctrl)
|
|||||||
char *p;
|
char *p;
|
||||||
size_t dnamelen = strlen (dname);
|
size_t dnamelen = strlen (dname);
|
||||||
|
|
||||||
assert (dnamelen);
|
log_assert (dnamelen);
|
||||||
|
|
||||||
hdr = xtrycalloc (1, sizeof *hdr + dnamelen + 1
|
hdr = xtrycalloc (1, sizeof *hdr + dnamelen + 1
|
||||||
+ (entryname? strlen (entryname) : 0) + 1);
|
+ (entryname? strlen (entryname) : 0) + 1);
|
||||||
@ -300,7 +332,7 @@ scan_directory (const char *dname, scanctrl_t scanctrl)
|
|||||||
for (p=fname; *p; p++)
|
for (p=fname; *p; p++)
|
||||||
if (*p == '/')
|
if (*p == '/')
|
||||||
*p = '\\';
|
*p = '\\';
|
||||||
wfname = native_to_wchar (fname);
|
wfname = utf8_to_wchar (fname);
|
||||||
xfree (fname);
|
xfree (fname);
|
||||||
if (!wfname)
|
if (!wfname)
|
||||||
{
|
{
|
||||||
@ -323,7 +355,7 @@ scan_directory (const char *dname, scanctrl_t scanctrl)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
char *fname = wchar_to_native (fi.cFileName);
|
char *fname = wchar_to_utf8 (fi.cFileName);
|
||||||
if (!fname)
|
if (!fname)
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
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;
|
estream_t cipher_stream = NULL;
|
||||||
int eof_seen = 0;
|
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 (!inpattern)
|
||||||
{
|
{
|
||||||
if (!files_from || !strcmp (files_from, "-"))
|
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))
|
if (opt.directory && gnupg_chdir (opt.directory))
|
||||||
{
|
{
|
||||||
@ -805,7 +848,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
|
|||||||
if (!*pattern)
|
if (!*pattern)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pat = xtrystrdup (pattern);
|
pat = name_to_utf8 (pattern, 0);
|
||||||
}
|
}
|
||||||
else /* Read Nul or LF delimited pattern from files_from_stream. */
|
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)
|
if (skip_this || n < 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pat = xtrystrdup (namebuf);
|
pat = name_to_utf8 (namebuf, opt.utf8strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pat)
|
if (!pat)
|
||||||
|
@ -73,6 +73,7 @@ enum cmd_and_opt_values
|
|||||||
oCMS,
|
oCMS,
|
||||||
oSetFilename,
|
oSetFilename,
|
||||||
oNull,
|
oNull,
|
||||||
|
oUtf8Strings,
|
||||||
|
|
||||||
/* Compatibility with gpg-zip. */
|
/* Compatibility with gpg-zip. */
|
||||||
oGpgArgs,
|
oGpgArgs,
|
||||||
@ -117,6 +118,12 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
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")),
|
||||||
|
#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 (oGpgArgs, "gpg-args", "@"),
|
||||||
ARGPARSE_s_s (oTarArgs, "tar-args", "@"),
|
ARGPARSE_s_s (oTarArgs, "tar-args", "@"),
|
||||||
@ -319,6 +326,7 @@ parse_arguments (ARGPARSE_ARGS *pargs, ARGPARSE_OPTS *popts)
|
|||||||
case oNoVerbose: opt.verbose = 0; break;
|
case oNoVerbose: opt.verbose = 0; break;
|
||||||
case oFilesFrom: files_from = pargs->r.ret_str; break;
|
case oFilesFrom: files_from = pargs->r.ret_str; break;
|
||||||
case oNull: null_names = 1; break;
|
case oNull: null_names = 1; break;
|
||||||
|
case oUtf8Strings: opt.utf8strings = 1; break;
|
||||||
|
|
||||||
case aList:
|
case aList:
|
||||||
case aDecrypt:
|
case aDecrypt:
|
||||||
|
@ -32,6 +32,7 @@ struct
|
|||||||
unsigned int debug_level;
|
unsigned int debug_level;
|
||||||
int quiet;
|
int quiet;
|
||||||
int dry_run;
|
int dry_run;
|
||||||
|
int utf8strings;
|
||||||
const char *gpg_program;
|
const char *gpg_program;
|
||||||
strlist_t gpg_arguments;
|
strlist_t gpg_arguments;
|
||||||
const char *outfile;
|
const char *outfile;
|
||||||
@ -121,7 +122,7 @@ struct tar_header_s
|
|||||||
|
|
||||||
unsigned long long nrecords; /* Number of data records. */
|
unsigned long long nrecords; /* Number of data records. */
|
||||||
|
|
||||||
char name[1]; /* Filename (dynamically extended). */
|
char name[1]; /* Filename (UTF-8, dynamically extended). */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user