Android: Get rid of extra dup()s on launching child processes
[chromium-blink-merge.git] / chrome / installer / util / copy_tree_work_item.cc
blob88bc244ef5e60ca2d96d7da82b0020cbe7caac23
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
3 // found in the LICENSE file.
5 #include "chrome/installer/util/copy_tree_work_item.h"
7 #include <shlwapi.h>
9 #include "base/files/file_util.h"
10 #include "base/logging.h"
11 #include "chrome/installer/util/logging_installer.h"
13 CopyTreeWorkItem::~CopyTreeWorkItem() {
16 CopyTreeWorkItem::CopyTreeWorkItem(const base::FilePath& source_path,
17 const base::FilePath& dest_path,
18 const base::FilePath& temp_dir,
19 CopyOverWriteOption overwrite_option,
20 const base::FilePath& alternative_path)
21 : source_path_(source_path),
22 dest_path_(dest_path),
23 temp_dir_(temp_dir),
24 overwrite_option_(overwrite_option),
25 alternative_path_(alternative_path),
26 copied_to_dest_path_(false),
27 moved_to_backup_(false),
28 copied_to_alternate_path_(false) {
31 bool CopyTreeWorkItem::Do() {
32 if (!base::PathExists(source_path_)) {
33 LOG(ERROR) << source_path_.value() << " does not exist";
34 return false;
37 bool dest_exist = base::PathExists(dest_path_);
38 // handle overwrite_option_ = IF_DIFFERENT case.
39 if ((dest_exist) &&
40 (overwrite_option_ == WorkItem::IF_DIFFERENT) && // only for single file
41 (!base::DirectoryExists(source_path_)) &&
42 (!base::DirectoryExists(dest_path_)) &&
43 (base::ContentsEqual(source_path_, dest_path_))) {
44 VLOG(1) << "Source file " << source_path_.value()
45 << " and destination file " << dest_path_.value()
46 << " are exactly same. Returning true.";
47 return true;
48 } else if ((dest_exist) &&
49 (overwrite_option_ == WorkItem::NEW_NAME_IF_IN_USE) &&
50 (!base::DirectoryExists(source_path_)) &&
51 (!base::DirectoryExists(dest_path_)) &&
52 (IsFileInUse(dest_path_))) {
53 // handle overwrite_option_ = NEW_NAME_IF_IN_USE case.
54 if (alternative_path_.empty() ||
55 base::PathExists(alternative_path_) ||
56 !base::CopyFile(source_path_, alternative_path_)) {
57 LOG(ERROR) << "failed to copy " << source_path_.value()
58 << " to " << alternative_path_.value();
59 return false;
60 } else {
61 copied_to_alternate_path_ = true;
62 VLOG(1) << "Copied source file " << source_path_.value()
63 << " to alternative path " << alternative_path_.value();
64 return true;
66 } else if ((dest_exist) &&
67 (overwrite_option_ == WorkItem::IF_NOT_PRESENT)) {
68 // handle overwrite_option_ = IF_NOT_PRESENT case.
69 return true;
72 // In all cases that reach here, move dest to a backup path.
73 if (dest_exist) {
74 if (!backup_path_.CreateUniqueTempDirUnderPath(temp_dir_)) {
75 PLOG(ERROR) << "Failed to get backup path in folder "
76 << temp_dir_.value();
77 return false;
80 base::FilePath backup = backup_path_.path().Append(dest_path_.BaseName());
81 if (base::Move(dest_path_, backup)) {
82 moved_to_backup_ = true;
83 VLOG(1) << "Moved destination " << dest_path_.value() <<
84 " to backup path " << backup.value();
85 } else {
86 LOG(ERROR) << "failed moving " << dest_path_.value()
87 << " to " << backup.value();
88 return false;
92 // In all cases that reach here, copy source to destination.
93 if (base::CopyDirectory(source_path_, dest_path_, true)) {
94 copied_to_dest_path_ = true;
95 VLOG(1) << "Copied source " << source_path_.value()
96 << " to destination " << dest_path_.value();
97 } else {
98 LOG(ERROR) << "failed copy " << source_path_.value()
99 << " to " << dest_path_.value();
100 return false;
103 return true;
106 void CopyTreeWorkItem::Rollback() {
107 // Normally the delete operations below should not fail unless some
108 // programs like anti-virus are inspecting the files we just copied.
109 // If this does happen sometimes, we may consider using Move instead of
110 // Delete here. For now we just log the error and continue with the
111 // rest of rollback operation.
112 if (copied_to_dest_path_ && !base::DeleteFile(dest_path_, true)) {
113 LOG(ERROR) << "Can not delete " << dest_path_.value();
115 if (moved_to_backup_) {
116 base::FilePath backup(backup_path_.path().Append(dest_path_.BaseName()));
117 if (!base::Move(backup, dest_path_)) {
118 LOG(ERROR) << "failed move " << backup.value()
119 << " to " << dest_path_.value();
122 if (copied_to_alternate_path_ &&
123 !base::DeleteFile(alternative_path_, true)) {
124 LOG(ERROR) << "Can not delete " << alternative_path_.value();
128 bool CopyTreeWorkItem::IsFileInUse(const base::FilePath& path) {
129 if (!base::PathExists(path))
130 return false;
132 HANDLE handle = ::CreateFile(path.value().c_str(), FILE_ALL_ACCESS,
133 NULL, NULL, OPEN_EXISTING, NULL, NULL);
134 if (handle == INVALID_HANDLE_VALUE)
135 return true;
137 CloseHandle(handle);
138 return false;