Chromium Code Reviews| 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 <sys/types.h> | 5 #include <sys/types.h> |
| 6 #include <sys/stat.h> | 6 #include <sys/stat.h> |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <unistd.h> | 9 #include <unistd.h> |
| 10 | 10 |
| 11 #include <set> | 11 #include <set> |
| 12 #include <string> | 12 #include <string> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include <base/command_line.h> | 15 #include <base/command_line.h> |
| 16 #include <base/logging.h> | 16 #include <base/logging.h> |
| 17 #include <gflags/gflags.h> | 17 #include <gflags/gflags.h> |
| 18 #include <glib.h> | 18 #include <glib.h> |
| 19 | 19 |
| 20 #include "update_engine/delta_diff_generator.h" | 20 #include "update_engine/delta_diff_generator.h" |
| 21 #include "update_engine/delta_performer.h" | 21 #include "update_engine/delta_performer.h" |
| 22 #include "update_engine/payload_signer.h" | |
| 22 #include "update_engine/prefs.h" | 23 #include "update_engine/prefs.h" |
| 23 #include "update_engine/subprocess.h" | 24 #include "update_engine/subprocess.h" |
| 24 #include "update_engine/terminator.h" | 25 #include "update_engine/terminator.h" |
| 25 #include "update_engine/update_metadata.pb.h" | 26 #include "update_engine/update_metadata.pb.h" |
| 26 #include "update_engine/utils.h" | 27 #include "update_engine/utils.h" |
| 27 | 28 |
| 28 DEFINE_string(old_dir, "", | 29 DEFINE_string(old_dir, "", |
| 29 "Directory where the old rootfs is loop mounted read-only"); | 30 "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.
| |
| 30 DEFINE_string(new_dir, "", | 31 DEFINE_string(new_dir, "", |
| 31 "Directory where the new rootfs is loop mounted read-only"); | 32 "Directory where the new rootfs is loop mounted read-only"); |
| 32 DEFINE_string(old_image, "", "Path to the old rootfs"); | 33 DEFINE_string(old_image, "", "Path to the old rootfs"); |
| 33 DEFINE_string(new_image, "", "Path to the new rootfs"); | 34 DEFINE_string(new_image, "", "Path to the new rootfs"); |
| 34 DEFINE_string(out_file, "", "Path to output file"); | |
| 35 DEFINE_string(old_kernel, "", "Path to the old kernel partition image"); | 35 DEFINE_string(old_kernel, "", "Path to the old kernel partition image"); |
| 36 DEFINE_string(new_kernel, "", "Path to the new kernel partition image"); | 36 DEFINE_string(new_kernel, "", "Path to the new kernel partition image"); |
| 37 DEFINE_string(in_file, "", | |
| 38 "Path to input delta payload file used to hash/sign payloads " | |
| 39 "and apply delta over old_image (for debugging)"); | |
| 40 DEFINE_string(out_file, "", "Path to output delta payload file"); | |
| 41 DEFINE_string(out_hash_file, "", "Path to output hash file"); | |
| 37 DEFINE_string(private_key, "", "Path to private key in .pem format"); | 42 DEFINE_string(private_key, "", "Path to private key in .pem format"); |
| 38 DEFINE_string(apply_delta, "", | |
| 39 "If set, apply delta over old_image. (For debugging.)"); | |
| 40 DEFINE_string(prefs_dir, "/tmp/update_engine_prefs", | 43 DEFINE_string(prefs_dir, "/tmp/update_engine_prefs", |
| 41 "Preferences directory, used with apply_delta."); | 44 "Preferences directory, used with apply_delta."); |
| 45 DEFINE_int32(signature_size, 0, "Raw signature size used for hash calculation"); | |
| 46 DEFINE_string(signature_file, "", "Raw signature file to sign payload with"); | |
| 42 | 47 |
| 43 // This file contains a simple program that takes an old path, a new path, | 48 // This file contains a simple program that takes an old path, a new path, |
| 44 // and an output file as arguments and the path to an output file and | 49 // and an output file as arguments and the path to an output file and |
| 45 // generates a delta that can be sent to Chrome OS clients. | 50 // generates a delta that can be sent to Chrome OS clients. |
| 46 | 51 |
| 47 using std::set; | 52 using std::set; |
| 48 using std::string; | 53 using std::string; |
| 49 using std::vector; | 54 using std::vector; |
| 50 | 55 |
| 51 namespace chromeos_update_engine { | 56 namespace chromeos_update_engine { |
| 52 | 57 |
| 53 namespace { | 58 namespace { |
| 54 | 59 |
| 55 bool IsDir(const char* path) { | 60 bool IsDir(const char* path) { |
| 56 struct stat stbuf; | 61 struct stat stbuf; |
| 57 TEST_AND_RETURN_FALSE_ERRNO(lstat(path, &stbuf) == 0); | 62 TEST_AND_RETURN_FALSE_ERRNO(lstat(path, &stbuf) == 0); |
| 58 return S_ISDIR(stbuf.st_mode); | 63 return S_ISDIR(stbuf.st_mode); |
| 59 } | 64 } |
| 60 | 65 |
| 66 void CalculatePayloadHashForSigning() { | |
| 67 LOG(INFO) << "Calculating payload hash for signing."; | |
| 68 LOG_IF(FATAL, FLAGS_in_file.empty()) | |
| 69 << "Must pass --in_file to calculate hash for signing."; | |
| 70 LOG_IF(FATAL, FLAGS_out_hash_file.empty()) | |
| 71 << "Must pass --out_hash_file to calculate hash for signing."; | |
| 72 LOG_IF(FATAL, FLAGS_signature_size <= 0) | |
| 73 << "Must pass --signature_size to calculate hash for signing."; | |
| 74 vector<char> hash; | |
| 75 CHECK(PayloadSigner::HashPayloadForSigning( | |
| 76 FLAGS_in_file, FLAGS_signature_size, &hash)); | |
| 77 CHECK(utils::WriteFile( | |
| 78 FLAGS_out_hash_file.c_str(), hash.data(), hash.size())); | |
| 79 LOG(INFO) << "Done calculating payload hash for signing."; | |
| 80 } | |
| 81 | |
| 82 void SignPayload() { | |
| 83 LOG(INFO) << "Signing payload."; | |
| 84 LOG_IF(FATAL, FLAGS_in_file.empty()) | |
| 85 << "Must pass --in_file to sign payload."; | |
| 86 LOG_IF(FATAL, FLAGS_out_file.empty()) | |
| 87 << "Must pass --out_file to sign payload."; | |
| 88 LOG_IF(FATAL, FLAGS_signature_file.empty()) | |
| 89 << "Must pass --signature_file to sign payload."; | |
| 90 vector<char> signature; | |
| 91 CHECK(utils::ReadFile(FLAGS_signature_file, &signature)); | |
| 92 CHECK(PayloadSigner::AddSignatureToPayload( | |
| 93 FLAGS_in_file, signature, FLAGS_out_file)); | |
| 94 LOG(INFO) << "Done signing payload."; | |
| 95 } | |
| 96 | |
| 97 void ApplyDelta() { | |
| 98 LOG(INFO) << "Applying delta."; | |
| 99 LOG_IF(FATAL, FLAGS_old_image.empty()) | |
| 100 << "Must pass --old_image to apply delta."; | |
| 101 Prefs prefs; | |
| 102 LOG(INFO) << "Setting up preferences under: " << FLAGS_prefs_dir; | |
| 103 LOG_IF(ERROR, !prefs.Init(FilePath(FLAGS_prefs_dir))) | |
| 104 << "Failed to initialize preferences."; | |
| 105 // Get original checksums | |
| 106 LOG(INFO) << "Calculating original checksums"; | |
| 107 PartitionInfo kern_info, root_info; | |
| 108 CHECK(DeltaDiffGenerator::InitializePartitionInfo(true, // is_kernel | |
| 109 FLAGS_old_kernel, | |
| 110 &kern_info)); | |
| 111 CHECK(DeltaDiffGenerator::InitializePartitionInfo(false, // is_kernel | |
| 112 FLAGS_old_image, | |
| 113 &root_info)); | |
| 114 vector<char> kern_hash(kern_info.hash().begin(), | |
| 115 kern_info.hash().end()); | |
| 116 vector<char> root_hash(root_info.hash().begin(), | |
| 117 root_info.hash().end()); | |
| 118 DeltaPerformer performer(&prefs); | |
| 119 performer.set_current_kernel_hash(kern_hash); | |
| 120 performer.set_current_rootfs_hash(root_hash); | |
| 121 CHECK_EQ(performer.Open(FLAGS_old_image.c_str(), 0, 0), 0); | |
| 122 CHECK(performer.OpenKernel(FLAGS_old_kernel.c_str())); | |
| 123 vector<char> buf(1024 * 1024); | |
| 124 int fd = open(FLAGS_in_file.c_str(), O_RDONLY, 0); | |
| 125 CHECK_GE(fd, 0); | |
| 126 ScopedFdCloser fd_closer(&fd); | |
| 127 for (off_t offset = 0;; offset += buf.size()) { | |
| 128 ssize_t bytes_read; | |
| 129 CHECK(utils::PReadAll(fd, &buf[0], buf.size(), offset, &bytes_read)); | |
| 130 if (bytes_read == 0) | |
| 131 break; | |
| 132 CHECK_EQ(performer.Write(&buf[0], bytes_read), bytes_read); | |
| 133 } | |
| 134 CHECK_EQ(performer.Close(), 0); | |
| 135 DeltaPerformer::ResetUpdateProgress(&prefs, false); | |
| 136 LOG(INFO) << "Done applying delta."; | |
| 137 } | |
| 138 | |
| 61 int Main(int argc, char** argv) { | 139 int Main(int argc, char** argv) { |
| 62 g_thread_init(NULL); | 140 g_thread_init(NULL); |
| 63 google::ParseCommandLineFlags(&argc, &argv, true); | 141 google::ParseCommandLineFlags(&argc, &argv, true); |
| 64 CommandLine::Init(argc, argv); | 142 CommandLine::Init(argc, argv); |
| 65 Terminator::Init(); | 143 Terminator::Init(); |
| 66 Subprocess::Init(); | 144 Subprocess::Init(); |
| 67 logging::InitLogging("delta_generator.log", | 145 logging::InitLogging("delta_generator.log", |
| 68 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, | 146 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, |
| 69 logging::DONT_LOCK_LOG_FILE, | 147 logging::DONT_LOCK_LOG_FILE, |
| 70 logging::APPEND_TO_OLD_LOG_FILE); | 148 logging::APPEND_TO_OLD_LOG_FILE); |
| 71 if (!FLAGS_apply_delta.empty()) { | 149 if (FLAGS_signature_size > 0 || !FLAGS_out_hash_file.empty()) { |
| 72 if (FLAGS_old_image.empty()) { | 150 CalculatePayloadHashForSigning(); |
| 73 LOG(FATAL) << "Must pass --old_image with --apply_delta."; | 151 return 0; |
| 74 } | 152 } |
| 75 Prefs prefs; | 153 if (!FLAGS_signature_file.empty()) { |
| 76 LOG(INFO) << "Setting up preferences under: " << FLAGS_prefs_dir; | 154 SignPayload(); |
| 77 LOG_IF(ERROR, !prefs.Init(FilePath(FLAGS_prefs_dir))) | 155 return 0; |
| 78 << "Failed to initialize preferences."; | 156 } |
| 79 // Get original checksums | 157 if (!FLAGS_in_file.empty()) { |
| 80 LOG(INFO) << "Calculating original checksums"; | 158 ApplyDelta(); |
| 81 PartitionInfo kern_info, root_info; | |
| 82 CHECK(DeltaDiffGenerator::InitializePartitionInfo(true, // is_kernel | |
| 83 FLAGS_old_kernel, | |
| 84 &kern_info)); | |
| 85 CHECK(DeltaDiffGenerator::InitializePartitionInfo(false, // is_kernel | |
| 86 FLAGS_old_image, | |
| 87 &root_info)); | |
| 88 vector<char> kern_hash(kern_info.hash().begin(), | |
| 89 kern_info.hash().end()); | |
| 90 vector<char> root_hash(root_info.hash().begin(), | |
| 91 root_info.hash().end()); | |
| 92 DeltaPerformer performer(&prefs); | |
| 93 performer.set_current_kernel_hash(kern_hash); | |
| 94 performer.set_current_rootfs_hash(root_hash); | |
| 95 CHECK_EQ(performer.Open(FLAGS_old_image.c_str(), 0, 0), 0); | |
| 96 CHECK(performer.OpenKernel(FLAGS_old_kernel.c_str())); | |
| 97 vector<char> buf(1024 * 1024); | |
| 98 int fd = open(FLAGS_apply_delta.c_str(), O_RDONLY, 0); | |
| 99 CHECK_GE(fd, 0); | |
| 100 ScopedFdCloser fd_closer(&fd); | |
| 101 for (off_t offset = 0;; offset += buf.size()) { | |
| 102 ssize_t bytes_read; | |
| 103 CHECK(utils::PReadAll(fd, &buf[0], buf.size(), offset, &bytes_read)); | |
| 104 if (bytes_read == 0) | |
| 105 break; | |
| 106 CHECK_EQ(performer.Write(&buf[0], bytes_read), bytes_read); | |
| 107 } | |
| 108 CHECK_EQ(performer.Close(), 0); | |
| 109 DeltaPerformer::ResetUpdateProgress(&prefs, false); | |
| 110 LOG(INFO) << "done applying delta."; | |
| 111 return 0; | 159 return 0; |
| 112 } | 160 } |
| 113 CHECK(!FLAGS_new_image.empty()); | 161 CHECK(!FLAGS_new_image.empty()); |
| 114 CHECK(!FLAGS_out_file.empty()); | 162 CHECK(!FLAGS_out_file.empty()); |
| 115 CHECK(!FLAGS_new_kernel.empty()); | 163 CHECK(!FLAGS_new_kernel.empty()); |
| 116 if (FLAGS_old_image.empty()) { | 164 if (FLAGS_old_image.empty()) { |
| 117 LOG(INFO) << "Generating full update"; | 165 LOG(INFO) << "Generating full update"; |
| 118 } else { | 166 } else { |
| 119 LOG(INFO) << "Generating delta update"; | 167 LOG(INFO) << "Generating delta update"; |
| 120 CHECK(!FLAGS_old_dir.empty()); | 168 CHECK(!FLAGS_old_dir.empty()); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 135 return 0; | 183 return 0; |
| 136 } | 184 } |
| 137 | 185 |
| 138 } // namespace {} | 186 } // namespace {} |
| 139 | 187 |
| 140 } // namespace chromeos_update_engine | 188 } // namespace chromeos_update_engine |
| 141 | 189 |
| 142 int main(int argc, char** argv) { | 190 int main(int argc, char** argv) { |
| 143 return chromeos_update_engine::Main(argc, argv); | 191 return chromeos_update_engine::Main(argc, argv); |
| 144 } | 192 } |
| OLD | NEW |