| 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_diff_generator.h" | 5 #include "update_engine/delta_diff_generator.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <inttypes.h> | 9 #include <inttypes.h> |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 TEST_AND_RETURN_FALSE( | 584 TEST_AND_RETURN_FALSE( |
| 585 GatherExtents(new_filename, operation.mutable_dst_extents())); | 585 GatherExtents(new_filename, operation.mutable_dst_extents())); |
| 586 operation.set_dst_length(new_data.size()); | 586 operation.set_dst_length(new_data.size()); |
| 587 | 587 |
| 588 out_data->swap(data); | 588 out_data->swap(data); |
| 589 *out_op = operation; | 589 *out_op = operation; |
| 590 | 590 |
| 591 return true; | 591 return true; |
| 592 } | 592 } |
| 593 | 593 |
| 594 bool InitializePartitionInfo(const string& partition, PartitionInfo* info) { | 594 bool InitializePartitionInfo(bool is_kernel, |
| 595 const off_t size = utils::FileSize(partition); | 595 const string& partition, |
| 596 TEST_AND_RETURN_FALSE(size >= 0); | 596 PartitionInfo* info) { |
| 597 int64_t size = 0; |
| 598 if (is_kernel) { |
| 599 size = utils::FileSize(partition); |
| 600 } else { |
| 601 int block_count = 0, block_size = 0; |
| 602 TEST_AND_RETURN_FALSE(utils::GetFilesystemSize(partition, |
| 603 &block_count, |
| 604 &block_size)); |
| 605 size = static_cast<int64_t>(block_count) * block_size; |
| 606 } |
| 607 TEST_AND_RETURN_FALSE(size > 0); |
| 597 info->set_size(size); | 608 info->set_size(size); |
| 598 OmahaHashCalculator hasher; | 609 OmahaHashCalculator hasher; |
| 599 TEST_AND_RETURN_FALSE(hasher.UpdateFile(partition, -1) == size); | 610 TEST_AND_RETURN_FALSE(hasher.UpdateFile(partition, size) == size); |
| 600 TEST_AND_RETURN_FALSE(hasher.Finalize()); | 611 TEST_AND_RETURN_FALSE(hasher.Finalize()); |
| 601 const vector<char>& hash = hasher.raw_hash(); | 612 const vector<char>& hash = hasher.raw_hash(); |
| 602 info->set_hash(hash.data(), hash.size()); | 613 info->set_hash(hash.data(), hash.size()); |
| 603 return true; | 614 return true; |
| 604 } | 615 } |
| 605 | 616 |
| 606 bool InitializePartitionInfos(const string& old_kernel, | 617 bool InitializePartitionInfos(const string& old_kernel, |
| 607 const string& new_kernel, | 618 const string& new_kernel, |
| 608 const string& old_rootfs, | 619 const string& old_rootfs, |
| 609 const string& new_rootfs, | 620 const string& new_rootfs, |
| 610 DeltaArchiveManifest* manifest) { | 621 DeltaArchiveManifest* manifest) { |
| 611 if (!old_kernel.empty()) { | 622 if (!old_kernel.empty()) { |
| 612 TEST_AND_RETURN_FALSE( | 623 TEST_AND_RETURN_FALSE( |
| 613 InitializePartitionInfo(old_kernel, | 624 InitializePartitionInfo(true, |
| 625 old_kernel, |
| 614 manifest->mutable_old_kernel_info())); | 626 manifest->mutable_old_kernel_info())); |
| 615 } | 627 } |
| 616 TEST_AND_RETURN_FALSE( | 628 TEST_AND_RETURN_FALSE( |
| 617 InitializePartitionInfo(new_kernel, manifest->mutable_new_kernel_info())); | 629 InitializePartitionInfo(true, |
| 630 new_kernel, |
| 631 manifest->mutable_new_kernel_info())); |
| 618 if (!old_rootfs.empty()) { | 632 if (!old_rootfs.empty()) { |
| 619 TEST_AND_RETURN_FALSE( | 633 TEST_AND_RETURN_FALSE( |
| 620 InitializePartitionInfo(old_rootfs, | 634 InitializePartitionInfo(false, |
| 635 old_rootfs, |
| 621 manifest->mutable_old_rootfs_info())); | 636 manifest->mutable_old_rootfs_info())); |
| 622 } | 637 } |
| 623 TEST_AND_RETURN_FALSE( | 638 TEST_AND_RETURN_FALSE( |
| 624 InitializePartitionInfo(new_rootfs, manifest->mutable_new_rootfs_info())); | 639 InitializePartitionInfo(false, |
| 640 new_rootfs, |
| 641 manifest->mutable_new_rootfs_info())); |
| 625 return true; | 642 return true; |
| 626 } | 643 } |
| 627 | 644 |
| 628 namespace { | 645 namespace { |
| 629 | 646 |
| 630 // Takes a collection (vector or RepeatedPtrField) of Extent and | 647 // Takes a collection (vector or RepeatedPtrField) of Extent and |
| 631 // returns a vector of the blocks referenced, in order. | 648 // returns a vector of the blocks referenced, in order. |
| 632 template<typename T> | 649 template<typename T> |
| 633 vector<uint64_t> ExpandExtents(const T& extents) { | 650 vector<uint64_t> ExpandExtents(const T& extents) { |
| 634 vector<uint64_t> ret; | 651 vector<uint64_t> ret; |
| (...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 graph_utils::DumpGraph(*graph); | 1174 graph_utils::DumpGraph(*graph); |
| 1158 CHECK(NoTempBlocksRemain(*graph)); | 1175 CHECK(NoTempBlocksRemain(*graph)); |
| 1159 LOG(INFO) << "done making sure all temp blocks are allocated"; | 1176 LOG(INFO) << "done making sure all temp blocks are allocated"; |
| 1160 return true; | 1177 return true; |
| 1161 } | 1178 } |
| 1162 | 1179 |
| 1163 bool DeltaDiffGenerator::ReadFullUpdateFromDisk( | 1180 bool DeltaDiffGenerator::ReadFullUpdateFromDisk( |
| 1164 Graph* graph, | 1181 Graph* graph, |
| 1165 const std::string& new_kernel_part, | 1182 const std::string& new_kernel_part, |
| 1166 const std::string& new_image, | 1183 const std::string& new_image, |
| 1184 off_t image_size, |
| 1167 int fd, | 1185 int fd, |
| 1168 off_t* data_file_size, | 1186 off_t* data_file_size, |
| 1169 off_t chunk_size, | 1187 off_t chunk_size, |
| 1170 vector<DeltaArchiveManifest_InstallOperation>* kernel_ops, | 1188 vector<DeltaArchiveManifest_InstallOperation>* kernel_ops, |
| 1171 std::vector<Vertex::Index>* final_order) { | 1189 std::vector<Vertex::Index>* final_order) { |
| 1172 TEST_AND_RETURN_FALSE(chunk_size > 0); | 1190 TEST_AND_RETURN_FALSE(chunk_size > 0); |
| 1173 TEST_AND_RETURN_FALSE((chunk_size % kBlockSize) == 0); | 1191 TEST_AND_RETURN_FALSE((chunk_size % kBlockSize) == 0); |
| 1174 | 1192 |
| 1175 // Get the sizes early in the function, so we can fail fast if the user | 1193 // Get the sizes early in the function, so we can fail fast if the user |
| 1176 // passed us bad paths. | 1194 // passed us bad paths. |
| 1177 const off_t image_size = utils::FileSize(new_image); | 1195 TEST_AND_RETURN_FALSE(image_size >= 0 && |
| 1178 TEST_AND_RETURN_FALSE(image_size >= 0); | 1196 image_size <= utils::FileSize(new_image)); |
| 1179 const off_t kernel_size = utils::FileSize(new_kernel_part); | 1197 const off_t kernel_size = utils::FileSize(new_kernel_part); |
| 1180 TEST_AND_RETURN_FALSE(kernel_size >= 0); | 1198 TEST_AND_RETURN_FALSE(kernel_size >= 0); |
| 1181 | 1199 |
| 1182 off_t part_sizes[] = { image_size, kernel_size }; | 1200 off_t part_sizes[] = { image_size, kernel_size }; |
| 1183 string paths[] = { new_image, new_kernel_part }; | 1201 string paths[] = { new_image, new_kernel_part }; |
| 1184 | 1202 |
| 1185 for (int partition = 0; partition < 2; ++partition) { | 1203 for (int partition = 0; partition < 2; ++partition) { |
| 1186 const string& path = paths[partition]; | 1204 const string& path = paths[partition]; |
| 1187 LOG(INFO) << "compressing " << path; | 1205 LOG(INFO) << "compressing " << path; |
| 1188 | 1206 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 | 1257 |
| 1240 bool DeltaDiffGenerator::GenerateDeltaUpdateFile( | 1258 bool DeltaDiffGenerator::GenerateDeltaUpdateFile( |
| 1241 const string& old_root, | 1259 const string& old_root, |
| 1242 const string& old_image, | 1260 const string& old_image, |
| 1243 const string& new_root, | 1261 const string& new_root, |
| 1244 const string& new_image, | 1262 const string& new_image, |
| 1245 const string& old_kernel_part, | 1263 const string& old_kernel_part, |
| 1246 const string& new_kernel_part, | 1264 const string& new_kernel_part, |
| 1247 const string& output_path, | 1265 const string& output_path, |
| 1248 const string& private_key_path) { | 1266 const string& private_key_path) { |
| 1249 struct stat old_image_stbuf; | 1267 int old_image_block_count = 0, old_image_block_size = 0; |
| 1250 struct stat new_image_stbuf; | 1268 int new_image_block_count = 0, new_image_block_size = 0; |
| 1251 TEST_AND_RETURN_FALSE_ERRNO(stat(new_image.c_str(), &new_image_stbuf) == 0); | 1269 TEST_AND_RETURN_FALSE(utils::GetFilesystemSize(new_image, |
| 1270 &new_image_block_count, |
| 1271 &new_image_block_size)); |
| 1252 if (!old_image.empty()) { | 1272 if (!old_image.empty()) { |
| 1253 TEST_AND_RETURN_FALSE_ERRNO(stat(old_image.c_str(), &old_image_stbuf) == 0); | 1273 TEST_AND_RETURN_FALSE(utils::GetFilesystemSize(old_image, |
| 1254 LOG_IF(WARNING, new_image_stbuf.st_size != old_image_stbuf.st_size) | 1274 &old_image_block_count, |
| 1255 << "Old and new images are different sizes."; | 1275 &old_image_block_size)); |
| 1256 LOG_IF(FATAL, old_image_stbuf.st_size % kBlockSize) | 1276 TEST_AND_RETURN_FALSE(old_image_block_size == new_image_block_size); |
| 1257 << "Old image not a multiple of block size " << kBlockSize; | 1277 LOG_IF(WARNING, old_image_block_count != new_image_block_count) |
| 1278 << "Old and new images have different block counts."; |
| 1258 // Sanity check kernel partition arg | 1279 // Sanity check kernel partition arg |
| 1259 TEST_AND_RETURN_FALSE(utils::FileSize(old_kernel_part) >= 0); | 1280 TEST_AND_RETURN_FALSE(utils::FileSize(old_kernel_part) >= 0); |
| 1260 } else { | |
| 1261 old_image_stbuf.st_size = 0; | |
| 1262 } | 1281 } |
| 1263 LOG_IF(FATAL, new_image_stbuf.st_size % kBlockSize) | |
| 1264 << "New image not a multiple of block size " << kBlockSize; | |
| 1265 | |
| 1266 // Sanity check kernel partition arg | 1282 // Sanity check kernel partition arg |
| 1267 TEST_AND_RETURN_FALSE(utils::FileSize(new_kernel_part) >= 0); | 1283 TEST_AND_RETURN_FALSE(utils::FileSize(new_kernel_part) >= 0); |
| 1268 | 1284 |
| 1269 vector<Block> blocks(max(old_image_stbuf.st_size / kBlockSize, | 1285 vector<Block> blocks(max(old_image_block_count, new_image_block_count)); |
| 1270 new_image_stbuf.st_size / kBlockSize)); | 1286 LOG(INFO) << "Invalid block index: " << Vertex::kInvalidIndex; |
| 1271 LOG(INFO) << "invalid: " << Vertex::kInvalidIndex; | 1287 LOG(INFO) << "Block count: " << blocks.size(); |
| 1272 LOG(INFO) << "len: " << blocks.size(); | |
| 1273 for (vector<Block>::size_type i = 0; i < blocks.size(); i++) { | 1288 for (vector<Block>::size_type i = 0; i < blocks.size(); i++) { |
| 1274 CHECK(blocks[i].reader == Vertex::kInvalidIndex); | 1289 CHECK(blocks[i].reader == Vertex::kInvalidIndex); |
| 1275 CHECK(blocks[i].writer == Vertex::kInvalidIndex); | 1290 CHECK(blocks[i].writer == Vertex::kInvalidIndex); |
| 1276 } | 1291 } |
| 1277 Graph graph; | 1292 Graph graph; |
| 1278 CheckGraph(graph); | 1293 CheckGraph(graph); |
| 1279 | 1294 |
| 1280 const string kTempFileTemplate("/tmp/CrAU_temp_data.XXXXXX"); | 1295 const string kTempFileTemplate("/tmp/CrAU_temp_data.XXXXXX"); |
| 1281 string temp_file_path; | 1296 string temp_file_path; |
| 1282 off_t data_file_size = 0; | 1297 off_t data_file_size = 0; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1326 LOG(INFO) << "Done creating edges"; | 1341 LOG(INFO) << "Done creating edges"; |
| 1327 CheckGraph(graph); | 1342 CheckGraph(graph); |
| 1328 | 1343 |
| 1329 TEST_AND_RETURN_FALSE(ConvertGraphToDag(&graph, | 1344 TEST_AND_RETURN_FALSE(ConvertGraphToDag(&graph, |
| 1330 new_root, | 1345 new_root, |
| 1331 fd, | 1346 fd, |
| 1332 &data_file_size, | 1347 &data_file_size, |
| 1333 &final_order)); | 1348 &final_order)); |
| 1334 } else { | 1349 } else { |
| 1335 // Full update | 1350 // Full update |
| 1351 off_t new_image_size = |
| 1352 static_cast<off_t>(new_image_block_count) * new_image_block_size; |
| 1336 TEST_AND_RETURN_FALSE(ReadFullUpdateFromDisk(&graph, | 1353 TEST_AND_RETURN_FALSE(ReadFullUpdateFromDisk(&graph, |
| 1337 new_kernel_part, | 1354 new_kernel_part, |
| 1338 new_image, | 1355 new_image, |
| 1356 new_image_size, |
| 1339 fd, | 1357 fd, |
| 1340 &data_file_size, | 1358 &data_file_size, |
| 1341 kFullUpdateChunkSize, | 1359 kFullUpdateChunkSize, |
| 1342 &kernel_ops, | 1360 &kernel_ops, |
| 1343 &final_order)); | 1361 &final_order)); |
| 1344 } | 1362 } |
| 1345 } | 1363 } |
| 1346 | 1364 |
| 1347 // Convert to protobuf Manifest object | 1365 // Convert to protobuf Manifest object |
| 1348 DeltaArchiveManifest manifest; | 1366 DeltaArchiveManifest manifest; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1494 | 1512 |
| 1495 LOG(INFO) << "All done. Successfully created delta file."; | 1513 LOG(INFO) << "All done. Successfully created delta file."; |
| 1496 return true; | 1514 return true; |
| 1497 } | 1515 } |
| 1498 | 1516 |
| 1499 const char* const kBsdiffPath = "/usr/bin/bsdiff"; | 1517 const char* const kBsdiffPath = "/usr/bin/bsdiff"; |
| 1500 const char* const kBspatchPath = "/usr/bin/bspatch"; | 1518 const char* const kBspatchPath = "/usr/bin/bspatch"; |
| 1501 const char* const kDeltaMagic = "CrAU"; | 1519 const char* const kDeltaMagic = "CrAU"; |
| 1502 | 1520 |
| 1503 }; // namespace chromeos_update_engine | 1521 }; // namespace chromeos_update_engine |
| OLD | NEW |