diff options
author | skerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-17 22:44:31 +0000 |
---|---|---|
committer | skerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-17 22:44:31 +0000 |
commit | 71b7da7dbd4ed7fa4e28e23a796bd203601613aa (patch) | |
tree | d365103619c0a86e56d05eb74c2a121fb4424645 /base | |
parent | 3a2630d61cbff2fffff994b9f9bcdb7f9fcc1893 (diff) | |
download | chromium_src-71b7da7dbd4ed7fa4e28e23a796bd203601613aa.zip chromium_src-71b7da7dbd4ed7fa4e28e23a796bd203601613aa.tar.gz chromium_src-71b7da7dbd4ed7fa4e28e23a796bd203601613aa.tar.bz2 |
Match whole path components in DevicePathToDriveLetterPath(). Add tests.
+rvargas, who understands the code
+brettw, who is in OWNERS
BUG=109577
TEST=FileUtilTest.DevicePathToDriveLetter
Review URL: http://codereview.chromium.org/9167004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117986 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/file_util.h | 17 | ||||
-rw-r--r-- | base/file_util_unittest.cc | 72 | ||||
-rw-r--r-- | base/file_util_win.cc | 88 |
3 files changed, 128 insertions, 49 deletions
diff --git a/base/file_util.h b/base/file_util.h index 78827e9..384f394 100644 --- a/base/file_util.h +++ b/base/file_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -324,10 +324,17 @@ BASE_EXPORT bool IsDotDot(const FilePath& path); BASE_EXPORT bool NormalizeFilePath(const FilePath& path, FilePath* real_path); #if defined(OS_WIN) -// Given an existing file in |path|, it returns in |real_path| the path -// in the native NT format, of the form "\Device\HarddiskVolumeXX\..". -// Returns false it it fails. Empty files cannot be resolved with this -// function. + +// Given a path in NT native form ("\Device\HarddiskVolumeXX\..."), +// return in |drive_letter_path| the equivalent path that starts with +// a drive letter ("C:\..."). Return false if no such path exists. +BASE_EXPORT bool DevicePathToDriveLetterPath(const FilePath& device_path, + FilePath* drive_letter_path); + +// Given an existing file in |path|, set |real_path| to the path +// in native NT format, of the form "\Device\HarddiskVolumeXX\..". +// Returns false if the path can not be found. Empty files cannot +// be resolved with this function. BASE_EXPORT bool NormalizeToNativeFilePath(const FilePath& path, FilePath* nt_path); #endif diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc index 0cade2a..ee73ef3 100644 --- a/base/file_util_unittest.cc +++ b/base/file_util_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -580,6 +580,76 @@ TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) { &normalized_path)); } +TEST_F(FileUtilTest, DevicePathToDriveLetter) { + // Get a drive letter. + std::wstring real_drive_letter = temp_dir_.path().value().substr(0, 2); + if (!isalpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) { + LOG(ERROR) << "Can't get a drive letter to test with."; + return; + } + + // Get the NT style path to that drive. + wchar_t device_path[MAX_PATH] = {'\0'}; + ASSERT_TRUE( + ::QueryDosDevice(real_drive_letter.c_str(), device_path, MAX_PATH)); + FilePath actual_device_path(device_path); + FilePath win32_path; + + // Run DevicePathToDriveLetterPath() on the NT style path we got from + // QueryDosDevice(). Expect the drive letter we started with. + ASSERT_TRUE(file_util::DevicePathToDriveLetterPath(actual_device_path, + &win32_path)); + ASSERT_EQ(real_drive_letter, win32_path.value()); + + // Add some directories to the path. Expect those extra path componenets + // to be preserved. + FilePath kRelativePath(FPL("dir1\\dir2\\file.txt")); + ASSERT_TRUE(file_util::DevicePathToDriveLetterPath( + actual_device_path.Append(kRelativePath), + &win32_path)); + EXPECT_EQ(FilePath(real_drive_letter + L"\\").Append(kRelativePath).value(), + win32_path.value()); + + // Deform the real path so that it is invalid by removing the last four + // characters. The way windows names devices that are hard disks + // (\Device\HardDiskVolume${NUMBER}) guarantees that the string is longer + // than three characters. The only way the truncated string could be a + // real drive is if more than 10^3 disks are mounted: + // \Device\HardDiskVolume10000 would be truncated to \Device\HardDiskVolume1 + // Check that DevicePathToDriveLetterPath fails. + int path_length = actual_device_path.value().length(); + int new_length = path_length - 4; + ASSERT_LT(0, new_length); + FilePath prefix_of_real_device_path( + actual_device_path.value().substr(0, new_length)); + ASSERT_FALSE(file_util::DevicePathToDriveLetterPath( + prefix_of_real_device_path, + &win32_path)); + + ASSERT_FALSE(file_util::DevicePathToDriveLetterPath( + prefix_of_real_device_path.Append(kRelativePath), + &win32_path)); + + // Deform the real path so that it is invalid by adding some characters. For + // example, if C: maps to \Device\HardDiskVolume8, then we simulate a + // request for the drive letter whose native path is + // \Device\HardDiskVolume812345 . We assume such a device does not exist, + // because drives are numbered in order and mounting 112345 hard disks will + // never happen. + const FilePath::StringType kExtraChars = FPL("12345"); + + FilePath real_device_path_plus_numbers( + actual_device_path.value() + kExtraChars); + + ASSERT_FALSE(file_util::DevicePathToDriveLetterPath( + real_device_path_plus_numbers, + &win32_path)); + + ASSERT_FALSE(file_util::DevicePathToDriveLetterPath( + real_device_path_plus_numbers.Append(kRelativePath), + &win32_path)); +} + TEST_F(FileUtilTest, GetPlatformFileInfoForDirectory) { FilePath empty_dir = temp_dir_.path().Append(FPL("gpfi_test")); ASSERT_TRUE(file_util::CreateDirectory(empty_dir)); diff --git a/base/file_util_win.cc b/base/file_util_win.cc index 31d2f05..d1337a2 100644 --- a/base/file_util_win.cc +++ b/base/file_util_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -35,48 +35,6 @@ namespace { const DWORD kFileShareAll = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; -// Helper for NormalizeFilePath(), defined below. -bool DevicePathToDriveLetterPath(const FilePath& device_path, - FilePath* drive_letter_path) { - base::ThreadRestrictions::AssertIOAllowed(); - - // Get the mapping of drive letters to device paths. - const int kDriveMappingSize = 1024; - wchar_t drive_mapping[kDriveMappingSize] = {'\0'}; - if (!::GetLogicalDriveStrings(kDriveMappingSize - 1, drive_mapping)) { - DLOG(ERROR) << "Failed to get drive mapping."; - return false; - } - - // The drive mapping is a sequence of null terminated strings. - // The last string is empty. - wchar_t* drive_map_ptr = drive_mapping; - wchar_t device_name[MAX_PATH]; - wchar_t drive[] = L" :"; - - // For each string in the drive mapping, get the junction that links - // to it. If that junction is a prefix of |device_path|, then we - // know that |drive| is the real path prefix. - while (*drive_map_ptr) { - drive[0] = drive_map_ptr[0]; // Copy the drive letter. - - if (QueryDosDevice(drive, device_name, MAX_PATH) && - StartsWith(device_path.value(), device_name, true)) { - *drive_letter_path = FilePath(drive + - device_path.value().substr(wcslen(device_name))); - return true; - } - // Move to the next drive letter string, which starts one - // increment after the '\0' that terminates the current string. - while (*drive_map_ptr++); - } - - // No drive matched. The path does not start with a device junction - // that is mounted as a drive letter. This means there is no drive - // letter path to the volume that holds |device_path|, so fail. - return false; -} - } // namespace bool AbsolutePath(FilePath* path) { @@ -1047,6 +1005,50 @@ bool NormalizeFilePath(const FilePath& path, FilePath* real_path) { return DevicePathToDriveLetterPath(mapped_file, real_path); } +bool DevicePathToDriveLetterPath(const FilePath& nt_device_path, + FilePath* out_drive_letter_path) { + base::ThreadRestrictions::AssertIOAllowed(); + + // Get the mapping of drive letters to device paths. + const int kDriveMappingSize = 1024; + wchar_t drive_mapping[kDriveMappingSize] = {'\0'}; + if (!::GetLogicalDriveStrings(kDriveMappingSize - 1, drive_mapping)) { + DLOG(ERROR) << "Failed to get drive mapping."; + return false; + } + + // The drive mapping is a sequence of null terminated strings. + // The last string is empty. + wchar_t* drive_map_ptr = drive_mapping; + wchar_t device_path_as_string[MAX_PATH]; + wchar_t drive[] = L" :"; + + // For each string in the drive mapping, get the junction that links + // to it. If that junction is a prefix of |device_path|, then we + // know that |drive| is the real path prefix. + while (*drive_map_ptr) { + drive[0] = drive_map_ptr[0]; // Copy the drive letter. + + if (QueryDosDevice(drive, device_path_as_string, MAX_PATH)) { + FilePath device_path(device_path_as_string); + if (device_path == nt_device_path || + device_path.IsParent(nt_device_path)) { + *out_drive_letter_path = FilePath(drive + + nt_device_path.value().substr(wcslen(device_path_as_string))); + return true; + } + } + // Move to the next drive letter string, which starts one + // increment after the '\0' that terminates the current string. + while (*drive_map_ptr++); + } + + // No drive matched. The path does not start with a device junction + // that is mounted as a drive letter. This means there is no drive + // letter path to the volume that holds |device_path|, so fail. + return false; +} + bool NormalizeToNativeFilePath(const FilePath& path, FilePath* nt_path) { base::ThreadRestrictions::AssertIOAllowed(); // In Vista, GetFinalPathNameByHandle() would give us the real path |