summaryrefslogtreecommitdiff
path: root/file.c
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-04-30 17:56:23 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-04-30 17:56:23 +0000
commit6c28f99d8894b9f9a3c1394d120115f69012f2c3 (patch)
tree967e8f5c37611f009640580566540a001df60bf3 /file.c
parentbfeeb913fed701b552cb6c7331b33062b7922de3 (diff)
* merge some patches from win32-uncode-test branch.
see #1685. * file.c, include/ruby/intern.h (rb_str_encode_ospath): new function to convert encoding for pathname. * win32.c, include/ruby/win32.h (rb_w32_ulink, rb_w32_urename, rb_w32_ustati64, rb_w32_uopen, rb_w32_uutime, rb_w32_uchdir, rb_w32_umkdir, rb_w32_urmdir, rb_w32_uunlink): new functions to accept UTF-8 path. * win32/win32.c (rb_w32_opendir, link, rb_w32_stati64, rb_w32_utime, rb_w32_unlink): use WCHAR path internally. * file.c (rb_stat, eaccess, access_internal, rb_file_s_ftype, chmod_internal, rb_file_chmod, rb_file_chown, utime_internal, rb_file_s_link, unlink_internal, rb_file_s_rename): use UTF-8 version functions on Win32. * file.c (apply2files, rb_stat, rb_file_s_lstat, rb_file_symlink_p, rb_file_readable_p, rb_file_writable_p, rb_file_executable_p, check3rdbyte, rb_file_identical_p, rb_file_chmod, rb_file_chown, rb_file_s_link, rb_file_s_symlink, rb_file_s_rename): call rb_str_encode_ospath() before passing the path to system. * io.c (rb_sysopen): ditto. * dir.c (dir_chdir, dir_s_mkdir, dir_s_rmdir): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27570 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'file.c')
-rw-r--r--file.c139
1 files changed, 111 insertions, 28 deletions
diff --git a/file.c b/file.c
index 9b6c56f0cf..ee57381ed7 100644
--- a/file.c
+++ b/file.c
@@ -70,13 +70,36 @@ int flock(int, int);
#define lstat stat
#endif
+/* define system APIs */
+#ifdef _WIN32
+#define STAT(p, s) rb_w32_ustati64(p, s)
+#undef lstat
+#define lstat(p, s) rb_w32_ustati64(p, s)
+#undef access
+#define access(p, m) rb_w32_uaccess(p, m)
+#undef chmod
+#define chmod(p, m) rb_w32_uchmod(p, m)
+#undef chown
+#define chown(p, o, g) rb_w32_uchown(p, o, g)
+#undef utime
+#define utime(p, t) rb_w32_uutime(p, t)
+#undef link
+#define link(f, t) rb_w32_ulink(f, t)
+#undef unlink
+#define unlink(p) rb_w32_uunlink(p)
+#undef rename
+#define rename(f, t) rb_w32_urename(f, t)
+#else
+#define STAT(p, s) stat(p, s)
+#endif
+
#if defined(__BEOS__) || defined(__HAIKU__) /* should not change ID if -1 */
static int
be_chown(const char *path, uid_t owner, gid_t group)
{
if (owner == (uid_t)-1 || group == (gid_t)-1) {
struct stat st;
- if (stat(path, &st) < 0) return -1;
+ if (STAT(path, &st) < 0) return -1;
if (owner == (uid_t)-1) owner = st.st_uid;
if (group == (gid_t)-1) group = st.st_gid;
}
@@ -158,6 +181,23 @@ rb_get_path(VALUE obj)
return rb_get_path_check(obj, rb_safe_level());
}
+VALUE
+rb_str_encode_ospath(VALUE path)
+{
+#ifdef _WIN32
+ char *s;
+ rb_encoding *enc = rb_enc_get(path);
+ if (enc != rb_ascii8bit_encoding()) {
+ rb_encoding *utf8 = rb_utf8_encoding();
+ if (enc != utf8)
+ path = rb_str_encode(path, rb_enc_from_encoding(utf8), 0, Qnil);
+ }
+ else if (RSTRING_LEN(path) > 0)
+ path = rb_str_encode(path, rb_enc_from_encoding(rb_filesystem_encoding()), 0, Qnil);
+#endif
+ return path;
+}
+
static long
apply2files(void (*func)(const char *, void *), VALUE vargs, void *arg)
{
@@ -167,6 +207,7 @@ apply2files(void (*func)(const char *, void *), VALUE vargs, void *arg)
rb_secure(4);
for (i=0; i<RARRAY_LEN(vargs); i++) {
path = rb_get_path(RARRAY_PTR(vargs)[i]);
+ path = rb_str_encode_ospath(path);
(*func)(StringValueCStr(path), arg);
}
@@ -754,6 +795,7 @@ rb_stat(VALUE file, struct stat *st)
return fstat(fptr->fd, st);
}
FilePathValue(file);
+ file = rb_str_encode_ospath(file);
return stat(StringValueCStr(file), st);
}
@@ -773,10 +815,18 @@ w32_io_info(VALUE *file, BY_HANDLE_FILE_INFORMATION *st)
if (f == (HANDLE)-1) return INVALID_HANDLE_VALUE;
}
else {
+ VALUE tmp;
+ WCHAR *ptr;
+ int len;
FilePathValue(*file);
- f = CreateFile(StringValueCStr(*file), 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
- rb_w32_iswin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ tmp = rb_str_encode_ospath(*file);
+ len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, NULL, 0);
+ ptr = ALLOCA_N(WCHAR, len);
+ MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(tmp), -1, ptr, len);
+ f = CreateFileW(ptr, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+ rb_w32_iswin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
if (f == INVALID_HANDLE_VALUE) return f;
ret = f;
}
@@ -864,6 +914,7 @@ rb_file_s_lstat(VALUE klass, VALUE fname)
rb_secure(2);
FilePathValue(fname);
+ fname = rb_str_encode_ospath(fname);
if (lstat(StringValueCStr(fname), &st) == -1) {
rb_sys_fail(RSTRING_PTR(fname));
}
@@ -893,11 +944,13 @@ rb_file_lstat(VALUE obj)
#ifdef HAVE_LSTAT
rb_io_t *fptr;
struct stat st;
+ VALUE path;
rb_secure(2);
GetOpenFile(obj, fptr);
if (NIL_P(fptr->pathv)) return Qnil;
- if (lstat(RSTRING_PTR(fptr->pathv), &st) == -1) {
+ path = rb_str_encode_ospath(fptr->pathv);
+ if (lstat(RSTRING_PTR(path), &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return stat_new(&st);
@@ -951,7 +1004,8 @@ eaccess(const char *path, int mode)
struct stat st;
rb_uid_t euid;
- if (stat(path, &st) < 0) return -1;
+ if (STAT(path, &st) < 0)
+ return -1;
euid = geteuid();
@@ -982,6 +1036,12 @@ eaccess(const char *path, int mode)
}
#endif
+static inline int
+access_internal(const char *path, int mode)
+{
+ return access(path, mode);
+}
+
/*
* Document-class: FileTest
@@ -1094,6 +1154,7 @@ rb_file_symlink_p(VALUE obj, VALUE fname)
rb_secure(2);
FilePathValue(fname);
+ fname = rb_str_encode_ospath(fname);
if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
if (S_ISLNK(st.st_mode)) return Qtrue;
#endif
@@ -1214,6 +1275,7 @@ rb_file_readable_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
+ fname = rb_str_encode_ospath(fname);
if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
return Qtrue;
}
@@ -1231,7 +1293,8 @@ rb_file_readable_real_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
- if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
+ fname = rb_str_encode_ospath(fname);
+ if (access_internal(StringValueCStr(fname), R_OK) < 0) return Qfalse;
return Qtrue;
}
@@ -1284,6 +1347,7 @@ rb_file_writable_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
+ fname = rb_str_encode_ospath(fname);
if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
return Qtrue;
}
@@ -1301,7 +1365,8 @@ rb_file_writable_real_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
- if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse;
+ fname = rb_str_encode_ospath(fname);
+ if (access_internal(StringValueCStr(fname), W_OK) < 0) return Qfalse;
return Qtrue;
}
@@ -1346,6 +1411,7 @@ rb_file_executable_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
+ fname = rb_str_encode_ospath(fname);
if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
return Qtrue;
}
@@ -1363,7 +1429,8 @@ rb_file_executable_real_p(VALUE obj, VALUE fname)
{
rb_secure(2);
FilePathValue(fname);
- if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
+ fname = rb_str_encode_ospath(fname);
+ if (access_internal(StringValueCStr(fname), X_OK) < 0) return Qfalse;
return Qtrue;
}
@@ -1483,7 +1550,8 @@ check3rdbyte(VALUE fname, int mode)
rb_secure(2);
FilePathValue(fname);
- if (stat(StringValueCStr(fname), &st) < 0) return Qfalse;
+ fname = rb_str_encode_ospath(fname);
+ if (STAT(StringValueCStr(fname), &st) < 0) return Qfalse;
if (st.st_mode & mode) return Qtrue;
return Qfalse;
}
@@ -1568,13 +1636,13 @@ rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
if (st1.st_dev != st2.st_dev) return Qfalse;
if (st1.st_ino != st2.st_ino) return Qfalse;
#else
-#ifdef _WIN32
+# ifdef _WIN32
BY_HANDLE_FILE_INFORMATION st1, st2;
HANDLE f1 = 0, f2 = 0;
-#endif
+# endif
rb_secure(2);
-#ifdef _WIN32
+# ifdef _WIN32
f1 = w32_io_info(&fname1, &st1);
if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
f2 = w32_io_info(&fname2, &st2);
@@ -1588,13 +1656,15 @@ rb_file_identical_p(VALUE obj, VALUE fname1, VALUE fname2)
return Qtrue;
if (!f1 || !f2) return Qfalse;
if (rb_w32_iswin95()) return Qfalse;
-#else
+# else
FilePathValue(fname1);
fname1 = rb_str_new4(fname1);
+ fname1 = rb_str_encode_ospath(fname1);
FilePathValue(fname2);
+ fname2 = rb_str_encode_ospath(fname2);
if (access(RSTRING_PTR(fname1), 0)) return Qfalse;
if (access(RSTRING_PTR(fname2), 0)) return Qfalse;
-#endif
+# endif
fname1 = rb_file_expand_path(fname1, Qnil);
fname2 = rb_file_expand_path(fname2, Qnil);
if (RSTRING_LEN(fname1) != RSTRING_LEN(fname2)) return Qfalse;
@@ -1686,6 +1756,7 @@ rb_file_s_ftype(VALUE klass, VALUE fname)
rb_secure(2);
FilePathValue(fname);
+ fname = rb_str_encode_ospath(fname);
if (lstat(StringValueCStr(fname), &st) == -1) {
rb_sys_fail(RSTRING_PTR(fname));
}
@@ -1912,6 +1983,9 @@ rb_file_chmod(VALUE obj, VALUE vmode)
{
rb_io_t *fptr;
int mode;
+#ifndef HAVE_FCHMOD
+ VALUE path;
+#endif
rb_secure(2);
mode = NUM2INT(vmode);
@@ -1922,7 +1996,8 @@ rb_file_chmod(VALUE obj, VALUE vmode)
rb_sys_fail_path(fptr->pathv);
#else
if (NIL_P(fptr->pathv)) return Qnil;
- if (chmod(RSTRING_PTR(fptr->pathv), mode) == -1)
+ path = rb_str_encode_ospath(fptr->pathv);
+ if (chmod(RSTRING_PTR(path), mode) == -1)
rb_sys_fail_path(fptr->pathv);
#endif
@@ -2039,6 +2114,9 @@ rb_file_chown(VALUE obj, VALUE owner, VALUE group)
{
rb_io_t *fptr;
int o, g;
+#ifndef HAVE_FCHOWN
+ VALUE path;
+#endif
rb_secure(2);
o = NIL_P(owner) ? -1 : NUM2INT(owner);
@@ -2046,7 +2124,8 @@ rb_file_chown(VALUE obj, VALUE owner, VALUE group)
GetOpenFile(obj, fptr);
#ifndef HAVE_FCHOWN
if (NIL_P(fptr->pathv)) return Qnil;
- if (chown(RSTRING_PTR(fptr->pathv), o, g) == -1)
+ path = rb_str_encode_ospath(fptr->pathv);
+ if (chown(RSTRING_PTR(path), o, g) == -1)
rb_sys_fail_path(fptr->pathv);
#else
if (fchown(fptr->fd, o, g) == -1)
@@ -2295,6 +2374,8 @@ rb_file_s_link(VALUE klass, VALUE from, VALUE to)
rb_secure(2);
FilePathValue(from);
FilePathValue(to);
+ from = rb_str_encode_ospath(from);
+ to = rb_str_encode_ospath(to);
if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
sys_fail2(from, to);
@@ -2324,6 +2405,8 @@ rb_file_s_symlink(VALUE klass, VALUE from, VALUE to)
rb_secure(2);
FilePathValue(from);
FilePathValue(to);
+ from = rb_str_encode_ospath(from);
+ to = rb_str_encode_ospath(to);
if (symlink(StringValueCStr(from), StringValueCStr(to)) < 0) {
sys_fail2(from, to);
@@ -2356,6 +2439,7 @@ rb_file_s_readlink(VALUE klass, VALUE path)
rb_secure(2);
FilePathValue(path);
+ path = rb_str_encode_ospath(path);
buf = xmalloc(size);
while ((rv = readlink(RSTRING_PTR(path), buf, size)) == size
#ifdef _AIX
@@ -2419,17 +2503,20 @@ static VALUE
rb_file_s_rename(VALUE klass, VALUE from, VALUE to)
{
const char *src, *dst;
+ VALUE f, t;
rb_secure(2);
FilePathValue(from);
FilePathValue(to);
- src = StringValueCStr(from);
- dst = StringValueCStr(to);
+ f = rb_str_encode_ospath(from);
+ t = rb_str_encode_ospath(to);
+ src = StringValueCStr(f);
+ dst = StringValueCStr(t);
#if defined __CYGWIN__
errno = 0;
#endif
if (rename(src, dst) < 0) {
-#if defined DOSISH && !defined _WIN32
+#if defined DOSISH
switch (errno) {
case EEXIST:
#if defined (__EMX__)
@@ -3691,6 +3778,7 @@ rb_file_s_truncate(VALUE klass, VALUE path, VALUE len)
rb_secure(2);
pos = NUM2OFFT(len);
FilePathValue(path);
+ path = rb_str_encode_ospath(path);
#ifdef HAVE_TRUNCATE
if (truncate(StringValueCStr(path), pos) < 0)
rb_sys_fail(RSTRING_PTR(path));
@@ -3698,15 +3786,9 @@ rb_file_s_truncate(VALUE klass, VALUE path, VALUE len)
{
int tmpfd;
-# ifdef _WIN32
- if ((tmpfd = open(StringValueCStr(path), O_RDWR)) < 0) {
- rb_sys_fail(RSTRING_PTR(path));
- }
-# else
if ((tmpfd = open(StringValueCStr(path), 0)) < 0) {
rb_sys_fail(RSTRING_PTR(path));
}
-# endif
if (chsize(tmpfd, pos) < 0) {
close(tmpfd);
rb_sys_fail(RSTRING_PTR(path));
@@ -4135,7 +4217,8 @@ rb_stat_init(VALUE obj, VALUE fname)
rb_secure(2);
FilePathValue(fname);
- if (stat(StringValueCStr(fname), &st) == -1) {
+ fname = rb_str_encode_ospath(fname);
+ if (STAT(StringValueCStr(fname), &st) == -1) {
rb_sys_fail(RSTRING_PTR(fname));
}
if (DATA_PTR(obj)) {
@@ -4793,7 +4876,7 @@ path_check_0(VALUE path, int execpath)
#ifndef S_IWOTH
# define S_IWOTH 002
#endif
- if (stat(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
+ if (STAT(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
#ifdef S_ISVTX
&& !(p && execpath && (st.st_mode & S_ISVTX))
#endif