| 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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 if (manifest.has_old_rootfs_info()) | 187 if (manifest.has_old_rootfs_info()) |
| 188 LogPartitionInfoHash(manifest.old_rootfs_info(), "old_rootfs_info"); | 188 LogPartitionInfoHash(manifest.old_rootfs_info(), "old_rootfs_info"); |
| 189 if (manifest.has_new_kernel_info()) | 189 if (manifest.has_new_kernel_info()) |
| 190 LogPartitionInfoHash(manifest.new_kernel_info(), "new_kernel_info"); | 190 LogPartitionInfoHash(manifest.new_kernel_info(), "new_kernel_info"); |
| 191 if (manifest.has_new_rootfs_info()) | 191 if (manifest.has_new_rootfs_info()) |
| 192 LogPartitionInfoHash(manifest.new_rootfs_info(), "new_rootfs_info"); | 192 LogPartitionInfoHash(manifest.new_rootfs_info(), "new_rootfs_info"); |
| 193 } | 193 } |
| 194 | 194 |
| 195 } // namespace {} | 195 } // namespace {} |
| 196 | 196 |
| 197 DeltaPerformer::MetadataParseResult DeltaPerformer::ParsePayloadMetadata( |
| 198 const std::vector<char>& payload, |
| 199 DeltaArchiveManifest* manifest, |
| 200 uint64_t* metadata_size) { |
| 201 if (payload.size() < strlen(kDeltaMagic) + |
| 202 kDeltaVersionLength + kDeltaProtobufLengthLength) { |
| 203 // Don't have enough bytes to know the protobuf length. |
| 204 return kMetadataParseInsufficientData; |
| 205 } |
| 206 if (memcmp(payload.data(), kDeltaMagic, strlen(kDeltaMagic)) != 0) { |
| 207 LOG(ERROR) << "Bad payload format -- invalid delta magic."; |
| 208 return kMetadataParseError; |
| 209 } |
| 210 uint64_t protobuf_length; |
| 211 COMPILE_ASSERT(sizeof(protobuf_length) == kDeltaProtobufLengthLength, |
| 212 protobuf_length_size_mismatch); |
| 213 memcpy(&protobuf_length, |
| 214 &payload[strlen(kDeltaMagic) + kDeltaVersionLength], |
| 215 kDeltaProtobufLengthLength); |
| 216 protobuf_length = be64toh(protobuf_length); // switch big endian to host |
| 217 if (payload.size() < strlen(kDeltaMagic) + kDeltaVersionLength + |
| 218 kDeltaProtobufLengthLength + protobuf_length) { |
| 219 return kMetadataParseInsufficientData; |
| 220 } |
| 221 // We have the full proto buffer in |payload|. Parse it. |
| 222 const int offset = strlen(kDeltaMagic) + kDeltaVersionLength + |
| 223 kDeltaProtobufLengthLength; |
| 224 if (!manifest->ParseFromArray(&payload[offset], protobuf_length)) { |
| 225 LOG(ERROR) << "Unable to parse manifest in update file."; |
| 226 return kMetadataParseError; |
| 227 } |
| 228 *metadata_size = strlen(kDeltaMagic) + kDeltaVersionLength + |
| 229 kDeltaProtobufLengthLength + protobuf_length; |
| 230 return kMetadataParseSuccess; |
| 231 } |
| 232 |
| 233 |
| 197 // Wrapper around write. Returns bytes written on success or | 234 // Wrapper around write. Returns bytes written on success or |
| 198 // -errno on error. | 235 // -errno on error. |
| 199 // This function performs as many actions as it can, given the amount of | 236 // This function performs as many actions as it can, given the amount of |
| 200 // data received thus far. | 237 // data received thus far. |
| 201 ssize_t DeltaPerformer::Write(const void* bytes, size_t count) { | 238 ssize_t DeltaPerformer::Write(const void* bytes, size_t count) { |
| 202 const char* c_bytes = reinterpret_cast<const char*>(bytes); | 239 const char* c_bytes = reinterpret_cast<const char*>(bytes); |
| 203 buffer_.insert(buffer_.end(), c_bytes, c_bytes + count); | 240 buffer_.insert(buffer_.end(), c_bytes, c_bytes + count); |
| 204 | 241 |
| 205 if (!manifest_valid_) { | 242 if (!manifest_valid_) { |
| 206 if (buffer_.size() < strlen(kDeltaMagic) + | 243 MetadataParseResult result = ParsePayloadMetadata(buffer_, |
| 207 kDeltaVersionLength + kDeltaProtobufLengthLength) { | 244 &manifest_, |
| 208 // Don't have enough bytes to know the protobuf length. | 245 &manifest_metadata_size_); |
| 209 return count; | 246 if (result == kMetadataParseError) { |
| 210 } | |
| 211 if (memcmp(buffer_.data(), kDeltaMagic, strlen(kDeltaMagic)) != 0) { | |
| 212 LOG(ERROR) << "Bad payload format -- invalid delta magic."; | |
| 213 return -EINVAL; | 247 return -EINVAL; |
| 214 } | 248 } |
| 215 uint64_t protobuf_length; | 249 if (result == kMetadataParseInsufficientData) { |
| 216 COMPILE_ASSERT(sizeof(protobuf_length) == kDeltaProtobufLengthLength, | |
| 217 protobuf_length_size_mismatch); | |
| 218 memcpy(&protobuf_length, | |
| 219 &buffer_[strlen(kDeltaMagic) + kDeltaVersionLength], | |
| 220 kDeltaProtobufLengthLength); | |
| 221 protobuf_length = be64toh(protobuf_length); // switch big endian to host | |
| 222 if (buffer_.size() < strlen(kDeltaMagic) + kDeltaVersionLength + | |
| 223 kDeltaProtobufLengthLength + protobuf_length) { | |
| 224 return count; | 250 return count; |
| 225 } | 251 } |
| 226 // We have the full proto buffer in buffer_. Parse it. | |
| 227 const int offset = strlen(kDeltaMagic) + kDeltaVersionLength + | |
| 228 kDeltaProtobufLengthLength; | |
| 229 if (!manifest_.ParseFromArray(&buffer_[offset], protobuf_length)) { | |
| 230 LOG(ERROR) << "Unable to parse manifest in update file."; | |
| 231 return -EINVAL; | |
| 232 } | |
| 233 // Remove protobuf and header info from buffer_, so buffer_ contains | 252 // Remove protobuf and header info from buffer_, so buffer_ contains |
| 234 // just data blobs | 253 // just data blobs |
| 235 manifest_metadata_size_ = strlen(kDeltaMagic) + kDeltaVersionLength + | |
| 236 kDeltaProtobufLengthLength + protobuf_length; | |
| 237 DiscardBufferHeadBytes(manifest_metadata_size_); | 254 DiscardBufferHeadBytes(manifest_metadata_size_); |
| 238 LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize, | 255 LOG_IF(WARNING, !prefs_->SetInt64(kPrefsManifestMetadataSize, |
| 239 manifest_metadata_size_)) | 256 manifest_metadata_size_)) |
| 240 << "Unable to save the manifest metadata size."; | 257 << "Unable to save the manifest metadata size."; |
| 241 manifest_valid_ = true; | 258 manifest_valid_ = true; |
| 242 LogPartitionInfo(manifest_); | 259 LogPartitionInfo(manifest_); |
| 243 if (!PrimeUpdateState()) { | 260 if (!PrimeUpdateState()) { |
| 244 LOG(ERROR) << "Unable to prime the update state."; | 261 LOG(ERROR) << "Unable to prime the update state."; |
| 245 return -EINVAL; | 262 return -EINVAL; |
| 246 } | 263 } |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 if (prefs_->GetInt64(kPrefsResumedUpdateFailures, &resumed_update_failures)) { | 762 if (prefs_->GetInt64(kPrefsResumedUpdateFailures, &resumed_update_failures)) { |
| 746 resumed_update_failures++; | 763 resumed_update_failures++; |
| 747 } else { | 764 } else { |
| 748 resumed_update_failures = 1; | 765 resumed_update_failures = 1; |
| 749 } | 766 } |
| 750 prefs_->SetInt64(kPrefsResumedUpdateFailures, resumed_update_failures); | 767 prefs_->SetInt64(kPrefsResumedUpdateFailures, resumed_update_failures); |
| 751 return true; | 768 return true; |
| 752 } | 769 } |
| 753 | 770 |
| 754 } // namespace chromeos_update_engine | 771 } // namespace chromeos_update_engine |
| OLD | NEW |