blob: 50ee05f559e0c468463953374d44fcdb0890c735 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/installer/zucchini/zucchini_integration.h"
#include "base/logging.h"
#include "chrome/installer/zucchini/buffer_view.h"
#include "chrome/installer/zucchini/mapped_file.h"
#include "chrome/installer/zucchini/patch_reader.h"
namespace zucchini {
status::Code Apply(const base::FilePath& old_path,
const base::FilePath& patch_path,
const base::FilePath& new_path) {
MappedFileReader patch_file(patch_path);
if (!patch_file.IsValid())
return status::kStatusFileReadError;
auto patch_reader =
zucchini::EnsemblePatchReader::Create(patch_file.region());
if (!patch_reader.has_value()) {
LOG(ERROR) << "Error reading patch header.";
return status::kStatusPatchReadError;
}
MappedFileReader old_file(old_path);
if (!old_file.IsValid())
return status::kStatusFileReadError;
if (!patch_reader->CheckOldFile(old_file.region())) {
LOG(ERROR) << "Invalid old_file.";
return status::kStatusInvalidOldImage;
}
zucchini::PatchHeader header = patch_reader->header();
// By default, delete output on destruction, to avoid having lingering files
// in case of a failure. On Windows deletion can be done by the OS.
MappedFileWriter new_file(new_path, header.new_size);
if (!new_file.IsValid())
return status::kStatusFileWriteError;
zucchini::status::Code result =
zucchini::Apply(old_file.region(), *patch_reader, new_file.region());
if (result != status::kStatusSuccess) {
LOG(ERROR) << "Fatal error encountered while applying patch.";
return result;
}
// Successfully patch |new_file|. Explicitly request file to be kept.
if (!new_file.Keep())
return status::kStatusFileWriteError;
return status::kStatusSuccess;
}
} // namespace zucchini