Chromium Code Reviews| Index: generate_delta_main.cc |
| diff --git a/generate_delta_main.cc b/generate_delta_main.cc |
| index 6e9e5530b1f0ac650fcc93f4a0a18aaf71e7b9f5..d82b7e0af7b9f719be7e939e0080d00e82fafbea 100644 |
| --- a/generate_delta_main.cc |
| +++ b/generate_delta_main.cc |
| @@ -19,6 +19,7 @@ |
| #include "update_engine/delta_diff_generator.h" |
| #include "update_engine/delta_performer.h" |
| +#include "update_engine/payload_signer.h" |
| #include "update_engine/prefs.h" |
| #include "update_engine/subprocess.h" |
| #include "update_engine/terminator.h" |
| @@ -26,19 +27,23 @@ |
| #include "update_engine/utils.h" |
| DEFINE_string(old_dir, "", |
| - "Directory where the old rootfs is loop mounted read-only"); |
| + "Directory where the old rootfs is loop mounted read-only."); |
|
adlr
2011/01/13 20:42:37
be consistent w/ adding a period to the end of hel
petkov
2011/01/13 20:47:35
Done.
|
| DEFINE_string(new_dir, "", |
| "Directory where the new rootfs is loop mounted read-only"); |
| DEFINE_string(old_image, "", "Path to the old rootfs"); |
| DEFINE_string(new_image, "", "Path to the new rootfs"); |
| -DEFINE_string(out_file, "", "Path to output file"); |
| DEFINE_string(old_kernel, "", "Path to the old kernel partition image"); |
| DEFINE_string(new_kernel, "", "Path to the new kernel partition image"); |
| +DEFINE_string(in_file, "", |
| + "Path to input delta payload file used to hash/sign payloads " |
| + "and apply delta over old_image (for debugging)"); |
| +DEFINE_string(out_file, "", "Path to output delta payload file"); |
| +DEFINE_string(out_hash_file, "", "Path to output hash file"); |
| DEFINE_string(private_key, "", "Path to private key in .pem format"); |
| -DEFINE_string(apply_delta, "", |
| - "If set, apply delta over old_image. (For debugging.)"); |
| DEFINE_string(prefs_dir, "/tmp/update_engine_prefs", |
| "Preferences directory, used with apply_delta."); |
| +DEFINE_int32(signature_size, 0, "Raw signature size used for hash calculation"); |
| +DEFINE_string(signature_file, "", "Raw signature file to sign payload with"); |
| // This file contains a simple program that takes an old path, a new path, |
| // and an output file as arguments and the path to an output file and |
| @@ -58,6 +63,79 @@ bool IsDir(const char* path) { |
| return S_ISDIR(stbuf.st_mode); |
| } |
| +void CalculatePayloadHashForSigning() { |
| + LOG(INFO) << "Calculating payload hash for signing."; |
| + LOG_IF(FATAL, FLAGS_in_file.empty()) |
| + << "Must pass --in_file to calculate hash for signing."; |
| + LOG_IF(FATAL, FLAGS_out_hash_file.empty()) |
| + << "Must pass --out_hash_file to calculate hash for signing."; |
| + LOG_IF(FATAL, FLAGS_signature_size <= 0) |
| + << "Must pass --signature_size to calculate hash for signing."; |
| + vector<char> hash; |
| + CHECK(PayloadSigner::HashPayloadForSigning( |
| + FLAGS_in_file, FLAGS_signature_size, &hash)); |
| + CHECK(utils::WriteFile( |
| + FLAGS_out_hash_file.c_str(), hash.data(), hash.size())); |
| + LOG(INFO) << "Done calculating payload hash for signing."; |
| +} |
| + |
| +void SignPayload() { |
| + LOG(INFO) << "Signing payload."; |
| + LOG_IF(FATAL, FLAGS_in_file.empty()) |
| + << "Must pass --in_file to sign payload."; |
| + LOG_IF(FATAL, FLAGS_out_file.empty()) |
| + << "Must pass --out_file to sign payload."; |
| + LOG_IF(FATAL, FLAGS_signature_file.empty()) |
| + << "Must pass --signature_file to sign payload."; |
| + vector<char> signature; |
| + CHECK(utils::ReadFile(FLAGS_signature_file, &signature)); |
| + CHECK(PayloadSigner::AddSignatureToPayload( |
| + FLAGS_in_file, signature, FLAGS_out_file)); |
| + LOG(INFO) << "Done signing payload."; |
| +} |
| + |
| +void ApplyDelta() { |
| + LOG(INFO) << "Applying delta."; |
| + LOG_IF(FATAL, FLAGS_old_image.empty()) |
| + << "Must pass --old_image to apply delta."; |
| + Prefs prefs; |
| + LOG(INFO) << "Setting up preferences under: " << FLAGS_prefs_dir; |
| + LOG_IF(ERROR, !prefs.Init(FilePath(FLAGS_prefs_dir))) |
| + << "Failed to initialize preferences."; |
| + // Get original checksums |
| + LOG(INFO) << "Calculating original checksums"; |
| + PartitionInfo kern_info, root_info; |
| + CHECK(DeltaDiffGenerator::InitializePartitionInfo(true, // is_kernel |
| + FLAGS_old_kernel, |
| + &kern_info)); |
| + CHECK(DeltaDiffGenerator::InitializePartitionInfo(false, // is_kernel |
| + FLAGS_old_image, |
| + &root_info)); |
| + vector<char> kern_hash(kern_info.hash().begin(), |
| + kern_info.hash().end()); |
| + vector<char> root_hash(root_info.hash().begin(), |
| + root_info.hash().end()); |
| + DeltaPerformer performer(&prefs); |
| + performer.set_current_kernel_hash(kern_hash); |
| + performer.set_current_rootfs_hash(root_hash); |
| + CHECK_EQ(performer.Open(FLAGS_old_image.c_str(), 0, 0), 0); |
| + CHECK(performer.OpenKernel(FLAGS_old_kernel.c_str())); |
| + vector<char> buf(1024 * 1024); |
| + int fd = open(FLAGS_in_file.c_str(), O_RDONLY, 0); |
| + CHECK_GE(fd, 0); |
| + ScopedFdCloser fd_closer(&fd); |
| + for (off_t offset = 0;; offset += buf.size()) { |
| + ssize_t bytes_read; |
| + CHECK(utils::PReadAll(fd, &buf[0], buf.size(), offset, &bytes_read)); |
| + if (bytes_read == 0) |
| + break; |
| + CHECK_EQ(performer.Write(&buf[0], bytes_read), bytes_read); |
| + } |
| + CHECK_EQ(performer.Close(), 0); |
| + DeltaPerformer::ResetUpdateProgress(&prefs, false); |
| + LOG(INFO) << "Done applying delta."; |
| +} |
| + |
| int Main(int argc, char** argv) { |
| g_thread_init(NULL); |
| google::ParseCommandLineFlags(&argc, &argv, true); |
| @@ -68,46 +146,16 @@ int Main(int argc, char** argv) { |
| logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, |
| logging::DONT_LOCK_LOG_FILE, |
| logging::APPEND_TO_OLD_LOG_FILE); |
| - if (!FLAGS_apply_delta.empty()) { |
| - if (FLAGS_old_image.empty()) { |
| - LOG(FATAL) << "Must pass --old_image with --apply_delta."; |
| - } |
| - Prefs prefs; |
| - LOG(INFO) << "Setting up preferences under: " << FLAGS_prefs_dir; |
| - LOG_IF(ERROR, !prefs.Init(FilePath(FLAGS_prefs_dir))) |
| - << "Failed to initialize preferences."; |
| - // Get original checksums |
| - LOG(INFO) << "Calculating original checksums"; |
| - PartitionInfo kern_info, root_info; |
| - CHECK(DeltaDiffGenerator::InitializePartitionInfo(true, // is_kernel |
| - FLAGS_old_kernel, |
| - &kern_info)); |
| - CHECK(DeltaDiffGenerator::InitializePartitionInfo(false, // is_kernel |
| - FLAGS_old_image, |
| - &root_info)); |
| - vector<char> kern_hash(kern_info.hash().begin(), |
| - kern_info.hash().end()); |
| - vector<char> root_hash(root_info.hash().begin(), |
| - root_info.hash().end()); |
| - DeltaPerformer performer(&prefs); |
| - performer.set_current_kernel_hash(kern_hash); |
| - performer.set_current_rootfs_hash(root_hash); |
| - CHECK_EQ(performer.Open(FLAGS_old_image.c_str(), 0, 0), 0); |
| - CHECK(performer.OpenKernel(FLAGS_old_kernel.c_str())); |
| - vector<char> buf(1024 * 1024); |
| - int fd = open(FLAGS_apply_delta.c_str(), O_RDONLY, 0); |
| - CHECK_GE(fd, 0); |
| - ScopedFdCloser fd_closer(&fd); |
| - for (off_t offset = 0;; offset += buf.size()) { |
| - ssize_t bytes_read; |
| - CHECK(utils::PReadAll(fd, &buf[0], buf.size(), offset, &bytes_read)); |
| - if (bytes_read == 0) |
| - break; |
| - CHECK_EQ(performer.Write(&buf[0], bytes_read), bytes_read); |
| - } |
| - CHECK_EQ(performer.Close(), 0); |
| - DeltaPerformer::ResetUpdateProgress(&prefs, false); |
| - LOG(INFO) << "done applying delta."; |
| + if (FLAGS_signature_size > 0 || !FLAGS_out_hash_file.empty()) { |
| + CalculatePayloadHashForSigning(); |
| + return 0; |
| + } |
| + if (!FLAGS_signature_file.empty()) { |
| + SignPayload(); |
| + return 0; |
| + } |
| + if (!FLAGS_in_file.empty()) { |
| + ApplyDelta(); |
| return 0; |
| } |
| CHECK(!FLAGS_new_image.empty()); |