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:
parent
bfeeb913fe
commit
6c28f99d88
7 changed files with 606 additions and 200 deletions
31
ChangeLog
31
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):
|
||||
|
|
20
dir.c
20
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)
|
||||
{
|
||||
|
|
139
file.c
139
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
49
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) {
|
||||
|
|
552
win32/win32.c
552
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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue