Skip to content

Instantly share code, notes, and snippets.

@shirosaki
Created December 13, 2011 15:38
Show Gist options
  • Save shirosaki/1472566 to your computer and use it in GitHub Desktop.
Save shirosaki/1472566 to your computer and use it in GitHub Desktop.
Replace lstat to GetFileAttributes
ruby 2.0.0dev (2011-12-09 trunk 33995) [i386-mingw32]
Windows 7 on VirtualBox
2.4GHz Core 2 Duo
Rails 3.1.3
command: ruby script/rails r "p 1"
Average and standard deviation of 10 times trials
+----------+--------+----------+---------+
| realpath |
+----------+--------+----------+---------+
| ruby | time | average | stddev |
+----------+--------+----------+---------+
| trunk | real | 11.03240 | 0.09976 |
| trunk | system | 5.64950 | 0.29720 |
| trunk | user | 2.56050 | 0.25395 |
| patched | real | 10.52460 | 0.09762 |
| patched | system | 5.02600 | 0.13435 |
| patched | user | 2.61360 | 0.10037 |
+----------+--------+----------+---------+
diff --git a/file.c b/file.c
index fb62c51..c260a63 100644
--- a/file.c
+++ b/file.c
@@ -3306,6 +3306,45 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, char *unresolved, VALUE loopche
struct stat sbuf;
int ret;
VALUE testpath2 = rb_str_encode_ospath(testpath);
+#ifdef _WIN32
+ static int use_attribute = -1;
+ if (use_attribute == -1) {
+ if (getenv("RUBY_REALPATH_REPLACE") == NULL) {
+ use_attribute = 0;
+ }
+ else {
+ use_attribute = 1;
+ }
+ }
+ if (use_attribute) {
+ ret = rb_w32_GetFileAttributes(RSTRING_PTR(testpath2));
+ if (ret == -1) {
+ if (GetLastError() == ERROR_FILE_NOT_FOUND) {
+ if (strict || !last || *unresolved_firstsep)
+ rb_sys_fail(RSTRING_PTR(testpath));
+ *resolvedp = testpath;
+ break;
+ }
+ else {
+ rb_sys_fail(RSTRING_PTR(testpath));
+ }
+ }
+ }
+ else {
+ ret = lstat(RSTRING_PTR(testpath2), &sbuf);
+ if (ret == -1) {
+ if (errno == ENOENT) {
+ if (strict || !last || *unresolved_firstsep)
+ rb_sys_fail(RSTRING_PTR(testpath));
+ *resolvedp = testpath;
+ break;
+ }
+ else {
+ rb_sys_fail(RSTRING_PTR(testpath));
+ }
+ }
+ }
+#else
ret = lstat(RSTRING_PTR(testpath2), &sbuf);
if (ret == -1) {
if (errno == ENOENT) {
@@ -3318,6 +3357,7 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, char *unresolved, VALUE loopche
rb_sys_fail(RSTRING_PTR(testpath));
}
}
+#endif
#ifdef HAVE_READLINK
if (S_ISLNK(sbuf.st_mode)) {
volatile VALUE link;
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index 83da87a..c9ac6e5 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -304,6 +304,7 @@ 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);
+extern int rb_w32_GetFileAttributes(const char *);
#ifdef __BORLANDC__
extern int rb_w32_fstati64(int, struct stati64 *);
diff --git a/win32/win32.c b/win32/win32.c
index 67a392e..7726607 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4612,6 +4612,20 @@ rb_w32_ustati64(const char *path, struct stati64 *st)
return ret;
}
+int
+rb_w32_GetFileAttributes(const char *path)
+{
+ WCHAR *wpath;
+ int ret;
+
+ if (!(wpath = utf8_to_wstr(path, NULL)))
+ return -1;
+ ret = GetFileAttributesW(wpath);
+ free(wpath);
+ return ret;
+}
+
+
/* License: Ruby's */
int
rb_w32_stati64(const char *path, struct stati64 *st)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment