Skip to content

Instantly share code, notes, and snippets.

@shirosaki
Created March 6, 2012 15:01
Show Gist options
  • Save shirosaki/1986693 to your computer and use it in GitHub Desktop.
Save shirosaki/1986693 to your computer and use it in GitHub Desktop.
Fenix integration
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);
+}
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