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_.value() << " does not exist"; | 34 LOG(ERROR) << source_path_ << " 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 (!file_util::DirectoryExists(source_path_)) && | 42 (!PathIsDirectory(source_path_.c_str())) && |
43 (!file_util::DirectoryExists(dest_path_)) && | 43 (!PathIsDirectory(dest_path_.c_str())) && |
44 (file_util::ContentsEqual(source_path_, dest_path_))) { | 44 (file_util::ContentsEqual(source_path_, dest_path_))) { |
45 LOG(INFO) << "Source file " << source_path_.value() | 45 LOG(INFO) << "Source file " << source_path_ |
46 << " and destination file " << dest_path_.value() | 46 << " and destination file " << dest_path_ |
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 (!file_util::DirectoryExists(source_path_)) && | 51 (!PathIsDirectory(source_path_.c_str())) && |
52 (!file_util::DirectoryExists(dest_path_)) && | 52 (!PathIsDirectory(dest_path_.c_str())) && |
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_.value() << | 58 LOG(ERROR) << "failed to copy " << source_path_ << |
59 " to " << alternative_path_.value(); | 59 " to " << alternative_path_; |
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_.value() | 63 LOG(INFO) << "Copied source file " << source_path_ |
64 << " to alternative path " << alternative_path_.value(); | 64 << " to alternative path " << alternative_path_; |
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_.value() << | 80 LOG(INFO) << "Moved destination " << dest_path_ |
81 " to backup path " << backup_path_.value(); | 81 << " to backup path " << backup_path_; |
82 } else { | 82 } else { |
83 LOG(ERROR) << "failed moving " << dest_path_.value() << " to " << | 83 LOG(ERROR) << "failed moving " << dest_path_ << " to " << backup_path_; |
84 backup_path_.value(); | |
85 return false; | 84 return false; |
86 } | 85 } |
87 } | 86 } |
88 | 87 |
89 // In all cases that reach here, copy source to destination. | 88 // In all cases that reach here, copy source to destination. |
90 if (file_util::CopyDirectory(source_path_, dest_path_, true)) { | 89 if (file_util::CopyDirectory(source_path_, dest_path_, true)) { |
91 copied_to_dest_path_ = true; | 90 copied_to_dest_path_ = true; |
92 LOG(INFO) << "Copied source " << source_path_.value() | 91 LOG(INFO) << "Copied source " << source_path_ |
93 << " to destination " << dest_path_.value(); | 92 << " to destination " << dest_path_; |
94 } else { | 93 } else { |
95 LOG(ERROR) << "failed copy " << source_path_.value() << | 94 LOG(ERROR) << "failed copy " << source_path_ << " to " << dest_path_; |
96 " to " << dest_path_.value(); | |
97 return false; | 95 return false; |
98 } | 96 } |
99 | 97 |
100 return true; | 98 return true; |
101 } | 99 } |
102 | 100 |
103 void CopyTreeWorkItem::Rollback() { | 101 void CopyTreeWorkItem::Rollback() { |
104 // Normally the delete operations below should not fail unless some | 102 // Normally the delete operations below should not fail unless some |
105 // programs like anti-virus are inpecting the files we just copied. | 103 // programs like anti-virus are inpecting the files we just copied. |
106 // If this does happen sometimes, we may consider using Move instead of | 104 // If this does happen sometimes, we may consider using Move instead of |
107 // Delete here. For now we just log the error and continue with the | 105 // Delete here. For now we just log the error and continue with the |
108 // rest of rollback operation. | 106 // rest of rollback operation. |
109 if (copied_to_dest_path_ && !file_util::Delete(dest_path_, true)) { | 107 if (copied_to_dest_path_ && !file_util::Delete(dest_path_, true)) { |
110 LOG(ERROR) << "Can not delete " << dest_path_.value(); | 108 LOG(ERROR) << "Can not delete " << dest_path_; |
111 } | 109 } |
112 if (moved_to_backup_ && !file_util::Move(backup_path_, dest_path_)) { | 110 if (moved_to_backup_ && !file_util::Move(backup_path_, dest_path_)) { |
113 LOG(ERROR) << "failed move " << backup_path_.value() << " to " << | 111 LOG(ERROR) << "failed move " << backup_path_ << " to " << dest_path_; |
114 dest_path_.value(); | |
115 } | 112 } |
116 if (copied_to_alternate_path_ && | 113 if (copied_to_alternate_path_ && |
117 !file_util::Delete(alternative_path_, true)) { | 114 !file_util::Delete(alternative_path_, true)) { |
118 LOG(ERROR) << "Can not delete " << alternative_path_.value(); | 115 LOG(ERROR) << "Can not delete " << alternative_path_; |
119 } | 116 } |
120 } | 117 } |
121 | 118 |
122 bool CopyTreeWorkItem::IsFileInUse(const FilePath& path) { | 119 bool CopyTreeWorkItem::IsFileInUse(const std::wstring& path) { |
123 if (!file_util::PathExists(path)) | 120 if (!file_util::PathExists(path)) |
124 return false; | 121 return false; |
125 | 122 |
126 HANDLE handle = ::CreateFile(path.value().c_str(), FILE_ALL_ACCESS, | 123 HANDLE handle = ::CreateFile(path.c_str(), FILE_ALL_ACCESS, |
127 NULL, NULL, OPEN_EXISTING, NULL, NULL); | 124 NULL, NULL, OPEN_EXISTING, NULL, NULL); |
128 if (handle == INVALID_HANDLE_VALUE) | 125 if (handle == INVALID_HANDLE_VALUE) |
129 return true; | 126 return true; |
130 | 127 |
131 CloseHandle(handle); | 128 CloseHandle(handle); |
132 return false; | 129 return false; |
133 } | 130 } |
134 | 131 |
135 bool CopyTreeWorkItem::GetBackupPath() { | 132 bool CopyTreeWorkItem::GetBackupPath() { |
136 backup_path_ = temp_dir_.Append(dest_path_.BaseName()); | 133 std::wstring file_name = file_util::GetFilenameFromPath(dest_path_); |
| 134 backup_path_.assign(temp_dir_); |
| 135 file_util::AppendToPath(&backup_path_, file_name); |
137 | 136 |
138 if (file_util::PathExists(backup_path_)) { | 137 if (file_util::PathExists(backup_path_)) { |
139 // Ideally we should not fail immediately. Instead we could try some | 138 // Ideally we should not fail immediately. Instead we could try some |
140 // random paths under temp_dir_ until we reach certain limit. | 139 // random paths under temp_dir_ until we reach certain limit. |
141 // For now our caller always provides a good temporary directory so | 140 // For now our caller always provides a good temporary directory so |
142 // we don't bother. | 141 // we don't bother. |
143 LOG(ERROR) << "backup path " << backup_path_.value() << " already exists"; | 142 LOG(ERROR) << "backup path " << backup_path_ << " already exists"; |
144 return false; | 143 return false; |
145 } | 144 } |
146 | 145 |
147 return true; | 146 return true; |
148 } | 147 } |
OLD | NEW |