[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]