summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-08-20 14:56:23 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-08-20 14:56:23 +0000
commit36c9cddf6cc5306b792669ce31825a6e2d065a5c (patch)
tree3741165e94ecc76eaa21063fc54bf9b7f0bb7c1b /io.c
parent4c5d7d53b210017ac71ccb958155ba2dc241e220 (diff)
* io.c (rb_sysopen): moved sysopen_struct from rb_sysopen_internal.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c74
1 files changed, 44 insertions, 30 deletions
diff --git a/io.c b/io.c
index 16cb9b5607..263c40a768 100644
--- a/io.c
+++ b/io.c
@@ -4406,7 +4406,7 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
}
struct sysopen_struct {
- const char *fname;
+ VALUE fname;
int oflags;
mode_t perm;
#ifdef _WIN32
@@ -4414,62 +4414,76 @@ struct sysopen_struct {
#endif
};
-static VALUE
-sysopen_func(void *ptr)
-{
- struct sysopen_struct *data = ptr;
#ifdef _WIN32
- if (data->wchar)
- return (VALUE)rb_w32_wopen((WCHAR *)data->fname, data->oflags,
- data->perm);
-#endif
- return (VALUE)open(data->fname, data->oflags, data->perm);
-}
-
-static int
-rb_sysopen_internal(VALUE fname, int oflags, mode_t perm)
+static rb_encoding *
+w32_utf16(void)
{
-#ifdef _WIN32
static rb_encoding *utf16 = (rb_encoding *)-1;
-#endif
- struct sysopen_struct data;
- 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;
}
+ return utf16;
+}
+
+static int
+w32_conv_to_utf16(volatile VALUE *strp)
+{
+ rb_encoding *utf16 = w32_utf16();
if (utf16) {
- VALUE wfname = rb_str_encode(fname, rb_enc_from_encoding(utf16), 0,
- Qnil);
- rb_enc_str_buf_cat(wfname, "", 1, utf16); /* workaround */
- data.fname = RSTRING_PTR(wfname);
- data.wchar = 1;
+ 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 {
- data.wchar = 0;
+ return 0;
}
+}
#endif
- return (int)rb_thread_blocking_region(sysopen_func, &data, RUBY_UBF_IO, 0);
+
+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);
+}
+
+static inline int
+rb_sysopen_internal(const struct sysopen_struct *data)
+{
+ return (int)rb_thread_blocking_region(sysopen_func, data, RUBY_UBF_IO, 0);
}
static int
rb_sysopen(VALUE fname, int oflags, mode_t perm)
{
int fd;
+ struct sysopen_struct data;
#ifdef O_BINARY
oflags |= O_BINARY;
#endif
+ data.fname = 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(fname, oflags, perm);
+ fd = rb_sysopen_internal(&data);
if (fd < 0) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
- fd = rb_sysopen_internal(fname, oflags, perm);
+ fd = rb_sysopen_internal(&data);
}
if (fd < 0) {
rb_sys_fail(RSTRING_PTR(fname));