Index: third_party/courgette/ensemble_apply.cc |
=================================================================== |
--- third_party/courgette/ensemble_apply.cc (revision 15668) |
+++ third_party/courgette/ensemble_apply.cc (working copy) |
@@ -1,412 +0,0 @@ |
-// Copyright (c) 2009 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. |
- |
-// This file contains the code to apply a Courgette patch. |
- |
-#include "third_party/courgette/ensemble.h" |
- |
-#include "base/basictypes.h" |
-#include "base/file_util.h" |
-#include "base/logging.h" |
- |
-#include "third_party/courgette/crc.h" |
-#include "third_party/courgette/image_info.h" |
-#include "third_party/courgette/region.h" |
-#include "third_party/courgette/streams.h" |
-#include "third_party/courgette/simple_delta.h" |
-#include "third_party/courgette/win32_x86_patcher.h" |
- |
-namespace courgette { |
- |
-// EnsemblePatchApplication is all the logic and data required to apply the |
-// multi-stage patch. |
-class EnsemblePatchApplication { |
- public: |
- EnsemblePatchApplication(); |
- ~EnsemblePatchApplication(); |
- |
- Status ReadHeader(SourceStream* header_stream); |
- |
- Status InitBase(const Region& region); |
- |
- Status ValidateBase(); |
- |
- Status ReadInitialParameters(SourceStream* initial_parameters); |
- |
- Status PredictTransformParameters(SinkStreamSet* predicted_parameters); |
- |
- Status SubpatchTransformParameters(SinkStreamSet* prediction, |
- SourceStream* correction, |
- SourceStreamSet* corrected_parameters); |
- |
- Status TransformUp(SourceStreamSet* parameters, |
- SinkStreamSet* transformed_elements); |
- |
- Status SubpatchTransformedElements(SinkStreamSet* elements, |
- SourceStream* correction, |
- SourceStreamSet* corrected_elements); |
- |
- Status TransformDown(SourceStreamSet* transformed_elements, |
- SinkStream* basic_elements); |
- |
- Status SubpatchFinalOutput(SourceStream* original, |
- SourceStream* correction, |
- SinkStream* corrected_ensemble); |
- |
- private: |
- Status SubpatchStreamSets(SinkStreamSet* predicted_items, |
- SourceStream* correction, |
- SourceStreamSet* corrected_items, |
- SinkStream* corrected_items_storage); |
- |
- Region base_region_; // Location of in-memory copy of 'old' version. |
- |
- uint32 source_checksum_; |
- uint32 target_checksum_; |
- |
- std::vector<TransformationPatcher*> patchers_; |
- |
- SinkStream corrected_parameters_storage_; |
- SinkStream corrected_elements_storage_; |
- |
- DISALLOW_COPY_AND_ASSIGN(EnsemblePatchApplication); |
-}; |
- |
-EnsemblePatchApplication::EnsemblePatchApplication() |
- : source_checksum_(0), target_checksum_(0) { |
-} |
- |
-EnsemblePatchApplication::~EnsemblePatchApplication() { |
- for (size_t i = 0; i < patchers_.size(); ++i) { |
- delete patchers_[i]; |
- } |
-} |
- |
-Status EnsemblePatchApplication::ReadHeader(SourceStream* header_stream) { |
- uint32 magic; |
- if (!header_stream->ReadVarint32(&magic)) |
- return C_BAD_ENSEMBLE_MAGIC; |
- |
- if (magic != CourgettePatchFile::kMagic) |
- return C_BAD_ENSEMBLE_MAGIC; |
- |
- uint32 version; |
- if (!header_stream->ReadVarint32(&version)) |
- return C_BAD_ENSEMBLE_VERSION; |
- |
- if (version != CourgettePatchFile::kVersion) |
- return C_BAD_ENSEMBLE_VERSION; |
- |
- if (!header_stream->ReadVarint32(&source_checksum_)) |
- return C_BAD_ENSEMBLE_HEADER; |
- |
- if (!header_stream->ReadVarint32(&target_checksum_)) |
- return C_BAD_ENSEMBLE_HEADER; |
- |
- return C_OK; |
-} |
- |
-Status EnsemblePatchApplication::InitBase(const Region& region) { |
- base_region_.assign(region); |
- return C_OK; |
-} |
- |
-Status EnsemblePatchApplication::ValidateBase() { |
- uint32 checksum = CalculateCrc(base_region_.start(), base_region_.length()); |
- if (source_checksum_ != checksum) |
- return C_BAD_ENSEMBLE_CRC; |
- |
- return C_OK; |
-} |
- |
-Status EnsemblePatchApplication::ReadInitialParameters( |
- SourceStream* transformation_parameters) { |
- uint32 number_of_transformations = 0; |
- if (!transformation_parameters->ReadVarint32(&number_of_transformations)) |
- return C_BAD_ENSEMBLE_HEADER; |
- |
- for (size_t i = 0; i < number_of_transformations; ++i) { |
- uint32 kind; |
- if (!transformation_parameters->ReadVarint32(&kind)) |
- return C_BAD_ENSEMBLE_HEADER; |
- |
- if (kind == CourgettePatchFile::T_COURGETTE_WIN32_X86) { |
- TransformationPatcher* patcher = |
- new CourgetteWin32X86Patcher(base_region_); |
- patchers_.push_back(patcher); |
- } else { |
- return C_BAD_ENSEMBLE_HEADER; |
- } |
- } |
- |
- for (size_t i = 0; i < patchers_.size(); ++i) { |
- Status status = patchers_[i]->Init(transformation_parameters); |
- if (status != C_OK) |
- return status; |
- } |
- |
- // All transformation_parameters should have been consumed by the above loop. |
- if (!transformation_parameters->Empty()) |
- return C_BAD_ENSEMBLE_HEADER; |
- |
- return C_OK; |
-} |
- |
-Status EnsemblePatchApplication::PredictTransformParameters( |
- SinkStreamSet* all_predicted_parameters) { |
- for (size_t i = 0; i < patchers_.size(); ++i) { |
- SinkStreamSet single_predicted_parameters; |
- Status status = |
- patchers_[i]->PredictTransformParameters(&single_predicted_parameters); |
- if (status != C_OK) |
- return status; |
- if (!all_predicted_parameters->WriteSet(&single_predicted_parameters)) |
- return C_STREAM_ERROR; |
- } |
- return C_OK; |
-} |
- |
-Status EnsemblePatchApplication::SubpatchTransformParameters( |
- SinkStreamSet* predicted_parameters, |
- SourceStream* correction, |
- SourceStreamSet* corrected_parameters) { |
- return SubpatchStreamSets(predicted_parameters, |
- correction, |
- corrected_parameters, |
- &corrected_parameters_storage_); |
-} |
- |
-Status EnsemblePatchApplication::TransformUp( |
- SourceStreamSet* parameters, |
- SinkStreamSet* transformed_elements) { |
- for (size_t i = 0; i < patchers_.size(); ++i) { |
- SourceStreamSet single_parameters; |
- if (!parameters->ReadSet(&single_parameters)) |
- return C_STREAM_ERROR; |
- SinkStreamSet single_transformed_element; |
- Status status = patchers_[i]->Transform(&single_parameters, |
- &single_transformed_element); |
- if (status != C_OK) |
- return status; |
- if (!single_parameters.Empty()) |
- return C_STREAM_NOT_CONSUMED; |
- if (!transformed_elements->WriteSet(&single_transformed_element)) |
- return C_STREAM_ERROR; |
- } |
- |
- if (!parameters->Empty()) |
- return C_STREAM_NOT_CONSUMED; |
- return C_OK; |
-} |
- |
-Status EnsemblePatchApplication::SubpatchTransformedElements( |
- SinkStreamSet* predicted_elements, |
- SourceStream* correction, |
- SourceStreamSet* corrected_elements) { |
- return SubpatchStreamSets(predicted_elements, |
- correction, |
- corrected_elements, |
- &corrected_elements_storage_); |
-} |
- |
-Status EnsemblePatchApplication::TransformDown( |
- SourceStreamSet* transformed_elements, |
- SinkStream* basic_elements) { |
- // Construct blob of original input followed by reformed elements. |
- |
- // The original input: |
- basic_elements->Write(base_region_.start(), base_region_.length()); |
- |
- for (size_t i = 0; i < patchers_.size(); ++i) { |
- SourceStreamSet single_corrected_element; |
- if (!transformed_elements->ReadSet(&single_corrected_element)) |
- return C_STREAM_ERROR; |
- Status status = patchers_[i]->Reform(&single_corrected_element, |
- basic_elements); |
- if (status != C_OK) |
- return status; |
- if (!single_corrected_element.Empty()) |
- return C_STREAM_NOT_CONSUMED; |
- } |
- |
- if (!transformed_elements->Empty()) |
- return C_STREAM_NOT_CONSUMED; |
- |
- return C_OK; |
-} |
- |
-Status EnsemblePatchApplication::SubpatchFinalOutput( |
- SourceStream* original, |
- SourceStream* correction, |
- SinkStream* corrected_ensemble) { |
- Status delta_status = ApplySimpleDelta(original, correction, |
- corrected_ensemble); |
- if (delta_status != C_OK) |
- return delta_status; |
- |
- if (CalculateCrc(corrected_ensemble->Buffer(), |
- corrected_ensemble->Length()) != target_checksum_) |
- return C_BAD_ENSEMBLE_CRC; |
- |
- return C_OK; |
-} |
- |
-Status EnsemblePatchApplication::SubpatchStreamSets( |
- SinkStreamSet* predicted_items, |
- SourceStream* correction, |
- SourceStreamSet* corrected_items, |
- SinkStream* corrected_items_storage) { |
- SinkStream linearized_predicted_items; |
- if (!predicted_items->CopyTo(&linearized_predicted_items)) |
- return C_STREAM_ERROR; |
- |
- SourceStream prediction; |
- prediction.Init(linearized_predicted_items); |
- |
- Status status = ApplySimpleDelta(&prediction, |
- correction, |
- corrected_items_storage); |
- if (status != C_OK) |
- return status; |
- |
- if (!corrected_items->Init(corrected_items_storage->Buffer(), |
- corrected_items_storage->Length())) |
- return C_STREAM_ERROR; |
- |
- return C_OK; |
-} |
- |
-Status ApplyEnsemblePatch(SourceStream* base, |
- SourceStream* patch, |
- SinkStream* output) { |
- Status status; |
- EnsemblePatchApplication patch_process; |
- |
- status = patch_process.ReadHeader(patch); |
- if (status != C_OK) |
- return status; |
- |
- status = patch_process.InitBase(Region(base->Buffer(), base->Remaining())); |
- if (status != C_OK) |
- return status; |
- |
- status = patch_process.ValidateBase(); |
- if (status != C_OK) |
- return status; |
- |
- // The rest of the patch stream is a StreamSet. |
- SourceStreamSet patch_streams; |
- patch_streams.Init(patch); |
- |
- SourceStream* transformation_descriptions = patch_streams.stream(0); |
- SourceStream* parameter_correction = patch_streams.stream(1); |
- SourceStream* transformed_elements_correction = patch_streams.stream(2); |
- SourceStream* ensemble_correction = patch_streams.stream(3); |
- |
- status = patch_process.ReadInitialParameters(transformation_descriptions); |
- if (status != C_OK) |
- return status; |
- |
- SinkStreamSet predicted_parameters; |
- status = patch_process.PredictTransformParameters(&predicted_parameters); |
- if (status != C_OK) |
- return status; |
- |
- SourceStreamSet corrected_parameters; |
- status = patch_process.SubpatchTransformParameters(&predicted_parameters, |
- parameter_correction, |
- &corrected_parameters); |
- if (status != C_OK) |
- return status; |
- |
- SinkStreamSet transformed_elements; |
- status = patch_process.TransformUp(&corrected_parameters, |
- &transformed_elements); |
- if (status != C_OK) |
- return status; |
- |
- SourceStreamSet corrected_transformed_elements; |
- status = patch_process.SubpatchTransformedElements( |
- &transformed_elements, |
- transformed_elements_correction, |
- &corrected_transformed_elements); |
- if (status != C_OK) |
- return status; |
- |
- SinkStream original_ensemble_and_corrected_base_elements; |
- status = patch_process.TransformDown( |
- &corrected_transformed_elements, |
- &original_ensemble_and_corrected_base_elements); |
- if (status != C_OK) |
- return status; |
- |
- SourceStream final_patch_prediction; |
- final_patch_prediction.Init(original_ensemble_and_corrected_base_elements); |
- status = patch_process.SubpatchFinalOutput(&final_patch_prediction, |
- ensemble_correction, output); |
- if (status != C_OK) |
- return status; |
- |
- return C_OK; |
-} |
- |
-Status ApplyEnsemblePatch(const wchar_t* old_file_name, |
- const wchar_t* patch_file_name, |
- const wchar_t* new_file_name) { |
- Status status; |
- |
- // First read enough of the patch file to validate the header is well-formed. |
- // A few varint32 numbers should fit in 100. |
- FilePath patch_file_path(patch_file_name); |
- const int BIG_ENOUGH_FOR_HEADER = 100; |
- char buffer[BIG_ENOUGH_FOR_HEADER]; |
- int read_count = |
- file_util::ReadFile(patch_file_path, buffer, sizeof(buffer)); |
- if (read_count < 0) |
- return C_READ_OPEN_ERROR; |
- |
- // 'Dry-run' the first step of the patch process to validate format of header. |
- SourceStream patch_header_stream; |
- patch_header_stream.Init(buffer, read_count); |
- EnsemblePatchApplication patch_process; |
- status = patch_process.ReadHeader(&patch_header_stream); |
- if (status != C_OK) |
- return status; |
- |
- // Header smells good so read the whole patch file for real. |
- std::string patch_file_buffer; |
- if (!file_util::ReadFileToString(patch_file_path, &patch_file_buffer)) |
- return C_READ_ERROR; |
- |
- // Read the old_file. |
- FilePath old_file_path(old_file_name); |
- std::string old_file_buffer; |
- if (!file_util::ReadFileToString(old_file_path, &old_file_buffer)) |
- return C_READ_ERROR; |
- |
- // Apply patch on streams. |
- SourceStream old_source_stream; |
- SourceStream patch_source_stream; |
- old_source_stream.Init(old_file_buffer); |
- patch_source_stream.Init(patch_file_buffer); |
- SinkStream new_sink_stream; |
- status = ApplyEnsemblePatch(&old_source_stream, &patch_source_stream, |
- &new_sink_stream); |
- |
- // Write the patched data to |new_file_name|. |
- FilePath new_file_path(new_file_name); |
- int written = |
- file_util::WriteFile( |
- new_file_path, |
- reinterpret_cast<const char*>(new_sink_stream.Buffer()), |
- new_sink_stream.Length()); |
- if (written == -1) |
- return C_WRITE_OPEN_ERROR; |
- if (written != new_sink_stream.Length()) |
- return C_WRITE_ERROR; |
- |
- return C_OK; |
-} |
- |
-} // namespace |