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

Side by Side Diff: chrome/installer/util/copy_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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "chrome/installer/util/logging_installer.h" 11 #include "chrome/installer/util/logging_installer.h"
12 12
13 CopyTreeWorkItem::~CopyTreeWorkItem() { 13 CopyTreeWorkItem::~CopyTreeWorkItem() {
14 if (file_util::PathExists(backup_path_)) {
15 file_util::Delete(backup_path_, true);
16 }
17 } 14 }
18 15
19 CopyTreeWorkItem::CopyTreeWorkItem(const FilePath& source_path, 16 CopyTreeWorkItem::CopyTreeWorkItem(const FilePath& source_path,
20 const FilePath& dest_path, 17 const FilePath& dest_path,
21 const FilePath& temp_dir, 18 const FilePath& temp_dir,
22 CopyOverWriteOption overwrite_option, 19 CopyOverWriteOption overwrite_option,
23 const FilePath& alternative_path) 20 const FilePath& alternative_path)
24 : source_path_(source_path), 21 : source_path_(source_path),
25 dest_path_(dest_path), 22 dest_path_(dest_path),
26 temp_dir_(temp_dir), 23 temp_dir_(temp_dir),
27 overwrite_option_(overwrite_option), 24 overwrite_option_(overwrite_option),
28 alternative_path_(alternative_path), 25 alternative_path_(alternative_path),
29 copied_to_dest_path_(false), 26 copied_to_dest_path_(false),
30 moved_to_backup_(false), 27 moved_to_backup_(false),
31 copied_to_alternate_path_(false) { 28 copied_to_alternate_path_(false) {
32 } 29 }
33 30
34 bool CopyTreeWorkItem::Do() { 31 bool CopyTreeWorkItem::Do() {
35 if (!file_util::PathExists(source_path_)) { 32 if (!file_util::PathExists(source_path_)) {
36 LOG(ERROR) << source_path_.value() << " does not exist"; 33 LOG(ERROR) << source_path_.value() << " does not exist";
37 return false; 34 return false;
38 } 35 }
39 36
40 bool dest_exist = file_util::PathExists(dest_path_); 37 bool dest_exist = file_util::PathExists(dest_path_);
41 // handle overwrite_option_ = IF_DIFFERENT case. 38 // handle overwrite_option_ = IF_DIFFERENT case.
42 if ((dest_exist) && 39 if ((dest_exist) &&
43 (overwrite_option_ == WorkItem::IF_DIFFERENT) && // only for single file 40 (overwrite_option_ == WorkItem::IF_DIFFERENT) && // only for single file
44 (!file_util::DirectoryExists(source_path_)) && 41 (!file_util::DirectoryExists(source_path_)) &&
45 (!file_util::DirectoryExists(dest_path_)) && 42 (!file_util::DirectoryExists(dest_path_)) &&
46 (file_util::ContentsEqual(source_path_, dest_path_))) { 43 (file_util::ContentsEqual(source_path_, dest_path_))) {
47 VLOG(1) << "Source file " << source_path_.value() 44 VLOG(1) << "Source file " << source_path_.value()
48 << " and destination file " << dest_path_.value() 45 << " and destination file " << dest_path_.value()
49 << " are exactly same. Returning true."; 46 << " are exactly same. Returning true.";
50 return true; 47 return true;
51 } else if ((dest_exist) && 48 } else if ((dest_exist) &&
52 (overwrite_option_ == WorkItem::NEW_NAME_IF_IN_USE) && 49 (overwrite_option_ == WorkItem::NEW_NAME_IF_IN_USE) &&
53 (!file_util::DirectoryExists(source_path_)) && 50 (!file_util::DirectoryExists(source_path_)) &&
(...skipping 13 matching lines...) Expand all
67 return true; 64 return true;
68 } 65 }
69 } else if ((dest_exist) && 66 } else if ((dest_exist) &&
70 (overwrite_option_ == WorkItem::IF_NOT_PRESENT)) { 67 (overwrite_option_ == WorkItem::IF_NOT_PRESENT)) {
71 // handle overwrite_option_ = IF_NOT_PRESENT case. 68 // handle overwrite_option_ = IF_NOT_PRESENT case.
72 return true; 69 return true;
73 } 70 }
74 71
75 // In all cases that reach here, move dest to a backup path. 72 // In all cases that reach here, move dest to a backup path.
76 if (dest_exist) { 73 if (dest_exist) {
77 if (!GetBackupPath()) 74 if (!backup_path_.CreateUniqueTempDirUnderPath(temp_dir_)) {
75 LOG(ERROR) << "Failed to get backup path in folder " << temp_dir_.value();
tommi (sloooow) - chröme 2011/02/17 20:00:49 PLOG
grt (UTC plus 2) 2011/02/17 20:26:41 Done.
78 return false; 76 return false;
77 }
79 78
80 if (file_util::Move(dest_path_, backup_path_)) { 79 FilePath backup = backup_path_.path().Append(dest_path_.BaseName());
80 if (file_util::Move(dest_path_, backup)) {
81 moved_to_backup_ = true; 81 moved_to_backup_ = true;
82 VLOG(1) << "Moved destination " << dest_path_.value() << 82 VLOG(1) << "Moved destination " << dest_path_.value() <<
83 " to backup path " << backup_path_.value(); 83 " to backup path " << backup.value();
84 } else { 84 } else {
85 LOG(ERROR) << "failed moving " << dest_path_.value() 85 LOG(ERROR) << "failed moving " << dest_path_.value()
tommi (sloooow) - chröme 2011/02/17 20:00:49 I think PLOG would also be useful here (MoveFileEx
grt (UTC plus 2) 2011/02/17 20:26:41 Agreed, but I've found through experimentation tha
86 << " to " << backup_path_.value(); 86 << " to " << backup.value();
87 return false; 87 return false;
88 } 88 }
89 } 89 }
90 90
91 // In all cases that reach here, copy source to destination. 91 // In all cases that reach here, copy source to destination.
92 if (file_util::CopyDirectory(source_path_, dest_path_, true)) { 92 if (file_util::CopyDirectory(source_path_, dest_path_, true)) {
93 copied_to_dest_path_ = true; 93 copied_to_dest_path_ = true;
94 VLOG(1) << "Copied source " << source_path_.value() 94 VLOG(1) << "Copied source " << source_path_.value()
95 << " to destination " << dest_path_.value(); 95 << " to destination " << dest_path_.value();
96 } else { 96 } else {
97 LOG(ERROR) << "failed copy " << source_path_.value() 97 LOG(ERROR) << "failed copy " << source_path_.value()
98 << " to " << dest_path_.value(); 98 << " to " << dest_path_.value();
99 return false; 99 return false;
100 } 100 }
101 101
102 return true; 102 return true;
103 } 103 }
104 104
105 void CopyTreeWorkItem::Rollback() { 105 void CopyTreeWorkItem::Rollback() {
106 // Normally the delete operations below should not fail unless some 106 // Normally the delete operations below should not fail unless some
107 // programs like anti-virus are inpecting the files we just copied. 107 // programs like anti-virus are inspecting the files we just copied.
108 // If this does happen sometimes, we may consider using Move instead of 108 // If this does happen sometimes, we may consider using Move instead of
109 // Delete here. For now we just log the error and continue with the 109 // Delete here. For now we just log the error and continue with the
110 // rest of rollback operation. 110 // rest of rollback operation.
111 if (copied_to_dest_path_ && !file_util::Delete(dest_path_, true)) { 111 if (copied_to_dest_path_ && !file_util::Delete(dest_path_, true)) {
112 LOG(ERROR) << "Can not delete " << dest_path_.value(); 112 LOG(ERROR) << "Can not delete " << dest_path_.value();
113 } 113 }
114 if (moved_to_backup_ && !file_util::Move(backup_path_, dest_path_)) { 114 if (moved_to_backup_) {
115 LOG(ERROR) << "failed move " << backup_path_.value() 115 FilePath backup = backup_path_.path().Append(dest_path_.BaseName());
tommi (sloooow) - chröme 2011/02/17 20:00:49 FilePath backup(...);
grt (UTC plus 2) 2011/02/17 20:26:41 Done.
116 << " to " << dest_path_.value(); 116 if (!file_util::Move(backup, dest_path_)) {
117 LOG(ERROR) << "failed move " << backup.value()
118 << " to " << dest_path_.value();
119 }
117 } 120 }
118 if (copied_to_alternate_path_ && 121 if (copied_to_alternate_path_ &&
119 !file_util::Delete(alternative_path_, true)) { 122 !file_util::Delete(alternative_path_, true)) {
120 LOG(ERROR) << "Can not delete " << alternative_path_.value(); 123 LOG(ERROR) << "Can not delete " << alternative_path_.value();
121 } 124 }
122 } 125 }
123 126
124 bool CopyTreeWorkItem::IsFileInUse(const FilePath& path) { 127 bool CopyTreeWorkItem::IsFileInUse(const FilePath& path) {
125 if (!file_util::PathExists(path)) 128 if (!file_util::PathExists(path))
126 return false; 129 return false;
127 130
128 HANDLE handle = ::CreateFile(path.value().c_str(), FILE_ALL_ACCESS, 131 HANDLE handle = ::CreateFile(path.value().c_str(), FILE_ALL_ACCESS,
129 NULL, NULL, OPEN_EXISTING, NULL, NULL); 132 NULL, NULL, OPEN_EXISTING, NULL, NULL);
130 if (handle == INVALID_HANDLE_VALUE) 133 if (handle == INVALID_HANDLE_VALUE)
131 return true; 134 return true;
132 135
133 CloseHandle(handle); 136 CloseHandle(handle);
134 return false; 137 return false;
135 } 138 }
136
137 bool CopyTreeWorkItem::GetBackupPath() {
138 backup_path_ = temp_dir_.Append(dest_path_.BaseName());
139
140 if (file_util::PathExists(backup_path_)) {
141 // Ideally we should not fail immediately. Instead we could try some
142 // random paths under temp_dir_ until we reach certain limit.
143 // For now our caller always provides a good temporary directory so
144 // we don't bother.
145 LOG(ERROR) << "backup path " << backup_path_.value() << " already exists";
146 return false;
147 }
148
149 return true;
150 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698