summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorskerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-17 22:44:31 +0000
committerskerner@chromium.org <skerner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-17 22:44:31 +0000
commit71b7da7dbd4ed7fa4e28e23a796bd203601613aa (patch)
treed365103619c0a86e56d05eb74c2a121fb4424645 /base
parent3a2630d61cbff2fffff994b9f9bcdb7f9fcc1893 (diff)
downloadchromium_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.h17
-rw-r--r--base/file_util_unittest.cc72
-rw-r--r--base/file_util_win.cc88
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