1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
usa 2010-04-30 17:56:23 +00:00
parent bfeeb913fe
commit 6c28f99d88
7 changed files with 606 additions and 200 deletions

View file

@ -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):

20
dir.c
View file

@ -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)
{

139
file.c
View file

@ -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

View file

@ -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);

View file

@ -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);

49
io.c
View file

@ -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) {

View file

@ -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;
}
static int
isUNCRoot(const char *path)
int rb_w32_urename(const char *from, const char *to)
{
if (path[0] == '\\' && path[1] == '\\') {
const char *p;
for (p = path + 2; *p; p = CharNext(p)) {
if (*p == '\\')
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 WCHAR *path)
{
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)
{
@ -4524,11 +4677,10 @@ rb_w32_getppid(void)
}
int
rb_w32_open(const char *file, int oflag, ...)
rb_w32_uopen(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 +4688,33 @@ rb_w32_open(const char *file, int oflag, ...)
pmode = va_arg(arg, int);
va_end(arg);
if ((oflag & O_TEXT) || !(oflag & O_BINARY)) {
return _open(file, oflag, pmode);
}
if (!(wfile = utf8_to_wstr(file, NULL)))
return -1;
ret = rb_w32_wopen(wfile, oflag, pmode);
free(wfile);
return ret;
}
len = MultiByteToWideChar(cp, 0, file, -1, NULL, 0);
if (len <= 0) {
errno = map_errno(GetLastError());
int
rb_w32_open(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 ((oflag & O_TEXT) || !(oflag & O_BINARY))
return _open(file, oflag, pmode);
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)