Created
March 6, 2012 15:01
-
-
Save shirosaki/1986693 to your computer and use it in GitHub Desktop.
Fenix integration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/configure.in b/configure.in | |
index 9a679de..aad31de 100644 | |
--- a/configure.in | |
+++ b/configure.in | |
@@ -1055,7 +1055,7 @@ main() | |
AC_CHECK_FUNCS(cygwin_conv_path) | |
AC_LIBOBJ([langinfo]) | |
], | |
-[mingw*], [ LIBS="-lshell32 -lws2_32 -limagehlp $LIBS" | |
+[mingw*], [ LIBS="-lshell32 -lws2_32 -limagehlp -lshlwapi $LIBS" | |
ac_cv_header_a_out_h=no | |
ac_cv_header_pwd_h=no | |
ac_cv_header_utime_h=no | |
diff --git a/file.c b/file.c | |
index 9f3f72a..5d4722a 100644 | |
--- a/file.c | |
+++ b/file.c | |
@@ -2889,8 +2889,9 @@ append_fspath(VALUE result, VALUE fname, char *dir, rb_encoding **enc, rb_encodi | |
return buf + dirlen; | |
} | |
-static VALUE | |
-file_expand_path(VALUE fname, VALUE dname, int abs_mode, VALUE result) | |
+#ifndef _WIN32 | |
+VALUE | |
+rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, VALUE result) | |
{ | |
const char *s, *b, *fend; | |
char *buf, *p, *pend, *root; | |
@@ -2952,7 +2953,7 @@ file_expand_path(VALUE fname, VALUE dname, int abs_mode, VALUE result) | |
/* specified drive, but not full path */ | |
int same = 0; | |
if (!NIL_P(dname) && !not_same_drive(dname, s[0])) { | |
- file_expand_path(dname, Qnil, abs_mode, result); | |
+ rb_file_expand_path_internal(dname, Qnil, abs_mode, result); | |
BUFINIT(); | |
if (has_drive_letter(p) && TOLOWER(p[0]) == TOLOWER(s[0])) { | |
/* ok, same drive */ | |
@@ -2976,7 +2977,7 @@ file_expand_path(VALUE fname, VALUE dname, int abs_mode, VALUE result) | |
#endif | |
else if (!rb_is_absolute_path(s)) { | |
if (!NIL_P(dname)) { | |
- file_expand_path(dname, Qnil, abs_mode, result); | |
+ rb_file_expand_path_internal(dname, Qnil, abs_mode, result); | |
rb_enc_associate(result, rb_enc_check(result, fname)); | |
BUFINIT(); | |
p = pend; | |
@@ -3229,6 +3230,7 @@ file_expand_path(VALUE fname, VALUE dname, int abs_mode, VALUE result) | |
ENC_CODERANGE_CLEAR(result); | |
return result; | |
} | |
+#endif | |
#define EXPAND_PATH_BUFFER() rb_usascii_str_new(0, MAXPATHLEN + 2) | |
@@ -3239,14 +3241,14 @@ file_expand_path(VALUE fname, VALUE dname, int abs_mode, VALUE result) | |
static VALUE | |
file_expand_path_1(VALUE fname) | |
{ | |
- return file_expand_path(fname, Qnil, 0, EXPAND_PATH_BUFFER()); | |
+ return rb_file_expand_path_internal(fname, Qnil, 0, EXPAND_PATH_BUFFER()); | |
} | |
VALUE | |
rb_file_expand_path(VALUE fname, VALUE dname) | |
{ | |
check_expand_path_args(fname, dname); | |
- return file_expand_path(fname, dname, 0, EXPAND_PATH_BUFFER()); | |
+ return rb_file_expand_path_internal(fname, dname, 0, EXPAND_PATH_BUFFER()); | |
} | |
/* | |
@@ -3283,7 +3285,7 @@ VALUE | |
rb_file_absolute_path(VALUE fname, VALUE dname) | |
{ | |
check_expand_path_args(fname, dname); | |
- return file_expand_path(fname, dname, 1, EXPAND_PATH_BUFFER()); | |
+ return rb_file_expand_path_internal(fname, dname, 1, EXPAND_PATH_BUFFER()); | |
} | |
/* | |
@@ -5243,7 +5245,7 @@ rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int safe_level) | |
RB_GC_GUARD(str) = rb_get_path_check(str, safe_level); | |
if (RSTRING_LEN(str) == 0) continue; | |
- file_expand_path(fname, str, 0, tmp); | |
+ rb_file_expand_path_internal(fname, str, 0, tmp); | |
if (rb_file_load_ok(RSTRING_PTR(tmp))) { | |
*filep = copy_path_class(tmp, *filep); | |
return (int)(j+1); | |
@@ -5302,7 +5304,7 @@ rb_find_file_safe(VALUE path, int safe_level) | |
VALUE str = RARRAY_PTR(load_path)[i]; | |
RB_GC_GUARD(str) = rb_get_path_check(str, safe_level); | |
if (RSTRING_LEN(str) > 0) { | |
- file_expand_path(path, str, 0, tmp); | |
+ rb_file_expand_path_internal(path, str, 0, tmp); | |
f = RSTRING_PTR(tmp); | |
if (rb_file_load_ok(f)) goto found; | |
} | |
@@ -5537,4 +5539,8 @@ Init_File(void) | |
rb_define_method(rb_cStat, "setuid?", rb_stat_suid, 0); | |
rb_define_method(rb_cStat, "setgid?", rb_stat_sgid, 0); | |
rb_define_method(rb_cStat, "sticky?", rb_stat_sticky, 0); | |
+ | |
+#ifdef _WIN32 | |
+ rb_w32_init_file(); | |
+#endif | |
} | |
diff --git a/include/ruby/win32.h b/include/ruby/win32.h | |
index d49a9b4..e2cf2c1 100644 | |
--- a/include/ruby/win32.h | |
+++ b/include/ruby/win32.h | |
@@ -305,6 +305,7 @@ 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); | |
extern char rb_w32_fd_is_text(int); | |
+extern void rb_w32_init_file(); | |
#ifdef __BORLANDC__ | |
extern int rb_w32_fstati64(int, struct stati64 *); | |
diff --git a/internal.h b/internal.h | |
index cf274ac..04080b2 100644 | |
--- a/internal.h | |
+++ b/internal.h | |
@@ -95,6 +95,7 @@ VALUE rb_home_dir(const char *user, VALUE result); | |
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); | |
void rb_file_const(const char*, VALUE); | |
int rb_file_load_ok(const char *); | |
+VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, VALUE result); | |
void Init_File(void); | |
/* gc.c */ | |
diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb | |
index a19fcd9..ead2838 100644 | |
--- a/test/ruby/test_file_exhaustive.rb | |
+++ b/test/ruby/test_file_exhaustive.rb | |
@@ -431,7 +431,13 @@ class TestFileExhaustive < Test::Unit::TestCase | |
begin | |
bug3630 = '[ruby-core:31537]' | |
home = ENV["HOME"] | |
+ home_drive = ENV["HOMEDRIVE"] | |
+ home_path = ENV["HOMEPATH"] | |
+ user_profile = ENV["USERPROFILE"] | |
ENV["HOME"] = nil | |
+ ENV["HOMEDRIVE"] = nil | |
+ ENV["HOMEPATH"] = nil | |
+ ENV["USERPROFILE"] = nil | |
assert_raise(ArgumentError) { File.expand_path("~") } | |
ENV["HOME"] = "~" | |
assert_raise(ArgumentError, bug3630) { File.expand_path("~") } | |
@@ -439,6 +445,9 @@ class TestFileExhaustive < Test::Unit::TestCase | |
assert_raise(ArgumentError, bug3630) { File.expand_path("~") } | |
ensure | |
ENV["HOME"] = home | |
+ ENV["HOMEDRIVE"] = home_drive | |
+ ENV["HOMEPATH"] = home_path | |
+ ENV["USERPROFILE"] = user_profile | |
end | |
assert_incompatible_encoding {|d| File.expand_path(d)} | |
end | |
diff --git a/win32/Makefile.sub b/win32/Makefile.sub | |
index df3ae39..951cd89 100644 | |
--- a/win32/Makefile.sub | |
+++ b/win32/Makefile.sub | |
@@ -223,7 +223,7 @@ RFLAGS = -r | |
EXTLIBS = | |
!endif | |
!if !defined(LIBS) | |
-LIBS = oldnames.lib user32.lib advapi32.lib shell32.lib ws2_32.lib imagehlp.lib $(EXTLIBS) | |
+LIBS = oldnames.lib user32.lib advapi32.lib shell32.lib ws2_32.lib imagehlp.lib shlwapi.lib $(EXTLIBS) | |
!endif | |
!if "$(ENABLE_WIN95)" == "yes" | |
LIBS = unicows.lib $(LIBS) | |
diff --git a/win32/file.c b/win32/file.c | |
index 13325a3..631c0ad 100644 | |
--- a/win32/file.c | |
+++ b/win32/file.c | |
@@ -1,5 +1,15 @@ | |
#include "ruby/ruby.h" | |
+#include "ruby/encoding.h" | |
#include <winbase.h> | |
+#include <wchar.h> | |
+#include <shlwapi.h> | |
+ | |
+#define IS_DIR_SEPARATOR_P(c) (c == L'\\' || c == L'/') | |
+#define IS_DIR_UNC_P(c) (IS_DIR_SEPARATOR_P(c[0]) && IS_DIR_SEPARATOR_P(c[1])) | |
+ | |
+#define malloc xmalloc | |
+#define free xfree | |
+ | |
int | |
rb_file_load_ok(const char *path) | |
@@ -23,3 +33,502 @@ rb_file_load_ok(const char *path) | |
} | |
return ret; | |
} | |
+ | |
+ | |
+static inline void | |
+replace_wchar(wchar_t *s, int find, int replace) | |
+{ | |
+ while (*s != 0) { | |
+ if (*s == find) | |
+ *s = replace; | |
+ s++; | |
+ } | |
+} | |
+ | |
+/* | |
+ * Return user's home directory using environment variables combinations. | |
+ * Memory allocated by this function should be manually freeded afterwards. | |
+ */ | |
+static wchar_t * | |
+home_dir() | |
+{ | |
+ wchar_t *buffer = NULL; | |
+ size_t buffer_len = 0, len = 0; | |
+ size_t home_env = 0; | |
+ | |
+ // determine User's home directory trying: | |
+ // HOME, HOMEDRIVE + HOMEPATH and USERPROFILE environment variables | |
+ // TODO: Special Folders - Profile and Personal | |
+ | |
+ /* | |
+ * GetEnvironmentVariableW when used with NULL will return the required | |
+ * buffer size and its terminating character. | |
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx | |
+ */ | |
+ | |
+ if (len = GetEnvironmentVariableW(L"HOME", NULL, 0)) { | |
+ buffer_len = len; | |
+ home_env = 1; | |
+ } else if (len = GetEnvironmentVariableW(L"HOMEDRIVE", NULL, 0)) { | |
+ buffer_len = len; | |
+ if (len = GetEnvironmentVariableW(L"HOMEPATH", NULL, 0)) { | |
+ buffer_len += len; | |
+ home_env = 2; | |
+ } else { | |
+ buffer_len = 0; | |
+ } | |
+ } else if (len = GetEnvironmentVariableW(L"USERPROFILE", NULL, 0)) { | |
+ buffer_len = len; | |
+ home_env = 3; | |
+ } | |
+ | |
+ // allocate buffer | |
+ if (home_env) | |
+ buffer = (wchar_t *)malloc(buffer_len * sizeof(wchar_t)); | |
+ | |
+ switch (home_env) { | |
+ case 1: // HOME | |
+ GetEnvironmentVariableW(L"HOME", buffer, buffer_len); | |
+ break; | |
+ case 2: // HOMEDRIVE + HOMEPATH | |
+ len = GetEnvironmentVariableW(L"HOMEDRIVE", buffer, buffer_len); | |
+ GetEnvironmentVariableW(L"HOMEPATH", buffer + len, buffer_len - len); | |
+ break; | |
+ case 3: // USERPROFILE | |
+ GetEnvironmentVariableW(L"USERPROFILE", buffer, buffer_len); | |
+ break; | |
+ default: | |
+ // wprintf(L"Failed to determine user home directory.\n"); | |
+ break; | |
+ } | |
+ | |
+ if (home_env) { | |
+ // sanitize backslashes with forwardslashes | |
+ replace_wchar(buffer, L'\\', L'/'); | |
+ | |
+ // wprintf(L"home dir: '%s' using home_env (%i)\n", buffer, home_env); | |
+ return buffer; | |
+ } | |
+ | |
+ return NULL; | |
+} | |
+ | |
+ | |
+/* Convert the path from char to wchar with specified code page */ | |
+static inline void | |
+path_to_wchar(VALUE path, wchar_t **wpath, wchar_t **wpath_pos, size_t *wpath_len, UINT code_page) | |
+{ | |
+ size_t size; | |
+ | |
+ if (NIL_P(path)) | |
+ return; | |
+ | |
+ size = MultiByteToWideChar(code_page, 0, RSTRING_PTR(path), -1, NULL, 0) + 1; | |
+ *wpath = (wchar_t *)malloc(size * sizeof(wchar_t)); | |
+ if (wpath_pos) | |
+ *wpath_pos = *wpath; | |
+ | |
+ MultiByteToWideChar(code_page, 0, RSTRING_PTR(path), -1, *wpath, size); | |
+ *wpath_len = size - 2; // wcslen(*wpath); | |
+} | |
+ | |
+/* Remove trailing invalid ':$DATA' of the path. */ | |
+static inline size_t | |
+remove_invalid_alternative_data(wchar_t *wfullpath, size_t size) { | |
+ static const wchar_t prime[] = L":$DATA"; | |
+ enum {prime_len = (sizeof(prime) / sizeof(wchar_t)) -1}; | |
+ | |
+ if (size <= prime_len || _wcsnicmp(wfullpath + size - prime_len, prime, prime_len) != 0) | |
+ return size; | |
+ | |
+ // wprintf(L"remove trailng ':$DATA': %s, %s\n", wfullpath, &wfullpath[size - prime_len]); | |
+ /* alias of stream */ | |
+ /* get rid of a bug of x64 VC++ */ | |
+ if (wfullpath[size - (prime_len + 1)] == ':') { | |
+ /* remove trailing '::$DATA' */ | |
+ size -= prime_len + 1; /* prime */ | |
+ wfullpath[size] = L'\0'; | |
+ // wprintf(L"removed trailng '::$DATA': %s\n", wfullpath); | |
+ } else { | |
+ /* remove trailing ':$DATA' of paths like '/aa:a:$DATA' */ | |
+ wchar_t *pos = wfullpath + size - (prime_len + 1); | |
+ while (!IS_DIR_SEPARATOR_P(*pos) && pos != wfullpath) { | |
+ if (*pos == L':') { | |
+ size -= prime_len; /* alternative */ | |
+ wfullpath[size] = L'\0'; | |
+ // wprintf(L"removed trailng ':$DATA': %s\n", wfullpath); | |
+ break; | |
+ } | |
+ pos--; | |
+ } | |
+ } | |
+ return size; | |
+} | |
+ | |
+/* Return system code page. */ | |
+static inline UINT | |
+system_code_page() { | |
+ return AreFileApisANSI() ? CP_ACP : CP_OEMCP; | |
+} | |
+ | |
+/* cache 'encoding name' => 'code page' into a hash */ | |
+static VALUE rb_code_page; | |
+ | |
+/* | |
+ * Return code page number of the encoding. | |
+ * Cache code page into a hash for performance since finding the code page in | |
+ * Encoding#names is slow. | |
+ */ | |
+static UINT | |
+code_page(rb_encoding *enc) | |
+{ | |
+ VALUE code_page_value, name_key; | |
+ VALUE encoding, names_ary = Qundef, name; | |
+ char *enc_name; | |
+ struct RString fake_str; | |
+ ID names; | |
+ long i; | |
+ | |
+ if (!enc) | |
+ return system_code_page(); | |
+ | |
+ enc_name = (char *)rb_enc_name(enc); | |
+ | |
+ fake_str.basic.flags = T_STRING|RSTRING_NOEMBED; | |
+ fake_str.basic.klass = rb_cString; | |
+ fake_str.as.heap.len = strlen(enc_name); | |
+ fake_str.as.heap.ptr = enc_name; | |
+ fake_str.as.heap.aux.capa = fake_str.as.heap.len; | |
+ name_key = (VALUE)&fake_str; | |
+ ENCODING_CODERANGE_SET(name_key, rb_usascii_encindex(), ENC_CODERANGE_7BIT); | |
+ OBJ_FREEZE(name_key); | |
+ | |
+ code_page_value = rb_hash_lookup(rb_code_page, name_key); | |
+ if (code_page_value != Qnil) { | |
+ // printf("cached code page: %i\n", FIX2INT(code_page_value)); | |
+ if (FIX2INT(code_page_value) == -1) { | |
+ return system_code_page(); | |
+ } else { | |
+ return (UINT)FIX2INT(code_page_value); | |
+ } | |
+ } | |
+ | |
+ name_key = rb_usascii_str_new2(enc_name); | |
+ | |
+ encoding = rb_enc_from_encoding(enc); | |
+ if (!NIL_P(encoding)) { | |
+ CONST_ID(names, "names"); | |
+ names_ary = rb_funcall(encoding, names, 0); | |
+ } | |
+ | |
+ if (names_ary != Qundef) { | |
+ for (i = 0; i < RARRAY_LEN(names_ary); i++) { | |
+ name = RARRAY_PTR(names_ary)[i]; | |
+ if (strncmp("CP", RSTRING_PTR(name), 2) == 0) { | |
+ int code_page = atoi(RSTRING_PTR(name) + 2); | |
+ rb_hash_aset(rb_code_page, name_key, INT2FIX(code_page)); | |
+ return (UINT)code_page; | |
+ } | |
+ } | |
+ } | |
+ | |
+ rb_hash_aset(rb_code_page, name_key, INT2FIX(-1)); | |
+ return system_code_page(); | |
+} | |
+ | |
+#define PATH_BUFFER_SIZE MAX_PATH * 2 | |
+ | |
+// TODO: can we fail allocating memory? | |
+VALUE | |
+rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, VALUE result) | |
+{ | |
+ size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0; | |
+ size_t buffer_len = 0; | |
+ wchar_t *wfullpath = NULL, *wpath = NULL, *wpath_pos = NULL, *wdir = NULL; | |
+ wchar_t *whome = NULL, *buffer = NULL, *buffer_pos = NULL; | |
+ UINT cp; | |
+ VALUE path = fname, dir = dname; | |
+ wchar_t wfullpath_buffer[PATH_BUFFER_SIZE]; | |
+ wchar_t path_drive = L'\0', dir_drive = L'\0'; | |
+ int ignore_dir = 0; | |
+ rb_encoding *path_encoding; | |
+ | |
+ // get path encoding | |
+ if (NIL_P(dir)) { | |
+ path_encoding = rb_enc_get(path); | |
+ } else { | |
+ path_encoding = rb_enc_check(path, dir); | |
+ } | |
+ cp = code_page(path_encoding); | |
+ // printf("code page: %i\n", cp); | |
+ | |
+ // coerce them to string | |
+ // path = coerce_to_path(path); | |
+ | |
+ // convert char * to wchar_t | |
+ // path | |
+ path_to_wchar(path, &wpath, &wpath_pos, &wpath_len, cp); | |
+ // wprintf(L"wpath: '%s' with (%i) characters long.\n", wpath, wpath_len); | |
+ | |
+ /* determine if we need the user's home directory */ | |
+ /* execute only if NOT absolute_path(). `abs_mode` is 1 if absolute_path() */ | |
+ if (abs_mode == 0 && ((wpath_len == 1 && wpath_pos[0] == L'~') || | |
+ (wpath_len >= 2 && wpath_pos[0] == L'~' && IS_DIR_SEPARATOR_P(wpath_pos[1])))) { | |
+ // wprintf(L"wpath requires expansion.\n"); | |
+ whome = home_dir(); | |
+ if (whome == NULL) { | |
+ free(wpath); | |
+ rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); | |
+ } | |
+ if (PathIsRelativeW(whome)) { | |
+ free(wpath); | |
+ rb_raise(rb_eArgError, "non-absolute home"); | |
+ } | |
+ whome_len = wcslen(whome); | |
+ | |
+ // wprintf(L"whome: '%s' with (%i) characters long.\n", whome, whome_len); | |
+ | |
+ /* ignores dir since we are expading home */ | |
+ ignore_dir = 1; | |
+ | |
+ /* exclude ~ from the result */ | |
+ wpath_pos++; | |
+ wpath_len--; | |
+ | |
+ /* exclude separator if present */ | |
+ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { | |
+ // wprintf(L"excluding expansion character and separator\n"); | |
+ wpath_pos++; | |
+ wpath_len--; | |
+ } | |
+ } else if (wpath_len >= 2 && wpath_pos[1] == L':') { | |
+ if (wpath_len >= 3 && IS_DIR_SEPARATOR_P(wpath_pos[2])) { | |
+ /* ignore dir since path contains a drive letter and a root slash */ | |
+ // wprintf(L"Ignore dir since we have drive letter and root slash\n"); | |
+ ignore_dir = 1; | |
+ } else { | |
+ /* determine if we ignore dir or not later */ | |
+ path_drive = wpath_pos[0]; | |
+ } | |
+ } else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L'~') { | |
+ wchar_t *wuser = wpath_pos + 1; | |
+ wchar_t *pos = wuser; | |
+ char *user; | |
+ | |
+ while (!IS_DIR_SEPARATOR_P(*pos) && *pos != '\0') | |
+ pos++; | |
+ | |
+ *pos = '\0'; | |
+ size = WideCharToMultiByte(cp, 0, wuser, -1, NULL, 0, NULL, NULL); | |
+ user = (char *)malloc(size * sizeof(char)); | |
+ WideCharToMultiByte(cp, 0, wuser, -1, user, size, NULL, NULL); | |
+ | |
+ /* convert to VALUE and set the path encoding */ | |
+ result = rb_enc_str_new(user, size - 1, path_encoding); | |
+ | |
+ free(wpath); | |
+ if (user) | |
+ free(user); | |
+ | |
+ rb_raise(rb_eArgError, "can't find user %s", StringValuePtr(result)); | |
+ } | |
+ | |
+ /* convert dir */ | |
+ if (!ignore_dir && !NIL_P(dir)) { | |
+ // coerce them to string | |
+ // dir = coerce_to_path(dir); | |
+ | |
+ // convert char * to wchar_t | |
+ // dir | |
+ path_to_wchar(dir, &wdir, NULL, &wdir_len, cp); | |
+ // wprintf(L"wdir: '%s' with (%i) characters long.\n", wdir, wdir_len); | |
+ | |
+ if (wdir_len >= 2 && wdir[1] == L':') { | |
+ dir_drive = wdir[0]; | |
+ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { | |
+ wdir_len = 2; | |
+ } | |
+ } else if (wdir_len >= 2 && IS_DIR_UNC_P(wdir)) { | |
+ /* UNC path */ | |
+ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { | |
+ /* cut the UNC path tail to '//host/share' */ | |
+ size_t separators = 0; | |
+ size_t pos = 2; | |
+ while (pos < wdir_len && separators < 2) { | |
+ if (IS_DIR_SEPARATOR_P(wdir[pos])) { | |
+ separators++; | |
+ } | |
+ pos++; | |
+ } | |
+ if (separators == 2) | |
+ wdir_len = pos - 1; | |
+ // wprintf(L"UNC wdir: '%s' with (%i) characters.\n", wdir, wdir_len); | |
+ } | |
+ } | |
+ } | |
+ | |
+ /* determine if we ignore dir or not */ | |
+ if (!ignore_dir && path_drive && dir_drive) { | |
+ if (towupper(path_drive) == towupper(dir_drive)) { | |
+ /* exclude path drive letter to use dir */ | |
+ // wprintf(L"excluding path drive letter\n"); | |
+ wpath_pos += 2; | |
+ wpath_len -= 2; | |
+ } else { | |
+ /* ignore dir since path drive is different from dir drive */ | |
+ ignore_dir = 1; | |
+ wdir_len = 0; | |
+ } | |
+ } | |
+ | |
+ if (!ignore_dir && wpath_len >= 2 && IS_DIR_UNC_P(wpath)) { | |
+ /* ignore dir since path has UNC root */ | |
+ ignore_dir = 1; | |
+ wdir_len = 0; | |
+ } else if (!ignore_dir && wpath_len >= 1 && IS_DIR_SEPARATOR_P(wpath[0]) && | |
+ !dir_drive && !(wdir_len >= 2 && IS_DIR_UNC_P(wdir))) { | |
+ /* ignore dir since path has root slash and dir doesn't have drive or UNC root */ | |
+ ignore_dir = 1; | |
+ wdir_len = 0; | |
+ } | |
+ | |
+ // wprintf(L"wpath_len: %i\n", wpath_len); | |
+ // wprintf(L"wdir_len: %i\n", wdir_len); | |
+ // wprintf(L"whome_len: %i\n", whome_len); | |
+ | |
+ buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1; | |
+ // wprintf(L"buffer_len: %i\n", buffer_len + 1); | |
+ | |
+ buffer = buffer_pos = (wchar_t *)malloc((buffer_len + 1) * sizeof(wchar_t)); | |
+ | |
+ /* add home */ | |
+ if (whome_len) { | |
+ // wprintf(L"Copying whome...\n"); | |
+ wcsncpy(buffer_pos, whome, whome_len); | |
+ buffer_pos += whome_len; | |
+ } | |
+ | |
+ /* Add separator if required */ | |
+ if (whome_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) { | |
+ // wprintf(L"Adding separator after whome\n"); | |
+ buffer_pos[0] = L'\\'; | |
+ buffer_pos++; | |
+ } | |
+ | |
+ if (wdir_len) { | |
+ // wprintf(L"Copying wdir...\n"); | |
+ wcsncpy(buffer_pos, wdir, wdir_len); | |
+ buffer_pos += wdir_len; | |
+ } | |
+ | |
+ /* add separator if required */ | |
+ if (wdir_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) { | |
+ // wprintf(L"Adding separator after wdir\n"); | |
+ buffer_pos[0] = L'\\'; | |
+ buffer_pos++; | |
+ } | |
+ | |
+ /* now deal with path */ | |
+ if (wpath_len) { | |
+ // wprintf(L"Copying wpath...\n"); | |
+ wcsncpy(buffer_pos, wpath_pos, wpath_len); | |
+ buffer_pos += wpath_len; | |
+ } | |
+ | |
+ /* GetFullPathNameW requires at least "." to determine current directory */ | |
+ if (wpath_len == 0) { | |
+ // wprintf(L"Adding '.' to buffer\n"); | |
+ buffer_pos[0] = L'.'; | |
+ buffer_pos++; | |
+ } | |
+ | |
+ /* Ensure buffer is NULL terminated */ | |
+ buffer_pos[0] = L'\0'; | |
+ | |
+ // wprintf(L"buffer: '%s'\n", buffer); | |
+ | |
+ // FIXME: Make this more robust | |
+ // Determine require buffer size | |
+ size = GetFullPathNameW(buffer, PATH_BUFFER_SIZE, wfullpath_buffer, NULL); | |
+ if (size) { | |
+ if (size > PATH_BUFFER_SIZE) { | |
+ // allocate enough memory to contain the response | |
+ wfullpath = (wchar_t *)malloc(size * sizeof(wchar_t)); | |
+ size = GetFullPathNameW(buffer, size, wfullpath, NULL); | |
+ } else { | |
+ wfullpath = wfullpath_buffer; | |
+ } | |
+ // wprintf(L"wfullpath: '%s'\n", wfullpath); | |
+ | |
+ | |
+ /* Calculate the new size and leave the garbage out */ | |
+ // size = wcslen(wfullpath); | |
+ | |
+ /* Remove any trailing slashes */ | |
+ if (IS_DIR_SEPARATOR_P(wfullpath[size - 1]) && | |
+ wfullpath[size - 2] != L':' && | |
+ !(size == 2 && IS_DIR_UNC_P(wfullpath))) { | |
+ // wprintf(L"Removing trailing slash\n"); | |
+ size -= 1; | |
+ wfullpath[size] = L'\0'; | |
+ } | |
+ // wprintf(L"wfullpath: '%s'\n", wfullpath); | |
+ | |
+ /* Remove any trailing dot */ | |
+ if (wfullpath[size - 1] == L'.') { | |
+ // wprintf(L"Removing trailing dot\n"); | |
+ size -= 1; | |
+ wfullpath[size] = L'\0'; | |
+ } | |
+ | |
+ /* removes trailing invalid ':$DATA' */ | |
+ size = remove_invalid_alternative_data(wfullpath, size); | |
+ | |
+ // sanitize backslashes with forwardslashes | |
+ replace_wchar(wfullpath, L'\\', L'/'); | |
+ // wprintf(L"wfullpath: '%s'\n", wfullpath); | |
+ | |
+ // What CodePage should we use? | |
+ // cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP; | |
+ | |
+ // convert to char * | |
+ size = WideCharToMultiByte(cp, 0, wfullpath, -1, NULL, 0, NULL, NULL); | |
+ // fullpath = (char *)malloc(size * sizeof(char)); | |
+ if (size > (size_t)RSTRING_LEN(result)) | |
+ rb_str_resize(result, size); | |
+ | |
+ WideCharToMultiByte(cp, 0, wfullpath, -1, RSTRING_PTR(result), size, NULL, NULL); | |
+ | |
+ /* set the String VALUE length and the path encoding */ | |
+ rb_str_set_len(result, size - 1); | |
+ rb_enc_associate(result, path_encoding); | |
+ } | |
+ | |
+ // TODO: better cleanup | |
+ if (buffer) | |
+ free(buffer); | |
+ | |
+ if (wpath) | |
+ free(wpath); | |
+ | |
+ if (wdir) | |
+ free(wdir); | |
+ | |
+ if (whome) | |
+ free(whome); | |
+ | |
+ if (wfullpath && wfullpath != wfullpath_buffer) | |
+ free(wfullpath); | |
+ | |
+ return result; | |
+} | |
+ | |
+ | |
+void | |
+rb_w32_init_file() | |
+{ | |
+ rb_code_page = rb_hash_new(); | |
+ | |
+ /* prevent GC removing rb_code_page */ | |
+ rb_gc_register_mark_object(rb_code_page); | |
+} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50) Failure: | |
test_generate_bin_bindir_with_user_install_warning(TestGemInstaller) [c:/Users/h | |
iroshi/work/ruby/test/rubygems/test_gem_installer.rb:226]: | |
--- expected | |
+++ actual | |
@@ -1 +1,3 @@ | |
-"" | |
+"WARNING: You don't have C:\\Windows in your PATH, | |
+\t gem executables will not run. | |
+" | |
51) Failure: | |
test_constants(OpenSSL::TestConfig) [c:/Users/hiroshi/work/ruby/test/openssl/tes | |
t_config.rb:20]: | |
Exception raised: | |
<#<Errno::ENOENT: No such file or directory - C:/projects/rubyinstaller-git/sand | |
box/openssl/ssl/openssl.cnf>>. | |
52) Failure: | |
test_short_filename(WEBrick::TestFileHandler) [c:/Users/hiroshi/work/ruby/test/w | |
ebrick/test_filehandler.rb:240]: | |
webrick log start: | |
[2012-03-06 23:52:31] INFO WEBrick 1.3.1 | |
[2012-03-06 23:52:31] INFO ruby 2.0.0 (2012-03-06) [i386-mingw32] | |
[2012-03-06 23:52:31] INFO WEBrick::HTTPServer#start: pid=5964 port=50922 | |
[2012-03-06 23:52:31] WARN the request refers nondisclosure name `.htaccess'. | |
[2012-03-06 23:52:31] ERROR `/.htaccess' not found. | |
webrick log end. | |
<"404"> expected but was | |
<"200">. | |
53) Failure: | |
test_s_open_error(TestGDBM) [c:/Users/hiroshi/work/ruby/test/gdbm/test_gdbm.rb:2 | |
27]: | |
[Errno::EACCES, Errno::EWOULDBLOCK] expected but nothing was raised. | |
54) Failure: | |
test_reorganize(TestGDBM) [c:/Users/hiroshi/work/ruby/test/gdbm/test_gdbm.rb:611 | |
]: | |
<true> expected but was | |
<false>. | |
10717 tests, 1912796 assertions, 5 failures, 0 errors, 80 skips | |
ruby -v: ruby 2.0.0dev (2012-03-06 trunk 34931) [i386-mingw32] | |
make: *** [yes-test-all] Error 5 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment