archive_patch_helper.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/installer/setup/archive_patch_helper.h"
6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/file_util.h"
8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/logging.h"
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/installer/util/lzma_util.h"
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "courgette/courgette.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "third_party/bspatch/mbspatch.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace installer {
14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochArchivePatchHelper::ArchivePatchHelper(const base::FilePath& working_directory,
16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                       const base::FilePath& compressed_archive,
17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                       const base::FilePath& patch_source,
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                       const base::FilePath& target)
19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : working_directory_(working_directory),
20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      compressed_archive_(compressed_archive),
21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      patch_source_(patch_source),
22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      target_(target) {}
23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochArchivePatchHelper::~ArchivePatchHelper() {}
25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// static
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool ArchivePatchHelper::UncompressAndPatch(
28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::FilePath& working_directory,
29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::FilePath& compressed_archive,
30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::FilePath& patch_source,
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::FilePath& target) {
32ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ArchivePatchHelper instance(working_directory, compressed_archive,
33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                              patch_source, target);
34ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return (instance.Uncompress(NULL) &&
35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          (instance.EnsemblePatch() || instance.BinaryPatch()));
36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool ArchivePatchHelper::Uncompress(base::FilePath* last_uncompressed_file) {
39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // The target shouldn't already exist.
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(!base::PathExists(target_));
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // UnPackArchive takes care of logging.
43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  string16 output_file;
44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int32 lzma_result = LzmaUtil::UnPackArchive(compressed_archive_.value(),
45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                              working_directory_.value(),
46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                              &output_file);
47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (lzma_result != NO_ERROR)
48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return false;
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  last_uncompressed_file_ = base::FilePath(output_file);
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (last_uncompressed_file)
52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    *last_uncompressed_file = last_uncompressed_file_;
53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return true;
54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool ArchivePatchHelper::EnsemblePatch() {
57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (last_uncompressed_file_.empty()) {
58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(ERROR) << "No patch file found in compressed archive.";
59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return false;
60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  courgette::Status result =
63ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      courgette::ApplyEnsemblePatch(patch_source_.value().c_str(),
64ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                    last_uncompressed_file_.value().c_str(),
65ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                    target_.value().c_str());
66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (result == courgette::C_OK)
67ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  LOG(ERROR)
70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      << "Failed to apply patch " << last_uncompressed_file_.value()
71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      << " to file " << patch_source_.value()
72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      << " and generating file " << target_.value()
73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      << " using courgette. err=" << result;
74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Ensure a partial output is not left behind.
76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::DeleteFile(target_, false);
77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return false;
79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool ArchivePatchHelper::BinaryPatch() {
82ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (last_uncompressed_file_.empty()) {
83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(ERROR) << "No patch file found in compressed archive.";
84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return false;
85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int result = ApplyBinaryPatch(patch_source_.value().c_str(),
88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                last_uncompressed_file_.value().c_str(),
89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                target_.value().c_str());
90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (result == OK)
91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  LOG(ERROR)
94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      << "Failed to apply patch " << last_uncompressed_file_.value()
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      << " to file " << patch_source_.value()
96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      << " and generating file " << target_.value()
97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      << " using bsdiff. err=" << result;
98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Ensure a partial output is not left behind.
100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::DeleteFile(target_, false);
101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return false;
103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace installer
106