summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/protos.h1
-rw-r--r--src/stringutils.c2
-rw-r--r--src/sysutils.c38
-rw-r--r--src/w32-gettext.c55
-rw-r--r--tests/t-stringutils.c99
5 files changed, 172 insertions, 23 deletions
diff --git a/src/protos.h b/src/protos.h
index 9a8d57a..7cc3489 100644
--- a/src/protos.h
+++ b/src/protos.h
@@ -24,6 +24,7 @@
/*-- w32-gettext.c --*/
wchar_t *_gpgrt_utf8_to_wchar (const char *string);
void _gpgrt_free_wchar (wchar_t *wstring);
+char *_gpgrt_wchar_to_utf8 (const wchar_t *string, size_t length);
void _gpgrt_w32_set_errno (int ec);
diff --git a/src/stringutils.c b/src/stringutils.c
index d92398d..0be8769 100644
--- a/src/stringutils.c
+++ b/src/stringutils.c
@@ -48,7 +48,7 @@ _gpgrt_vfnameconcat (int want_abs, const char *first_part, va_list arg_ptr)
char *home_buffer = NULL;
char *name, *home, *p;
- /* Put all args into an array becuase we need to scan them twice. */
+ /* Put all args into an array because we need to scan them twice. */
n = strlen (first_part) + 1;
argc = 0;
while ((argv[argc] = va_arg (arg_ptr, const char *)))
diff --git a/src/sysutils.c b/src/sysutils.c
index eb5249a..36daaec 100644
--- a/src/sysutils.c
+++ b/src/sysutils.c
@@ -345,27 +345,53 @@ _gpgrt_chdir (const char *name)
char *
_gpgrt_getcwd (void)
{
+#ifdef HAVE_W32CE_SYSTEM
+
+ return xtrystrdup ("/");
+
+#elif defined(HAVE_W32_SYSTEM)
+ wchar_t wbuffer[MAX_PATH + sizeof(wchar_t)];
+ DWORD wlen;
+ char *buf, *p;
+
+ wlen = GetCurrentDirectoryW (MAX_PATH, wbuffer);
+ if (!wlen)
+ {
+ _gpgrt_w32_set_errno (-1);
+ return NULL;
+
+ }
+ else if (wlen > MAX_PATH)
+ {
+ _gpg_err_set_errno (ENAMETOOLONG);
+ return NULL;
+ }
+ buf = _gpgrt_wchar_to_utf8 (wbuffer, wlen);
+ if (buf)
+ {
+ for (p=buf; *p; p++)
+ if (*p == '\\')
+ *p = '/';
+ }
+ return buf;
+
+#else /*Unix*/
char *buffer;
size_t size = 100;
- /* FIXME: We need to support utf8 */
for (;;)
{
buffer = xtrymalloc (size+1);
if (!buffer)
return NULL;
-#ifdef HAVE_W32CE_SYSTEM
- strcpy (buffer, "/"); /* Always "/". */
- return buffer;
-#else
if (getcwd (buffer, size) == buffer)
return buffer;
xfree (buffer);
if (errno != ERANGE)
return NULL;
size *= 2;
-#endif
}
+#endif /*Unix*/
}
diff --git a/src/w32-gettext.c b/src/w32-gettext.c
index a734ef2..569b126 100644
--- a/src/w32-gettext.c
+++ b/src/w32-gettext.c
@@ -1417,27 +1417,20 @@ _gpgrt_free_wchar (wchar_t *wstring)
}
-/* Return a malloced string encoded in the native console codepage
- from the wide char input string STRING.
- Caller must free this value. On failure returns NULL.
- The result of calling this function with STRING set to NULL
- is not defined. */
+/* Helper for wchar_to_native and wchar_to_utf8. */
static char *
-wchar_to_native (const wchar_t *string, size_t length, size_t *retlen)
+wchar_to_cp (const wchar_t *string, size_t length, size_t *retlen,
+ unsigned int cpno)
{
int n;
char *result;
- unsigned int cpno = GetConsoleOutputCP ();
-
- /* GetConsoleOutputCP returns the 8-Bit codepage that should be used
- for console output. If the codepage is not returned we fall back
- to the codepage GUI programs should use (CP_ACP). */
- if (!cpno)
- cpno = GetACP ();
n = WideCharToMultiByte (cpno, 0, string, length, NULL, 0, NULL, NULL);
if (n < 0 || (n+1) <= 0)
- return NULL;
+ {
+ _gpgrt_w32_set_errno (-1);
+ return NULL;
+ }
result = jnlib_malloc (n+1);
if (!result)
@@ -1446,14 +1439,46 @@ wchar_to_native (const wchar_t *string, size_t length, size_t *retlen)
n = WideCharToMultiByte (cpno, 0, string, length, result, n, NULL, NULL);
if (n < 0)
{
+ _gpgrt_w32_set_errno (-1);
jnlib_free (result);
return NULL;
}
- *retlen = n;
+ result[n] = 0;
+ if (retlen)
+ *retlen = n;
return result;
}
+/* Return a malloced string encoded in the native console codepage
+ from the wide char input string STRING.
+ Caller must free this value. On failure returns NULL.
+ The result of calling this function with STRING set to NULL
+ is not defined. */
+static char *
+wchar_to_native (const wchar_t *string, size_t length, size_t *retlen)
+{
+ unsigned int cpno = GetConsoleOutputCP ();
+
+ /* GetConsoleOutputCP returns the 8-Bit codepage that should be used
+ for console output. If the codepage is not returned we fall back
+ to the codepage GUI programs should use (CP_ACP). */
+ if (!cpno)
+ cpno = GetACP ();
+
+ return wchar_to_cp (string, length, retlen, cpno);
+}
+
+
+/* Convert a WCHAR string to UTF-8. Caller should use xfree to
+ * release the result. Returns NULL on error and sets ERRNO. */
+char *
+_gpgrt_wchar_to_utf8 (const wchar_t *string, size_t length)
+{
+ return wchar_to_cp (string, length, NULL, CP_UTF8);
+}
+
+
/* Convert UTF8 to the native codepage. Caller must free the return value. */
static char *
utf8_to_native (const char *string, size_t length, size_t *retlen)
diff --git a/tests/t-stringutils.c b/tests/t-stringutils.c
index 01094bf..a7351e5 100644
--- a/tests/t-stringutils.c
+++ b/tests/t-stringutils.c
@@ -35,6 +35,9 @@
# include <pwd.h>
#endif
#include <errno.h>
+#ifdef HAVE_W32_SYSTEM
+# include <windows.h>
+#endif
#define PGM "t-stringutils"
#include "t-common.h"
@@ -81,9 +84,80 @@ mygethome (void)
}
+#ifdef HAVE_W32_SYSTEM
+static wchar_t *
+utf8_to_wchar (const char *string)
+{
+ int n;
+ wchar_t *result;
+ size_t nbytes;
+ int cbmultibyte = -1;
+
+ n = MultiByteToWideChar (CP_UTF8, 0, string, cbmultibyte, NULL, 0);
+ if (n < 0 || (n+1) <= 0)
+ die ("utf8_to_wchar failed\n");
+ nbytes = (size_t)(n+1) * sizeof(*result);
+ if (nbytes / sizeof(*result) != (n+1))
+ die ("utf8_to_wchar failed\n");
+ result = xmalloc (nbytes);
+ n = MultiByteToWideChar (CP_UTF8, 0, string, cbmultibyte, result, n);
+ if (n < 0)
+ die ("utf8_to_wchar failed\n");
+ return result;
+
+}
+
+
+static char *
+wchar_to_utf8 (const wchar_t *string, size_t length)
+{
+ int n;
+ char *result;
+
+ n = WideCharToMultiByte (CP_UTF8, 0, string, length, NULL, 0, NULL, NULL);
+ if (n < 0 || (n+1) <= 0)
+ die ("wchar_to_utf8 failed\n");
+
+ result = xmalloc (n+1);
+ if (!result)
+ die ("wchar_to_utf8 failed\n");
+ n = WideCharToMultiByte (CP_UTF8, 0, string, length, result, n, NULL, NULL);
+ if (n < 0)
+ die ("wchar_to_utf8 failed\n");
+ result[n] = 0;
+ return result;
+}
+#endif
+
static char *
mygetcwd (void)
{
+#ifdef HAVE_W32_SYSTEM
+ wchar_t wbuffer[MAX_PATH + sizeof(wchar_t)];
+ wchar_t *wp;
+ DWORD wlen;
+ char *buf, *p;
+
+ wlen = GetCurrentDirectoryW (MAX_PATH, wbuffer);
+ if (!wlen)
+ die ("GCDW failed - error code: %d\n", (int)GetLastError ());
+ else if (wlen > MAX_PATH)
+ die ("GCDW failed - wlen too large\n");
+
+ buf = wchar_to_utf8 (wbuffer, wlen);
+
+ /* Quick test that the reverse works. */
+ wp = utf8_to_wchar (buf);
+ if (wcscmp (wp, wbuffer))
+ die ("GCDW: reverse converting failed\n");
+ xfree (wp);
+
+ for (p=buf; *p; p++)
+ if (*p == '\\')
+ *p = '/';
+ return buf;
+
+#else
char *buffer;
size_t size = 100;
@@ -91,12 +165,15 @@ mygetcwd (void)
{
buffer = xmalloc (size+1);
if (getcwd (buffer, size) == buffer)
- return buffer;
+ {
+ return buffer;
+ }
xfree (buffer);
if (errno != ERANGE)
die ("error getting current cwd: %s\n", strerror (errno));
size *= 2;
}
+#endif
}
@@ -254,9 +331,12 @@ main (int argc, char **argv)
gpgrt_opt_t opts[] = {
ARGPARSE_x ('v', "verbose", NONE, 0, "Print more diagnostics"),
ARGPARSE_s_n('d', "debug", "Flyswatter"),
+ ARGPARSE_x (501, "pwd", NONE, 0, "Print working directory"),
ARGPARSE_end()
};
gpgrt_argparse_t pargs = { &argc, &argv, 0 };
+ char *cwd;
+ int opt_pwd = 0;
gpgrt_set_strusage (my_strusage);
gpgrt_log_set_prefix (gpgrt_strusage (11), GPGRT_LOG_WITH_PREFIX);
@@ -267,11 +347,28 @@ main (int argc, char **argv)
{
case 'v': verbose++; break;
case 'd': debug++; break;
+ case 501: opt_pwd = 1; break;
default : pargs.err = ARGPARSE_PRINT_ERROR; break;
}
}
gpgrt_argparse (NULL, &pargs, NULL);
+ cwd = gpgrt_getcwd ();
+ if (!cwd)
+ fail ("gpgrt_getcwd returned error: %s\n",
+ gpg_strerror (gpg_error_from_syserror ()));
+ else
+ {
+ if (opt_pwd)
+ {
+ int save_verbose = verbose;
+ verbose = 1;
+ show ("getcwd -> '%s'\n", cwd);
+ verbose = save_verbose;
+ }
+ xfree (cwd);
+ }
+
show ("testing string utilities\n");
check_fnameconcat ();