| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/installer/util/copy_tree_work_item.h" | 5 #include "chrome/installer/util/copy_tree_work_item.h" |
| 6 | 6 |
| 7 #include <shlwapi.h> | 7 #include <shlwapi.h> |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "chrome/installer/util/logging_installer.h" | 9 #include "chrome/installer/util/logging_installer.h" |
| 10 | 10 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 temp_dir_(temp_dir), | 24 temp_dir_(temp_dir), |
| 25 overwrite_option_(overwrite_option), | 25 overwrite_option_(overwrite_option), |
| 26 alternative_path_(alternative_path), | 26 alternative_path_(alternative_path), |
| 27 copied_to_dest_path_(false), | 27 copied_to_dest_path_(false), |
| 28 moved_to_backup_(false), | 28 moved_to_backup_(false), |
| 29 copied_to_alternate_path_(false) { | 29 copied_to_alternate_path_(false) { |
| 30 } | 30 } |
| 31 | 31 |
| 32 bool CopyTreeWorkItem::Do() { | 32 bool CopyTreeWorkItem::Do() { |
| 33 if (!file_util::PathExists(source_path_)) { | 33 if (!file_util::PathExists(source_path_)) { |
| 34 LOG(ERROR) << source_path_ << " does not exist"; | 34 LOG(ERROR) << source_path_.value() << " does not exist"; |
| 35 return false; | 35 return false; |
| 36 } | 36 } |
| 37 | 37 |
| 38 bool dest_exist = file_util::PathExists(dest_path_); | 38 bool dest_exist = file_util::PathExists(dest_path_); |
| 39 // handle overwrite_option_ = IF_DIFFERENT case. | 39 // handle overwrite_option_ = IF_DIFFERENT case. |
| 40 if ((dest_exist) && | 40 if ((dest_exist) && |
| 41 (overwrite_option_ == WorkItem::IF_DIFFERENT) && // only for single file | 41 (overwrite_option_ == WorkItem::IF_DIFFERENT) && // only for single file |
| 42 (!PathIsDirectory(source_path_.c_str())) && | 42 (!file_util::DirectoryExists(source_path_)) && |
| 43 (!PathIsDirectory(dest_path_.c_str())) && | 43 (!file_util::DirectoryExists(dest_path_)) && |
| 44 (file_util::ContentsEqual(source_path_, dest_path_))) { | 44 (file_util::ContentsEqual(source_path_, dest_path_))) { |
| 45 LOG(INFO) << "Source file " << source_path_ | 45 LOG(INFO) << "Source file " << source_path_.value() |
| 46 << " and destination file " << dest_path_ | 46 << " and destination file " << dest_path_.value() |
| 47 << " are exactly same. Returning true."; | 47 << " are exactly same. Returning true."; |
| 48 return true; | 48 return true; |
| 49 } else if ((dest_exist) && | 49 } else if ((dest_exist) && |
| 50 (overwrite_option_ == WorkItem::NEW_NAME_IF_IN_USE) && | 50 (overwrite_option_ == WorkItem::NEW_NAME_IF_IN_USE) && |
| 51 (!PathIsDirectory(source_path_.c_str())) && | 51 (!file_util::DirectoryExists(source_path_)) && |
| 52 (!PathIsDirectory(dest_path_.c_str())) && | 52 (!file_util::DirectoryExists(dest_path_)) && |
| 53 (IsFileInUse(dest_path_))) { | 53 (IsFileInUse(dest_path_))) { |
| 54 // handle overwrite_option_ = NEW_NAME_IF_IN_USE case. | 54 // handle overwrite_option_ = NEW_NAME_IF_IN_USE case. |
| 55 if (alternative_path_.empty() || | 55 if (alternative_path_.empty() || |
| 56 file_util::PathExists(alternative_path_) || | 56 file_util::PathExists(alternative_path_) || |
| 57 !file_util::CopyFile(source_path_, alternative_path_)) { | 57 !file_util::CopyFile(source_path_, alternative_path_)) { |
| 58 LOG(ERROR) << "failed to copy " << source_path_ << | 58 LOG(ERROR) << "failed to copy " << source_path_.value() << |
| 59 " to " << alternative_path_; | 59 " to " << alternative_path_.value(); |
| 60 return false; | 60 return false; |
| 61 } else { | 61 } else { |
| 62 copied_to_alternate_path_ = true; | 62 copied_to_alternate_path_ = true; |
| 63 LOG(INFO) << "Copied source file " << source_path_ | 63 LOG(INFO) << "Copied source file " << source_path_.value() |
| 64 << " to alternative path " << alternative_path_; | 64 << " to alternative path " << alternative_path_.value(); |
| 65 return true; | 65 return true; |
| 66 } | 66 } |
| 67 } else if ((dest_exist) && | 67 } else if ((dest_exist) && |
| 68 (overwrite_option_ == WorkItem::IF_NOT_PRESENT)) { | 68 (overwrite_option_ == WorkItem::IF_NOT_PRESENT)) { |
| 69 // handle overwrite_option_ = IF_NOT_PRESENT case. | 69 // handle overwrite_option_ = IF_NOT_PRESENT case. |
| 70 return true; | 70 return true; |
| 71 } | 71 } |
| 72 | 72 |
| 73 // In all cases that reach here, move dest to a backup path. | 73 // In all cases that reach here, move dest to a backup path. |
| 74 if (dest_exist) { | 74 if (dest_exist) { |
| 75 if (!GetBackupPath()) | 75 if (!GetBackupPath()) |
| 76 return false; | 76 return false; |
| 77 | 77 |
| 78 if (file_util::Move(dest_path_, backup_path_)) { | 78 if (file_util::Move(dest_path_, backup_path_)) { |
| 79 moved_to_backup_ = true; | 79 moved_to_backup_ = true; |
| 80 LOG(INFO) << "Moved destination " << dest_path_ | 80 LOG(INFO) << "Moved destination " << dest_path_.value() << |
| 81 << " to backup path " << backup_path_; | 81 " to backup path " << backup_path_.value(); |
| 82 } else { | 82 } else { |
| 83 LOG(ERROR) << "failed moving " << dest_path_ << " to " << backup_path_; | 83 LOG(ERROR) << "failed moving " << dest_path_.value() << " to " << |
| 84 backup_path_.value(); |
| 84 return false; | 85 return false; |
| 85 } | 86 } |
| 86 } | 87 } |
| 87 | 88 |
| 88 // In all cases that reach here, copy source to destination. | 89 // In all cases that reach here, copy source to destination. |
| 89 if (file_util::CopyDirectory(source_path_, dest_path_, true)) { | 90 if (file_util::CopyDirectory(source_path_, dest_path_, true)) { |
| 90 copied_to_dest_path_ = true; | 91 copied_to_dest_path_ = true; |
| 91 LOG(INFO) << "Copied source " << source_path_ | 92 LOG(INFO) << "Copied source " << source_path_.value() |
| 92 << " to destination " << dest_path_; | 93 << " to destination " << dest_path_.value(); |
| 93 } else { | 94 } else { |
| 94 LOG(ERROR) << "failed copy " << source_path_ << " to " << dest_path_; | 95 LOG(ERROR) << "failed copy " << source_path_.value() << |
| 96 " to " << dest_path_.value(); |
| 95 return false; | 97 return false; |
| 96 } | 98 } |
| 97 | 99 |
| 98 return true; | 100 return true; |
| 99 } | 101 } |
| 100 | 102 |
| 101 void CopyTreeWorkItem::Rollback() { | 103 void CopyTreeWorkItem::Rollback() { |
| 102 // Normally the delete operations below should not fail unless some | 104 // Normally the delete operations below should not fail unless some |
| 103 // programs like anti-virus are inpecting the files we just copied. | 105 // programs like anti-virus are inpecting the files we just copied. |
| 104 // If this does happen sometimes, we may consider using Move instead of | 106 // If this does happen sometimes, we may consider using Move instead of |
| 105 // Delete here. For now we just log the error and continue with the | 107 // Delete here. For now we just log the error and continue with the |
| 106 // rest of rollback operation. | 108 // rest of rollback operation. |
| 107 if (copied_to_dest_path_ && !file_util::Delete(dest_path_, true)) { | 109 if (copied_to_dest_path_ && !file_util::Delete(dest_path_, true)) { |
| 108 LOG(ERROR) << "Can not delete " << dest_path_; | 110 LOG(ERROR) << "Can not delete " << dest_path_.value(); |
| 109 } | 111 } |
| 110 if (moved_to_backup_ && !file_util::Move(backup_path_, dest_path_)) { | 112 if (moved_to_backup_ && !file_util::Move(backup_path_, dest_path_)) { |
| 111 LOG(ERROR) << "failed move " << backup_path_ << " to " << dest_path_; | 113 LOG(ERROR) << "failed move " << backup_path_.value() << " to " << |
| 114 dest_path_.value(); |
| 112 } | 115 } |
| 113 if (copied_to_alternate_path_ && | 116 if (copied_to_alternate_path_ && |
| 114 !file_util::Delete(alternative_path_, true)) { | 117 !file_util::Delete(alternative_path_, true)) { |
| 115 LOG(ERROR) << "Can not delete " << alternative_path_; | 118 LOG(ERROR) << "Can not delete " << alternative_path_.value(); |
| 116 } | 119 } |
| 117 } | 120 } |
| 118 | 121 |
| 119 bool CopyTreeWorkItem::IsFileInUse(const std::wstring& path) { | 122 bool CopyTreeWorkItem::IsFileInUse(const FilePath& path) { |
| 120 if (!file_util::PathExists(path)) | 123 if (!file_util::PathExists(path)) |
| 121 return false; | 124 return false; |
| 122 | 125 |
| 123 HANDLE handle = ::CreateFile(path.c_str(), FILE_ALL_ACCESS, | 126 HANDLE handle = ::CreateFile(path.value().c_str(), FILE_ALL_ACCESS, |
| 124 NULL, NULL, OPEN_EXISTING, NULL, NULL); | 127 NULL, NULL, OPEN_EXISTING, NULL, NULL); |
| 125 if (handle == INVALID_HANDLE_VALUE) | 128 if (handle == INVALID_HANDLE_VALUE) |
| 126 return true; | 129 return true; |
| 127 | 130 |
| 128 CloseHandle(handle); | 131 CloseHandle(handle); |
| 129 return false; | 132 return false; |
| 130 } | 133 } |
| 131 | 134 |
| 132 bool CopyTreeWorkItem::GetBackupPath() { | 135 bool CopyTreeWorkItem::GetBackupPath() { |
| 133 std::wstring file_name = file_util::GetFilenameFromPath(dest_path_); | 136 backup_path_ = temp_dir_.Append(dest_path_.BaseName()); |
| 134 backup_path_.assign(temp_dir_); | |
| 135 file_util::AppendToPath(&backup_path_, file_name); | |
| 136 | 137 |
| 137 if (file_util::PathExists(backup_path_)) { | 138 if (file_util::PathExists(backup_path_)) { |
| 138 // Ideally we should not fail immediately. Instead we could try some | 139 // Ideally we should not fail immediately. Instead we could try some |
| 139 // random paths under temp_dir_ until we reach certain limit. | 140 // random paths under temp_dir_ until we reach certain limit. |
| 140 // For now our caller always provides a good temporary directory so | 141 // For now our caller always provides a good temporary directory so |
| 141 // we don't bother. | 142 // we don't bother. |
| 142 LOG(ERROR) << "backup path " << backup_path_ << " already exists"; | 143 LOG(ERROR) << "backup path " << backup_path_.value() << " already exists"; |
| 143 return false; | 144 return false; |
| 144 } | 145 } |
| 145 | 146 |
| 146 return true; | 147 return true; |
| 147 } | 148 } |
| OLD | NEW |