ruby-changes:24741
From: naruse <ko1@a...>
Date: Thu, 23 Aug 2012 12:10:38 +0900 (JST)
Subject: [ruby-changes:24741] naruse:r36792 (ruby_1_9_3): merge revision(s) 36668: [Backport #6846]
naruse 2012-08-23 12:10:26 +0900 (Thu, 23 Aug 2012) New Revision: 36792 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36792 Log: 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] Modified files: branches/ruby_1_9_3/ChangeLog branches/ruby_1_9_3/test/ruby/test_file_exhaustive.rb branches/ruby_1_9_3/version.h branches/ruby_1_9_3/win32/win32.c Index: ruby_1_9_3/ChangeLog =================================================================== --- ruby_1_9_3/ChangeLog (revision 36791) +++ ruby_1_9_3/ChangeLog (revision 36792) @@ -1,3 +1,18 @@ +Thu Aug 23 12:08:25 2012 Hiroshi Shirosaki <h.shirosaki@g...> + + * 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@r...> * thread_pthread.c (ruby_init_stack): STACK_GROW_DIR_DETECTION is Index: ruby_1_9_3/win32/win32.c =================================================================== --- ruby_1_9_3/win32/win32.c (revision 36791) +++ ruby_1_9_3/win32/win32.c (revision 36792) @@ -4234,7 +4234,14 @@ 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 @@ { HANDLE h; WIN32_FIND_DATAW wfd; + WIN32_FILE_ATTRIBUTE_DATA wfa; memset(st, 0, sizeof(*st)); st->st_nlink = 1; @@ -4254,27 +4262,43 @@ 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) { + /* 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; + } + + /* 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; } - if (attr & FILE_ATTRIBUTE_DIRECTORY) { - if (check_valid_dir(path)) return -1; - } - st->st_mode = fileattr_to_unixmode(attr, path); } st->st_dev = st->st_rdev = (iswalpha(path[0]) && path[1] == L':') ? Index: ruby_1_9_3/version.h =================================================================== --- ruby_1_9_3/version.h (revision 36791) +++ ruby_1_9_3/version.h (revision 36792) @@ -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 Index: ruby_1_9_3/test/ruby/test_file_exhaustive.rb =================================================================== --- ruby_1_9_3/test/ruby/test_file_exhaustive.rb (revision 36791) +++ ruby_1_9_3/test/ruby/test_file_exhaustive.rb (revision 36792) @@ -3,6 +3,8 @@ 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 @@ 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 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/