summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-04-30 17:56:23 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-04-30 17:56:23 +0000
commit6c28f99d8894b9f9a3c1394d120115f69012f2c3 (patch)
tree967e8f5c37611f009640580566540a001df60bf3
parentbfeeb913fed701b552cb6c7331b33062b7922de3 (diff)
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog31
-rw-r--r--dir.c20
-rw-r--r--file.c139
-rw-r--r--include/ruby/intern.h1
-rw-r--r--include/ruby/win32.h14
-rw-r--r--io.c49
-rw-r--r--win32/win32.c546
7 files changed, 603 insertions, 197 deletions
diff --git a/ChangeLog b/ChangeLog
index 6547d1ed33..19e62b2186 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+Sat May 1 02:41:33 2010 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * 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@ruby-lang.org>
* lib/test/unit/assertions.rb (Test::Unit::Assertions#assert):
diff --git a/dir.c b/dir.c
index 9c1c792cbe..c709b9446f 100644
--- a/dir.c
+++ b/dir.c
@@ -67,6 +67,16 @@ char *strchr(char*,char);
#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 @@ dir_close(VALUE dir)
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 @@ dir_s_chroot(VALUE dir, VALUE path)
{
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 @@ dir_s_mkdir(int argc, VALUE *argv, VALUE obj)
}
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 @@ static VALUE
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 @@ ruby_brace_glob(const char *str, int flags, ruby_glob_func *func, VALUE arg)
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)
{
diff --git a/file.c b/file.c
index 9b6c56f0cf..ee57381ed7 100644
--- a/file.c
+++ b/file.c
@@ -70,13 +70,36 @@ int flock(int, int);
#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 @@ rb_get_path(VALUE obj)
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 @@ apply2files(void (*func)(const char *, void *), VALUE vargs, void *arg)
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 @@ rb_stat(VALUE file, struct stat *st)
return fstat(fptr->fd, st);
}
FilePathValue(file);
+ file = rb_str_encode_ospath(file);
return stat(StringValueCStr(file), st);
}
@@ -773,10 +815,18 @@ w32_io_info(VALUE *file, BY_HANDLE_FILE_INFORMATION *st)
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_file_s_lstat(VALUE klass, VALUE fname)
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 @@ rb_file_lstat(VALUE obj)
#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 @@ eaccess(const char *path, int mode)
struct stat st;
rb_uid_t euid;
- if (stat(path, &st) < 0) return -1;
+ if (STAT(path, &st) < 0)
+ return -1;
euid = geteuid();
@@ -982,6 +1036,12 @@ eaccess(const char *path, int mode)
}
#endif
+static inline int
+access_internal(const char *path, int mode)
+{
+ return access(path, mode);
+}
+
/*
* Document-class: FileTest
@@ -1094,6 +1154,7 @@ rb_file_symlink_p(VALUE obj, VALUE fname)
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_file_readable_p(VALUE obj, VALUE fname)
{
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_file_readable_real_p(VALUE obj, VALUE fname)
{
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_file_writable_p(VALUE obj, VALUE fname)
{
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_file_writable_real_p(VALUE obj, VALUE fname)
{
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_file_executable_p(VALUE obj, VALUE fname)
{
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_file_executable_real_p(VALUE obj, VALUE fname)
{
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 @@ check3rdbyte(VALUE fname, int mode)
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 @@ rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
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 @@ rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
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_file_s_ftype(VALUE klass, VALUE fname)
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_file_chmod(VALUE obj, VALUE vmode)
{
rb_io_t *fptr;
int mode;
+#ifndef HAVE_FCHMOD
+ VALUE path;
+#endif
rb_secure(2);
mode = NUM2INT(vmode);
@@ -1922,7 +1996,8 @@ rb_file_chmod(VALUE obj, VALUE vmode)
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_file_chown(VALUE obj, VALUE owner, VALUE group)
{
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 @@ rb_file_chown(VALUE obj, VALUE owner, VALUE group)
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_file_s_link(VALUE klass, VALUE from, VALUE to)
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_file_s_symlink(VALUE klass, VALUE from, VALUE to)
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_file_s_readlink(VALUE klass, VALUE path)
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 @@ static VALUE
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_file_s_truncate(VALUE klass, VALUE path, VALUE len)
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 @@ rb_file_s_truncate(VALUE klass, VALUE path, VALUE len)
{
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_stat_init(VALUE obj, VALUE fname)
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 @@ path_check_0(VALUE path, int execpath)
#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
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index c53728eec8..e46e19aac4 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -367,6 +367,7 @@ char *rb_path_skip_prefix(const char *);
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);
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index 8ea3f3b1c4..a71fb97b1e 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -256,12 +256,15 @@ extern int rb_w32_socketpair(int, int, int, int *);
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 rb_pid_t rb_w32_getppid(void);
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 @@ HANDLE GetCurrentThreadHandle(void);
int rb_w32_sleep(unsigned long msec);
int rb_w32_putc(int, FILE*);
int rb_w32_getc(FILE*);
-int rb_w32_wopen(const WCHAR *, int, ...);
int rb_w32_open(const char *, int, ...);
+int rb_w32_uopen(const char *, int, ...);
+int rb_w32_wopen(const WCHAR *, 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);
diff --git a/io.c b/io.c
index 8a61940824..1b9124134e 100644
--- a/io.c
+++ b/io.c
@@ -114,6 +114,12 @@ extern void Init_File(void);
#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 @@ struct sysopen_struct {
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 @@ rb_sysopen(VALUE fname, int oflags, mode_t perm)
#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) {
diff --git a/win32/win32.c b/win32/win32.c
index 26477e86be..6f27437c58 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -1592,11 +1592,10 @@ rb_w32_cmdvector(const char *cmd, char ***vec)
#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 @@ open_dir_handle(const char *filename, WIN32_FIND_DATAW *fd)
//
// 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 @@ opendir_internal(HANDLE fh, WIN32_FIND_DATAW *fd)
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 @@ move_to_next_entry(DIR *dirp)
}
}
-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 @@ win32_conv_from_wstr(const WCHAR *wstr, long *len)
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 @@ rb_w32_conv_from_wstr(const WCHAR *wstr, long *lenp, rb_encoding *enc)
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 @@ chown(const char *path, int owner, int group)
}
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 @@ kill(int pid, int sig)
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 @@ link(const char *from, const char *to)
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 @@ link(const char *from, const char *to)
}
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 @@ rb_w32_getenv(const char *name)
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 @@ rb_w32_rename(const char *oldpath, const char *newpath)
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 @@ rb_w32_rename(const char *oldpath, const char *newpath)
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 @@ rb_w32_rename(const char *oldpath, const char *newpath)
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 @@ filetime_to_unixtime(const FILETIME *ft)
}
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 @@ fileattr_to_unixmode(DWORD attr, const char *path)
}
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 @@ fileattr_to_unixmode(DWORD attr, const char *path)
}
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 @@ check_valid_dir(const char *path)
}
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 @@ winnt_stat(const char *path, struct stati64 *st)
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 @@ winnt_stat(const char *path, struct stati64 *st)
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 @@ rb_w32_stat(const char *path, struct stat *st)
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 @@ rb_w32_stati64(const char *path, struct stati64 *st)
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 @@ rb_w32_stati64(const char *path, struct stati64 *st)
}
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 @@ rb_w32_access(const char *path, int mode)
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 @@ rb_w32_getppid(void)
}
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 @@ rb_w32_open(const char *file, int oflag, ...)
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 @@ unixtime_to_filetime(time_t time, FILETIME *ft)
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 @@ rb_w32_utime(const char *path, const struct utimbuf *times)
}
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 @@ rb_w32_utime(const char *path, const struct utimbuf *times)
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 @@ rb_w32_mkdir(const char *path, int mode)
}
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 @@ rb_w32_rmdir(const char *path)
}
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)