Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: third_party/courgette/ensemble_apply.cc

Issue 115062: Move Courgette... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/courgette/ensemble.cc ('k') | third_party/courgette/ensemble_create.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 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.
4
5 // This file contains the code to apply a Courgette patch.
6
7 #include "third_party/courgette/ensemble.h"
8
9 #include "base/basictypes.h"
10 #include "base/file_util.h"
11 #include "base/logging.h"
12
13 #include "third_party/courgette/crc.h"
14 #include "third_party/courgette/image_info.h"
15 #include "third_party/courgette/region.h"
16 #include "third_party/courgette/streams.h"
17 #include "third_party/courgette/simple_delta.h"
18 #include "third_party/courgette/win32_x86_patcher.h"
19
20 namespace courgette {
21
22 // EnsemblePatchApplication is all the logic and data required to apply the
23 // multi-stage patch.
24 class EnsemblePatchApplication {
25 public:
26 EnsemblePatchApplication();
27 ~EnsemblePatchApplication();
28
29 Status ReadHeader(SourceStream* header_stream);
30
31 Status InitBase(const Region& region);
32
33 Status ValidateBase();
34
35 Status ReadInitialParameters(SourceStream* initial_parameters);
36
37 Status PredictTransformParameters(SinkStreamSet* predicted_parameters);
38
39 Status SubpatchTransformParameters(SinkStreamSet* prediction,
40 SourceStream* correction,
41 SourceStreamSet* corrected_parameters);
42
43 Status TransformUp(SourceStreamSet* parameters,
44 SinkStreamSet* transformed_elements);
45
46 Status SubpatchTransformedElements(SinkStreamSet* elements,
47 SourceStream* correction,
48 SourceStreamSet* corrected_elements);
49
50 Status TransformDown(SourceStreamSet* transformed_elements,
51 SinkStream* basic_elements);
52
53 Status SubpatchFinalOutput(SourceStream* original,
54 SourceStream* correction,
55 SinkStream* corrected_ensemble);
56
57 private:
58 Status SubpatchStreamSets(SinkStreamSet* predicted_items,
59 SourceStream* correction,
60 SourceStreamSet* corrected_items,
61 SinkStream* corrected_items_storage);
62
63 Region base_region_; // Location of in-memory copy of 'old' version.
64
65 uint32 source_checksum_;
66 uint32 target_checksum_;
67
68 std::vector<TransformationPatcher*> patchers_;
69
70 SinkStream corrected_parameters_storage_;
71 SinkStream corrected_elements_storage_;
72
73 DISALLOW_COPY_AND_ASSIGN(EnsemblePatchApplication);
74 };
75
76 EnsemblePatchApplication::EnsemblePatchApplication()
77 : source_checksum_(0), target_checksum_(0) {
78 }
79
80 EnsemblePatchApplication::~EnsemblePatchApplication() {
81 for (size_t i = 0; i < patchers_.size(); ++i) {
82 delete patchers_[i];
83 }
84 }
85
86 Status EnsemblePatchApplication::ReadHeader(SourceStream* header_stream) {
87 uint32 magic;
88 if (!header_stream->ReadVarint32(&magic))
89 return C_BAD_ENSEMBLE_MAGIC;
90
91 if (magic != CourgettePatchFile::kMagic)
92 return C_BAD_ENSEMBLE_MAGIC;
93
94 uint32 version;
95 if (!header_stream->ReadVarint32(&version))
96 return C_BAD_ENSEMBLE_VERSION;
97
98 if (version != CourgettePatchFile::kVersion)
99 return C_BAD_ENSEMBLE_VERSION;
100
101 if (!header_stream->ReadVarint32(&source_checksum_))
102 return C_BAD_ENSEMBLE_HEADER;
103
104 if (!header_stream->ReadVarint32(&target_checksum_))
105 return C_BAD_ENSEMBLE_HEADER;
106
107 return C_OK;
108 }
109
110 Status EnsemblePatchApplication::InitBase(const Region& region) {
111 base_region_.assign(region);
112 return C_OK;
113 }
114
115 Status EnsemblePatchApplication::ValidateBase() {
116 uint32 checksum = CalculateCrc(base_region_.start(), base_region_.length());
117 if (source_checksum_ != checksum)
118 return C_BAD_ENSEMBLE_CRC;
119
120 return C_OK;
121 }
122
123 Status EnsemblePatchApplication::ReadInitialParameters(
124 SourceStream* transformation_parameters) {
125 uint32 number_of_transformations = 0;
126 if (!transformation_parameters->ReadVarint32(&number_of_transformations))
127 return C_BAD_ENSEMBLE_HEADER;
128
129 for (size_t i = 0; i < number_of_transformations; ++i) {
130 uint32 kind;
131 if (!transformation_parameters->ReadVarint32(&kind))
132 return C_BAD_ENSEMBLE_HEADER;
133
134 if (kind == CourgettePatchFile::T_COURGETTE_WIN32_X86) {
135 TransformationPatcher* patcher =
136 new CourgetteWin32X86Patcher(base_region_);
137 patchers_.push_back(patcher);
138 } else {
139 return C_BAD_ENSEMBLE_HEADER;
140 }
141 }
142
143 for (size_t i = 0; i < patchers_.size(); ++i) {
144 Status status = patchers_[i]->Init(transformation_parameters);
145 if (status != C_OK)
146 return status;
147 }
148
149 // All transformation_parameters should have been consumed by the above loop.
150 if (!transformation_parameters->Empty())
151 return C_BAD_ENSEMBLE_HEADER;
152
153 return C_OK;
154 }
155
156 Status EnsemblePatchApplication::PredictTransformParameters(
157 SinkStreamSet* all_predicted_parameters) {
158 for (size_t i = 0; i < patchers_.size(); ++i) {
159 SinkStreamSet single_predicted_parameters;
160 Status status =
161 patchers_[i]->PredictTransformParameters(&single_predicted_parameters);
162 if (status != C_OK)
163 return status;
164 if (!all_predicted_parameters->WriteSet(&single_predicted_parameters))
165 return C_STREAM_ERROR;
166 }
167 return C_OK;
168 }
169
170 Status EnsemblePatchApplication::SubpatchTransformParameters(
171 SinkStreamSet* predicted_parameters,
172 SourceStream* correction,
173 SourceStreamSet* corrected_parameters) {
174 return SubpatchStreamSets(predicted_parameters,
175 correction,
176 corrected_parameters,
177 &corrected_parameters_storage_);
178 }
179
180 Status EnsemblePatchApplication::TransformUp(
181 SourceStreamSet* parameters,
182 SinkStreamSet* transformed_elements) {
183 for (size_t i = 0; i < patchers_.size(); ++i) {
184 SourceStreamSet single_parameters;
185 if (!parameters->ReadSet(&single_parameters))
186 return C_STREAM_ERROR;
187 SinkStreamSet single_transformed_element;
188 Status status = patchers_[i]->Transform(&single_parameters,
189 &single_transformed_element);
190 if (status != C_OK)
191 return status;
192 if (!single_parameters.Empty())
193 return C_STREAM_NOT_CONSUMED;
194 if (!transformed_elements->WriteSet(&single_transformed_element))
195 return C_STREAM_ERROR;
196 }
197
198 if (!parameters->Empty())
199 return C_STREAM_NOT_CONSUMED;
200 return C_OK;
201 }
202
203 Status EnsemblePatchApplication::SubpatchTransformedElements(
204 SinkStreamSet* predicted_elements,
205 SourceStream* correction,
206 SourceStreamSet* corrected_elements) {
207 return SubpatchStreamSets(predicted_elements,
208 correction,
209 corrected_elements,
210 &corrected_elements_storage_);
211 }
212
213 Status EnsemblePatchApplication::TransformDown(
214 SourceStreamSet* transformed_elements,
215 SinkStream* basic_elements) {
216 // Construct blob of original input followed by reformed elements.
217
218 // The original input:
219 basic_elements->Write(base_region_.start(), base_region_.length());
220
221 for (size_t i = 0; i < patchers_.size(); ++i) {
222 SourceStreamSet single_corrected_element;
223 if (!transformed_elements->ReadSet(&single_corrected_element))
224 return C_STREAM_ERROR;
225 Status status = patchers_[i]->Reform(&single_corrected_element,
226 basic_elements);
227 if (status != C_OK)
228 return status;
229 if (!single_corrected_element.Empty())
230 return C_STREAM_NOT_CONSUMED;
231 }
232
233 if (!transformed_elements->Empty())
234 return C_STREAM_NOT_CONSUMED;
235
236 return C_OK;
237 }
238
239 Status EnsemblePatchApplication::SubpatchFinalOutput(
240 SourceStream* original,
241 SourceStream* correction,
242 SinkStream* corrected_ensemble) {
243 Status delta_status = ApplySimpleDelta(original, correction,
244 corrected_ensemble);
245 if (delta_status != C_OK)
246 return delta_status;
247
248 if (CalculateCrc(corrected_ensemble->Buffer(),
249 corrected_ensemble->Length()) != target_checksum_)
250 return C_BAD_ENSEMBLE_CRC;
251
252 return C_OK;
253 }
254
255 Status EnsemblePatchApplication::SubpatchStreamSets(
256 SinkStreamSet* predicted_items,
257 SourceStream* correction,
258 SourceStreamSet* corrected_items,
259 SinkStream* corrected_items_storage) {
260 SinkStream linearized_predicted_items;
261 if (!predicted_items->CopyTo(&linearized_predicted_items))
262 return C_STREAM_ERROR;
263
264 SourceStream prediction;
265 prediction.Init(linearized_predicted_items);
266
267 Status status = ApplySimpleDelta(&prediction,
268 correction,
269 corrected_items_storage);
270 if (status != C_OK)
271 return status;
272
273 if (!corrected_items->Init(corrected_items_storage->Buffer(),
274 corrected_items_storage->Length()))
275 return C_STREAM_ERROR;
276
277 return C_OK;
278 }
279
280 Status ApplyEnsemblePatch(SourceStream* base,
281 SourceStream* patch,
282 SinkStream* output) {
283 Status status;
284 EnsemblePatchApplication patch_process;
285
286 status = patch_process.ReadHeader(patch);
287 if (status != C_OK)
288 return status;
289
290 status = patch_process.InitBase(Region(base->Buffer(), base->Remaining()));
291 if (status != C_OK)
292 return status;
293
294 status = patch_process.ValidateBase();
295 if (status != C_OK)
296 return status;
297
298 // The rest of the patch stream is a StreamSet.
299 SourceStreamSet patch_streams;
300 patch_streams.Init(patch);
301
302 SourceStream* transformation_descriptions = patch_streams.stream(0);
303 SourceStream* parameter_correction = patch_streams.stream(1);
304 SourceStream* transformed_elements_correction = patch_streams.stream(2);
305 SourceStream* ensemble_correction = patch_streams.stream(3);
306
307 status = patch_process.ReadInitialParameters(transformation_descriptions);
308 if (status != C_OK)
309 return status;
310
311 SinkStreamSet predicted_parameters;
312 status = patch_process.PredictTransformParameters(&predicted_parameters);
313 if (status != C_OK)
314 return status;
315
316 SourceStreamSet corrected_parameters;
317 status = patch_process.SubpatchTransformParameters(&predicted_parameters,
318 parameter_correction,
319 &corrected_parameters);
320 if (status != C_OK)
321 return status;
322
323 SinkStreamSet transformed_elements;
324 status = patch_process.TransformUp(&corrected_parameters,
325 &transformed_elements);
326 if (status != C_OK)
327 return status;
328
329 SourceStreamSet corrected_transformed_elements;
330 status = patch_process.SubpatchTransformedElements(
331 &transformed_elements,
332 transformed_elements_correction,
333 &corrected_transformed_elements);
334 if (status != C_OK)
335 return status;
336
337 SinkStream original_ensemble_and_corrected_base_elements;
338 status = patch_process.TransformDown(
339 &corrected_transformed_elements,
340 &original_ensemble_and_corrected_base_elements);
341 if (status != C_OK)
342 return status;
343
344 SourceStream final_patch_prediction;
345 final_patch_prediction.Init(original_ensemble_and_corrected_base_elements);
346 status = patch_process.SubpatchFinalOutput(&final_patch_prediction,
347 ensemble_correction, output);
348 if (status != C_OK)
349 return status;
350
351 return C_OK;
352 }
353
354 Status ApplyEnsemblePatch(const wchar_t* old_file_name,
355 const wchar_t* patch_file_name,
356 const wchar_t* new_file_name) {
357 Status status;
358
359 // First read enough of the patch file to validate the header is well-formed.
360 // A few varint32 numbers should fit in 100.
361 FilePath patch_file_path(patch_file_name);
362 const int BIG_ENOUGH_FOR_HEADER = 100;
363 char buffer[BIG_ENOUGH_FOR_HEADER];
364 int read_count =
365 file_util::ReadFile(patch_file_path, buffer, sizeof(buffer));
366 if (read_count < 0)
367 return C_READ_OPEN_ERROR;
368
369 // 'Dry-run' the first step of the patch process to validate format of header.
370 SourceStream patch_header_stream;
371 patch_header_stream.Init(buffer, read_count);
372 EnsemblePatchApplication patch_process;
373 status = patch_process.ReadHeader(&patch_header_stream);
374 if (status != C_OK)
375 return status;
376
377 // Header smells good so read the whole patch file for real.
378 std::string patch_file_buffer;
379 if (!file_util::ReadFileToString(patch_file_path, &patch_file_buffer))
380 return C_READ_ERROR;
381
382 // Read the old_file.
383 FilePath old_file_path(old_file_name);
384 std::string old_file_buffer;
385 if (!file_util::ReadFileToString(old_file_path, &old_file_buffer))
386 return C_READ_ERROR;
387
388 // Apply patch on streams.
389 SourceStream old_source_stream;
390 SourceStream patch_source_stream;
391 old_source_stream.Init(old_file_buffer);
392 patch_source_stream.Init(patch_file_buffer);
393 SinkStream new_sink_stream;
394 status = ApplyEnsemblePatch(&old_source_stream, &patch_source_stream,
395 &new_sink_stream);
396
397 // Write the patched data to |new_file_name|.
398 FilePath new_file_path(new_file_name);
399 int written =
400 file_util::WriteFile(
401 new_file_path,
402 reinterpret_cast<const char*>(new_sink_stream.Buffer()),
403 new_sink_stream.Length());
404 if (written == -1)
405 return C_WRITE_OPEN_ERROR;
406 if (written != new_sink_stream.Length())
407 return C_WRITE_ERROR;
408
409 return C_OK;
410 }
411
412 } // namespace
OLDNEW
« no previous file with comments | « third_party/courgette/ensemble.cc ('k') | third_party/courgette/ensemble_create.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698