Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(457)

Side by Side Diff: chrome/installer/util/delete_tree_work_item.cc

Issue 6538025: Temp dir cleanup:... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/delete_tree_work_item.h"
6
7 #include <algorithm>
8 #include <limits>
9
5 #include "base/file_util.h" 10 #include "base/file_util.h"
6 #include "base/logging.h" 11 #include "base/logging.h"
7 #include "chrome/installer/util/delete_tree_work_item.h" 12
13 namespace {
14
15 // Casts a value of an unsigned type to a signed type of the same size provided
16 // that there is no overflow.
17 template<typename L, typename R>
18 bool SafeCast(L left, R* right) {
19 DCHECK(right);
20 COMPILE_ASSERT(sizeof(left) == sizeof(right),
21 must_add_support_for_crazy_data_types);
22 if (left > static_cast<L>(std::numeric_limits<R>::max()))
23 return false;
24 *right = static_cast<L>(left);
25 return true;
26 }
27
28 } // namespace
8 29
9 DeleteTreeWorkItem::DeleteTreeWorkItem( 30 DeleteTreeWorkItem::DeleteTreeWorkItem(
10 const FilePath& root_path, 31 const FilePath& root_path,
32 const FilePath& temp_path,
11 const std::vector<FilePath>& key_paths) 33 const std::vector<FilePath>& key_paths)
12 : root_path_(root_path) { 34 : root_path_(root_path),
13 // Populate our key_paths_ list with empty backup path values. 35 temp_path_(temp_path) {
14 std::vector<FilePath>::const_iterator it(key_paths.begin()); 36 if (!SafeCast(key_paths.size(), &num_key_files_)) {
15 for (; it != key_paths.end(); ++it) { 37 NOTREACHED() << "Impossibly large key_paths collection";
16 key_paths_.push_back(KeyFileList::value_type(*it, FilePath())); 38 } else if (num_key_files_ != 0) {
39 key_paths_.reset(new FilePath[num_key_files_]);
40 key_backup_paths_.reset(new ScopedTempDir[num_key_files_]);
41 std::copy(key_paths.begin(), key_paths.end(), &key_paths_[0]);
17 } 42 }
18 } 43 }
19 44
20 DeleteTreeWorkItem::~DeleteTreeWorkItem() { 45 DeleteTreeWorkItem::~DeleteTreeWorkItem() {
21 if (!backup_path_.empty()) {
22 FilePath tmp_dir = backup_path_.DirName();
23 if (file_util::PathExists(tmp_dir)) {
24 file_util::Delete(tmp_dir, true);
25 }
26 }
27
28 KeyFileList::const_iterator it(key_paths_.begin());
29 for (; it != key_paths_.end(); ++it) {
30 if (!it->second.empty()) {
31 FilePath tmp_dir = it->second.DirName();
32 if (file_util::PathExists(tmp_dir)) {
33 file_util::Delete(tmp_dir, true);
34 }
35 }
36 }
37 } 46 }
38 47
39 // We first try to move key_path_ to backup_path. If it succeeds, we go ahead 48 // We first try to move key_path_ to backup_path. If it succeeds, we go ahead
40 // and move the rest. 49 // and move the rest.
41 bool DeleteTreeWorkItem::Do() { 50 bool DeleteTreeWorkItem::Do() {
42 // Go through all the key files and see if we can open them exclusively 51 // Go through all the key files and see if we can open them exclusively
43 // with only the FILE_SHARE_DELETE flag. Once we know we have all of them, 52 // with only the FILE_SHARE_DELETE flag. Once we know we have all of them,
44 // we can delete them. 53 // we can delete them.
45 KeyFileList::iterator it(key_paths_.begin());
46 std::vector<HANDLE> opened_key_files; 54 std::vector<HANDLE> opened_key_files;
55 opened_key_files.reserve(num_key_files_);
47 bool abort = false; 56 bool abort = false;
48 for (; !abort && it != key_paths_.end(); ++it) { 57 for (ptrdiff_t i = 0; !abort && i != num_key_files_; ++i) {
49 if (!GetBackupPath(it->first, &it->second) || 58 FilePath& key_file = key_paths_[i];
tommi (sloooow) - chröme 2011/02/17 20:00:49 key_file(key_paths[i])
grt (UTC plus 2) 2011/02/17 20:26:41 Disregarding as per our discussion since key_file
50 !file_util::CopyFile(it->first, it->second)) { 59 ScopedTempDir& backup = key_backup_paths_[i];
tommi (sloooow) - chröme 2011/02/17 20:00:49 ditto
grt (UTC plus 2) 2011/02/17 20:26:41 Disregarding as per our discussion since key_file
51 PLOG(ERROR) << "Could not back up: " << it->first.value(); 60 if (!key_backup_paths_[i].CreateUniqueTempDirUnderPath(temp_path_) ||
61 !file_util::CopyFile(key_file,
62 backup.path().Append(key_file.BaseName()))) {
63 PLOG(ERROR) << "Could not back up: " << key_file.value();
52 abort = true; 64 abort = true;
53 } else { 65 } else {
54 HANDLE file = ::CreateFile(it->first.value().c_str(), FILE_ALL_ACCESS, 66 HANDLE file = ::CreateFile(key_file.value().c_str(), FILE_ALL_ACCESS,
55 FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 67 FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0,
56 NULL); 68 NULL);
57 if (file != INVALID_HANDLE_VALUE) { 69 if (file != INVALID_HANDLE_VALUE) {
58 VLOG(1) << "Acquired exclusive lock for key file: " 70 VLOG(1) << "Acquired exclusive lock for key file: " << key_file.value();
59 << it->first.value();
60 opened_key_files.push_back(file); 71 opened_key_files.push_back(file);
61 } else { 72 } else {
62 if (::GetLastError() != ERROR_FILE_NOT_FOUND) 73 if (::GetLastError() != ERROR_FILE_NOT_FOUND)
63 abort = true; 74 abort = true;
64 PLOG(INFO) << "Failed to open " << it->first.value(); 75 PLOG(INFO) << "Failed to open " << key_file.value();
65 } 76 }
66 } 77 }
67 } 78 }
68 79
69 if (!abort) { 80 if (!abort) {
70 // We now hold exclusive locks with "share delete" permissions for each 81 // We now hold exclusive locks with "share delete" permissions for each
71 // of the key files and also have created backups of those files. 82 // of the key files and also have created backups of those files.
72 // We can safely delete the key files now. 83 // We can safely delete the key files now.
73 it = key_paths_.begin(); 84 for (ptrdiff_t i = 0; !abort && i != num_key_files_; ++i) {
74 for (; !abort && it != key_paths_.end(); ++it) { 85 FilePath& key_file = key_paths_[i];
75 if (!file_util::Delete(it->first, true)) { 86 if (!file_util::Delete(key_file, true)) {
76 // This should not really be possible because of the above. 87 // This should not really be possible because of the above.
77 NOTREACHED(); 88 PLOG(DFATAL) << "Unexpectedly could not delete " << key_file.value();
78 PLOG(ERROR) << "Unexpectedly could not delete " << it->first.value();
79 abort = true; 89 abort = true;
80 } 90 }
81 } 91 }
82 } 92 }
83 93
84 std::vector<HANDLE>::const_iterator file_it(opened_key_files.begin()); 94 std::for_each(opened_key_files.begin(), opened_key_files.end(), CloseHandle);
85 for (; file_it != opened_key_files.end(); ++file_it)
86 ::CloseHandle(*file_it);
87
88 opened_key_files.clear(); 95 opened_key_files.clear();
89 96
90 if (abort) { 97 if (abort) {
91 LOG(ERROR) << "Could not exclusively hold all key files."; 98 LOG(ERROR) << "Could not exclusively hold all key files.";
92 return false; 99 return false;
93 } 100 }
94 101
95 // Now that we've taken care of the key files, take care of the rest. 102 // Now that we've taken care of the key files, take care of the rest.
96 if (!root_path_.empty() && file_util::PathExists(root_path_)) { 103 if (!root_path_.empty() && file_util::PathExists(root_path_)) {
97 if (!GetBackupPath(root_path_, &backup_path_) || 104 if (!backup_path_.CreateUniqueTempDirUnderPath(temp_path_)) {
98 !file_util::CopyDirectory(root_path_, backup_path_, true) || 105 LOG(ERROR) << "Failed to get backup path in folder "
99 !file_util::Delete(root_path_, true)) { 106 << temp_path_.value();
100 LOG(ERROR) << "can not delete " << root_path_.value()
101 << " OR copy it to backup path " << backup_path_.value();
102 return false; 107 return false;
108 } else {
109 FilePath backup = backup_path_.path().Append(root_path_.BaseName());
110 if (!file_util::CopyDirectory(root_path_, backup, true) ||
111 !file_util::Delete(root_path_, true)) {
112 LOG(ERROR) << "can not delete " << root_path_.value()
113 << " OR copy it to backup path " << backup.value();
114 return false;
115 }
103 } 116 }
104 } 117 }
105 118
106 return true; 119 return true;
107 } 120 }
108 121
109 // If there are files in backup paths move them back. 122 // If there are files in backup paths move them back.
110 void DeleteTreeWorkItem::Rollback() { 123 void DeleteTreeWorkItem::Rollback() {
111 if (!backup_path_.empty() && file_util::PathExists(backup_path_)) { 124 if (!backup_path_.path().empty()) {
112 file_util::Move(backup_path_, root_path_); 125 FilePath backup = backup_path_.path().Append(root_path_.BaseName());
126 if (file_util::PathExists(backup))
127 file_util::Move(backup, root_path_);
113 } 128 }
114 129
115 KeyFileList::const_iterator it(key_paths_.begin()); 130 for (ptrdiff_t i = 0; i != num_key_files_; ++i) {
116 for (; it != key_paths_.end(); ++it) { 131 ScopedTempDir& backup_dir = key_backup_paths_[i];
117 if (!it->second.empty() && file_util::PathExists(it->second)) { 132 if (!backup_dir.path().empty()) {
118 if (!file_util::Move(it->second, it->first)) { 133 FilePath& key_file = key_paths_[i];
tommi (sloooow) - chröme 2011/02/17 20:00:49 dittos
grt (UTC plus 2) 2011/02/17 20:26:41 Disregarding ditto.
134 FilePath backup_file = backup_dir.path().Append(key_file.BaseName());
135 if (file_util::PathExists(backup_file) &&
136 !file_util::Move(backup_file, key_file)) {
119 // This could happen if we could not delete the key file to begin with. 137 // This could happen if we could not delete the key file to begin with.
120 PLOG(WARNING) << "Rollback: Failed to move backup file back in place: " 138 PLOG(WARNING) << "Rollback: Failed to move backup file back in place: "
121 << it->second.value() << " to " << it->first.value(); 139 << backup_file.value() << " to " << key_file.value();
122 } 140 }
123 } 141 }
124 } 142 }
125 } 143 }
126
127 bool DeleteTreeWorkItem::GetBackupPath(const FilePath& for_path,
128 FilePath* backup_path) {
129 if (!file_util::CreateNewTempDirectory(L"", backup_path)) {
130 // We assume that CreateNewTempDirectory() is doing its job well.
131 LOG(ERROR) << "Couldn't get backup path for delete.";
132 return false;
133 }
134
135 *backup_path = backup_path->Append(for_path.BaseName());
136 return true;
137 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698