summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-08-23 03:10:26 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-08-23 03:10:26 +0000
commit8433e20f65d04545227824ca9672de2892577317 (patch)
treec584000b4d74fc5ba767ff29834c0142d3ae2885
parentcc8354ba83e311056b2ccf69de0d67aa547afe27 (diff)
merge revision(s) 36668: [Backport #6846]
* test/ruby/test_file_exhaustive.rb (TestFileExhaustive#test_stat_special_file): add a test. GetFileAttributesExW fails to get attributes of special files such as pagefile.sys. * win32/win32.c (check_valid_dir): for performance, check the path by FindFirstFileW only if the path contains "...". * win32/win32.c (winnt_stat): use GetFileAttributesExW instead of FindFirstFileW since GetFileAttributesExW is faster. Based on the patch by Dusan D. Majkic. [ruby-core:47083] [Feature #6845] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_3@36792 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog15
-rw-r--r--test/ruby/test_file_exhaustive.rb9
-rw-r--r--version.h2
-rw-r--r--win32/win32.c58
4 files changed, 66 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index db45f9e3be..ce047864e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Thu Aug 23 12:08:25 2012 Hiroshi Shirosaki <h.shirosaki@gmail.com>
+
+ * test/ruby/test_file_exhaustive.rb
+ (TestFileExhaustive#test_stat_special_file): add a test.
+ GetFileAttributesExW fails to get attributes of special files
+ such as pagefile.sys.
+
+ * win32/win32.c (check_valid_dir): for performance, check the path
+ by FindFirstFileW only if the path contains "...".
+
+ * win32/win32.c (winnt_stat): use GetFileAttributesExW instead of
+ FindFirstFileW since GetFileAttributesExW is faster.
+ Based on the patch by Dusan D. Majkic.
+ [ruby-core:47083] [Feature #6845]
+
Thu Aug 23 11:19:51 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* thread_pthread.c (ruby_init_stack): STACK_GROW_DIR_DETECTION is
diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb
index c10b05a86b..f89e2512d0 100644
--- a/test/ruby/test_file_exhaustive.rb
+++ b/test/ruby/test_file_exhaustive.rb
@@ -3,6 +3,8 @@ require "fileutils"
require "tmpdir"
class TestFileExhaustive < Test::Unit::TestCase
+ DRIVE = Dir.pwd[%r'\A(?:[a-z]:|//[^/]+/[^/]+)'i]
+
def assert_incompatible_encoding
d = "\u{3042}\u{3044}".encode("utf-16le")
assert_raise(Encoding::CompatibilityError) {yield d}
@@ -770,6 +772,13 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_equal(0, File::Stat.new(@zerofile).size)
end
+ def test_stat_special_file
+ # test for special files such as pagefile.sys on Windows
+ assert_nothing_raised do
+ Dir::glob("C:/*.sys") {|f| File::Stat.new(f) }
+ end
+ end if DRIVE
+
def test_path_check
assert_nothing_raised { ENV["PATH"] }
end
diff --git a/version.h b/version.h
index 92b8bf5382..6f86349ec6 100644
--- a/version.h
+++ b/version.h
@@ -1,5 +1,5 @@
#define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 262
+#define RUBY_PATCHLEVEL 263
#define RUBY_RELEASE_DATE "2012-08-23"
#define RUBY_RELEASE_YEAR 2012
diff --git a/win32/win32.c b/win32/win32.c
index 253a462f23..7c2671f43a 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4234,7 +4234,14 @@ static int
check_valid_dir(const WCHAR *path)
{
WIN32_FIND_DATAW fd;
- HANDLE fh = open_dir_handle(path, &fd);
+ HANDLE fh;
+
+ /* GetFileAttributes() determines "..." as directory. */
+ /* We recheck it by FindFirstFile(). */
+ if (wcsstr(path, L"...") == NULL)
+ return 0;
+
+ fh = open_dir_handle(path, &fd);
if (fh == INVALID_HANDLE_VALUE)
return -1;
FindClose(fh);
@@ -4246,6 +4253,7 @@ winnt_stat(const WCHAR *path, struct stati64 *st)
{
HANDLE h;
WIN32_FIND_DATAW wfd;
+ WIN32_FILE_ATTRIBUTE_DATA wfa;
memset(st, 0, sizeof(*st));
st->st_nlink = 1;
@@ -4254,27 +4262,43 @@ winnt_stat(const WCHAR *path, struct stati64 *st)
errno = ENOENT;
return -1;
}
- h = FindFirstFileW(path, &wfd);
- if (h != INVALID_HANDLE_VALUE) {
- FindClose(h);
- st->st_mode = fileattr_to_unixmode(wfd.dwFileAttributes, path);
- st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime);
- st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
- st->st_ctime = filetime_to_unixtime(&wfd.ftCreationTime);
- st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
+ if (GetFileAttributesExW(path, GetFileExInfoStandard, (void*)&wfa)) {
+ if (wfa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ if (check_valid_dir(path)) return -1;
+ st->st_size = 0;
+ }
+ else {
+ st->st_size = ((__int64)wfa.nFileSizeHigh << 32) | wfa.nFileSizeLow;
+ }
+ st->st_mode = fileattr_to_unixmode(wfa.dwFileAttributes, path);
+ st->st_atime = filetime_to_unixtime(&wfa.ftLastAccessTime);
+ st->st_mtime = filetime_to_unixtime(&wfa.ftLastWriteTime);
+ st->st_ctime = filetime_to_unixtime(&wfa.ftCreationTime);
}
else {
- // If runtime stat(2) is called for network shares, it fails on WinNT.
- // Because GetDriveType returns 1 for network shares. (Win98 returns 4)
- DWORD attr = GetFileAttributesW(path);
- if (attr == (DWORD)-1L) {
- errno = map_errno(GetLastError());
+ /* GetFileAttributesEx failed; check why. */
+ int e = GetLastError();
+
+ if ((e == ERROR_FILE_NOT_FOUND) || (e == ERROR_INVALID_NAME)
+ || (e == ERROR_PATH_NOT_FOUND || (e == ERROR_BAD_NETPATH))) {
+ errno = map_errno(e);
return -1;
}
- if (attr & FILE_ATTRIBUTE_DIRECTORY) {
- if (check_valid_dir(path)) return -1;
+
+ /* Fall back to FindFirstFile for ERROR_SHARING_VIOLATION */
+ h = FindFirstFileW(path, &wfd);
+ if (h != INVALID_HANDLE_VALUE) {
+ FindClose(h);
+ st->st_mode = fileattr_to_unixmode(wfd.dwFileAttributes, path);
+ st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime);
+ st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
+ st->st_ctime = filetime_to_unixtime(&wfd.ftCreationTime);
+ st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
+ }
+ else {
+ errno = map_errno(GetLastError());
+ return -1;
}
- st->st_mode = fileattr_to_unixmode(attr, path);
}
st->st_dev = st->st_rdev = (iswalpha(path[0]) && path[1] == L':') ?