123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- // 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 "components/zucchini/zucchini_integration.h"
- #include <utility>
- #include "base/logging.h"
- #include "components/zucchini/buffer_view.h"
- #include "components/zucchini/mapped_file.h"
- #include "components/zucchini/patch_reader.h"
- namespace zucchini {
- namespace {
- struct FileNames {
- FileNames() : is_dummy(true) {
- // Use fake names.
- old_name = old_name.AppendASCII("old_name");
- new_name = new_name.AppendASCII("new_name");
- patch_name = patch_name.AppendASCII("patch_name");
- }
- FileNames(const base::FilePath& old_name,
- const base::FilePath& new_name,
- const base::FilePath& patch_name)
- : old_name(old_name),
- new_name(new_name),
- patch_name(patch_name),
- is_dummy(false) {}
- base::FilePath old_name;
- base::FilePath new_name;
- base::FilePath patch_name;
- // A flag to decide whether the filenames are only for error output.
- const bool is_dummy;
- };
- status::Code GenerateCommon(base::File old_file,
- base::File new_file,
- base::File patch_file,
- const FileNames& names,
- bool force_keep,
- bool is_raw,
- std::string imposed_matches) {
- MappedFileReader mapped_old(std::move(old_file));
- if (mapped_old.HasError()) {
- LOG(ERROR) << "Error with file " << names.old_name.value() << ": "
- << mapped_old.error();
- return status::kStatusFileReadError;
- }
- MappedFileReader mapped_new(std::move(new_file));
- if (mapped_new.HasError()) {
- LOG(ERROR) << "Error with file " << names.new_name.value() << ": "
- << mapped_new.error();
- return status::kStatusFileReadError;
- }
- status::Code result = status::kStatusSuccess;
- EnsemblePatchWriter patch_writer(mapped_old.region(), mapped_new.region());
- if (is_raw) {
- result = GenerateBufferRaw(mapped_old.region(), mapped_new.region(),
- &patch_writer);
- } else {
- result = GenerateBufferImposed(mapped_old.region(), mapped_new.region(),
- std::move(imposed_matches), &patch_writer);
- }
- if (result != status::kStatusSuccess) {
- LOG(ERROR) << "Fatal error encountered when generating patch.";
- return result;
- }
- // By default, delete patch on destruction, to avoid having lingering files in
- // case of a failure. On Windows deletion can be done by the OS.
- MappedFileWriter mapped_patch(names.patch_name, std::move(patch_file),
- patch_writer.SerializedSize());
- if (mapped_patch.HasError()) {
- LOG(ERROR) << "Error with file " << names.patch_name.value() << ": "
- << mapped_patch.error();
- return status::kStatusFileWriteError;
- }
- if (force_keep)
- mapped_patch.Keep();
- if (!patch_writer.SerializeInto(mapped_patch.region()))
- return status::kStatusPatchWriteError;
- // Successfully created patch. Explicitly request file to be kept.
- if (!mapped_patch.Keep())
- return status::kStatusFileWriteError;
- return status::kStatusSuccess;
- }
- status::Code ApplyCommon(base::File old_file,
- base::File patch_file,
- base::File new_file,
- const FileNames& names,
- bool force_keep) {
- MappedFileReader mapped_patch(std::move(patch_file));
- if (mapped_patch.HasError()) {
- LOG(ERROR) << "Error with file " << names.patch_name.value() << ": "
- << mapped_patch.error();
- return status::kStatusFileReadError;
- }
- auto patch_reader = EnsemblePatchReader::Create(mapped_patch.region());
- if (!patch_reader.has_value()) {
- LOG(ERROR) << "Error reading patch header.";
- return status::kStatusPatchReadError;
- }
- MappedFileReader mapped_old(std::move(old_file));
- if (mapped_old.HasError()) {
- LOG(ERROR) << "Error with file " << names.old_name.value() << ": "
- << mapped_old.error();
- return status::kStatusFileReadError;
- }
- 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 mapped_new(names.new_name, std::move(new_file),
- header.new_size);
- if (mapped_new.HasError()) {
- LOG(ERROR) << "Error with file " << names.new_name.value() << ": "
- << mapped_new.error();
- return status::kStatusFileWriteError;
- }
- if (force_keep)
- mapped_new.Keep();
- status::Code result =
- ApplyBuffer(mapped_old.region(), *patch_reader, mapped_new.region());
- if (result != status::kStatusSuccess) {
- LOG(ERROR) << "Fatal error encountered while applying patch.";
- return result;
- }
- // Successfully patch |mapped_new|. Explicitly request file to be kept.
- if (!mapped_new.Keep())
- return status::kStatusFileWriteError;
- return status::kStatusSuccess;
- }
- status::Code VerifyPatchCommon(base::File patch_file,
- base::FilePath patch_name) {
- MappedFileReader mapped_patch(std::move(patch_file));
- if (mapped_patch.HasError()) {
- LOG(ERROR) << "Error with file " << patch_name.value() << ": "
- << mapped_patch.error();
- return status::kStatusFileReadError;
- }
- auto patch_reader = EnsemblePatchReader::Create(mapped_patch.region());
- if (!patch_reader.has_value()) {
- LOG(ERROR) << "Error reading patch header.";
- return status::kStatusPatchReadError;
- }
- return status::kStatusSuccess;
- }
- } // namespace
- status::Code Generate(base::File old_file,
- base::File new_file,
- base::File patch_file,
- bool force_keep,
- bool is_raw,
- std::string imposed_matches) {
- const FileNames file_names;
- return GenerateCommon(std::move(old_file), std::move(new_file),
- std::move(patch_file), file_names, force_keep, is_raw,
- std::move(imposed_matches));
- }
- status::Code Generate(const base::FilePath& old_path,
- const base::FilePath& new_path,
- const base::FilePath& patch_path,
- bool force_keep,
- bool is_raw,
- std::string imposed_matches) {
- using base::File;
- File old_file(old_path, File::FLAG_OPEN | File::FLAG_READ |
- base::File::FLAG_WIN_SHARE_DELETE);
- File new_file(new_path, File::FLAG_OPEN | File::FLAG_READ |
- base::File::FLAG_WIN_SHARE_DELETE);
- File patch_file(patch_path, File::FLAG_CREATE_ALWAYS | File::FLAG_READ |
- File::FLAG_WRITE |
- File::FLAG_WIN_SHARE_DELETE |
- File::FLAG_CAN_DELETE_ON_CLOSE);
- const FileNames file_names(old_path, new_path, patch_path);
- return GenerateCommon(std::move(old_file), std::move(new_file),
- std::move(patch_file), file_names, force_keep, is_raw,
- std::move(imposed_matches));
- }
- status::Code Apply(base::File old_file,
- base::File patch_file,
- base::File new_file,
- bool force_keep) {
- const FileNames file_names;
- return ApplyCommon(std::move(old_file), std::move(patch_file),
- std::move(new_file), file_names, force_keep);
- }
- status::Code Apply(const base::FilePath& old_path,
- const base::FilePath& patch_path,
- const base::FilePath& new_path,
- bool force_keep) {
- using base::File;
- File old_file(old_path, File::FLAG_OPEN | File::FLAG_READ |
- base::File::FLAG_WIN_SHARE_DELETE);
- File patch_file(patch_path, File::FLAG_OPEN | File::FLAG_READ |
- base::File::FLAG_WIN_SHARE_DELETE);
- File new_file(new_path, File::FLAG_CREATE_ALWAYS | File::FLAG_READ |
- File::FLAG_WRITE | File::FLAG_WIN_SHARE_DELETE |
- File::FLAG_CAN_DELETE_ON_CLOSE);
- const FileNames file_names(old_path, new_path, patch_path);
- return ApplyCommon(std::move(old_file), std::move(patch_file),
- std::move(new_file), file_names, force_keep);
- }
- status::Code VerifyPatch(base::File patch_file) {
- return VerifyPatchCommon(std::move(patch_file), base::FilePath());
- }
- status::Code VerifyPatch(const base::FilePath& patch_path) {
- using base::File;
- File patch_file(patch_path, File::FLAG_OPEN | File::FLAG_READ |
- base::File::FLAG_WIN_SHARE_DELETE);
- return VerifyPatchCommon(std::move(patch_file), patch_path);
- }
- } // namespace zucchini
|