| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "update_engine/delta_performer.h" | 5 #include "update_engine/delta_performer.h" |
| 6 | 6 |
| 7 #include <endian.h> | 7 #include <endian.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 } | 191 } |
| 192 // Remove protobuf and header info from buffer_, so buffer_ contains | 192 // Remove protobuf and header info from buffer_, so buffer_ contains |
| 193 // just data blobs | 193 // just data blobs |
| 194 manifest_metadata_size_ = strlen(kDeltaMagic) + kDeltaVersionLength + | 194 manifest_metadata_size_ = strlen(kDeltaMagic) + kDeltaVersionLength + |
| 195 kDeltaProtobufLengthLength + protobuf_length; | 195 kDeltaProtobufLengthLength + protobuf_length; |
| 196 DiscardBufferHeadBytes(manifest_metadata_size_); | 196 DiscardBufferHeadBytes(manifest_metadata_size_); |
| 197 LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize, | 197 LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize, |
| 198 manifest_metadata_size_)) | 198 manifest_metadata_size_)) |
| 199 << "Unable to save the manifest metadata size."; | 199 << "Unable to save the manifest metadata size."; |
| 200 manifest_valid_ = true; | 200 manifest_valid_ = true; |
| 201 block_size_ = manifest_.block_size(); | 201 if (!PrimeUpdateState()) { |
| 202 LOG(ERROR) << "Unable to prime the update state."; |
| 203 return -EINVAL; |
| 204 } |
| 202 } | 205 } |
| 203 ssize_t total_operations = manifest_.install_operations_size() + | 206 ssize_t total_operations = manifest_.install_operations_size() + |
| 204 manifest_.kernel_install_operations_size(); | 207 manifest_.kernel_install_operations_size(); |
| 205 while (next_operation_num_ < total_operations) { | 208 while (next_operation_num_ < total_operations) { |
| 206 const DeltaArchiveManifest_InstallOperation &op = | 209 const DeltaArchiveManifest_InstallOperation &op = |
| 207 next_operation_num_ < manifest_.install_operations_size() ? | 210 next_operation_num_ < manifest_.install_operations_size() ? |
| 208 manifest_.install_operations(next_operation_num_) : | 211 manifest_.install_operations(next_operation_num_) : |
| 209 manifest_.kernel_install_operations( | 212 manifest_.kernel_install_operations( |
| 210 next_operation_num_ - manifest_.install_operations_size()); | 213 next_operation_num_ - manifest_.install_operations_size()); |
| 211 if (!CanPerformInstallOperation(op)) | 214 if (!CanPerformInstallOperation(op)) |
| 212 break; | 215 break; |
| 213 ScopedTerminatorExitUnblocker exit_unblocker = | 216 ScopedTerminatorExitUnblocker exit_unblocker = |
| 214 ScopedTerminatorExitUnblocker(); // Avoids a compiler unused var bug. | 217 ScopedTerminatorExitUnblocker(); // Avoids a compiler unused var bug. |
| 215 // Log every thousandth operation, and also the first and last ones | 218 // Log every thousandth operation, and also the first and last ones |
| 216 if ((next_operation_num_ % 1000 == 0) || | 219 if ((next_operation_num_ % 1000 == 0) || |
| 217 (next_operation_num_ + 1 == total_operations)) { | 220 (next_operation_num_ + 1 == total_operations)) { |
| 218 LOG(INFO) << "Performing operation " << (next_operation_num_ + 1) << "/" | 221 LOG(INFO) << "Performing operation " << (next_operation_num_ + 1) << "/" |
| 219 << total_operations; | 222 << total_operations; |
| 220 } | 223 } |
| 221 bool is_kernel_partition = | 224 bool is_kernel_partition = |
| 222 (next_operation_num_ >= manifest_.install_operations_size()); | 225 (next_operation_num_ >= manifest_.install_operations_size()); |
| 223 // If about to start a non-idempotent operation, clear the update state so | 226 // If about to start a non-idempotent operation, clear the update state so |
| 224 // that if the operation gets interrupted, we don't try to resume the | 227 // that if the operation gets interrupted, we don't try to resume the |
| 225 // update. | 228 // update. |
| 226 if (!IsIdempotentOperation(op)) { | 229 if (!IsIdempotentOperation(op)) { |
| 227 Terminator::set_exit_blocked(true); | 230 Terminator::set_exit_blocked(true); |
| 228 ResetUpdateProgress(prefs_); | 231 ResetUpdateProgress(prefs_, true); |
| 229 } | 232 } |
| 230 if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE || | 233 if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE || |
| 231 op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) { | 234 op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) { |
| 232 if (!PerformReplaceOperation(op, is_kernel_partition)) { | 235 if (!PerformReplaceOperation(op, is_kernel_partition)) { |
| 233 LOG(ERROR) << "Failed to perform replace operation " | 236 LOG(ERROR) << "Failed to perform replace operation " |
| 234 << next_operation_num_; | 237 << next_operation_num_; |
| 235 return -EINVAL; | 238 return -EINVAL; |
| 236 } | 239 } |
| 237 } else if (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE) { | 240 } else if (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE) { |
| 238 if (!PerformMoveOperation(op, is_kernel_partition)) { | 241 if (!PerformMoveOperation(op, is_kernel_partition)) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 bool DeltaPerformer::PerformReplaceOperation( | 277 bool DeltaPerformer::PerformReplaceOperation( |
| 275 const DeltaArchiveManifest_InstallOperation& operation, | 278 const DeltaArchiveManifest_InstallOperation& operation, |
| 276 bool is_kernel_partition) { | 279 bool is_kernel_partition) { |
| 277 CHECK(operation.type() == \ | 280 CHECK(operation.type() == \ |
| 278 DeltaArchiveManifest_InstallOperation_Type_REPLACE || \ | 281 DeltaArchiveManifest_InstallOperation_Type_REPLACE || \ |
| 279 operation.type() == \ | 282 operation.type() == \ |
| 280 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ); | 283 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ); |
| 281 | 284 |
| 282 // Since we delete data off the beginning of the buffer as we use it, | 285 // Since we delete data off the beginning of the buffer as we use it, |
| 283 // the data we need should be exactly at the beginning of the buffer. | 286 // the data we need should be exactly at the beginning of the buffer. |
| 284 CHECK_EQ(buffer_offset_, operation.data_offset()); | 287 TEST_AND_RETURN_FALSE(buffer_offset_ == operation.data_offset()); |
| 285 CHECK_GE(buffer_.size(), operation.data_length()); | 288 TEST_AND_RETURN_FALSE(buffer_.size() >= operation.data_length()); |
| 286 | 289 |
| 287 // Extract the signature message if it's in this operation. | 290 // Extract the signature message if it's in this operation. |
| 288 ExtractSignatureMessage(operation); | 291 ExtractSignatureMessage(operation); |
| 289 | 292 |
| 290 DirectExtentWriter direct_writer; | 293 DirectExtentWriter direct_writer; |
| 291 ZeroPadExtentWriter zero_pad_writer(&direct_writer); | 294 ZeroPadExtentWriter zero_pad_writer(&direct_writer); |
| 292 scoped_ptr<BzipExtentWriter> bzip_writer; | 295 scoped_ptr<BzipExtentWriter> bzip_writer; |
| 293 | 296 |
| 294 // Since bzip decompression is optional, we have a variable writer that will | 297 // Since bzip decompression is optional, we have a variable writer that will |
| 295 // point to one of the ExtentWriter objects above. | 298 // point to one of the ExtentWriter objects above. |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 ret.resize(ret.size() - 1); // Strip trailing comma off | 401 ret.resize(ret.size() - 1); // Strip trailing comma off |
| 399 *positions_string = ret; | 402 *positions_string = ret; |
| 400 return true; | 403 return true; |
| 401 } | 404 } |
| 402 | 405 |
| 403 bool DeltaPerformer::PerformBsdiffOperation( | 406 bool DeltaPerformer::PerformBsdiffOperation( |
| 404 const DeltaArchiveManifest_InstallOperation& operation, | 407 const DeltaArchiveManifest_InstallOperation& operation, |
| 405 bool is_kernel_partition) { | 408 bool is_kernel_partition) { |
| 406 // Since we delete data off the beginning of the buffer as we use it, | 409 // Since we delete data off the beginning of the buffer as we use it, |
| 407 // the data we need should be exactly at the beginning of the buffer. | 410 // the data we need should be exactly at the beginning of the buffer. |
| 408 CHECK_EQ(buffer_offset_, operation.data_offset()); | 411 TEST_AND_RETURN_FALSE(buffer_offset_ == operation.data_offset()); |
| 409 CHECK_GE(buffer_.size(), operation.data_length()); | 412 TEST_AND_RETURN_FALSE(buffer_.size() >= operation.data_length()); |
| 410 | 413 |
| 411 string input_positions; | 414 string input_positions; |
| 412 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.src_extents(), | 415 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.src_extents(), |
| 413 block_size_, | 416 block_size_, |
| 414 operation.src_length(), | 417 operation.src_length(), |
| 415 &input_positions)); | 418 &input_positions)); |
| 416 string output_positions; | 419 string output_positions; |
| 417 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.dst_extents(), | 420 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.dst_extents(), |
| 418 block_size_, | 421 block_size_, |
| 419 operation.dst_length(), | 422 operation.dst_length(), |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 !sha256_context.empty()); | 567 !sha256_context.empty()); |
| 565 | 568 |
| 566 int64_t manifest_metadata_size = 0; | 569 int64_t manifest_metadata_size = 0; |
| 567 TEST_AND_RETURN_FALSE(prefs->GetInt64(kPrefsManifestMetadataSize, | 570 TEST_AND_RETURN_FALSE(prefs->GetInt64(kPrefsManifestMetadataSize, |
| 568 &manifest_metadata_size) && | 571 &manifest_metadata_size) && |
| 569 manifest_metadata_size > 0); | 572 manifest_metadata_size > 0); |
| 570 | 573 |
| 571 return true; | 574 return true; |
| 572 } | 575 } |
| 573 | 576 |
| 574 bool DeltaPerformer::ResetUpdateProgress(PrefsInterface* prefs) { | 577 bool DeltaPerformer::ResetUpdateProgress(PrefsInterface* prefs, bool quick) { |
| 575 TEST_AND_RETURN_FALSE(prefs->SetInt64(kPrefsUpdateStateNextOperation, | 578 TEST_AND_RETURN_FALSE(prefs->SetInt64(kPrefsUpdateStateNextOperation, |
| 576 kUpdateStateOperationInvalid)); | 579 kUpdateStateOperationInvalid)); |
| 580 if (!quick) { |
| 581 prefs->SetString(kPrefsUpdateCheckResponseHash, ""); |
| 582 prefs->SetInt64(kPrefsUpdateStateNextDataOffset, -1); |
| 583 prefs->SetString(kPrefsUpdateStateSHA256Context, ""); |
| 584 prefs->SetString(kPrefsUpdateStateSignedSHA256Context, ""); |
| 585 prefs->SetInt64(kPrefsManifestMetadataSize, -1); |
| 586 } |
| 577 return true; | 587 return true; |
| 578 } | 588 } |
| 579 | 589 |
| 580 bool DeltaPerformer::CheckpointUpdateProgress() { | 590 bool DeltaPerformer::CheckpointUpdateProgress() { |
| 581 Terminator::set_exit_blocked(true); | 591 Terminator::set_exit_blocked(true); |
| 582 if (last_updated_buffer_offset_ != buffer_offset_) { | 592 if (last_updated_buffer_offset_ != buffer_offset_) { |
| 583 // Resets the progress in case we die in the middle of the state update. | 593 // Resets the progress in case we die in the middle of the state update. |
| 584 ResetUpdateProgress(prefs_); | 594 ResetUpdateProgress(prefs_, true); |
| 585 TEST_AND_RETURN_FALSE( | 595 TEST_AND_RETURN_FALSE( |
| 586 prefs_->SetString(kPrefsUpdateStateSHA256Context, | 596 prefs_->SetString(kPrefsUpdateStateSHA256Context, |
| 587 hash_calculator_.GetContext())); | 597 hash_calculator_.GetContext())); |
| 588 TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextDataOffset, | 598 TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextDataOffset, |
| 589 buffer_offset_)); | 599 buffer_offset_)); |
| 590 last_updated_buffer_offset_ = buffer_offset_; | 600 last_updated_buffer_offset_ = buffer_offset_; |
| 591 } | 601 } |
| 592 TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextOperation, | 602 TEST_AND_RETURN_FALSE(prefs_->SetInt64(kPrefsUpdateStateNextOperation, |
| 593 next_operation_num_)); | 603 next_operation_num_)); |
| 594 return true; | 604 return true; |
| 595 } | 605 } |
| 596 | 606 |
| 607 bool DeltaPerformer::PrimeUpdateState() { |
| 608 CHECK(manifest_valid_); |
| 609 block_size_ = manifest_.block_size(); |
| 610 |
| 611 int64_t next_operation = kUpdateStateOperationInvalid; |
| 612 if (!prefs_->GetInt64(kPrefsUpdateStateNextOperation, &next_operation) || |
| 613 next_operation == kUpdateStateOperationInvalid || |
| 614 next_operation <= 0) { |
| 615 // Initiating a new update, no more state needs to be initialized. |
| 616 return true; |
| 617 } |
| 618 next_operation_num_ = next_operation; |
| 619 |
| 620 // Resuming an update -- load the rest of the update state. |
| 621 int64_t next_data_offset = -1; |
| 622 TEST_AND_RETURN_FALSE(prefs_->GetInt64(kPrefsUpdateStateNextDataOffset, |
| 623 &next_data_offset) && |
| 624 next_data_offset >= 0); |
| 625 buffer_offset_ = next_data_offset; |
| 626 |
| 627 // The signed hash context may be empty if the interrupted update didn't reach |
| 628 // the signature blob. |
| 629 prefs_->GetString(kPrefsUpdateStateSignedSHA256Context, |
| 630 &signed_hash_context_); |
| 631 |
| 632 string hash_context; |
| 633 TEST_AND_RETURN_FALSE(prefs_->GetString(kPrefsUpdateStateSHA256Context, |
| 634 &hash_context) && |
| 635 hash_calculator_.SetContext(hash_context)); |
| 636 |
| 637 int64_t manifest_metadata_size = 0; |
| 638 TEST_AND_RETURN_FALSE(prefs_->GetInt64(kPrefsManifestMetadataSize, |
| 639 &manifest_metadata_size) && |
| 640 manifest_metadata_size > 0); |
| 641 manifest_metadata_size_ = manifest_metadata_size; |
| 642 |
| 643 return true; |
| 644 } |
| 645 |
| 597 } // namespace chromeos_update_engine | 646 } // namespace chromeos_update_engine |
| OLD | NEW |