Project

General

Profile

Backport #6846 ยป backport_stat.patch

h.shirosaki (Hiroshi Shirosaki), 08/21/2012 09:05 AM

View differences:

ChangeLog
1
Thu Aug  9 20:03:11 2012  Hiroshi Shirosaki  <h.shirosaki@gmail.com>
2

  
3
	* test/ruby/test_file_exhaustive.rb
4
	  (TestFileExhaustive#test_stat_special_file): add a test.
5
	  GetFileAttributesExW fails to get attributes of special files
6
	  such as pagefile.sys.
7

  
8
	* win32/win32.c (check_valid_dir): for performance, check the path
9
	  by FindFirstFileW only if the path contains "...".
10

  
11
	* win32/win32.c (winnt_stat): use GetFileAttributesExW instead of
12
	  FindFirstFileW since GetFileAttributesExW is faster.
13
	  Based on the patch by Dusan D. Majkic.
14
	  [ruby-core:47083] [Feature #6845]
15

  
1 16
Mon Aug 20 17:11:01 2012  NARUSE, Yui  <naruse@ruby-lang.org>
2 17

  
3 18
	* file.c (file_path_convert): don't convert it when the path string is
test/ruby/test_file_exhaustive.rb
3 3
require "tmpdir"
4 4

  
5 5
class TestFileExhaustive < Test::Unit::TestCase
6
  DRIVE = Dir.pwd[%r'\A(?:[a-z]:|//[^/]+/[^/]+)'i]
7

  
6 8
  def assert_incompatible_encoding
7 9
    d = "\u{3042}\u{3044}".encode("utf-16le")
8 10
    assert_raise(Encoding::CompatibilityError) {yield d}
......
770 772
    assert_equal(0, File::Stat.new(@zerofile).size)
771 773
  end
772 774

  
775
  def test_stat_special_file
776
    # test for special files such as pagefile.sys on Windows
777
    assert_nothing_raised do
778
      Dir::glob("C:/*.sys") {|f| File::Stat.new(f) }
779
    end
780
  end if DRIVE
781

  
773 782
  def test_path_check
774 783
    assert_nothing_raised { ENV["PATH"] }
775 784
  end
win32/win32.c
4234 4234
check_valid_dir(const WCHAR *path)
4235 4235
{
4236 4236
    WIN32_FIND_DATAW fd;
4237
    HANDLE fh = open_dir_handle(path, &fd);
4237
    HANDLE fh;
4238

  
4239
    /* GetFileAttributes() determines "..." as directory. */
4240
    /* We recheck it by FindFirstFile(). */
4241
    if (wcsstr(path, L"...") == NULL)
4242
	return 0;
4243

  
4244
    fh = open_dir_handle(path, &fd);
4238 4245
    if (fh == INVALID_HANDLE_VALUE)
4239 4246
	return -1;
4240 4247
    FindClose(fh);
......
4246 4253
{
4247 4254
    HANDLE h;
4248 4255
    WIN32_FIND_DATAW wfd;
4256
    WIN32_FILE_ATTRIBUTE_DATA wfa;
4249 4257

  
4250 4258
    memset(st, 0, sizeof(*st));
4251 4259
    st->st_nlink = 1;
......
4254 4262
	errno = ENOENT;
4255 4263
	return -1;
4256 4264
    }
4257
    h = FindFirstFileW(path, &wfd);
4258
    if (h != INVALID_HANDLE_VALUE) {
4259
	FindClose(h);
4260
	st->st_mode  = fileattr_to_unixmode(wfd.dwFileAttributes, path);
4261
	st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime);
4262
	st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
4263
	st->st_ctime = filetime_to_unixtime(&wfd.ftCreationTime);
4264
	st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
4265
    if (GetFileAttributesExW(path, GetFileExInfoStandard, (void*)&wfa)) {
4266
	if (wfa.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
4267
	    if (check_valid_dir(path)) return -1;
4268
	    st->st_size = 0;
4269
	}
4270
	else {
4271
	    st->st_size = ((__int64)wfa.nFileSizeHigh << 32) | wfa.nFileSizeLow;
4272
	}
4273
	st->st_mode  = fileattr_to_unixmode(wfa.dwFileAttributes, path);
4274
	st->st_atime = filetime_to_unixtime(&wfa.ftLastAccessTime);
4275
	st->st_mtime = filetime_to_unixtime(&wfa.ftLastWriteTime);
4276
	st->st_ctime = filetime_to_unixtime(&wfa.ftCreationTime);
4265 4277
    }
4266 4278
    else {
4267
	// If runtime stat(2) is called for network shares, it fails on WinNT.
4268
	// Because GetDriveType returns 1 for network shares. (Win98 returns 4)
4269
	DWORD attr = GetFileAttributesW(path);
4270
	if (attr == (DWORD)-1L) {
4271
	    errno = map_errno(GetLastError());
4279
	/* GetFileAttributesEx failed; check why. */
4280
	int e = GetLastError();
4281

  
4282
	if ((e == ERROR_FILE_NOT_FOUND) || (e == ERROR_INVALID_NAME)
4283
	    || (e == ERROR_PATH_NOT_FOUND || (e == ERROR_BAD_NETPATH))) {
4284
	    errno = map_errno(e);
4272 4285
	    return -1;
4273 4286
	}
4274
	if (attr & FILE_ATTRIBUTE_DIRECTORY) {
4275
	    if (check_valid_dir(path)) return -1;
4287

  
4288
	/* Fall back to FindFirstFile for ERROR_SHARING_VIOLATION */
4289
	h = FindFirstFileW(path, &wfd);
4290
	if (h != INVALID_HANDLE_VALUE) {
4291
	    FindClose(h);
4292
	    st->st_mode  = fileattr_to_unixmode(wfd.dwFileAttributes, path);
4293
	    st->st_atime = filetime_to_unixtime(&wfd.ftLastAccessTime);
4294
	    st->st_mtime = filetime_to_unixtime(&wfd.ftLastWriteTime);
4295
	    st->st_ctime = filetime_to_unixtime(&wfd.ftCreationTime);
4296
	    st->st_size = ((__int64)wfd.nFileSizeHigh << 32) | wfd.nFileSizeLow;
4297
	}
4298
	else {
4299
	    errno = map_errno(GetLastError());
4300
	    return -1;
4276 4301
	}
4277
	st->st_mode  = fileattr_to_unixmode(attr, path);
4278 4302
    }
4279 4303

  
4280 4304
    st->st_dev = st->st_rdev = (iswalpha(path[0]) && path[1] == L':') ?