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 |