Fix resuming canceled updates.
Resuming an interrupted update was broken in several ways. First,
DeltaPerformer::CanResumeUpdate was checking for the number of
resume-failures to be more than the limit, not less. Then, the
resume logic didn't work for payload v2 when there was a
metadata signature included in the payload. Finally, resuming an
update after reading the payload signature (in payload v2) was not
updating the checkpoint, but storing the signature causing it to
attempt to parse it again and fail.
Bug: 27047026
Bug: chromium:590410
TEST=Manual procedure:
1. Start an update: update_engine_client --update ...
2. Cancel the update: update_engine_client --cancel
3. Re-start the same update: update_engine_client --update ...
-> The update should resume from the previous point.
Change-Id: I60134de155aa073a7ba91174cceea7297e5f8d17
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index cb3cdb5..f95679c 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -578,6 +578,9 @@
LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize,
metadata_size_))
<< "Unable to save the manifest metadata size.";
+ LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestSignatureSize,
+ metadata_signature_size_))
+ << "Unable to save the manifest signature size.";
if (!PrimeUpdateState()) {
*error = ErrorCode::kDownloadStateInitializationError;
@@ -686,8 +689,10 @@
}
// In major version 2, we don't add dummy operation to the payload.
+ // If we already extracted the signature we should skip this step.
if (major_payload_version_ == kBrilloMajorPayloadVersion &&
- manifest_.has_signatures_offset() && manifest_.has_signatures_size()) {
+ manifest_.has_signatures_offset() && manifest_.has_signatures_size() &&
+ signatures_message_data_.empty()) {
if (manifest_.signatures_offset() != buffer_offset_) {
LOG(ERROR) << "Payload signatures offset points to blob offset "
<< manifest_.signatures_offset()
@@ -706,6 +711,10 @@
return false;
}
DiscardBuffer(true, 0);
+ // Since we extracted the SignatureMessage we need to advance the
+ // checkpoint, otherwise we would reload the signature and try to extract
+ // it again.
+ CheckpointUpdateProgress();
}
return true;
@@ -1666,8 +1675,10 @@
return false;
int64_t resumed_update_failures;
- if (!(prefs->GetInt64(kPrefsResumedUpdateFailures, &resumed_update_failures)
- && resumed_update_failures > kMaxResumedUpdateFailures))
+ // Note that storing this value is optional, but if it is there it should not
+ // be more than the limit.
+ if (prefs->GetInt64(kPrefsResumedUpdateFailures, &resumed_update_failures) &&
+ resumed_update_failures > kMaxResumedUpdateFailures)
return false;
// Sanity check the rest.
@@ -1686,6 +1697,12 @@
manifest_metadata_size > 0))
return false;
+ int64_t manifest_signature_size = 0;
+ if (!(prefs->GetInt64(kPrefsManifestSignatureSize,
+ &manifest_signature_size) &&
+ manifest_signature_size >= 0))
+ return false;
+
return true;
}
@@ -1700,6 +1717,7 @@
prefs->SetString(kPrefsUpdateStateSignedSHA256Context, "");
prefs->SetString(kPrefsUpdateStateSignatureBlob, "");
prefs->SetInt64(kPrefsManifestMetadataSize, -1);
+ prefs->SetInt64(kPrefsManifestSignatureSize, -1);
prefs->SetInt64(kPrefsResumedUpdateFailures, 0);
}
return true;
@@ -1786,6 +1804,12 @@
manifest_metadata_size > 0);
metadata_size_ = manifest_metadata_size;
+ int64_t manifest_signature_size = 0;
+ TEST_AND_RETURN_FALSE(
+ prefs_->GetInt64(kPrefsManifestSignatureSize, &manifest_signature_size) &&
+ manifest_signature_size >= 0);
+ metadata_signature_size_ = manifest_signature_size;
+
// Advance the download progress to reflect what doesn't need to be
// re-downloaded.
total_bytes_received_ += buffer_offset_;