Index: delta_performer.cc |
diff --git a/delta_performer.cc b/delta_performer.cc |
index 10031eb8f8d5225ee4719d6a3ad648cf275676d6..0eccb09782b7d93db1acaa19743536eff80f0030 100644 |
--- a/delta_performer.cc |
+++ b/delta_performer.cc |
@@ -198,7 +198,10 @@ ssize_t DeltaPerformer::Write(const void* bytes, size_t count) { |
manifest_metadata_size_)) |
<< "Unable to save the manifest metadata size."; |
manifest_valid_ = true; |
- block_size_ = manifest_.block_size(); |
+ if (!PrimeUpdateState()) { |
+ LOG(ERROR) << "Unable to prime the update state."; |
+ return -EINVAL; |
+ } |
} |
ssize_t total_operations = manifest_.install_operations_size() + |
manifest_.kernel_install_operations_size(); |
@@ -225,7 +228,7 @@ ssize_t DeltaPerformer::Write(const void* bytes, size_t count) { |
// update. |
if (!IsIdempotentOperation(op)) { |
Terminator::set_exit_blocked(true); |
- ResetUpdateProgress(prefs_); |
+ ResetUpdateProgress(prefs_, true); |
} |
if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE || |
op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) { |
@@ -281,8 +284,8 @@ bool DeltaPerformer::PerformReplaceOperation( |
// Since we delete data off the beginning of the buffer as we use it, |
// the data we need should be exactly at the beginning of the buffer. |
- CHECK_EQ(buffer_offset_, operation.data_offset()); |
- CHECK_GE(buffer_.size(), operation.data_length()); |
+ TEST_AND_RETURN_FALSE(buffer_offset_ == operation.data_offset()); |
+ TEST_AND_RETURN_FALSE(buffer_.size() >= operation.data_length()); |
// Extract the signature message if it's in this operation. |
ExtractSignatureMessage(operation); |
@@ -405,8 +408,8 @@ bool DeltaPerformer::PerformBsdiffOperation( |
bool is_kernel_partition) { |
// Since we delete data off the beginning of the buffer as we use it, |
// the data we need should be exactly at the beginning of the buffer. |
- CHECK_EQ(buffer_offset_, operation.data_offset()); |
- CHECK_GE(buffer_.size(), operation.data_length()); |
+ TEST_AND_RETURN_FALSE(buffer_offset_ == operation.data_offset()); |
+ TEST_AND_RETURN_FALSE(buffer_.size() >= operation.data_length()); |
string input_positions; |
TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.src_extents(), |
@@ -571,9 +574,16 @@ bool DeltaPerformer::CanResumeUpdate(PrefsInterface* prefs, |
return true; |
} |
-bool DeltaPerformer::ResetUpdateProgress(PrefsInterface* prefs) { |
+bool DeltaPerformer::ResetUpdateProgress(PrefsInterface* prefs, bool quick) { |
TEST_AND_RETURN_FALSE(prefs->SetInt64(kPrefsUpdateStateNextOperation, |
kUpdateStateOperationInvalid)); |
+ if (!quick) { |
+ prefs->SetString(kPrefsUpdateCheckResponseHash, ""); |
+ prefs->SetInt64(kPrefsUpdateStateNextDataOffset, -1); |
+ prefs->SetString(kPrefsUpdateStateSHA256Context, ""); |
+ prefs->SetString(kPrefsUpdateStateSignedSHA256Context, ""); |
+ prefs->SetInt64(kPrefsManifestMetadataSize, -1); |
+ } |
return true; |
} |
@@ -581,7 +591,7 @@ bool DeltaPerformer::CheckpointUpdateProgress() { |
Terminator::set_exit_blocked(true); |
if (last_updated_buffer_offset_ != buffer_offset_) { |
// Resets the progress in case we die in the middle of the state update. |
- ResetUpdateProgress(prefs_); |
+ ResetUpdateProgress(prefs_, true); |
TEST_AND_RETURN_FALSE( |
prefs_->SetString(kPrefsUpdateStateSHA256Context, |
hash_calculator_.GetContext())); |
@@ -594,4 +604,43 @@ bool DeltaPerformer::CheckpointUpdateProgress() { |
return true; |
} |
+bool DeltaPerformer::PrimeUpdateState() { |
+ CHECK(manifest_valid_); |
+ block_size_ = manifest_.block_size(); |
+ |
+ int64_t next_operation = kUpdateStateOperationInvalid; |
+ if (!prefs_->GetInt64(kPrefsUpdateStateNextOperation, &next_operation) || |
+ next_operation == kUpdateStateOperationInvalid || |
+ next_operation <= 0) { |
+ // Initiating a new update, no more state needs to be initialized. |
+ return true; |
+ } |
+ next_operation_num_ = next_operation; |
+ |
+ // Resuming an update -- load the rest of the update state. |
+ int64_t next_data_offset = -1; |
+ TEST_AND_RETURN_FALSE(prefs_->GetInt64(kPrefsUpdateStateNextDataOffset, |
+ &next_data_offset) && |
+ next_data_offset >= 0); |
+ buffer_offset_ = next_data_offset; |
+ |
+ // The signed hash context may be empty if the interrupted update didn't reach |
+ // the signature blob. |
+ prefs_->GetString(kPrefsUpdateStateSignedSHA256Context, |
+ &signed_hash_context_); |
+ |
+ string hash_context; |
+ TEST_AND_RETURN_FALSE(prefs_->GetString(kPrefsUpdateStateSHA256Context, |
+ &hash_context) && |
+ hash_calculator_.SetContext(hash_context)); |
+ |
+ int64_t manifest_metadata_size = 0; |
+ TEST_AND_RETURN_FALSE(prefs_->GetInt64(kPrefsManifestMetadataSize, |
+ &manifest_metadata_size) && |
+ manifest_metadata_size > 0); |
+ manifest_metadata_size_ = manifest_metadata_size; |
+ |
+ return true; |
+} |
+ |
} // namespace chromeos_update_engine |