[前][次][番号順一覧][スレッド一覧]

ruby-changes:15653

From: usa <ko1@a...>
Date: Sat, 1 May 2010 02:57:34 +0900 (JST)
Subject: [ruby-changes:15653] Ruby:r27570 (trunk): * merge some patches from win32-uncode-test branch.

usa	2010-05-01 02:56:23 +0900 (Sat, 01 May 2010)

  New Revision: 27570

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=27570

  Log:
    * merge some patches from win32-uncode-test branch.
      see #1685.
    
    * file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
      to convert encoding for pathname.
    
    * win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
      rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
      rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
      accept UTF-8 path.
    
    * win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
      rb_w32_unlink): use WCHAR path internally.
    
    * file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
      chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
      rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
      functions on Win32.
    
    * file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
      rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
      check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
      rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
      rb_str_encode_ospath() before passing the path to system.
    
    * io.c (rb_sysopen): ditto.
    
    * dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/dir.c
    trunk/file.c
    trunk/include/ruby/intern.h
    trunk/include/ruby/win32.h
    trunk/io.c
    trunk/win32/win32.c

Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 27569)
+++ include/ruby/intern.h	(revision 27570)
@@ -367,6 +367,7 @@
 char *rb_path_last_separator(const char *);
 char *rb_path_end(const char *);
 VALUE rb_file_directory_p(VALUE,VALUE);
+VALUE rb_str_encode_ospath(VALUE);
 int rb_is_absolute_path(const char *);
 /* gc.c */
 void ruby_set_stack_size(size_t);
Index: include/ruby/win32.h
===================================================================
--- include/ruby/win32.h	(revision 27569)
+++ include/ruby/win32.h	(revision 27570)
@@ -256,12 +256,15 @@
 extern char * rb_w32_getcwd(char *, int);
 extern char * rb_w32_getenv(const char *);
 extern int    rb_w32_rename(const char *, const char *);
+extern int    rb_w32_urename(const char *, const char *);
 extern char **rb_w32_get_environ(void);
 extern void   rb_w32_free_environ(char **);
 extern int    rb_w32_map_errno(DWORD);
 
 extern int chown(const char *, int, int);
+extern int rb_w32_uchown(const char *, int, int);
 extern int link(const char *, const char *);
+extern int rb_w32_ulink(const char *, const char *);
 extern int gettimeofday(struct timeval *, struct timezone *);
 extern rb_pid_t waitpid (rb_pid_t, int *, int);
 extern rb_pid_t rb_w32_spawn(int, const char *, const char*);
@@ -274,10 +277,16 @@
 extern int rb_w32_isatty(int);
 #endif
 extern int rb_w32_mkdir(const char *, int);
+extern int rb_w32_umkdir(const char *, int);
 extern int rb_w32_rmdir(const char *);
+extern int rb_w32_urmdir(const char *);
 extern int rb_w32_unlink(const char *);
+extern int rb_w32_uunlink(const char *);
+extern int rb_w32_uchmod(const char *, int);
 extern int rb_w32_stati64(const char *, struct stati64 *);
+extern int rb_w32_ustati64(const char *, struct stati64 *);
 extern int rb_w32_access(const char *, int);
+extern int rb_w32_uaccess(const char *, int);
 
 #ifdef __BORLANDC__
 extern int rb_w32_fstati64(int, struct stati64 *);
@@ -627,14 +636,17 @@
 int  rb_w32_sleep(unsigned long msec);
 int  rb_w32_putc(int, FILE*);
 int  rb_w32_getc(FILE*);
+int  rb_w32_open(const char *, int, ...);
+int  rb_w32_uopen(const char *, int, ...);
 int  rb_w32_wopen(const WCHAR *, int, ...);
-int  rb_w32_open(const char *, int, ...);
 int  rb_w32_close(int);
 int  rb_w32_fclose(FILE*);
 int  rb_w32_pipe(int[2]);
 size_t rb_w32_read(int, void *, size_t);
 size_t rb_w32_write(int, const void *, size_t);
 int  rb_w32_utime(const char *, const struct utimbuf *);
+int  rb_w32_uutime(const char *, const struct utimbuf *);
+long rb_w32_write_console(unsigned long, int);
 int  WINAPI rb_w32_Sleep(unsigned long msec);
 int  rb_w32_wait_events_blocking(HANDLE *events, int num, DWORD timeout);
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 27569)
+++ ChangeLog	(revision 27570)
@@ -1,3 +1,34 @@
+Sat May  1 02:41:33 2010  NAKAMURA Usaku  <usa@r...>
+
+	* merge some patches from win32-uncode-test branch.
+	  see #1685.
+
+	* file.c, include/ruby/intern.h (rb_str_encode_ospath): new function
+	  to convert encoding for pathname.
+
+	* win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename,
+	  rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir,
+	  rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to
+	  accept UTF-8 path.
+
+	* win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime,
+	  rb_w32_unlink): use WCHAR path internally.
+
+	* file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype,
+	  chmod_internal, rb_file_chmod, rb_file_chown, utime_internal,
+	  rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version
+	  functions on Win32.
+
+	* file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p,
+	  rb_file_readable_p, rb_file_writable_p, rb_file_executable_p,
+	  check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown,
+	  rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call
+	  rb_str_encode_ospath() before passing the path to system.
+
+	* io.c (rb_sysopen): ditto.
+
+	* dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto.
+
 Sat May  1 00:26:31 2010  Nobuyoshi Nakada  <nobu@r...>
 
 	* lib/test/unit/assertions.rb (Test::Unit::Assertions#assert):
Index: io.c
===================================================================
--- io.c	(revision 27569)
+++ io.c	(revision 27570)
@@ -114,6 +114,12 @@
 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
 #define IO_WBUF_CAPA_MIN  8192
 
+/* define system APIs */
+#ifdef _WIN32
+#undef open
+#define open	rb_w32_uopen
+#endif
+
 VALUE rb_cIO;
 VALUE rb_eEOFError;
 VALUE rb_eIOError;
@@ -4464,49 +4470,13 @@
     VALUE fname;
     int oflags;
     mode_t perm;
-#ifdef _WIN32
-    int wchar;
-#endif
 };
 
-#ifdef _WIN32
-static rb_encoding *
-w32_utf16(void)
-{
-    static rb_encoding *utf16 = (rb_encoding *)-1;
-    if (utf16 == (rb_encoding *)-1) {
-	utf16 = rb_enc_find("UTF-16LE");
-	if (utf16 == rb_ascii8bit_encoding())
-	    utf16 = NULL;
-    }
-    return utf16;
-}
-
-static int
-w32_conv_to_utf16(volatile VALUE *strp)
-{
-    rb_encoding *utf16 = w32_utf16();
-    if (utf16) {
-	VALUE wstr = rb_str_encode(*strp, rb_enc_from_encoding(utf16), 0, Qnil);
-	rb_enc_str_buf_cat(wstr, "", 1, utf16); /* workaround */
-	*strp = wstr;
-	return 1;
-    }
-    else {
-	return 0;
-    }
-}
-#endif
-
 static VALUE
 sysopen_func(void *ptr)
 {
     const struct sysopen_struct *data = ptr;
     const char *fname = RSTRING_PTR(data->fname);
-#ifdef _WIN32
-    if (data->wchar)
-	return (VALUE)rb_w32_wopen((WCHAR *)fname, data->oflags, data->perm);
-#endif
     return (VALUE)open(fname, data->oflags, data->perm);
 }
 
@@ -4525,14 +4495,9 @@
 #ifdef O_BINARY
     oflags |= O_BINARY;
 #endif
-    data.fname = fname;
+    data.fname = rb_str_encode_ospath(fname);
     data.oflags = oflags;
     data.perm = perm;
-#ifdef _WIN32
-    if ((data.wchar = w32_conv_to_utf16(&data.fname)) != 0) {
-	OBJ_FREEZE(data.fname);
-    }
-#endif
 
     fd = rb_sysopen_internal(&data);
     if (fd < 0) {
Index: dir.c
===================================================================
--- dir.c	(revision 27569)
+++ dir.c	(revision 27570)
@@ -67,6 +67,16 @@
 #define lstat stat
 #endif
 
+/* define system APIs */
+#ifdef _WIN32
+#undef chdir
+#define chdir(p) rb_w32_uchdir(p)
+#undef mkdir
+#define mkdir(p, m) rb_w32_umkdir(p, m)
+#undef rmdir
+#define rmdir(p) rb_w32_urmdir(p)
+#endif
+
 #define FNM_NOESCAPE	0x01
 #define FNM_PATHNAME	0x02
 #define FNM_DOTMATCH	0x04
@@ -740,6 +750,7 @@
 static void
 dir_chdir(VALUE path)
 {
+    path = rb_str_encode_ospath(path);
     if (chdir(RSTRING_PTR(path)) < 0)
 	rb_sys_fail(RSTRING_PTR(path));
 }
@@ -911,6 +922,7 @@
 {
     check_dirname(&path);
 
+    path = rb_str_encode_ospath(path);
     if (chroot(RSTRING_PTR(path)) == -1)
 	rb_sys_fail(RSTRING_PTR(path));
 
@@ -947,6 +959,7 @@
     }
 
     check_dirname(&path);
+    path = rb_str_encode_ospath(path);
     if (mkdir(RSTRING_PTR(path), mode) == -1)
 	rb_sys_fail(RSTRING_PTR(path));
 
@@ -966,6 +979,7 @@
 dir_s_rmdir(VALUE obj, VALUE dir)
 {
     check_dirname(&dir);
+    dir = rb_str_encode_ospath(dir);
     if (rmdir(RSTRING_PTR(dir)) < 0)
 	rb_sys_fail(RSTRING_PTR(dir));
 
@@ -1617,6 +1631,12 @@
 			    rb_ascii8bit_encoding());
 }
 
+int
+ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE arg, rb_encoding *enc)
+{
+    return ruby_brace_glob0(str, flags & ~GLOB_VERBOSE, func, arg, enc);
+}
+
 static int
 push_glob(VALUE ary, VALUE str, int flags)
 {
Index: win32/win32.c
===================================================================
--- win32/win32.c	(revision 27569)
+++ win32/win32.c	(revision 27570)
@@ -1592,11 +1592,10 @@
 #define DIRENT_PER_CHAR (CHAR_BIT / 2)
 
 static HANDLE
-open_dir_handle(const char *filename, WIN32_FIND_DATAW *fd)
+open_dir_handle(const WCHAR *filename, WIN32_FIND_DATAW *fd)
 {
     HANDLE fh;
     static const WCHAR wildcard[] = L"\\*";
-    UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
     WCHAR *scanname;
     WCHAR *p;
     int len;
@@ -1604,18 +1603,9 @@
     //
     // Create the search pattern
     //
-    len = MultiByteToWideChar(cp, 0, filename, -1, NULL, 0);
-    if (len <= 0) {
-	errno = map_errno(GetLastError());
-	return INVALID_HANDLE_VALUE;
-    }
+    len = lstrlenW(filename);
     scanname = ALLOCA_N(WCHAR, len + sizeof(wildcard) / sizeof(WCHAR));
-    len = MultiByteToWideChar(cp, 0, filename, -1, scanname, len + 2);
-    if (len <= 0) {
-	errno = map_errno(GetLastError());
-	return INVALID_HANDLE_VALUE;
-    }
-
+    lstrcpyW(scanname, filename);
     p = CharPrevW(scanname, scanname + len);
     if (*p == L'/' || *p == L'\\' || *p == L':')
 	lstrcatW(scanname, wildcard + 1);
@@ -1700,26 +1690,80 @@
     return p;
 }
 
+static char *
+wstr_to_filecp(const WCHAR *wstr, long *plen)
+{
+    UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+    char *ptr;
+    int len = WideCharToMultiByte(cp, 0, wstr, -1, NULL, 0, NULL, NULL) - 1;
+    if (!(ptr = malloc(len + 1))) return 0;
+    WideCharToMultiByte(cp, 0, wstr, -1, ptr, len + 1, NULL, NULL);
+    if (plen) *plen = len;
+    return ptr;
+}
+
+static WCHAR *
+filecp_to_wstr(const char *str, long *plen)
+{
+    UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+    WCHAR *ptr;
+    int len = MultiByteToWideChar(cp, 0, str, -1, NULL, 0) - 1;
+    if (!(ptr = malloc(sizeof(WCHAR) * (len + 1)))) return 0;
+    MultiByteToWideChar(cp, 0, str, -1, ptr, len + 1);
+    if (plen) *plen = len;
+    return ptr;
+}
+
+static char *
+wstr_to_utf8(const WCHAR *wstr, long *plen)
+{
+    char *ptr;
+    int len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL) - 1;
+    if (!(ptr = malloc(len + 1))) return 0;
+    WideCharToMultiByte(CP_UTF8, 0, wstr, -1, ptr, len + 1, NULL, NULL);
+    if (plen) *plen = len;
+    return ptr;
+}
+
+static WCHAR *
+utf8_to_wstr(const char *str, long *plen)
+{
+    WCHAR *ptr;
+    int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0) - 1;
+    if (!(ptr = malloc(sizeof(WCHAR) * (len + 1)))) return 0;
+    MultiByteToWideChar(CP_UTF8, 0, str, -1, ptr, len + 1);
+    if (plen) *plen = len;
+    return ptr;
+}
+
 DIR *
 rb_w32_opendir(const char *filename)
 {
-    struct stati64     sbuf;
+    struct stati64 sbuf;
     WIN32_FIND_DATAW fd;
     HANDLE fh;
+    WCHAR *wpath;
 
+    if (!(wpath = filecp_to_wstr(filename, NULL)))
+	return NULL;
+
     //
     // check to see if we've got a directory
     //
-    if (rb_w32_stati64(filename, &sbuf) < 0)
+    if (wstati64(wpath, &sbuf) < 0) {
+	free(wpath);
 	return NULL;
+    }
     if (!(sbuf.st_mode & S_IFDIR) &&
 	(!ISALPHA(filename[0]) || filename[1] != ':' || filename[2] != '\0' ||
 	 ((1 << ((filename[0] & 0x5f) - 'A')) & GetLogicalDrives()) == 0)) {
+	free(wpath);
 	errno = ENOTDIR;
 	return NULL;
     }
 
-    fh = open_dir_handle(filename, &fd);
+    fh = open_dir_handle(wpath, &fd);
+    free(wpath);
     return opendir_internal(fh, &fd);
 }
 
@@ -1739,17 +1783,6 @@
     }
 }
 
-static char *
-win32_conv_from_wstr(const WCHAR *wstr, long *len)
-{
-    UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
-    char *ptr;
-    *len = WideCharToMultiByte(cp, 0, wstr, -1, NULL, 0, NULL, NULL) - 1;
-    if (!(ptr = malloc(*len + 1))) return 0;
-    WideCharToMultiByte(cp, 0, wstr, -1, ptr, *len + 1, NULL, NULL);
-    return ptr;
-}
-
 //
 // Readdir just returns the current string pointer and bumps the
 // string pointer to the next entry.
@@ -1757,7 +1790,7 @@
 static BOOL
 win32_direct_conv(const WCHAR *file, struct direct *entry, rb_encoding *dummy)
 {
-    if (!(entry->d_name = win32_conv_from_wstr(file, &entry->d_namlen)))
+    if (!(entry->d_name = wstr_to_filecp(file, &entry->d_namlen)))
 	return FALSE;
     return TRUE;
 }
@@ -1795,7 +1828,7 @@
     long len;
     char *ptr;
 
-    if (NIL_P(str)) return win32_conv_from_wstr(wstr, lenp);
+    if (NIL_P(str)) return wstr_to_filecp(wstr, lenp);
     *lenp = len = RSTRING_LEN(str);
     memcpy(ptr = malloc(len + 1), RSTRING_PTR(str), len);
     ptr[len] = '\0';
@@ -3665,6 +3698,12 @@
 }
 
 int
+rb_w32_uchown(const char *path, int owner, int group)
+{
+    return 0;
+}
+
+int
 kill(int pid, int sig)
 {
     int ret = 0;
@@ -3748,19 +3787,19 @@
     return ret;
 }
 
-int
-link(const char *from, const char *to)
+static int
+wlink(const WCHAR *from, const WCHAR *to)
 {
-    static BOOL (WINAPI *pCreateHardLink)(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES) = NULL;
+    static BOOL (WINAPI *pCreateHardLinkW)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES) = NULL;
     static int myerrno = 0;
 
-    if (!pCreateHardLink && !myerrno) {
+    if (!pCreateHardLinkW && !myerrno) {
 	HANDLE hKernel;
 
 	hKernel = GetModuleHandle("kernel32.dll");
 	if (hKernel) {
-	    pCreateHardLink = (BOOL (WINAPI *)(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES))GetProcAddress(hKernel, "CreateHardLinkA");
-	    if (!pCreateHardLink) {
+	    pCreateHardLinkW = (BOOL (WINAPI *)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES))GetProcAddress(hKernel, "CreateHardLinkW");
+	    if (!pCreateHardLinkW) {
 		myerrno = ENOSYS;
 	    }
 	}
@@ -3768,12 +3807,12 @@
 	    myerrno = map_errno(GetLastError());
 	}
     }
-    if (!pCreateHardLink) {
+    if (!pCreateHardLinkW) {
 	errno = myerrno;
 	return -1;
     }
 
-    if (!pCreateHardLink(to, from, NULL)) {
+    if (!pCreateHardLinkW(to, from, NULL)) {
 	errno = map_errno(GetLastError());
 	return -1;
     }
@@ -3782,6 +3821,44 @@
 }
 
 int
+rb_w32_ulink(const char *from, const char *to)
+{
+    WCHAR *wfrom;
+    WCHAR *wto;
+    int ret;
+
+    if (!(wfrom = utf8_to_wstr(from, NULL)))
+	return -1;
+    if (!(wto = utf8_to_wstr(to, NULL))) {
+	free(wfrom);
+	return -1;
+    }
+    ret = wlink(wfrom, wto);
+    free(wto);
+    free(wfrom);
+    return ret;
+}
+
+int
+link(const char *from, const char *to)
+{
+    WCHAR *wfrom;
+    WCHAR *wto;
+    int ret;
+
+    if (!(wfrom = filecp_to_wstr(from, NULL)))
+	return -1;
+    if (!(wto = filecp_to_wstr(to, NULL))) {
+	free(wfrom);
+	return -1;
+    }
+    ret = wlink(wfrom, wto);
+    free(wto);
+    free(wfrom);
+    return ret;
+}
+
+int
 wait(int *status)
 {
     return waitpid(-1, status, 0);
@@ -3808,15 +3885,15 @@
     return NULL;
 }
 
-int
-rb_w32_rename(const char *oldpath, const char *newpath)
+static int
+wrename(const WCHAR *oldpath, const WCHAR *newpath)
 {
     int res = 0;
     int oldatts;
     int newatts;
 
-    oldatts = GetFileAttributes(oldpath);
-    newatts = GetFileAttributes(newpath);
+    oldatts = GetFileAttributesW(oldpath);
+    newatts = GetFileAttributesW(newpath);
 
     if (oldatts == -1) {
 	errno = map_errno(GetLastError());
@@ -3825,9 +3902,9 @@
 
     RUBY_CRITICAL({
 	if (newatts != -1 && newatts & FILE_ATTRIBUTE_READONLY)
-	    SetFileAttributesA(newpath, newatts & ~ FILE_ATTRIBUTE_READONLY);
+	    SetFileAttributesW(newpath, newatts & ~ FILE_ATTRIBUTE_READONLY);
 
-	if (!MoveFile(oldpath, newpath))
+	if (!MoveFileW(oldpath, newpath))
 	    res = -1;
 
 	if (res) {
@@ -3835,13 +3912,13 @@
 	      case ERROR_ALREADY_EXISTS:
 	      case ERROR_FILE_EXISTS:
 		if (IsWinNT()) {
-		    if (MoveFileEx(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
+		    if (MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
 			res = 0;
 		} else {
 		    for (;;) {
-			if (!DeleteFile(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND)
+			if (!DeleteFileW(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND)
 			    break;
-			else if (MoveFile(oldpath, newpath)) {
+			else if (MoveFileW(oldpath, newpath)) {
 			    res = 0;
 			    break;
 			}
@@ -3853,27 +3930,63 @@
 	if (res)
 	    errno = map_errno(GetLastError());
 	else
-	    SetFileAttributes(newpath, oldatts);
+	    SetFileAttributesW(newpath, oldatts);
     });
 
     return res;
 }
 
+int rb_w32_urename(const char *from, const char *to)
+{
+    WCHAR *wfrom;
+    WCHAR *wto;
+    int ret = -1;
+
+    if (!(wfrom = utf8_to_wstr(from, NULL)))
+	return -1;
+    if (!(wto = utf8_to_wstr(to, NULL))) {
+	free(wfrom);
+	return -1;
+    }
+    ret = wrename(wfrom, wto);
+    free(wto);
+    free(wfrom);
+    return ret;
+}
+
+int rb_w32_rename(const char *from, const char *to)
+{
+    WCHAR *wfrom;
+    WCHAR *wto;
+    int ret = -1;
+
+    if (!(wfrom = filecp_to_wstr(from, NULL)))
+	return -1;
+    if (!(wto = filecp_to_wstr(to, NULL))) {
+	free(wfrom);
+	return -1;
+    }
+    ret = wrename(wfrom, wto);
+    free(wto);
+    free(wfrom);
+    return ret;
+}
+
 static int
-isUNCRoot(const char *path)
+isUNCRoot(const WCHAR *path)
 {
-    if (path[0] == '\\' && path[1] == '\\') {
-	const char *p;
-	for (p = path + 2; *p; p = CharNext(p)) {
-	    if (*p == '\\')
+    if (path[0] == L'\\' && path[1] == L'\\') {
+	const WCHAR *p;
+	for (p = path + 2; *p; p++) {
+	    if (*p == L'\\')
 		break;
 	}
 	if (p[0] && p[1]) {
-	    for (p++; *p; p = CharNext(p)) {
-		if (*p == '\\')
+	    for (p++; *p; p++) {
+		if (*p == L'\\')
 		    break;
 	    }
-	    if (!p[0] || !p[1] || (p[1] == '.' && !p[2]))
+	    if (!p[0] || !p[1] || (p[1] == L'.' && !p[2]))
 		return 1;
 	}
     }
@@ -3943,7 +4056,7 @@
 }
 
 static unsigned
-fileattr_to_unixmode(DWORD attr, const char *path)
+fileattr_to_unixmode(DWORD attr, const WCHAR *path)
 {
     unsigned mode = 0;
 
@@ -3962,14 +4075,14 @@
     }
 
     if (path && (mode & S_IFREG)) {
-	const char *end = path + strlen(path);
+	const WCHAR *end = path + lstrlenW(path);
 	while (path < end) {
-	    end = CharPrev(path, end);
-	    if (*end == '.') {
-		if ((strcasecmp(end, ".bat") == 0) ||
-		    (strcasecmp(end, ".cmd") == 0) ||
-		    (strcasecmp(end, ".com") == 0) ||
-		    (strcasecmp(end, ".exe") == 0)) {
+	    end = CharPrevW(path, end);
+	    if (*end == L'.') {
+		if ((_wcsicmp(end, L".bat") == 0) ||
+		    (_wcsicmp(end, L".cmd") == 0) ||
+		    (_wcsicmp(end, L".com") == 0) ||
+		    (_wcsicmp(end, L".exe") == 0)) {
 		    mode |= S_IEXEC;
 		}
 		break;
@@ -3984,7 +4097,7 @@
 }
 
 static int
-check_valid_dir(const char *path)
+check_valid_dir(const WCHAR *path)
 {
     WIN32_FIND_DATAW fd;
     HANDLE fh = open_dir_handle(path, &fd);
@@ -3995,19 +4108,19 @@
 }
 
 static int
-winnt_stat(const char *path, struct stati64 *st)
+winnt_stat(const WCHAR *path, struct stati64 *st)
 {
     HANDLE h;
-    WIN32_FIND_DATA wfd;
+    WIN32_FIND_DATAW wfd;
 
     memset(st, 0, sizeof(*st));
     st->st_nlink = 1;
 
-    if (_mbspbrk((const unsigned char *)path, (const unsigned char *)"?*")) {
+    if (wcspbrk(path, L"?*")) {
 	errno = ENOENT;
 	return -1;
     }
-    h = FindFirstFile(path, &wfd);
+    h = FindFirstFileW(path, &wfd);
     if (h != INVALID_HANDLE_VALUE) {
 	FindClose(h);
 	st->st_mode  = fileattr_to_unixmode(wfd.dwFileAttributes, path);
@@ -4019,7 +4132,7 @@
     else {
 	// If runtime stat(2) is called for network shares, it fails on WinNT.
 	// Because GetDriveType returns 1 for network shares. (Win98 returns 4)
-	DWORD attr = GetFileAttributes(path);
+	DWORD attr = GetFileAttributesW(path);
 	if (attr == (DWORD)-1L) {
 	    errno = map_errno(GetLastError());
 	    return -1;
@@ -4030,17 +4143,17 @@
 	st->st_mode  = fileattr_to_unixmode(attr, path);
     }
 
-    st->st_dev = st->st_rdev = (isalpha(path[0]) && path[1] == ':') ?
-	toupper(path[0]) - 'A' : _getdrive() - 1;
+    st->st_dev = st->st_rdev = (iswalpha(path[0]) && path[1] == L':') ?
+	towupper(path[0]) - L'A' : _getdrive() - 1;
 
     return 0;
 }
 
 #ifdef WIN95
 static int
-win95_stat(const char *path, struct stati64 *st)
+win95_stat(const WCHAR *path, struct stati64 *st)
 {
-    int ret = stati64(path, st);
+    int ret = _wstati64(path, st);
     if (ret) return ret;
     if (st->st_mode & S_IFDIR) {
 	return check_valid_dir(path);
@@ -4061,11 +4174,11 @@
     return 0;
 }
 
-int
-rb_w32_stati64(const char *path, struct stati64 *st)
+static int
+wstati64(const WCHAR *path, struct stati64 *st)
 {
-    const char *p;
-    char *buf1, *s, *end;
+    const WCHAR *p;
+    WCHAR *buf1, *s, *end;
     int len, size;
     int ret;
 
@@ -4073,30 +4186,30 @@
 	errno = EFAULT;
 	return -1;
     }
-    size = strlen(path) + 2;
-    buf1 = ALLOCA_N(char, size);
+    size = lstrlenW(path) + 2;
+    buf1 = ALLOCA_N(WCHAR, size);
     for (p = path, s = buf1; *p; p++, s++) {
-	if (*p == '/')
-	    *s = '\\';
+	if (*p == L'/')
+	    *s = L'\\';
 	else
 	    *s = *p;
     }
     *s = '\0';
     len = s - buf1;
-    if (!len || '\"' == *(--s)) {
+    if (!len || L'\"' == *(--s)) {
 	errno = ENOENT;
 	return -1;
     }
-    end = CharPrev(buf1, buf1 + len);
+    end = buf1 + len - 1;
 
     if (isUNCRoot(buf1)) {
-	if (*end == '.')
-	    *end = '\0';
-	else if (*end != '\\')
-	    strlcat(buf1, "\\", size);
+	if (*end == L'.')
+	    *end = L'\0';
+	else if (*end != L'\\')
+	    lstrcatW(buf1, L"\\");
     }
-    else if (*end == '\\' || (buf1 + 1 == end && *end == ':'))
-	strlcat(buf1, ".", size);
+    else if (*end == L'\\' || (buf1 + 1 == end && *end == L':'))
+	lstrcatW(buf1, L".");
 
     ret = IsWinNT() ? winnt_stat(buf1, st) : win95_stat(buf1, st);
     if (ret == 0) {
@@ -4106,6 +4219,32 @@
 }
 
 int
+rb_w32_ustati64(const char *path, struct stati64 *st)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = utf8_to_wstr(path, NULL)))
+	return -1;
+    ret = wstati64(wpath, st);
+    free(wpath);
+    return ret;
+}
+
+int
+rb_w32_stati64(const char *path, struct stati64 *st)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = filecp_to_wstr(path, NULL)))
+	return -1;
+    ret = wstati64(wpath, st);
+    free(wpath);
+    return ret;
+}
+
+int
 rb_w32_access(const char *path, int mode)
 {
     struct stati64 stat;
@@ -4119,6 +4258,20 @@
     return 0;
 }
 
+int
+rb_w32_uaccess(const char *path, int mode)
+{
+    struct stati64 stat;
+    if (rb_w32_ustati64(path, &stat) != 0)
+	return -1;
+    mode <<= 6;
+    if ((stat.st_mode & mode) != mode) {
+	errno = EACCES;
+	return -1;
+    }
+    return 0;
+}
+
 static int
 rb_chsize(HANDLE h, off_t size)
 {
@@ -4524,11 +4677,29 @@
 }
 
 int
+rb_w32_uopen(const char *file, int oflag, ...)
+{
+    WCHAR *wfile;
+    int ret;
+    int pmode;
+
+    va_list arg;
+    va_start(arg, oflag);
+    pmode = va_arg(arg, int);
+    va_end(arg);
+
+    if (!(wfile = utf8_to_wstr(file, NULL)))
+	return -1;
+    ret = rb_w32_wopen(wfile, oflag, pmode);
+    free(wfile);
+    return ret;
+}
+
+int
 rb_w32_open(const char *file, int oflag, ...)
 {
-    UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
-    int len;
     WCHAR *wfile;
+    int ret;
     int pmode;
 
     va_list arg;
@@ -4536,22 +4707,14 @@
     pmode = va_arg(arg, int);
     va_end(arg);
 
-    if ((oflag & O_TEXT) || !(oflag & O_BINARY)) {
+    if ((oflag & O_TEXT) || !(oflag & O_BINARY))
 	return _open(file, oflag, pmode);
-    }
 
-    len = MultiByteToWideChar(cp, 0, file, -1, NULL, 0);
-    if (len <= 0) {
-	errno = map_errno(GetLastError());
+    if (!(wfile = filecp_to_wstr(file, NULL)))
 	return -1;
-    }
-    wfile = ALLOCA_N(WCHAR, len);
-    MultiByteToWideChar(cp, 0, file, -1, wfile, len);
-    if (len <= 0) {
-	errno = map_errno(GetLastError());
-	return -1;
-    }
-    return rb_w32_wopen(wfile, oflag, pmode);
+    ret = rb_w32_wopen(wfile, oflag, pmode);
+    free(wfile);
+    return ret;
 }
 
 int
@@ -5143,15 +5306,15 @@
     return 0;
 }
 
-int
-rb_w32_utime(const char *path, const struct utimbuf *times)
+static int
+wutime(const WCHAR *path, const struct utimbuf *times)
 {
     HANDLE hFile;
     FILETIME atime, mtime;
     struct stati64 stat;
     int ret = 0;
 
-    if (rb_w32_stati64(path, &stat)) {
+    if (wstati64(path, &stat)) {
 	return -1;
     }
 
@@ -5169,11 +5332,11 @@
     }
 
     RUBY_CRITICAL({
-	const DWORD attr = GetFileAttributes(path);
+	const DWORD attr = GetFileAttributesW(path);
 	if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY))
-	    SetFileAttributes(path, attr & ~FILE_ATTRIBUTE_READONLY);
-	hFile = CreateFile(path, GENERIC_WRITE, 0, 0, OPEN_EXISTING,
-			   IsWin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS, 0);
+	    SetFileAttributesW(path, attr & ~FILE_ATTRIBUTE_READONLY);
+	hFile = CreateFileW(path, GENERIC_WRITE, 0, 0, OPEN_EXISTING,
+			    IsWin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS, 0);
 	if (hFile == INVALID_HANDLE_VALUE) {
 	    errno = map_errno(GetLastError());
 	    ret = -1;
@@ -5186,23 +5349,63 @@
 	    CloseHandle(hFile);
 	}
 	if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY))
-	    SetFileAttributes(path, attr);
+	    SetFileAttributesW(path, attr);
     });
 
     return ret;
 }
 
 int
-rb_w32_mkdir(const char *path, int mode)
+rb_w32_uutime(const char *path, const struct utimbuf *times)
 {
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = utf8_to_wstr(path, NULL)))
+	return -1;
+    ret = wutime(wpath, times);
+    free(wpath);
+    return ret;
+}
+
+int
+rb_w32_utime(const char *path, const struct utimbuf *times)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = filecp_to_wstr(path, NULL)))
+	return -1;
+    ret = wutime(wpath, times);
+    free(wpath);
+    return ret;
+}
+
+int
+rb_w32_uchdir(const char *path)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = utf8_to_wstr(path, NULL)))
+	return -1;
+    ret = _wchdir(wpath);
+    free(wpath);
+    return ret;
+}
+
+static int
+wmkdir(const WCHAR *wpath, int mode)
+{
     int ret = -1;
+
     RUBY_CRITICAL(do {
-	if (CreateDirectory(path, NULL) == FALSE) {
+	if (CreateDirectoryW(wpath, NULL) == FALSE) {
 	    errno = map_errno(GetLastError());
 	    break;
 	}
-	if (chmod(path, mode) == -1) {
-	    RemoveDirectory(path);
+	if (_wchmod(wpath, mode) == -1) {
+	    RemoveDirectoryW(wpath);
 	    break;
 	}
 	ret = 0;
@@ -5211,19 +5414,45 @@
 }
 
 int
-rb_w32_rmdir(const char *path)
+rb_w32_umkdir(const char *path, int mode)
 {
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = utf8_to_wstr(path, NULL)))
+	return -1;
+    ret = wmkdir(wpath, mode);
+    free(wpath);
+    return ret;
+}
+
+int
+rb_w32_mkdir(const char *path, int mode)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = filecp_to_wstr(path, NULL)))
+	return -1;
+    ret = wmkdir(wpath, mode);
+    free(wpath);
+    return ret;
+}
+
+static int
+wrmdir(const WCHAR *wpath)
+{
     int ret = 0;
     RUBY_CRITICAL({
-	const DWORD attr = GetFileAttributes(path);
+	const DWORD attr = GetFileAttributesW(wpath);
 	if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
-	    SetFileAttributes(path, attr & ~FILE_ATTRIBUTE_READONLY);
+	    SetFileAttributesW(wpath, attr & ~FILE_ATTRIBUTE_READONLY);
 	}
-	if (RemoveDirectory(path) == FALSE) {
+	if (RemoveDirectoryW(wpath) == FALSE) {
 	    errno = map_errno(GetLastError());
 	    ret = -1;
 	    if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
-		SetFileAttributes(path, attr);
+		SetFileAttributesW(wpath, attr);
 	    }
 	}
     });
@@ -5231,25 +5460,90 @@
 }
 
 int
-rb_w32_unlink(const char *path)
+rb_w32_rmdir(const char *path)
 {
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = filecp_to_wstr(path, NULL)))
+	return -1;
+    ret = wrmdir(wpath);
+    free(wpath);
+    return ret;
+}
+
+int
+rb_w32_urmdir(const char *path)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = utf8_to_wstr(path, NULL)))
+	return -1;
+    ret = wrmdir(wpath);
+    free(wpath);
+    return ret;
+}
+
+static int
+wunlink(const WCHAR *path)
+{
     int ret = 0;
     RUBY_CRITICAL({
-	const DWORD attr = GetFileAttributes(path);
+	const DWORD attr = GetFileAttributesW(path);
 	if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
-	    SetFileAttributes(path, attr & ~FILE_ATTRIBUTE_READONLY);
+	    SetFileAttributesW(path, attr & ~FILE_ATTRIBUTE_READONLY);
 	}
-	if (DeleteFile(path) == FALSE) {
+	if (DeleteFileW(path) == FALSE) {
 	    errno = map_errno(GetLastError());
 	    ret = -1;
 	    if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
-		SetFileAttributes(path, attr);
+		SetFileAttributesW(path, attr);
 	    }
 	}
     });
     return ret;
 }
 
+int
+rb_w32_uunlink(const char *path)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = utf8_to_wstr(path, NULL)))
+	return -1;
+    ret = wunlink(wpath);
+    free(wpath);
+    return ret;
+}
+
+int
+rb_w32_unlink(const char *path)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = filecp_to_wstr(path, NULL)))
+	return -1;
+    ret = wunlink(wpath);
+    free(wpath);
+    return ret;
+}
+
+int
+rb_w32_uchmod(const char *path, int mode)
+{
+    WCHAR *wpath;
+    int ret;
+
+    if (!(wpath = filecp_to_wstr(path, NULL)))
+	return -1;
+    ret = _wchmod(wpath, mode);
+    free(wpath);
+    return ret;
+}
+
 #if !defined(__BORLANDC__)
 int
 rb_w32_isatty(int fd)
Index: file.c
===================================================================
--- file.c	(revision 27569)
+++ file.c	(revision 27570)
@@ -70,13 +70,36 @@
 #define lstat stat
 #endif
 
+/* define system APIs */
+#ifdef _WIN32
+#define STAT(p, s)	rb_w32_ustati64(p, s)
+#undef lstat
+#define lstat(p, s)	rb_w32_ustati64(p, s)
+#undef access
+#define access(p, m)	rb_w32_uaccess(p, m)
+#undef chmod
+#define chmod(p, m)	rb_w32_uchmod(p, m)
+#undef chown
+#define chown(p, o, g)	rb_w32_uchown(p, o, g)
+#undef utime
+#define utime(p, t)	rb_w32_uutime(p, t)
+#undef link
+#define link(f, t)	rb_w32_ulink(f, t)
+#undef unlink
+#define unlink(p)	rb_w32_uunlink(p)
+#undef rename
+#define rename(f, t)	rb_w32_urename(f, t)
+#else
+#define STAT(p, s)	stat(p, s)
+#endif
+
 #if defined(__BEOS__) || defined(__HAIKU__) /* should not change ID if -1 */
 static int
 be_chown(const char *path, uid_t owner, gid_t group)
 {
     if (owner == (uid_t)-1 || group == (gid_t)-1) {
 	struct stat st;
-	if (stat(path, &st) < 0) return -1;
+	if (STAT(path, &st) < 0) return -1;
 	if (owner == (uid_t)-1) owner = st.st_uid;
 	if (group == (gid_t)-1) group = st.st_gid;
     }
@@ -158,6 +181,23 @@
     return rb_get_path_check(obj, rb_safe_level());
 }
 
+VALUE
+rb_str_encode_ospath(VALUE path)
+{
+#ifdef _WIN32
+    char *s;
+    rb_encoding *enc = rb_enc_get(path);
+    if (enc != rb_ascii8bit_encoding()) {
+	rb_encoding *utf8 = rb_utf8_encoding();
+	if (enc != utf8)
+	    path = rb_str_encode(path, rb_enc_from_encoding(utf8), 0, Qnil);
+    }
+    else if (RSTRING_LEN(path) > 0)
+	path = rb_str_encode(path, rb_enc_from_encoding(rb_filesystem_encoding()), 0, Qnil);
+#endif
+    return path;
+}
+
 static long
 apply2files(void (*func)(const char *, void *), VALUE vargs, void *arg)
 {
@@ -167,6 +207,7 @@
     rb_secure(4);
     for (i=0; i<RARRAY_LEN(vargs); i++) {
 	path = rb_get_path(RARRAY_PTR(vargs)[i]);
+	path = rb_str_encode_ospath(path);
 	(*func)(StringValueCStr(path), arg);
     }
 
@@ -754,6 +795,7 @@
 	return fstat(fptr->fd, st);
     }
     FilePathValue(file);
+    file = rb_str_encode_ospath(file);
     return stat(StringValueCStr(file), st);
 }
 
@@ -773,10 +815,18 @@
 	if (f == (HANDLE)-1) return INVALID_HANDLE_VALUE;
     }
     else {
+	VALUE tmp;
+	WCHAR *ptr;
+	int len;
 	FilePathValue(*file);
-	f = CreateFile(StringValueCStr(*file), 0,
-	               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
-	               rb_w32_iswin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS, NULL);
+	tmp = rb_str_encode_ospath(*file);
+	len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, NULL, 0);
+	ptr = ALLOCA_N(WCHAR, len);
+	MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, ptr, len);
+	f = CreateFileW(ptr, 0,
+			FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+			rb_w32_iswin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS,
+			NULL);
 	if (f == INVALID_HANDLE_VALUE) return f;
 	ret = f;
     }
@@ -864,6 +914,7 @@
 
     rb_secure(2);
     FilePathValue(fname);
+    fname = rb_str_encode_ospath(fname);
     if (lstat(StringValueCStr(fname), &st) == -1) {
 	rb_sys_fail(RSTRING_PTR(fname));
     }
@@ -893,11 +944,13 @@
 #ifdef HAVE_LSTAT
     rb_io_t *fptr;
     struct stat st;
+    VALUE path;
 
     rb_secure(2);
     GetOpenFile(obj, fptr);
     if (NIL_P(fptr->pathv)) return Qnil;
-    if (lstat(RSTRING_PTR(fptr->pathv), &st) == -1) {
+    path = rb_str_encode_ospath(fptr->pathv);
+    if (lstat(RSTRING_PTR(path), &st) == -1) {
 	rb_sys_fail_path(fptr->pathv);
     }
     return stat_new(&st);
@@ -951,7 +1004,8 @@
     struct stat st;
     rb_uid_t euid;
 
-    if (stat(path, &st) < 0) return -1;
+    if (STAT(path, &st) < 0)
+	return -1;
 
     euid = geteuid();
 
@@ -982,7 +1036,13 @@
 }
 #endif
 
+static inline int
+access_internal(const char *path, int mode)
+{
+    return access(path, mode);
+}
 
+
 /*
  * Document-class: FileTest
  *
@@ -1094,6 +1154,7 @@
 
     rb_secure(2);
     FilePathValue(fname);
+    fname = rb_str_encode_ospath(fname);
     if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
     if (S_ISLNK(st.st_mode)) return Qtrue;
 #endif
@@ -1214,6 +1275,7 @@
 {
     rb_secure(2);
     FilePathValue(fname);
+    fname = rb_str_encode_ospath(fname);
     if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
     return Qtrue;
 }
@@ -1231,7 +1293,8 @@
 {
     rb_secure(2);
     FilePathValue(fname);
-    if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
+    fname = rb_str_encode_ospath(fname);
+    if (access_internal(StringValueCStr(fname), R_OK) < 0) return Qfalse;
     return Qtrue;
 }
 
@@ -1284,6 +1347,7 @@
 {
     rb_secure(2);
     FilePathValue(fname);
+    fname = rb_str_encode_ospath(fname);
     if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
     return Qtrue;
 }
@@ -1301,7 +1365,8 @@
 {
     rb_secure(2);
     FilePathValue(fname);
-    if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse;
+    fname = rb_str_encode_ospath(fname);
+    if (access_internal(StringValueCStr(fname), W_OK) < 0) return Qfalse;
     return Qtrue;
 }
 
@@ -1346,6 +1411,7 @@
 {
     rb_secure(2);
     FilePathValue(fname);
+    fname = rb_str_encode_ospath(fname);
     if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
     return Qtrue;
 }
@@ -1363,7 +1429,8 @@
 {
     rb_secure(2);
     FilePathValue(fname);
-    if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
+    fname = rb_str_encode_ospath(fname);
+    if (access_internal(StringValueCStr(fname), X_OK) < 0) return Qfalse;
     return Qtrue;
 }
 
@@ -1483,7 +1550,8 @@
 
     rb_secure(2);
     FilePathValue(fname);
-    if (stat(StringValueCStr(fname), &st) < 0) return Qfalse;
+    fname = rb_str_encode_ospath(fname);
+    if (STAT(StringValueCStr(fname), &st) < 0) return Qfalse;
     if (st.st_mode & mode) return Qtrue;
     return Qfalse;
 }
@@ -1568,13 +1636,13 @@
     if (st1.st_dev != st2.st_dev) return Qfalse;
     if (st1.st_ino != st2.st_ino) return Qfalse;
 #else
-#ifdef _WIN32
+# ifdef _WIN32
     BY_HANDLE_FILE_INFORMATION st1, st2;
     HANDLE f1 = 0, f2 = 0;
-#endif
+# endif
 
     rb_secure(2);
-#ifdef _WIN32
+# ifdef _WIN32
     f1 = w32_io_info(&fname1, &st1);
     if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
     f2 = w32_io_info(&fname2, &st2);
@@ -1588,13 +1656,15 @@
 	return Qtrue;
     if (!f1 || !f2) return Qfalse;
     if (rb_w32_iswin95()) return Qfalse;
-#else
+# else
     FilePathValue(fname1);
     fname1 = rb_str_new4(fname1);
+    fname1 = rb_str_encode_ospath(fname1);
     FilePathValue(fname2);
+    fname2 = rb_str_encode_ospath(fname2);
     if (access(RSTRING_PTR(fname1), 0)) return Qfalse;
     if (access(RSTRING_PTR(fname2), 0)) return Qfalse;
-#endif
+# endif
     fname1 = rb_file_expand_path(fname1, Qnil);
     fname2 = rb_file_expand_path(fname2, Qnil);
     if (RSTRING_LEN(fname1) != RSTRING_LEN(fname2)) return Qfalse;
@@ -1686,6 +1756,7 @@
 
     rb_secure(2);
     FilePathValue(fname);
+    fname = rb_str_encode_ospath(fname);
     if (lstat(StringValueCStr(fname), &st) == -1) {
 	rb_sys_fail(RSTRING_PTR(fname));
     }
@@ -1912,6 +1983,9 @@
 {
     rb_io_t *fptr;
     int mode;
+#ifndef HAVE_FCHMOD
+    VALUE path;
+#endif
 
     rb_secure(2);
     mode = NUM2INT(vmode);
@@ -1922,7 +1996,8 @@
 	rb_sys_fail_path(fptr->pathv);
 #else
     if (NIL_P(fptr->pathv)) return Qnil;
-    if (chmod(RSTRING_PTR(fptr->pathv), mode) == -1)
+    path = rb_str_encode_ospath(fptr->pathv);
+    if (chmod(RSTRING_PTR(path), mode) == -1)
 	rb_sys_fail_path(fptr->pathv);
 #endif
 
@@ -2039,6 +2114,9 @@
 {
     rb_io_t *fptr;
     int o, g;
+#ifndef HAVE_FCHOWN
+    VALUE path;
+#endif
 
     rb_secure(2);
     o = NIL_P(owner) ? -1 : NUM2INT(owner);
@@ -2046,7 +2124,8 @@
     GetOpenFile(obj, fptr);
 #ifndef HAVE_FCHOWN
     if (NIL_P(fptr->pathv)) return Qnil;
-    if (chown(RSTRING_PTR(fptr->pathv), o, g) == -1)
+    path = rb_str_encode_ospath(fptr->pathv);
+    if (chown(RSTRING_PTR(path), o, g) == -1)
 	rb_sys_fail_path(fptr->pathv);
 #else
     if (fchown(fptr->fd, o, g) == -1)
@@ -2295,6 +2374,8 @@
     rb_secure(2);
     FilePathValue(from);
     FilePathValue(to);
+    from = rb_str_encode_ospath(from);
+    to = rb_str_encode_ospath(to);
 
     if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
 	sys_fail2(from, to);
@@ -2324,6 +2405,8 @@
     rb_secure(2);
     FilePathValue(from);
     FilePathValue(to);
+    from = rb_str_encode_ospath(from);
+    to = rb_str_encode_ospath(to);
 
     if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) {
 	sys_fail2(from, to);
@@ -2356,6 +2439,7 @@
 
     rb_secure(2);
     FilePathValue(path);
+    path = rb_str_encode_ospath(path);
     buf = xmalloc(size);
     while ((rv = readlink(RSTRING_PTR(path), buf, size)) == size
 #ifdef _AIX
@@ -2419,17 +2503,20 @@
 rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
 {
     const char *src, *dst;
+    VALUE f, t;
 
     rb_secure(2);
     FilePathValue(from);
     FilePathValue(to);
-    src = StringValueCStr(from);
-    dst = StringValueCStr(to);
+    f = rb_str_encode_ospath(from);
+    t = rb_str_encode_ospath(to);
+    src = StringValueCStr(f);
+    dst = StringValueCStr(t);
 #if defined __CYGWIN__
     errno = 0;
 #endif
     if (rename(src, dst) < 0) {
-#if defined DOSISH && !defined _WIN32
+#if defined DOSISH
 	switch (errno) {
 	  case EEXIST:
 #if defined (__EMX__)
@@ -3691,6 +3778,7 @@
     rb_secure(2);
     pos = NUM2OFFT(len);
     FilePathValue(path);
+    path = rb_str_encode_ospath(path);
 #ifdef HAVE_TRUNCATE
     if (truncate(StringValueCStr(path), pos) < 0)
 	rb_sys_fail(RSTRING_PTR(path));
@@ -3698,15 +3786,9 @@
     {
 	int tmpfd;
 
-#  ifdef _WIN32
-	if ((tmpfd = open(StringValueCStr(path), O_RDWR)) < 0) {
-	    rb_sys_fail(RSTRING_PTR(path));
-	}
-#  else
 	if ((tmpfd = open(StringValueCStr(path), 0)) < 0) {
 	    rb_sys_fail(RSTRING_PTR(path));
 	}
-#  endif
 	if (chsize(tmpfd, pos) < 0) {
 	    close(tmpfd);
 	    rb_sys_fail(RSTRING_PTR(path));
@@ -4135,7 +4217,8 @@
 
     rb_secure(2);
     FilePathValue(fname);
-    if (stat(StringValueCStr(fname), &st) == -1) {
+    fname = rb_str_encode_ospath(fname);
+    if (STAT(StringValueCStr(fname), &st) == -1) {
 	rb_sys_fail(RSTRING_PTR(fname));
     }
     if (DATA_PTR(obj)) {
@@ -4793,7 +4876,7 @@
 #ifndef S_IWOTH
 # define S_IWOTH 002
 #endif
-	if (stat(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
+	if (STAT(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
 #ifdef S_ISVTX
 	    && !(p && execpath && (st.st_mode & S_ISVTX))
 #endif

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]