* 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().



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22626 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
usa 2009-02-25 08:36:45 +00:00
parent 3540727af5
commit a898f0fb4b
3 changed files with 96 additions and 17 deletions

View File

@ -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> 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 * win32/Makefile.sub (config.status): use un.rb as cp instead of

60
io.c
View File

@ -4174,27 +4174,61 @@ struct sysopen_struct {
const char *fname; const char *fname;
int oflags; int oflags;
mode_t perm; mode_t perm;
#ifdef _WIN32
int wchar;
#endif
}; };
static VALUE static VALUE
sysopen_func(void *ptr) sysopen_func(void *ptr)
{ {
struct sysopen_struct *data = 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); return (VALUE)open(data->fname, data->oflags, data->perm);
} }
static int 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; struct sysopen_struct data;
data.fname = fname; data.fname = RSTRING_PTR(fname);
data.oflags = oflags; data.oflags = oflags;
data.perm = perm; 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); return (int)rb_thread_blocking_region(sysopen_func, &data, RUBY_UBF_IO, 0);
} }
static int static int
rb_sysopen(const char *fname, int oflags, mode_t perm) rb_sysopen(VALUE fname, int oflags, mode_t perm)
{ {
int fd; int fd;
@ -4209,7 +4243,7 @@ rb_sysopen(const char *fname, int oflags, mode_t perm)
fd = rb_sysopen_internal(fname, oflags, perm); fd = rb_sysopen_internal(fname, oflags, perm);
} }
if (fd < 0) { if (fd < 0) {
rb_sys_fail(fname); rb_sys_fail(RSTRING_PTR(fname));
} }
} }
UPDATE_MAXFD(fd); UPDATE_MAXFD(fd);
@ -4280,7 +4314,7 @@ rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig
fptr->mode = fmode; fptr->mode = fmode;
fptr->encs = *convconfig; fptr->encs = *convconfig;
fptr->pathv = rb_str_new_frozen(filename); 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); io_check_tty(fptr);
return io; return io;
@ -4933,7 +4967,7 @@ rb_scan_open_args(int argc, VALUE *argv,
opt = pop_last_hash(&argc, argv); opt = pop_last_hash(&argc, argv);
rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm); rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
FilePathValue(fname); FilePathValue(fname);
#if defined _WIN32 || defined __APPLE__ #if defined __APPLE__
{ {
static rb_encoding *fs_encoding; static rb_encoding *fs_encoding;
rb_encoding *fname_encoding = rb_enc_get(fname); rb_encoding *fname_encoding = rb_enc_get(fname);
@ -5039,7 +5073,6 @@ rb_io_s_sysopen(int argc, VALUE *argv)
VALUE intmode; VALUE intmode;
int oflags, fd; int oflags, fd;
mode_t perm; mode_t perm;
char *path;
rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm); rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
FilePathValue(fname); FilePathValue(fname);
@ -5056,8 +5089,7 @@ rb_io_s_sysopen(int argc, VALUE *argv)
else perm = NUM2UINT(vperm); else perm = NUM2UINT(vperm);
RB_GC_GUARD(fname) = rb_str_new4(fname); RB_GC_GUARD(fname) = rb_str_new4(fname);
path = RSTRING_PTR(fname); fd = rb_sysopen(fname, oflags, perm);
fd = rb_sysopen(path, oflags, perm);
return INT2NUM(fd); return INT2NUM(fd);
} }
@ -5397,7 +5429,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
fptr->pathv = rb_str_new_frozen(fname); fptr->pathv = rb_str_new_frozen(fname);
oflags = rb_io_fmode_oflags(fptr->mode); oflags = rb_io_fmode_oflags(fptr->mode);
if (fptr->fd < 0) { 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; fptr->stdio_file = 0;
return file; return file;
} }
@ -5422,7 +5454,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
if (close(fptr->fd) < 0) if (close(fptr->fd) < 0)
rb_sys_fail_path(fptr->pathv); rb_sys_fail_path(fptr->pathv);
fptr->fd = -1; fptr->fd = -1;
fptr->fd = rb_sysopen(RSTRING_PTR(fptr->pathv), oflags, 0666); fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
} }
return file; return file;
@ -6229,7 +6261,7 @@ argf_next_argv(VALUE argf)
} }
} }
else { else {
int fr = rb_sysopen(fn, O_RDONLY, 0); int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0);
if (ARGF.inplace) { if (ARGF.inplace) {
struct stat st; struct stat st;
@ -6254,7 +6286,7 @@ argf_next_argv(VALUE argf)
(void)close(fr); (void)close(fr);
(void)unlink(RSTRING_PTR(str)); (void)unlink(RSTRING_PTR(str));
(void)rename(fn, 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 #else
if (rename(fn, RSTRING_PTR(str)) < 0) { if (rename(fn, RSTRING_PTR(str)) < 0) {
rb_warn("Can't rename %s to %s: %s, skipping file", rb_warn("Can't rename %s to %s: %s, skipping file",
@ -6276,7 +6308,7 @@ argf_next_argv(VALUE argf)
} }
#endif #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 #ifndef NO_SAFE_RENAME
fstat(fw, &st2); fstat(fw, &st2);
#ifdef HAVE_FCHMOD #ifdef HAVE_FCHMOD

View File

@ -4150,6 +4150,37 @@ rb_w32_getppid(void)
int int
rb_w32_open(const char *file, int oflag, ...) 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; char flags = 0;
int fd; int fd;
@ -4165,7 +4196,7 @@ rb_w32_open(const char *file, int oflag, ...)
va_start(arg, oflag); va_start(arg, oflag);
pmode = va_arg(arg, int); pmode = va_arg(arg, int);
va_end(arg); va_end(arg);
return _open(file, oflag, pmode); return _wopen(file, oflag, pmode);
} }
sec.nLength = sizeof(sec); sec.nLength = sizeof(sec);
@ -4281,8 +4312,8 @@ rb_w32_open(const char *file, int oflag, ...)
/* open with FILE_FLAG_OVERLAPPED if have CancelIo */ /* open with FILE_FLAG_OVERLAPPED if have CancelIo */
if (cancel_io) if (cancel_io)
attr |= FILE_FLAG_OVERLAPPED; attr |= FILE_FLAG_OVERLAPPED;
h = CreateFile(file, access, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec, h = CreateFileW(file, access, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec,
create, attr, NULL); create, attr, NULL);
if (h == INVALID_HANDLE_VALUE) { if (h == INVALID_HANDLE_VALUE) {
errno = map_errno(GetLastError()); errno = map_errno(GetLastError());
MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock)); MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));