about summary refs log tree commit diff
path: root/src/rt/rust_builtin.cpp
diff options
context:
space:
mode:
authorLEE Wondong <wdlee91@gmail.com>2013-10-20 15:02:03 +0900
committerLEE Wondong <wdlee91@gmail.com>2013-10-20 15:02:03 +0900
commit3e53c929a2298e59d9abd3973094db3d34d59e98 (patch)
tree4c71a86df71ca96203455f7c9a16e4c14f4d5d8b /src/rt/rust_builtin.cpp
parenta1848bc755411285afb15f2453df7567e10ebc04 (diff)
downloadrust-3e53c929a2298e59d9abd3973094db3d34d59e98.tar.gz
rust-3e53c929a2298e59d9abd3973094db3d34d59e98.zip
Fix unicode errors on Windows in path_is_dir, path_exists, getcwd and rust_localtime.
This make these functions use wchar_t version of APIs, instead of char version.
Diffstat (limited to 'src/rt/rust_builtin.cpp')
-rw-r--r--src/rt/rust_builtin.cpp46
1 files changed, 42 insertions, 4 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 9750e22e945..d20e91f3917 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -107,7 +107,7 @@ rust_list_dir_wfd_fp_buf(void* wfd) {
 #endif
 
 extern "C" CDECL int
-rust_path_is_dir(char *path) {
+rust_path_is_dir(const char *path) {
     struct stat buf;
     if (stat(path, &buf)) {
         return 0;
@@ -116,7 +116,25 @@ rust_path_is_dir(char *path) {
 }
 
 extern "C" CDECL int
-rust_path_exists(char *path) {
+#if defined(__WIN32__)
+rust_path_is_dir_u16(const wchar_t *path) {
+    struct _stat buf;
+    // Don't use GetFileAttributesW, it cannot get attributes of
+    // some system files (e.g. pagefile.sys).
+    if (_wstat(path, &buf)) {
+        return 0;
+    }
+    return S_ISDIR(buf.st_mode);
+}
+#else
+rust_path_is_dir_u16(const void *path) {
+    // Wide version of function is only used on Windows.
+    return 0;
+}
+#endif
+
+extern "C" CDECL int
+rust_path_exists(const char *path) {
     struct stat buf;
     if (stat(path, &buf)) {
         return 0;
@@ -124,6 +142,22 @@ rust_path_exists(char *path) {
     return 1;
 }
 
+extern "C" CDECL int
+#if defined(__WIN32__)
+rust_path_exists_u16(const wchar_t *path) {
+    struct _stat buf;
+    if (_wstat(path, &buf)) {
+        return 0;
+    }
+    return 1;
+}
+#else
+rust_path_exists_u16(const void *path) {
+    // Wide version of function is only used on Windows.
+    return 0;
+}
+#endif
+
 extern "C" CDECL FILE* rust_get_stdin() {return stdin;}
 extern "C" CDECL FILE* rust_get_stdout() {return stdout;}
 extern "C" CDECL FILE* rust_get_stderr() {return stderr;}
@@ -294,8 +328,12 @@ rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) {
     const char* zone = NULL;
 #if defined(__WIN32__)
     int32_t gmtoff = -timezone;
-    char buffer[64];
-    if (strftime(buffer, sizeof(buffer), "%Z", &tm) > 0) {
+    wchar_t wbuffer[64];
+    char buffer[256];
+    // strftime("%Z") can contain non-UTF-8 characters on non-English locale (issue #9418),
+    // so time zone should be converted from UTF-16 string set by wcsftime.
+    if (wcsftime(wbuffer, sizeof(wbuffer) / sizeof(wchar_t), L"%Z", &tm) > 0) {
+        WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, sizeof(buffer), NULL, NULL);
         zone = buffer;
     }
 #else