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 |