diff options
-rw-r--r-- | src/protos.h | 1 | ||||
-rw-r--r-- | src/stringutils.c | 2 | ||||
-rw-r--r-- | src/sysutils.c | 38 | ||||
-rw-r--r-- | src/w32-gettext.c | 55 | ||||
-rw-r--r-- | tests/t-stringutils.c | 99 |
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 (); |