Index: base/file_util_win.cc |
diff --git a/base/file_util_win.cc b/base/file_util_win.cc |
index 2a56ea9468485f60ffc887b0e496d68467e03b78..928b66e525b16bd0f70426a0f625067a8a854ffc 100644 |
--- a/base/file_util_win.cc |
+++ b/base/file_util_win.cc |
@@ -34,6 +34,44 @@ namespace { |
const DWORD kFileShareAll = |
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; |
+bool ShellCopy(const FilePath& from_path, |
+ const FilePath& to_path, |
+ bool recursive) { |
+ // WinXP SHFileOperation doesn't like trailing separators. |
+ FilePath stripped_from = from_path.StripTrailingSeparators(); |
+ FilePath stripped_to = to_path.StripTrailingSeparators(); |
+ |
+ ThreadRestrictions::AssertIOAllowed(); |
+ |
+ // NOTE: I suspect we could support longer paths, but that would involve |
+ // analyzing all our usage of files. |
+ if (stripped_from.value().length() >= MAX_PATH || |
+ stripped_to.value().length() >= MAX_PATH) { |
+ return false; |
+ } |
+ |
+ // SHFILEOPSTRUCT wants the path to be terminated with two NULLs, |
+ // so we have to use wcscpy because wcscpy_s writes non-NULLs |
+ // into the rest of the buffer. |
+ wchar_t double_terminated_path_from[MAX_PATH + 1] = {0}; |
+ wchar_t double_terminated_path_to[MAX_PATH + 1] = {0}; |
+#pragma warning(suppress:4996) // don't complain about wcscpy deprecation |
+ wcscpy(double_terminated_path_from, stripped_from.value().c_str()); |
+#pragma warning(suppress:4996) // don't complain about wcscpy deprecation |
+ wcscpy(double_terminated_path_to, stripped_to.value().c_str()); |
+ |
+ SHFILEOPSTRUCT file_operation = {0}; |
+ file_operation.wFunc = FO_COPY; |
+ file_operation.pFrom = double_terminated_path_from; |
+ file_operation.pTo = double_terminated_path_to; |
+ file_operation.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION | |
+ FOF_NOCONFIRMMKDIR; |
+ if (!recursive) |
+ file_operation.fFlags |= FOF_NORECURSION | FOF_FILESONLY; |
+ |
+ return (SHFileOperation(&file_operation) == 0); |
+} |
+ |
} // namespace |
FilePath MakeAbsoluteFilePath(const FilePath& input) { |
@@ -109,40 +147,6 @@ bool DeleteAfterReboot(const FilePath& path) { |
MOVEFILE_REPLACE_EXISTING) != FALSE; |
} |
-bool MoveUnsafe(const FilePath& from_path, const FilePath& to_path) { |
- ThreadRestrictions::AssertIOAllowed(); |
- |
- // NOTE: I suspect we could support longer paths, but that would involve |
- // analyzing all our usage of files. |
- if (from_path.value().length() >= MAX_PATH || |
- to_path.value().length() >= MAX_PATH) { |
- return false; |
- } |
- if (MoveFileEx(from_path.value().c_str(), to_path.value().c_str(), |
- MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) != 0) |
- return true; |
- |
- // Keep the last error value from MoveFileEx around in case the below |
- // fails. |
- bool ret = false; |
- DWORD last_error = ::GetLastError(); |
- |
- if (file_util::DirectoryExists(from_path)) { |
- // MoveFileEx fails if moving directory across volumes. We will simulate |
- // the move by using Copy and Delete. Ideally we could check whether |
- // from_path and to_path are indeed in different volumes. |
- ret = file_util::CopyAndDeleteDirectory(from_path, to_path); |
- } |
- |
- if (!ret) { |
- // Leave a clue about what went wrong so that it can be (at least) picked |
- // up by a PLOG entry. |
- ::SetLastError(last_error); |
- } |
- |
- return ret; |
-} |
- |
bool ReplaceFile(const FilePath& from_path, |
const FilePath& to_path, |
PlatformFileError* error) { |
@@ -164,82 +168,23 @@ bool ReplaceFile(const FilePath& from_path, |
return false; |
} |
-} // namespace base |
- |
-// ----------------------------------------------------------------------------- |
- |
-namespace file_util { |
- |
-using base::FilePath; |
-using base::kFileShareAll; |
- |
-bool CopyFileUnsafe(const FilePath& from_path, const FilePath& to_path) { |
- base::ThreadRestrictions::AssertIOAllowed(); |
- |
- // NOTE: I suspect we could support longer paths, but that would involve |
- // analyzing all our usage of files. |
- if (from_path.value().length() >= MAX_PATH || |
- to_path.value().length() >= MAX_PATH) { |
- return false; |
- } |
- return (::CopyFile(from_path.value().c_str(), to_path.value().c_str(), |
- false) != 0); |
-} |
- |
-bool ShellCopy(const FilePath& from_path, const FilePath& to_path, |
- bool recursive) { |
- // WinXP SHFileOperation doesn't like trailing separators. |
- FilePath stripped_from = from_path.StripTrailingSeparators(); |
- FilePath stripped_to = to_path.StripTrailingSeparators(); |
- |
- base::ThreadRestrictions::AssertIOAllowed(); |
- |
- // NOTE: I suspect we could support longer paths, but that would involve |
- // analyzing all our usage of files. |
- if (stripped_from.value().length() >= MAX_PATH || |
- stripped_to.value().length() >= MAX_PATH) { |
- return false; |
- } |
- |
- // SHFILEOPSTRUCT wants the path to be terminated with two NULLs, |
- // so we have to use wcscpy because wcscpy_s writes non-NULLs |
- // into the rest of the buffer. |
- wchar_t double_terminated_path_from[MAX_PATH + 1] = {0}; |
- wchar_t double_terminated_path_to[MAX_PATH + 1] = {0}; |
-#pragma warning(suppress:4996) // don't complain about wcscpy deprecation |
- wcscpy(double_terminated_path_from, stripped_from.value().c_str()); |
-#pragma warning(suppress:4996) // don't complain about wcscpy deprecation |
- wcscpy(double_terminated_path_to, stripped_to.value().c_str()); |
- |
- SHFILEOPSTRUCT file_operation = {0}; |
- file_operation.wFunc = FO_COPY; |
- file_operation.pFrom = double_terminated_path_from; |
- file_operation.pTo = double_terminated_path_to; |
- file_operation.fFlags = FOF_NOERRORUI | FOF_SILENT | FOF_NOCONFIRMATION | |
- FOF_NOCONFIRMMKDIR; |
- if (!recursive) |
- file_operation.fFlags |= FOF_NORECURSION | FOF_FILESONLY; |
- |
- return (SHFileOperation(&file_operation) == 0); |
-} |
- |
bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, |
bool recursive) { |
- base::ThreadRestrictions::AssertIOAllowed(); |
+ ThreadRestrictions::AssertIOAllowed(); |
if (recursive) |
return ShellCopy(from_path, to_path, true); |
// The following code assumes that from path is a directory. |
- DCHECK(DirectoryExists(from_path)); |
+ DCHECK(file_util::DirectoryExists(from_path)); |
// Instead of creating a new directory, we copy the old one to include the |
// security information of the folder as part of the copy. |
- if (!PathExists(to_path)) { |
+ if (!file_util::PathExists(to_path)) { |
// Except that Vista fails to do that, and instead do a recursive copy if |
// the target directory doesn't exist. |
if (base::win::GetVersion() >= base::win::VERSION_VISTA) |
- CreateDirectory(to_path); |
+ file_util::CreateDirectory(to_path); |
else |
ShellCopy(from_path, to_path, false); |
} |
@@ -248,21 +193,14 @@ bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, |
return ShellCopy(directory, to_path, false); |
} |
-bool CopyAndDeleteDirectory(const FilePath& from_path, |
- const FilePath& to_path) { |
- base::ThreadRestrictions::AssertIOAllowed(); |
- if (CopyDirectory(from_path, to_path, true)) { |
- if (Delete(from_path, true)) { |
- return true; |
- } |
- // Like Move, this function is not transactional, so we just |
- // leave the copied bits behind if deleting from_path fails. |
- // If to_path exists previously then we have already overwritten |
- // it by now, we don't get better off by deleting the new bits. |
- } |
- return false; |
-} |
+} // namespace base |
+ |
+// ----------------------------------------------------------------------------- |
+ |
+namespace file_util { |
+using base::FilePath; |
+using base::kFileShareAll; |
bool PathExists(const FilePath& path) { |
base::ThreadRestrictions::AssertIOAllowed(); |
@@ -750,3 +688,71 @@ int GetMaximumPathComponentLength(const FilePath& path) { |
} |
} // namespace file_util |
+ |
+namespace base { |
+namespace internal { |
+ |
+bool MoveUnsafe(const FilePath& from_path, const FilePath& to_path) { |
+ ThreadRestrictions::AssertIOAllowed(); |
+ |
+ // NOTE: I suspect we could support longer paths, but that would involve |
+ // analyzing all our usage of files. |
+ if (from_path.value().length() >= MAX_PATH || |
+ to_path.value().length() >= MAX_PATH) { |
+ return false; |
+ } |
+ if (MoveFileEx(from_path.value().c_str(), to_path.value().c_str(), |
+ MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING) != 0) |
+ return true; |
+ |
+ // Keep the last error value from MoveFileEx around in case the below |
+ // fails. |
+ bool ret = false; |
+ DWORD last_error = ::GetLastError(); |
+ |
+ if (file_util::DirectoryExists(from_path)) { |
+ // MoveFileEx fails if moving directory across volumes. We will simulate |
+ // the move by using Copy and Delete. Ideally we could check whether |
+ // from_path and to_path are indeed in different volumes. |
+ ret = internal::CopyAndDeleteDirectory(from_path, to_path); |
+ } |
+ |
+ if (!ret) { |
+ // Leave a clue about what went wrong so that it can be (at least) picked |
+ // up by a PLOG entry. |
+ ::SetLastError(last_error); |
+ } |
+ |
+ return ret; |
+} |
+ |
+bool CopyFileUnsafe(const FilePath& from_path, const FilePath& to_path) { |
+ ThreadRestrictions::AssertIOAllowed(); |
+ |
+ // NOTE: I suspect we could support longer paths, but that would involve |
+ // analyzing all our usage of files. |
+ if (from_path.value().length() >= MAX_PATH || |
+ to_path.value().length() >= MAX_PATH) { |
+ return false; |
+ } |
+ return (::CopyFile(from_path.value().c_str(), to_path.value().c_str(), |
+ false) != 0); |
+} |
+ |
+bool CopyAndDeleteDirectory(const FilePath& from_path, |
+ const FilePath& to_path) { |
+ ThreadRestrictions::AssertIOAllowed(); |
+ if (CopyDirectory(from_path, to_path, true)) { |
+ if (Delete(from_path, true)) |
+ return true; |
+ |
+ // Like Move, this function is not transactional, so we just |
+ // leave the copied bits behind if deleting from_path fails. |
+ // If to_path exists previously then we have already overwritten |
+ // it by now, we don't get better off by deleting the new bits. |
+ } |
+ return false; |
+} |
+ |
+} // namespace internal |
+} // namespace base |