1 // Copyright 2013 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/setup/archive_patch_helper.h"
7 #include "base/files/file_util.h"
8 #include "base/logging.h"
9 #include "chrome/installer/util/lzma_util.h"
10 #include "courgette/courgette.h"
11 #include "third_party/bspatch/mbspatch.h"
15 ArchivePatchHelper::ArchivePatchHelper(const base::FilePath
& working_directory
,
16 const base::FilePath
& compressed_archive
,
17 const base::FilePath
& patch_source
,
18 const base::FilePath
& target
)
19 : working_directory_(working_directory
),
20 compressed_archive_(compressed_archive
),
21 patch_source_(patch_source
),
24 ArchivePatchHelper::~ArchivePatchHelper() {}
27 bool ArchivePatchHelper::UncompressAndPatch(
28 const base::FilePath
& working_directory
,
29 const base::FilePath
& compressed_archive
,
30 const base::FilePath
& patch_source
,
31 const base::FilePath
& target
) {
32 ArchivePatchHelper
instance(working_directory
, compressed_archive
,
33 patch_source
, target
);
34 return (instance
.Uncompress(NULL
) &&
35 (instance
.EnsemblePatch() || instance
.BinaryPatch()));
38 bool ArchivePatchHelper::Uncompress(base::FilePath
* last_uncompressed_file
) {
39 // The target shouldn't already exist.
40 DCHECK(!base::PathExists(target_
));
42 // UnPackArchive takes care of logging.
43 base::string16 output_file
;
44 int32 lzma_result
= LzmaUtil::UnPackArchive(compressed_archive_
.value(),
45 working_directory_
.value(),
47 if (lzma_result
!= NO_ERROR
)
50 last_uncompressed_file_
= base::FilePath(output_file
);
51 if (last_uncompressed_file
)
52 *last_uncompressed_file
= last_uncompressed_file_
;
56 bool ArchivePatchHelper::EnsemblePatch() {
57 if (last_uncompressed_file_
.empty()) {
58 LOG(ERROR
) << "No patch file found in compressed archive.";
62 courgette::Status result
=
63 courgette::ApplyEnsemblePatch(patch_source_
.value().c_str(),
64 last_uncompressed_file_
.value().c_str(),
65 target_
.value().c_str());
66 if (result
== courgette::C_OK
)
70 << "Failed to apply patch " << last_uncompressed_file_
.value()
71 << " to file " << patch_source_
.value()
72 << " and generating file " << target_
.value()
73 << " using courgette. err=" << result
;
75 // Ensure a partial output is not left behind.
76 base::DeleteFile(target_
, false);
81 bool ArchivePatchHelper::BinaryPatch() {
82 if (last_uncompressed_file_
.empty()) {
83 LOG(ERROR
) << "No patch file found in compressed archive.";
87 int result
= ApplyBinaryPatch(patch_source_
.value().c_str(),
88 last_uncompressed_file_
.value().c_str(),
89 target_
.value().c_str());
94 << "Failed to apply patch " << last_uncompressed_file_
.value()
95 << " to file " << patch_source_
.value()
96 << " and generating file " << target_
.value()
97 << " using bsdiff. err=" << result
;
99 // Ensure a partial output is not left behind.
100 base::DeleteFile(target_
, false);
105 } // namespace installer