diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | io.c | 60 | ||||
-rw-r--r-- | win32/win32.c | 37 |
3 files changed, 96 insertions, 17 deletions
@@ -1,3 +1,19 @@ +Wed Feb 25 17:31:32 2009 NAKAMURA Usaku <usa@ruby-lang.org> + + * io.c (sysopen_func, rb_sysopen_internal, rb_sysopen): open file + by UTF-16'ed filename on Windows. + + * io.c (rb_file_open_generic, rb_io_s_sysopen, rb_io_reopen, + argf_next_argv): follow above change. + + * io.c (rb_scan_open_args): no longer need to convert filepath here on + Windows. + + * win32/wio32.c (rb_w32_wopen): new function to open file by UTF-16'ed + filename. + + * win32/win32.c (rb_w32_open): call rb_w32_open(). + Wed Feb 25 15:05:35 2009 NAKAMURA Usaku <usa@ruby-lang.org> * win32/Makefile.sub (config.status): use un.rb as cp instead of @@ -4174,27 +4174,61 @@ struct sysopen_struct { const char *fname; int oflags; mode_t perm; +#ifdef _WIN32 + int wchar; +#endif }; static VALUE sysopen_func(void *ptr) { struct sysopen_struct *data = ptr; +#ifdef _WIN32 + if (data->wchar) + return (VALUE)rb_w32_wopen(data->fname, data->oflags, data->perm); +#endif return (VALUE)open(data->fname, data->oflags, data->perm); } static int -rb_sysopen_internal(const char *fname, int oflags, mode_t perm) +rb_sysopen_internal(VALUE fname, int oflags, mode_t perm) { +#ifdef _WIN32 + static rb_encoding *utf16 = (rb_encoding *)-1; +#endif struct sysopen_struct data; - data.fname = fname; + data.fname = RSTRING_PTR(fname); data.oflags = oflags; data.perm = perm; +#ifdef _WIN32 + if (utf16 == (rb_encoding *)-1) { + utf16 = rb_enc_find("UTF-16LE"); + if (utf16 == rb_ascii8bit_encoding()) + utf16 = NULL; + } + if (utf16) { + VALUE wfname; + VALUE opthash = rb_hash_new(); + int ecflags; + VALUE ecopts; + rb_hash_aset(opthash, ID2SYM(rb_intern("undef")), + ID2SYM(rb_intern("replace"))); + ecflags = rb_econv_prepare_opts(opthash, &ecopts); + wfname = rb_str_encode(fname, rb_enc_from_encoding(utf16), ecflags, + ecopts); + rb_enc_str_buf_cat(wfname, "", 1, utf16); /* workaround */ + data.fname = RSTRING_PTR(wfname); + data.wchar = 1; + } + else { + data.wchar = 0; + } +#endif return (int)rb_thread_blocking_region(sysopen_func, &data, RUBY_UBF_IO, 0); } static int -rb_sysopen(const char *fname, int oflags, mode_t perm) +rb_sysopen(VALUE fname, int oflags, mode_t perm) { int fd; @@ -4209,7 +4243,7 @@ rb_sysopen(const char *fname, int oflags, mode_t perm) fd = rb_sysopen_internal(fname, oflags, perm); } if (fd < 0) { - rb_sys_fail(fname); + rb_sys_fail(RSTRING_PTR(fname)); } } UPDATE_MAXFD(fd); @@ -4280,7 +4314,7 @@ rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig fptr->mode = fmode; fptr->encs = *convconfig; fptr->pathv = rb_str_new_frozen(filename); - fptr->fd = rb_sysopen(RSTRING_PTR(fptr->pathv), oflags, perm); + fptr->fd = rb_sysopen(fptr->pathv, oflags, perm); io_check_tty(fptr); return io; @@ -4933,7 +4967,7 @@ rb_scan_open_args(int argc, VALUE *argv, opt = pop_last_hash(&argc, argv); rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm); FilePathValue(fname); -#if defined _WIN32 || defined __APPLE__ +#if defined __APPLE__ { static rb_encoding *fs_encoding; rb_encoding *fname_encoding = rb_enc_get(fname); @@ -5039,7 +5073,6 @@ rb_io_s_sysopen(int argc, VALUE *argv) VALUE intmode; int oflags, fd; mode_t perm; - char *path; rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm); FilePathValue(fname); @@ -5056,8 +5089,7 @@ rb_io_s_sysopen(int argc, VALUE *argv) else perm = NUM2UINT(vperm); RB_GC_GUARD(fname) = rb_str_new4(fname); - path = RSTRING_PTR(fname); - fd = rb_sysopen(path, oflags, perm); + fd = rb_sysopen(fname, oflags, perm); return INT2NUM(fd); } @@ -5397,7 +5429,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file) fptr->pathv = rb_str_new_frozen(fname); oflags = rb_io_fmode_oflags(fptr->mode); if (fptr->fd < 0) { - fptr->fd = rb_sysopen(RSTRING_PTR(fptr->pathv), oflags, 0666); + fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666); fptr->stdio_file = 0; return file; } @@ -5422,7 +5454,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file) if (close(fptr->fd) < 0) rb_sys_fail_path(fptr->pathv); fptr->fd = -1; - fptr->fd = rb_sysopen(RSTRING_PTR(fptr->pathv), oflags, 0666); + fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666); } return file; @@ -6229,7 +6261,7 @@ argf_next_argv(VALUE argf) } } else { - int fr = rb_sysopen(fn, O_RDONLY, 0); + int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0); if (ARGF.inplace) { struct stat st; @@ -6254,7 +6286,7 @@ argf_next_argv(VALUE argf) (void)close(fr); (void)unlink(RSTRING_PTR(str)); (void)rename(fn, RSTRING_PTR(str)); - fr = rb_sysopen(RSTRING_PTR(str), O_RDONLY, 0); + fr = rb_sysopen(str, O_RDONLY, 0); #else if (rename(fn, RSTRING_PTR(str)) < 0) { rb_warn("Can't rename %s to %s: %s, skipping file", @@ -6276,7 +6308,7 @@ argf_next_argv(VALUE argf) } #endif } - fw = rb_sysopen(fn, O_WRONLY|O_CREAT|O_TRUNC, 0666); + fw = rb_sysopen(ARGF.filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); #ifndef NO_SAFE_RENAME fstat(fw, &st2); #ifdef HAVE_FCHMOD diff --git a/win32/win32.c b/win32/win32.c index 3bd857253a..9c1a92a55c 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -4151,6 +4151,37 @@ rb_w32_getppid(void) int rb_w32_open(const char *file, int oflag, ...) { + UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + int len; + WCHAR *wfile; + int pmode; + + va_list arg; + va_start(arg, oflag); + pmode = va_arg(arg, int); + va_end(arg); + + 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()); + 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); +} + +int +rb_w32_wopen(const WCHAR *file, int oflag, ...) +{ char flags = 0; int fd; DWORD access; @@ -4165,7 +4196,7 @@ rb_w32_open(const char *file, int oflag, ...) va_start(arg, oflag); pmode = va_arg(arg, int); va_end(arg); - return _open(file, oflag, pmode); + return _wopen(file, oflag, pmode); } sec.nLength = sizeof(sec); @@ -4281,8 +4312,8 @@ rb_w32_open(const char *file, int oflag, ...) /* open with FILE_FLAG_OVERLAPPED if have CancelIo */ if (cancel_io) attr |= FILE_FLAG_OVERLAPPED; - h = CreateFile(file, access, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec, - create, attr, NULL); + h = CreateFileW(file, access, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec, + create, attr, NULL); if (h == INVALID_HANDLE_VALUE) { errno = map_errno(GetLastError()); MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock)); |