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

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>
robertshield 2011/02/18 13:48:18 This is cool, but seems to exist only because num_
grt (UTC plus 2) 2011/02/18 14:12:31 Your cool is my annoying. You're right about the
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];
50 !file_util::CopyFile(it->first, it->second)) { 59 ScopedTempDir& backup = key_backup_paths_[i];
51 PLOG(ERROR) << "Could not back up: " << it->first.value(); 60 if (!backup.CreateUniqueTempDirUnderPath(temp_path_)) {
61 PLOG(ERROR) << "Could not create temp dir in " << temp_path_.value();
62 abort = true;
63 } else if (!file_util::CopyFile(key_file,
64 backup.path().Append(key_file.BaseName()))) {
65 PLOG(ERROR) << "Could not back up " << key_file.value()
66 << " to directory " << backup.path().value();
52 abort = true; 67 abort = true;
53 } else { 68 } else {
54 HANDLE file = ::CreateFile(it->first.value().c_str(), FILE_ALL_ACCESS, 69 HANDLE file = ::CreateFile(key_file.value().c_str(), FILE_ALL_ACCESS,
55 FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 70 FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0,
56 NULL); 71 NULL);
57 if (file != INVALID_HANDLE_VALUE) { 72 if (file != INVALID_HANDLE_VALUE) {
58 VLOG(1) << "Acquired exclusive lock for key file: " 73 VLOG(1) << "Acquired exclusive lock for key file: " << key_file.value();
59 << it->first.value();
60 opened_key_files.push_back(file); 74 opened_key_files.push_back(file);
61 } else { 75 } else {
62 if (::GetLastError() != ERROR_FILE_NOT_FOUND) 76 if (::GetLastError() != ERROR_FILE_NOT_FOUND)
63 abort = true; 77 abort = true;
64 PLOG(INFO) << "Failed to open " << it->first.value(); 78 PLOG(INFO) << "Failed to open " << key_file.value();
65 } 79 }
66 } 80 }
67 } 81 }
68 82
69 if (!abort) { 83 if (!abort) {
70 // We now hold exclusive locks with "share delete" permissions for each 84 // We now hold exclusive locks with "share delete" permissions for each
71 // of the key files and also have created backups of those files. 85 // of the key files and also have created backups of those files.
72 // We can safely delete the key files now. 86 // We can safely delete the key files now.
73 it = key_paths_.begin(); 87 for (ptrdiff_t i = 0; !abort && i != num_key_files_; ++i) {
74 for (; !abort && it != key_paths_.end(); ++it) { 88 FilePath& key_file = key_paths_[i];
75 if (!file_util::Delete(it->first, true)) { 89 if (!file_util::Delete(key_file, true)) {
76 // This should not really be possible because of the above. 90 // This should not really be possible because of the above.
77 NOTREACHED(); 91 PLOG(DFATAL) << "Unexpectedly could not delete " << key_file.value();
78 PLOG(ERROR) << "Unexpectedly could not delete " << it->first.value();
79 abort = true; 92 abort = true;
80 } 93 }
81 } 94 }
82 } 95 }
83 96
84 std::vector<HANDLE>::const_iterator file_it(opened_key_files.begin()); 97 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(); 98 opened_key_files.clear();
89 99
90 if (abort) { 100 if (abort) {
91 LOG(ERROR) << "Could not exclusively hold all key files."; 101 LOG(ERROR) << "Could not exclusively hold all key files.";
92 return false; 102 return false;
93 } 103 }
94 104
95 // Now that we've taken care of the key files, take care of the rest. 105 // 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_)) { 106 if (!root_path_.empty() && file_util::PathExists(root_path_)) {
97 if (!GetBackupPath(root_path_, &backup_path_) || 107 if (!backup_path_.CreateUniqueTempDirUnderPath(temp_path_)) {
98 !file_util::CopyDirectory(root_path_, backup_path_, true) || 108 PLOG(ERROR) << "Failed to get backup path in folder "
99 !file_util::Delete(root_path_, true)) { 109 << 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; 110 return false;
111 } else {
112 FilePath backup = backup_path_.path().Append(root_path_.BaseName());
113 if (!file_util::CopyDirectory(root_path_, backup, true) ||
114 !file_util::Delete(root_path_, true)) {
115 LOG(ERROR) << "can not delete " << root_path_.value()
116 << " OR copy it to backup path " << backup.value();
117 return false;
118 }
103 } 119 }
104 } 120 }
105 121
106 return true; 122 return true;
107 } 123 }
108 124
109 // If there are files in backup paths move them back. 125 // If there are files in backup paths move them back.
110 void DeleteTreeWorkItem::Rollback() { 126 void DeleteTreeWorkItem::Rollback() {
111 if (!backup_path_.empty() && file_util::PathExists(backup_path_)) { 127 if (!backup_path_.path().empty()) {
112 file_util::Move(backup_path_, root_path_); 128 FilePath backup = backup_path_.path().Append(root_path_.BaseName());
129 if (file_util::PathExists(backup))
130 file_util::Move(backup, root_path_);
113 } 131 }
114 132
115 KeyFileList::const_iterator it(key_paths_.begin()); 133 for (ptrdiff_t i = 0; i != num_key_files_; ++i) {
116 for (; it != key_paths_.end(); ++it) { 134 ScopedTempDir& backup_dir = key_backup_paths_[i];
117 if (!it->second.empty() && file_util::PathExists(it->second)) { 135 if (!backup_dir.path().empty()) {
118 if (!file_util::Move(it->second, it->first)) { 136 FilePath& key_file = key_paths_[i];
137 FilePath backup_file = backup_dir.path().Append(key_file.BaseName());
138 if (file_util::PathExists(backup_file) &&
139 !file_util::Move(backup_file, key_file)) {
119 // This could happen if we could not delete the key file to begin with. 140 // 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: " 141 PLOG(WARNING) << "Rollback: Failed to move backup file back in place: "
121 << it->second.value() << " to " << it->first.value(); 142 << backup_file.value() << " to " << key_file.value();
122 } 143 }
123 } 144 }
124 } 145 }
125 } 146 }
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
« no previous file with comments | « chrome/installer/util/delete_tree_work_item.h ('k') | chrome/installer/util/delete_tree_work_item_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698