ruby-changes:13563
From: usa <ko1@a...>
Date: Thu, 15 Oct 2009 14:28:09 +0900 (JST)
Subject: [ruby-changes:13563] Ruby:r25344 (win32-unicode-test): * file.c (rb_str_encode_ospath): use UTF-8 instead of UTF-16LE as
usa 2009-10-15 14:27:34 +0900 (Thu, 15 Oct 2009) New Revision: 25344 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=25344 Log: * file.c (rb_str_encode_ospath): use UTF-8 instead of UTF-16LE as internal path encoding on Windows. result of Ruby Developers' Meeting 20091013. * 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. * dir.c, file.c, io.c: follow above changes. Modified files: branches/win32-unicode-test/ChangeLog branches/win32-unicode-test/dir.c branches/win32-unicode-test/file.c branches/win32-unicode-test/include/ruby/win32.h branches/win32-unicode-test/io.c branches/win32-unicode-test/win32/win32.c Index: win32-unicode-test/include/ruby/win32.h =================================================================== --- win32-unicode-test/include/ruby/win32.h (revision 25343) +++ win32-unicode-test/include/ruby/win32.h (revision 25344) @@ -259,14 +259,15 @@ 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_wchown(const WCHAR *, int, int); +extern int rb_w32_uchown(const char *, int, int); extern int link(const char *, const char *); -extern int rb_w32_wlink(const WCHAR *, const WCHAR *); +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*); @@ -278,14 +279,17 @@ #if !defined(__BORLANDC__) extern int rb_w32_isatty(int); #endif -extern int rb_w32_wmkdir(const WCHAR *, int); 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_wunlink(const WCHAR *); +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_wstati64(const WCHAR *, 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 *); @@ -558,15 +562,16 @@ int rb_w32_sleep(unsigned long msec); int rb_w32_putc(int, FILE*); int rb_w32_getc(FILE*); +int rb_w32_open(const char *, int, ...); +int rb_w32_uopen(const char *, int, ...); int rb_w32_wopen(const WCHAR *, int, ...); -int rb_w32_open(const char *, 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_wutime(const WCHAR *, 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); Index: win32-unicode-test/ChangeLog =================================================================== --- win32-unicode-test/ChangeLog (revision 25343) +++ win32-unicode-test/ChangeLog (revision 25344) @@ -1,3 +1,16 @@ +Thu Oct 15 14:16:04 2009 NAKAMURA Usaku <usa@r...> + + * file.c (rb_str_encode_ospath): use UTF-8 instead of UTF-16LE as + internal path encoding on Windows. result of Ruby Developers' Meeting + 20091013. + + * 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. + + * dir.c, file.c, io.c: follow above changes. + Wed Oct 14 17:30:26 2009 NAKAMURA Usaku <usa@r...> * include/ruby/intern.h, dir.c, file.c, io.c (rb_str_encode_ospath): Index: win32-unicode-test/io.c =================================================================== --- win32-unicode-test/io.c (revision 25343) +++ win32-unicode-test/io.c (revision 25344) @@ -109,6 +109,12 @@ #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) +/* define system APIs */ +#ifdef _WIN32 +#undef open +#define open rb_w32_uopen +#endif + VALUE rb_cIO; VALUE rb_eEOFError; VALUE rb_eIOError; @@ -4417,11 +4423,7 @@ { const struct sysopen_struct *data = ptr; const char *fname = RSTRING_PTR(data->fname); -#ifdef _WIN32 - return (VALUE)rb_w32_wopen((WCHAR *)fname, data->oflags, data->perm); -#else return (VALUE)open(fname, data->oflags, data->perm); -#endif } static inline int Index: win32-unicode-test/dir.c =================================================================== --- win32-unicode-test/dir.c (revision 25343) +++ win32-unicode-test/dir.c (revision 25344) @@ -70,11 +70,11 @@ /* define system APIs */ #ifdef _WIN32 #undef chdir -#define chdir(p) _wchdir((WCHAR *)(p)) +#define chdir(p) rb_w32_uchdir(p) #undef mkdir -#define mkdir(p, m) rb_w32_wmkdir((WCHAR *)(p), m) +#define mkdir(p, m) rb_w32_umkdir(p, m) #undef rmdir -#define rmdir(p) _wrmdir((WCHAR *)(p)) +#define rmdir(p) rb_w32_urmdir(p) #endif #define FNM_NOESCAPE 0x01 Index: win32-unicode-test/win32/win32.c =================================================================== --- win32-unicode-test/win32/win32.c (revision 25343) +++ win32-unicode-test/win32/win32.c (revision 25344) @@ -1661,7 +1661,7 @@ } static char * -win32_conv_from_wstr(const WCHAR *wstr, long *plen) +wstr_to_filecp(const WCHAR *wstr, long *plen) { UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP; char *ptr; @@ -1673,7 +1673,7 @@ } static WCHAR * -win32_conv_to_wstr(const char *str, long *plen) +filecp_to_wstr(const char *str, long *plen) { UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP; WCHAR *ptr; @@ -1684,6 +1684,28 @@ 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) { @@ -1692,13 +1714,13 @@ HANDLE fh; WCHAR *wpath; - if (!(wpath = win32_conv_to_wstr(filename, NULL))) + if (!(wpath = filecp_to_wstr(filename, NULL))) return NULL; // // check to see if we've got a directory // - if (rb_w32_wstati64(wpath, &sbuf) < 0) { + if (wstati64(wpath, &sbuf) < 0) { free(wpath); return NULL; } @@ -1738,7 +1760,7 @@ 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; } @@ -1776,7 +1798,7 @@ 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'; @@ -3647,7 +3669,7 @@ } int -rb_w32_wchown(const WCHAR *path, int owner, int group) +rb_w32_uchown(const char *path, int owner, int group) { return 0; } @@ -3736,8 +3758,8 @@ return ret; } -int -rb_w32_wlink(const WCHAR *from, const WCHAR *to) +static int +wlink(const WCHAR *from, const WCHAR *to) { static BOOL (WINAPI *pCreateHardLinkW)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES) = NULL; static int myerrno = 0; @@ -3770,19 +3792,38 @@ } 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 = win32_conv_to_wstr(from, NULL))) + if (!(wfrom = filecp_to_wstr(from, NULL))) return -1; - if (!(wto = win32_conv_to_wstr(to, NULL))) { + if (!(wto = filecp_to_wstr(to, NULL))) { free(wfrom); return -1; } - ret = rb_w32_wlink(wfrom, wto); + ret = wlink(wfrom, wto); free(wto); free(wfrom); return ret; @@ -3815,15 +3856,15 @@ 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()); @@ -3832,9 +3873,9 @@ 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) { @@ -3842,13 +3883,13 @@ 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; } @@ -3860,12 +3901,48 @@ if (res) errno = map_errno(GetLastError()); else - SetFileAttributes(newpath, oldatts); + SetFileAttributesW(newpath, oldatts); }); return res; } +int rb_w32_urename(const char *from, const char *to) +{ + WCHAR *wfrom; + WCHAR *wto; + int ret = -1; + + if (!(wfrom = utf8_to_wstr(from, NULL))) + return -1; + if (!(wto = utf8_to_wstr(to, NULL))) { + free(wfrom); + return -1; + } + ret = wrename(wfrom, wto); + free(wto); + free(wfrom); + return ret; +} + +int rb_w32_rename(const char *from, const char *to) +{ + WCHAR *wfrom; + WCHAR *wto; + int ret = -1; + + if (!(wfrom = filecp_to_wstr(from, NULL))) + return -1; + if (!(wto = filecp_to_wstr(to, NULL))) { + free(wfrom); + return -1; + } + ret = wrename(wfrom, wto); + free(wto); + free(wfrom); + return ret; +} + static int isUNCRoot(const WCHAR *path) { @@ -4068,8 +4145,8 @@ return 0; } -int -rb_w32_wstati64(const WCHAR *path, struct stati64 *st) +static int +wstati64(const WCHAR *path, struct stati64 *st) { const WCHAR *p; WCHAR *buf1, *s, *end; @@ -4113,14 +4190,27 @@ } 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 = win32_conv_to_wstr(path, NULL))) + if (!(wpath = filecp_to_wstr(path, NULL))) return -1; - ret = rb_w32_wstati64(wpath, st); + ret = wstati64(wpath, st); free(wpath); return ret; } @@ -4139,6 +4229,20 @@ 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) { @@ -4544,6 +4648,25 @@ } int +rb_w32_uopen(const char *file, int oflag, ...) +{ + WCHAR *wfile; + int ret; + int pmode; + + va_list arg; + va_start(arg, oflag); + pmode = va_arg(arg, int); + va_end(arg); + + if (!(wfile = utf8_to_wstr(file, NULL))) + return -1; + ret = rb_w32_wopen(wfile, oflag, pmode); + free(wfile); + return ret; +} + +int rb_w32_open(const char *file, int oflag, ...) { WCHAR *wfile; @@ -4558,7 +4681,7 @@ if ((oflag & O_TEXT) || !(oflag & O_BINARY)) return _open(file, oflag, pmode); - if (!(wfile = win32_conv_to_wstr(file, NULL))) + if (!(wfile = filecp_to_wstr(file, NULL))) return -1; ret = rb_w32_wopen(wfile, oflag, pmode); free(wfile); @@ -5163,15 +5286,15 @@ return 0; } -int -rb_w32_wutime(const WCHAR *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_wstati64(path, &stat)) { + if (wstati64(path, &stat)) { return -1; } @@ -5213,29 +5336,56 @@ } int +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 = win32_conv_to_wstr(path, NULL))) + if (!(wpath = filecp_to_wstr(path, NULL))) return -1; - ret = rb_w32_wutime(wpath, times); + ret = wutime(wpath, times); free(wpath); return ret; } int -rb_w32_wmkdir(const WCHAR *path, int mode) +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 (CreateDirectoryW(path, NULL) == FALSE) { + if (CreateDirectoryW(wpath, NULL) == FALSE) { errno = map_errno(GetLastError()); break; } - if (_wchmod(path, mode) == -1) { - RemoveDirectoryW(path); + if (_wchmod(wpath, mode) == -1) { + RemoveDirectoryW(wpath); break; } ret = 0; @@ -5244,37 +5394,45 @@ } int -rb_w32_mkdir(const char *path, int mode) +rb_w32_umkdir(const char *path, int mode) { - int ret = -1; - RUBY_CRITICAL(do { - if (CreateDirectory(path, NULL) == FALSE) { - errno = map_errno(GetLastError()); - break; - } - if (chmod(path, mode) == -1) { - RemoveDirectory(path); - break; - } - ret = 0; - } while (0)); + WCHAR *wpath; + int ret; + + if (!(wpath = utf8_to_wstr(path, NULL))) + return -1; + ret = wmkdir(wpath, mode); + free(wpath); return ret; } int -rb_w32_rmdir(const char *path) +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); } } }); @@ -5282,8 +5440,34 @@ } int -rb_w32_wunlink(const WCHAR *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 = GetFileAttributesW(path); @@ -5302,18 +5486,44 @@ } 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 = win32_conv_to_wstr(path, NULL))) + if (!(wpath = filecp_to_wstr(path, NULL))) return -1; - ret = rb_w32_wunlink(wpath); + 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) Index: win32-unicode-test/file.c =================================================================== --- win32-unicode-test/file.c (revision 25343) +++ win32-unicode-test/file.c (revision 25344) @@ -72,23 +72,23 @@ /* define system APIs */ #ifdef _WIN32 -#define STAT(p, s) rb_w32_wstati64((WCHAR *)(p), s) +#define STAT(p, s) rb_w32_ustati64(p, s) #undef lstat -#define lstat(p, s) rb_w32_wstati64((WCHAR *)(p), s) +#define lstat(p, s) rb_w32_ustati64(p, s) #undef access -#define access(p, m) _waccess((WCHAR *)(p), m) +#define access(p, m) rb_w32_uaccess(p, m) #undef chmod -#define chmod(p, m) _wchmod((WCHAR *)(p), m) +#define chmod(p, m) rb_w32_uchmod(p, m) #undef chown -#define chown(p, o, g) rb_w32_wchown((WCHAR *)(p), o, g) +#define chown(p, o, g) rb_w32_uchown(p, o, g) #undef utime -#define utime(p, t) rb_w32_wutime((WCHAR *)(p), t) +#define utime(p, t) rb_w32_uutime(p, t) #undef link -#define link(f, t) rb_w32_wlink((WCHAR *)(f), (WCHAR *)(t)) +#define link(f, t) rb_w32_ulink(f, t) #undef unlink -#define unlink(p) rb_w32_wunlink((WCHAR *)(p)) +#define unlink(p) rb_w32_uunlink(p) #undef rename -#define rename(f, t) _wrename((WCHAR *)(f), (WCHAR *)(t)) +#define rename(f, t) rb_w32_urename(f, t) #else #define STAT(p, s) stat(p, s) #endif @@ -171,32 +171,14 @@ { char *s; #ifdef _WIN32 - static rb_encoding *utf16 = (rb_encoding *)-1; - VALUE wpath; - if (utf16 == (rb_encoding *)-1) { - utf16 = rb_enc_find("UTF-16LE"); - if (utf16 == rb_ascii8bit_encoding()) - utf16 = NULL; + 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); } - if (utf16 && rb_enc_get(path) != rb_ascii8bit_encoding()) { - wpath = rb_str_encode(path, rb_enc_from_encoding(utf16), 0, Qnil); - rb_enc_str_buf_cat(wpath, "", 1, utf16); /* workaround */ - return wpath; - } - else if (RSTRING_LEN(path) > 0) { - UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - int len = MultiByteToWideChar(cp, 0, RSTRING_PTR(path), -1, NULL, 0); - WCHAR *tmp; - if (len <= 0) - rb_raise(rb_eArgError, "broken pathname"); - tmp = ALLOCA_N(WCHAR, len); - len = MultiByteToWideChar(cp, 0, RSTRING_PTR(path), -1, tmp, len); - if (len <= 0) - rb_raise(rb_eArgError, "broken pathname"); - wpath = rb_str_new((char *)tmp, len * sizeof(WCHAR)); - OBJ_INFECT(wpath, path); - return wpath; - } + else if (RSTRING_LEN(path) > 0) + path = rb_str_encode(path, rb_enc_from_encoding(rb_filesystem_encoding()), 0, Qnil); #elif defined __APPLE__ rb_encoding *enc = rb_enc_get(path); rb_encoding *fenc = rb_filesystem_encoding(); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/