From 6c28f99d8894b9f9a3c1394d120115f69012f2c3 Mon Sep 17 00:00:00 2001 From: usa Date: Fri, 30 Apr 2010 17:56:23 +0000 Subject: * 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 --- ChangeLog | 31 +++ dir.c | 20 ++ file.c | 139 ++++++++++--- include/ruby/intern.h | 1 + include/ruby/win32.h | 14 +- io.c | 49 +---- win32/win32.c | 546 ++++++++++++++++++++++++++++++++++++++------------ 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 + + * 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 * 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; ifd, 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'; @@ -3664,6 +3697,12 @@ chown(const char *path, int owner, int group) return 0; } +int +rb_w32_uchown(const char *path, int owner, int group) +{ + return 0; +} + int kill(int pid, int sig) { @@ -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; } @@ -3781,6 +3820,44 @@ link(const char *from, const char *to) return 0; } +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) { @@ -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) { @@ -4105,6 +4218,32 @@ rb_w32_stati64(const char *path, struct stati64 *st) return ret; } +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) { @@ -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) { @@ -4523,12 +4676,30 @@ rb_w32_getppid(void) return ppid; } +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) -- cgit v1.2.3