Skip to content

Commit 0709c00

Browse files
committed
Fix strftime usage on Win32 when trying to fetch the locale-aware
parts of a time string so it properly handles different encodings. Original patch by Hiroshi Saito, heavily reworked by me and ITAGAKI Takahiro.
1 parent 58a81ba commit 0709c00

File tree

1 file changed

+74
-1
lines changed

1 file changed

+74
-1
lines changed

src/backend/utils/adt/pg_locale.c

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Portions Copyright (c) 2002-2009, PostgreSQL Global Development Group
66
*
7-
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.43 2009/01/01 17:23:49 momjian Exp $
7+
* $PostgreSQL: pgsql/src/backend/utils/adt/pg_locale.c,v 1.44 2009/01/09 13:03:55 mha Exp $
88
*
99
*-----------------------------------------------------------------------
1010
*/
@@ -51,6 +51,7 @@
5151
#include <time.h>
5252

5353
#include "catalog/pg_control.h"
54+
#include "mb/pg_wchar.h"
5455
#include "utils/memutils.h"
5556
#include "utils/pg_locale.h"
5657

@@ -452,6 +453,57 @@ PGLC_localeconv(void)
452453
return &CurrentLocaleConv;
453454
}
454455

456+
#ifdef WIN32
457+
/*
458+
* On win32, strftime() returns the encoding in CP_ACP, which is likely
459+
* different from SERVER_ENCODING. This is especially important in Japanese
460+
* versions of Windows which will use SJIS encoding, which we don't support
461+
* as a server encoding.
462+
*
463+
* Replace strftime() with a version that gets the string in UTF16 and then
464+
* converts it to the appropriate encoding as necessary.
465+
*
466+
* Note that this only affects the calls to strftime() in this file, which are
467+
* used to get the locale-aware strings. Other parts of the backend use
468+
* pg_strftime(), which isn't locale-aware and does not need to be replaced.
469+
*/
470+
static size_t
471+
strftime_win32(char *dst, size_t dstlen, const wchar_t *format, const struct tm *tm)
472+
{
473+
size_t len;
474+
wchar_t wbuf[MAX_L10N_DATA];
475+
int encoding;
476+
477+
encoding = GetDatabaseEncoding();
478+
479+
len = wcsftime(wbuf, sizeof(wbuf), format, tm);
480+
if (len == 0)
481+
/* strftime call failed - return 0 with the contents of dst unspecified */
482+
return 0;
483+
484+
len = WideCharToMultiByte(CP_UTF8, 0, wbuf, len, dst, dstlen, NULL, NULL);
485+
if (len == 0)
486+
elog(ERROR,
487+
"could not convert string to UTF-8:error %lu", GetLastError());
488+
489+
dst[len] = '\0';
490+
if (encoding != PG_UTF8)
491+
{
492+
char *convstr = pg_do_encoding_conversion(dst, len, PG_UTF8, encoding);
493+
if (dst != convstr)
494+
{
495+
StrNCpy(dst, convstr, dstlen);
496+
len = strlen(dst);
497+
}
498+
}
499+
500+
return len;
501+
}
502+
503+
#define strftime(a,b,c,d) strftime_win32(a,b,L##c,d)
504+
505+
#endif /* WIN32 */
506+
455507

456508
/*
457509
* Update the lc_time localization cache variables if needed.
@@ -465,13 +517,25 @@ cache_locale_time(void)
465517
char buf[MAX_L10N_DATA];
466518
char *ptr;
467519
int i;
520+
#ifdef WIN32
521+
char *save_lc_ctype;
522+
#endif
468523

469524
/* did we do this already? */
470525
if (CurrentLCTimeValid)
471526
return;
472527

473528
elog(DEBUG3, "cache_locale_time() executed; locale: \"%s\"", locale_time);
474529

530+
#ifdef WIN32
531+
/* set user's value of ctype locale */
532+
save_lc_ctype = setlocale(LC_CTYPE, NULL);
533+
if (save_lc_ctype)
534+
save_lc_ctype = pstrdup(save_lc_ctype);
535+
536+
setlocale(LC_CTYPE, locale_time);
537+
#endif
538+
475539
/* set user's value of time locale */
476540
save_lc_time = setlocale(LC_TIME, NULL);
477541
if (save_lc_time)
@@ -524,5 +588,14 @@ cache_locale_time(void)
524588
pfree(save_lc_time);
525589
}
526590

591+
#ifdef WIN32
592+
/* try to restore internal ctype settings */
593+
if (save_lc_ctype)
594+
{
595+
setlocale(LC_CTYPE, save_lc_ctype);
596+
pfree(save_lc_ctype);
597+
}
598+
#endif
599+
527600
CurrentLCTimeValid = true;
528601
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy