| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/file_util.h" | 5 #include "base/file_util.h" |
| 6 | 6 |
| 7 #include <stdio.h> | 7 #include <stdio.h> |
| 8 | 8 |
| 9 #include <fstream> | 9 #include <fstream> |
| 10 | 10 |
| 11 #include "base/file_path.h" | 11 #include "base/file_path.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 14 #include "unicode/uniset.h" | 14 #include "unicode/uniset.h" |
| 15 | 15 |
| 16 #include "base/string_piece.h" |
| 17 #include "base/sys_string_conversions.h" |
| 18 |
| 16 namespace file_util { | 19 namespace file_util { |
| 17 | 20 |
| 18 const wchar_t kExtensionSeparator = L'.'; | 21 void PathComponents(const FilePath& path, |
| 22 std::vector<FilePath::StringType>* components) { |
| 23 DCHECK(components); |
| 24 if (!components) |
| 25 return; |
| 19 | 26 |
| 20 void PathComponents(const std::wstring& path, | 27 FilePath::StringType path_str = path.value(); |
| 21 std::vector<std::wstring>* components) { | 28 FilePath::StringType::size_type start = 0; |
| 22 DCHECK(components != NULL); | 29 FilePath::StringType::size_type end = |
| 23 if (components == NULL) | 30 path_str.find_first_of(FilePath::kSeparators); |
| 24 return; | |
| 25 std::wstring::size_type start = 0; | |
| 26 std::wstring::size_type end = path.find(kPathSeparator, start); | |
| 27 | 31 |
| 28 // Special case the "/" or "\" directory. On Windows with a drive letter, | 32 // If the path starts with a separator, add it to components. |
| 29 // this code path won't hit, but the right thing should still happen. | |
| 30 // "E:\foo" will turn into "E:","foo". | |
| 31 if (end == start) { | 33 if (end == start) { |
| 32 components->push_back(std::wstring(path, 0, 1)); | 34 components->push_back(FilePath::StringType(path_str, 0, 1)); |
| 33 start = end + 1; | 35 start = end + 1; |
| 34 end = path.find(kPathSeparator, start); | 36 end = path_str.find_first_of(FilePath::kSeparators, start); |
| 35 } | 37 } |
| 36 while (end != std::wstring::npos) { | 38 while (end != FilePath::StringType::npos) { |
| 37 std::wstring component = std::wstring(path, start, end - start); | 39 FilePath::StringType component = |
| 40 FilePath::StringType(path_str, start, end - start); |
| 38 components->push_back(component); | 41 components->push_back(component); |
| 39 start = end + 1; | 42 start = end + 1; |
| 40 end = path.find(kPathSeparator, start); | 43 end = path_str.find(FilePath::kSeparators, start); |
| 41 } | 44 } |
| 42 std::wstring component = std::wstring(path, start); | 45 |
| 43 components->push_back(component); | 46 components->push_back(FilePath::StringType(path_str, start)); |
| 44 } | 47 } |
| 45 | 48 |
| 46 bool EndsWithSeparator(const FilePath& file_path) { | 49 bool EndsWithSeparator(const FilePath& path) { |
| 47 std::wstring path = file_path.ToWStringHack(); | 50 FilePath::StringType value = path.value(); |
| 48 bool is_sep = (path.length() > 0 && | 51 if (value.empty()) |
| 49 path[path.length() - 1] == kPathSeparator); | 52 return false; |
| 50 return is_sep; | 53 |
| 54 return FilePath::IsSeparator(value[value.size() - 1]); |
| 51 } | 55 } |
| 52 | 56 |
| 53 bool EnsureEndsWithSeparator(FilePath* path) { | 57 bool EnsureEndsWithSeparator(FilePath* path) { |
| 54 if (!DirectoryExists(*path)) | 58 if (!DirectoryExists(*path)) |
| 55 return false; | 59 return false; |
| 56 | 60 |
| 57 if (EndsWithSeparator(*path)) | 61 if (EndsWithSeparator(*path)) |
| 58 return true; | 62 return true; |
| 59 | 63 |
| 60 FilePath::StringType& path_str = | 64 FilePath::StringType& path_str = |
| 61 const_cast<FilePath::StringType&>(path->value()); | 65 const_cast<FilePath::StringType&>(path->value()); |
| 62 path_str.append(&FilePath::kSeparators[0], 1); | 66 path_str.append(&FilePath::kSeparators[0], 1); |
| 63 | 67 |
| 64 return true; | 68 return true; |
| 65 } | 69 } |
| 66 | 70 |
| 67 void TrimTrailingSeparator(std::wstring* dir) { | 71 void TrimTrailingSeparator(std::wstring* dir) { |
| 68 while (dir->length() > 1 && EndsWithSeparator(dir)) | 72 while (dir->length() > 1 && EndsWithSeparator(dir)) |
| 69 dir->resize(dir->length() - 1); | 73 dir->resize(dir->length() - 1); |
| 70 } | 74 } |
| 71 | 75 |
| 72 void UpOneDirectory(std::wstring* dir) { | |
| 73 TrimTrailingSeparator(dir); | |
| 74 | |
| 75 std::wstring::size_type last_sep = dir->find_last_of(kPathSeparator); | |
| 76 if (last_sep != std::wstring::npos) | |
| 77 dir->resize(last_sep); | |
| 78 } | |
| 79 | |
| 80 void UpOneDirectoryOrEmpty(std::wstring* dir) { | |
| 81 TrimTrailingSeparator(dir); | |
| 82 | |
| 83 std::wstring::size_type last_sep = dir->find_last_of(kPathSeparator); | |
| 84 if (last_sep != std::wstring::npos) | |
| 85 dir->resize(last_sep); | |
| 86 else | |
| 87 dir->clear(); | |
| 88 } | |
| 89 | |
| 90 void TrimFilename(std::wstring* path) { | |
| 91 if (EndsWithSeparator(path)) { | |
| 92 TrimTrailingSeparator(path); | |
| 93 } else { | |
| 94 std::wstring::size_type last_sep = path->find_last_of(kPathSeparator); | |
| 95 if (last_sep != std::wstring::npos) | |
| 96 path->resize(last_sep); | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 std::wstring GetFilenameFromPath(const std::wstring& path) { | 76 std::wstring GetFilenameFromPath(const std::wstring& path) { |
| 101 // TODO(erikkay): fix this - it's not using kPathSeparator, but win unit test | 77 // TODO(erikkay): fix this - it's not using kPathSeparator, but win unit test |
| 102 // are exercising '/' as a path separator as well. | 78 // are exercising '/' as a path separator as well. |
| 103 std::wstring::size_type pos = path.find_last_of(L"\\/"); | 79 std::wstring::size_type pos = path.find_last_of(L"\\/"); |
| 104 return std::wstring(path, pos == std::wstring::npos ? 0 : pos + 1); | 80 return std::wstring(path, pos == std::wstring::npos ? 0 : pos + 1); |
| 105 } | 81 } |
| 106 | 82 |
| 107 std::wstring GetFileExtensionFromPath(const std::wstring& path) { | 83 std::wstring GetFileExtensionFromPath(const std::wstring& path) { |
| 108 std::wstring file_name = GetFilenameFromPath(path); | 84 std::wstring file_name = GetFilenameFromPath(path); |
| 109 std::wstring::size_type last_dot = file_name.rfind(L'.'); | 85 std::wstring::size_type last_dot = file_name.rfind(L'.'); |
| 110 return std::wstring(last_dot == std::wstring::npos ? | 86 return std::wstring(last_dot == std::wstring::npos ? |
| 111 L"" : | 87 L"" : |
| 112 file_name, last_dot+1); | 88 file_name, last_dot+1); |
| 113 } | 89 } |
| 114 | 90 |
| 115 std::wstring GetFilenameWithoutExtensionFromPath(const std::wstring& path) { | 91 std::wstring GetFilenameWithoutExtensionFromPath(const std::wstring& path) { |
| 116 std::wstring file_name = GetFilenameFromPath(path); | 92 std::wstring file_name = GetFilenameFromPath(path); |
| 117 std::wstring::size_type last_dot = file_name.rfind(L'.'); | 93 std::wstring::size_type last_dot = file_name.rfind(L'.'); |
| 118 return file_name.substr(0, last_dot); | 94 return file_name.substr(0, last_dot); |
| 119 } | 95 } |
| 120 | 96 |
| 121 void AppendToPath(std::wstring* path, const std::wstring& new_ending) { | |
| 122 if (!path) { | |
| 123 NOTREACHED(); | |
| 124 return; // Don't crash in this function in release builds. | |
| 125 } | |
| 126 | |
| 127 if (!EndsWithSeparator(path)) | |
| 128 path->push_back(kPathSeparator); | |
| 129 path->append(new_ending); | |
| 130 } | |
| 131 | |
| 132 void InsertBeforeExtension(std::wstring* path, const std::wstring& suffix) { | |
| 133 DCHECK(path); | |
| 134 | |
| 135 const std::wstring::size_type last_dot = path->rfind(kExtensionSeparator); | |
| 136 const std::wstring::size_type last_sep = path->rfind(kPathSeparator); | |
| 137 | |
| 138 if (last_dot == std::wstring::npos || | |
| 139 (last_sep != std::wstring::npos && last_dot < last_sep)) { | |
| 140 // The path looks something like "C:\pics.old\jojo" or "C:\pics\jojo". | |
| 141 // We should just append the suffix to the entire path. | |
| 142 path->append(suffix); | |
| 143 return; | |
| 144 } | |
| 145 | |
| 146 path->insert(last_dot, suffix); | |
| 147 } | |
| 148 | |
| 149 void ReplaceIllegalCharacters(std::wstring* file_name, int replace_char) { | 97 void ReplaceIllegalCharacters(std::wstring* file_name, int replace_char) { |
| 150 DCHECK(file_name); | 98 DCHECK(file_name); |
| 151 | 99 |
| 152 // Control characters, formatting characters, non-characters, and | 100 // Control characters, formatting characters, non-characters, and |
| 153 // some printable ASCII characters regarded as dangerous ('"*/:<>?\\'). | 101 // some printable ASCII characters regarded as dangerous ('"*/:<>?\\'). |
| 154 // See http://blogs.msdn.com/michkap/archive/2006/11/03/941420.aspx | 102 // See http://blogs.msdn.com/michkap/archive/2006/11/03/941420.aspx |
| 155 // and http://msdn2.microsoft.com/en-us/library/Aa365247.aspx | 103 // and http://msdn2.microsoft.com/en-us/library/Aa365247.aspx |
| 156 // TODO(jungshik): Revisit the set. ZWJ and ZWNJ are excluded because they | 104 // TODO(jungshik): Revisit the set. ZWJ and ZWNJ are excluded because they |
| 157 // are legitimate in Arabic and some S/SE Asian scripts. However, when used | 105 // are legitimate in Arabic and some S/SE Asian scripts. However, when used |
| 158 // elsewhere, they can be confusing/problematic. | 106 // elsewhere, they can be confusing/problematic. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 if (illegal_characters.contains(wstr[i])) { | 157 if (illegal_characters.contains(wstr[i])) { |
| 210 (*file_name)[i] = replace_char; | 158 (*file_name)[i] = replace_char; |
| 211 } | 159 } |
| 212 ++i; | 160 ++i; |
| 213 } | 161 } |
| 214 #else | 162 #else |
| 215 #error wchar_t* should be either UTF-16 or UTF-32 | 163 #error wchar_t* should be either UTF-16 or UTF-32 |
| 216 #endif | 164 #endif |
| 217 } | 165 } |
| 218 | 166 |
| 219 // Appends the extension to file adding a '.' if extension doesn't contain one. | |
| 220 // This does nothing if extension is empty or '.'. This is used internally by | |
| 221 // ReplaceExtension. | |
| 222 static void AppendExtension(const std::wstring& extension, | |
| 223 std::wstring* file) { | |
| 224 if (!extension.empty() && extension != L".") { | |
| 225 if (extension[0] != L'.') | |
| 226 file->append(L"."); | |
| 227 file->append(extension); | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 void ReplaceExtension(std::wstring* file_name, const std::wstring& extension) { | |
| 232 const std::wstring::size_type last_dot = file_name->rfind(L'.'); | |
| 233 if (last_dot == std::wstring::npos) { | |
| 234 // No extension, just append the supplied extension. | |
| 235 AppendExtension(extension, file_name); | |
| 236 return; | |
| 237 } | |
| 238 const std::wstring::size_type last_separator = | |
| 239 file_name->rfind(kPathSeparator); | |
| 240 if (last_separator != std::wstring::npos && last_dot < last_separator) { | |
| 241 // File name doesn't have extension, but one of the directories does; don't | |
| 242 // replace it, just append the supplied extension. For example | |
| 243 // 'c:\tmp.bar\foo'. | |
| 244 AppendExtension(extension, file_name); | |
| 245 return; | |
| 246 } | |
| 247 std::wstring result = file_name->substr(0, last_dot); | |
| 248 AppendExtension(extension, &result); | |
| 249 file_name->swap(result); | |
| 250 } | |
| 251 | |
| 252 bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) { | 167 bool ContentsEqual(const FilePath& filename1, const FilePath& filename2) { |
| 253 // We open the file in binary format even if they are text files because | 168 // We open the file in binary format even if they are text files because |
| 254 // we are just comparing that bytes are exactly same in both files and not | 169 // we are just comparing that bytes are exactly same in both files and not |
| 255 // doing anything smart with text formatting. | 170 // doing anything smart with text formatting. |
| 256 std::ifstream file1(filename1.value().c_str(), | 171 std::ifstream file1(filename1.value().c_str(), |
| 257 std::ios::in | std::ios::binary); | 172 std::ios::in | std::ios::binary); |
| 258 std::ifstream file2(filename2.value().c_str(), | 173 std::ifstream file2(filename2.value().c_str(), |
| 259 std::ios::in | std::ios::binary); | 174 std::ios::in | std::ios::binary); |
| 260 | 175 |
| 261 // Even if both files aren't openable (and thus, in some sense, "equal"), | 176 // Even if both files aren't openable (and thus, in some sense, "equal"), |
| 262 // any unusable file yields a result of "false". | 177 // any unusable file yields a result of "false". |
| 263 if (!file1.is_open() || !file2.is_open()) | 178 if (!file1.is_open() || !file2.is_open()) |
| 264 return false; | 179 return false; |
| 265 | 180 |
| 266 const int BUFFER_SIZE = 2056; | 181 const int BUFFER_SIZE = 2056; |
| 267 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE]; | 182 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE]; |
| 268 do { | 183 do { |
| 269 file1.read(buffer1, BUFFER_SIZE); | 184 file1.read(buffer1, BUFFER_SIZE); |
| 270 file2.read(buffer2, BUFFER_SIZE); | 185 file2.read(buffer2, BUFFER_SIZE); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 | 231 |
| 317 // Deprecated functions ---------------------------------------------------- | 232 // Deprecated functions ---------------------------------------------------- |
| 318 | 233 |
| 319 bool AbsolutePath(std::wstring* path_str) { | 234 bool AbsolutePath(std::wstring* path_str) { |
| 320 FilePath path(FilePath::FromWStringHack(*path_str)); | 235 FilePath path(FilePath::FromWStringHack(*path_str)); |
| 321 if (!AbsolutePath(&path)) | 236 if (!AbsolutePath(&path)) |
| 322 return false; | 237 return false; |
| 323 *path_str = path.ToWStringHack(); | 238 *path_str = path.ToWStringHack(); |
| 324 return true; | 239 return true; |
| 325 } | 240 } |
| 326 bool Delete(const std::wstring& path, bool recursive) { | 241 void AppendToPath(std::wstring* path, const std::wstring& new_ending) { |
| 327 return Delete(FilePath::FromWStringHack(path), recursive); | 242 if (!path) { |
| 328 } | 243 NOTREACHED(); |
| 329 bool EndsWithSeparator(std::wstring* path) { | 244 return; // Don't crash in this function in release builds. |
| 330 return EndsWithSeparator(FilePath::FromWStringHack(*path)); | 245 } |
| 331 } | 246 |
| 332 bool EndsWithSeparator(const std::wstring& path) { | 247 if (!EndsWithSeparator(path)) |
| 333 return EndsWithSeparator(FilePath::FromWStringHack(path)); | 248 path->push_back(FilePath::kSeparators[0]); |
| 334 } | 249 path->append(new_ending); |
| 335 bool Move(const std::wstring& from_path, const std::wstring& to_path) { | |
| 336 return Move(FilePath::FromWStringHack(from_path), | |
| 337 FilePath::FromWStringHack(to_path)); | |
| 338 } | |
| 339 bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) { | |
| 340 return CopyFile(FilePath::FromWStringHack(from_path), | |
| 341 FilePath::FromWStringHack(to_path)); | |
| 342 } | 250 } |
| 343 bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path, | 251 bool CopyDirectory(const std::wstring& from_path, const std::wstring& to_path, |
| 344 bool recursive) { | 252 bool recursive) { |
| 345 return CopyDirectory(FilePath::FromWStringHack(from_path), | 253 return CopyDirectory(FilePath::FromWStringHack(from_path), |
| 346 FilePath::FromWStringHack(to_path), | 254 FilePath::FromWStringHack(to_path), |
| 347 recursive); | 255 recursive); |
| 348 } | 256 } |
| 349 bool PathExists(const std::wstring& path) { | |
| 350 return PathExists(FilePath::FromWStringHack(path)); | |
| 351 } | |
| 352 bool DirectoryExists(const std::wstring& path) { | |
| 353 return DirectoryExists(FilePath::FromWStringHack(path)); | |
| 354 } | |
| 355 bool ContentsEqual(const std::wstring& filename1, | 257 bool ContentsEqual(const std::wstring& filename1, |
| 356 const std::wstring& filename2) { | 258 const std::wstring& filename2) { |
| 357 return ContentsEqual(FilePath::FromWStringHack(filename1), | 259 return ContentsEqual(FilePath::FromWStringHack(filename1), |
| 358 FilePath::FromWStringHack(filename2)); | 260 FilePath::FromWStringHack(filename2)); |
| 359 } | 261 } |
| 262 bool CopyFile(const std::wstring& from_path, const std::wstring& to_path) { |
| 263 return CopyFile(FilePath::FromWStringHack(from_path), |
| 264 FilePath::FromWStringHack(to_path)); |
| 265 } |
| 360 bool CreateDirectory(const std::wstring& full_path) { | 266 bool CreateDirectory(const std::wstring& full_path) { |
| 361 return CreateDirectory(FilePath::FromWStringHack(full_path)); | 267 return CreateDirectory(FilePath::FromWStringHack(full_path)); |
| 362 } | 268 } |
| 363 bool CreateTemporaryFileName(std::wstring* temp_file) { | 269 bool CreateTemporaryFileName(std::wstring* temp_file) { |
| 364 FilePath temp_file_path; | 270 FilePath temp_file_path; |
| 365 if (!CreateTemporaryFileName(&temp_file_path)) | 271 if (!CreateTemporaryFileName(&temp_file_path)) |
| 366 return false; | 272 return false; |
| 367 *temp_file = temp_file_path.ToWStringHack(); | 273 *temp_file = temp_file_path.ToWStringHack(); |
| 368 return true; | 274 return true; |
| 369 } | 275 } |
| 276 bool Delete(const std::wstring& path, bool recursive) { |
| 277 return Delete(FilePath::FromWStringHack(path), recursive); |
| 278 } |
| 279 bool DirectoryExists(const std::wstring& path) { |
| 280 return DirectoryExists(FilePath::FromWStringHack(path)); |
| 281 } |
| 282 bool EndsWithSeparator(std::wstring* path) { |
| 283 return EndsWithSeparator(FilePath::FromWStringHack(*path)); |
| 284 } |
| 285 bool EndsWithSeparator(const std::wstring& path) { |
| 286 return EndsWithSeparator(FilePath::FromWStringHack(path)); |
| 287 } |
| 370 bool GetCurrentDirectory(std::wstring* path_str) { | 288 bool GetCurrentDirectory(std::wstring* path_str) { |
| 371 FilePath path; | 289 FilePath path; |
| 372 if (!GetCurrentDirectory(&path)) | 290 if (!GetCurrentDirectory(&path)) |
| 373 return false; | 291 return false; |
| 374 *path_str = path.ToWStringHack(); | 292 *path_str = path.ToWStringHack(); |
| 375 return true; | 293 return true; |
| 376 } | 294 } |
| 377 bool GetFileInfo(const std::wstring& file_path, FileInfo* results) { | 295 bool GetFileInfo(const std::wstring& file_path, FileInfo* results) { |
| 378 return GetFileInfo(FilePath::FromWStringHack(file_path), results); | 296 return GetFileInfo(FilePath::FromWStringHack(file_path), results); |
| 379 } | 297 } |
| 380 bool GetFileSize(const std::wstring& file_path, int64* file_size) { | 298 bool GetFileSize(const std::wstring& file_path, int64* file_size) { |
| 381 return GetFileSize(FilePath::FromWStringHack(file_path), file_size); | 299 return GetFileSize(FilePath::FromWStringHack(file_path), file_size); |
| 382 } | 300 } |
| 383 bool GetTempDir(std::wstring* path_str) { | 301 bool GetTempDir(std::wstring* path_str) { |
| 384 FilePath path; | 302 FilePath path; |
| 385 if (!GetTempDir(&path)) | 303 if (!GetTempDir(&path)) |
| 386 return false; | 304 return false; |
| 387 *path_str = path.ToWStringHack(); | 305 *path_str = path.ToWStringHack(); |
| 388 return true; | 306 return true; |
| 389 } | 307 } |
| 308 bool Move(const std::wstring& from_path, const std::wstring& to_path) { |
| 309 return Move(FilePath::FromWStringHack(from_path), |
| 310 FilePath::FromWStringHack(to_path)); |
| 311 } |
| 390 FILE* OpenFile(const std::wstring& filename, const char* mode) { | 312 FILE* OpenFile(const std::wstring& filename, const char* mode) { |
| 391 return OpenFile(FilePath::FromWStringHack(filename), mode); | 313 return OpenFile(FilePath::FromWStringHack(filename), mode); |
| 392 } | 314 } |
| 315 bool PathExists(const std::wstring& path) { |
| 316 return PathExists(FilePath::FromWStringHack(path)); |
| 317 } |
| 393 bool SetCurrentDirectory(const std::wstring& directory) { | 318 bool SetCurrentDirectory(const std::wstring& directory) { |
| 394 return SetCurrentDirectory(FilePath::FromWStringHack(directory)); | 319 return SetCurrentDirectory(FilePath::FromWStringHack(directory)); |
| 395 } | 320 } |
| 321 void TrimFilename(std::wstring* path) { |
| 322 if (EndsWithSeparator(path)) { |
| 323 TrimTrailingSeparator(path); |
| 324 } else { |
| 325 *path = FilePath::FromWStringHack(*path).DirName().ToWStringHack(); |
| 326 } |
| 327 } |
| 328 void UpOneDirectory(std::wstring* dir) { |
| 329 FilePath path = FilePath::FromWStringHack(*dir); |
| 330 *dir = path.DirName().ToWStringHack(); |
| 331 } |
| 332 void UpOneDirectoryOrEmpty(std::wstring* dir) { |
| 333 FilePath path = FilePath::FromWStringHack(*dir); |
| 334 FilePath directory = path.DirName(); |
| 396 | 335 |
| 336 if (directory == path) |
| 337 dir->clear(); |
| 338 else |
| 339 *dir = directory.ToWStringHack(); |
| 340 } |
| 397 } // namespace | 341 } // namespace |
| 398 | 342 |
| OLD | NEW |