| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium 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 <stdarg.h> |
| 5 #include <stddef.h> | 6 #include <stddef.h> |
| 6 #include <stdint.h> | 7 #include <stdint.h> |
| 7 | 8 |
| 9 #include <initializer_list> |
| 8 #include <memory> | 10 #include <memory> |
| 9 #include <string> | 11 #include <string> |
| 10 #include <vector> | 12 #include <vector> |
| 11 | 13 |
| 12 #include "base/at_exit.h" | 14 #include "base/at_exit.h" |
| 13 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 14 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
| 15 #include "base/files/file_util.h" | 17 #include "base/files/file_util.h" |
| 16 #include "base/files/memory_mapped_file.h" | 18 #include "base/files/memory_mapped_file.h" |
| 17 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/macros.h" |
| 18 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 23 #include "base/strings/utf_string_conversions.h" |
| 21 #include "courgette/assembly_program.h" | 24 #include "courgette/assembly_program.h" |
| 22 #include "courgette/courgette.h" | 25 #include "courgette/courgette.h" |
| 26 #include "courgette/courgette_flow.h" |
| 23 #include "courgette/encoded_program.h" | 27 #include "courgette/encoded_program.h" |
| 24 #include "courgette/program_detector.h" | 28 #include "courgette/program_detector.h" |
| 25 #include "courgette/streams.h" | 29 #include "courgette/streams.h" |
| 26 #include "courgette/third_party/bsdiff/bsdiff.h" | 30 #include "courgette/third_party/bsdiff/bsdiff.h" |
| 27 | 31 |
| 32 namespace { |
| 33 |
| 34 using courgette::CourgetteFlow; |
| 35 |
| 36 const char kUsageGen[] = "-gen <old_in> <new_in> <patch_out>"; |
| 37 const char kUsageApply[] = "-apply <old_in> <patch_in> <new_out>"; |
| 38 const char kUsageGenbsdiff[] = "-genbsdiff <old_in> <new_in> <patch_out>"; |
| 39 const char kUsageApplybsdiff[] = "-applybsdiff <old_in> <patch_in> <new_out>"; |
| 40 const char kUsageSupported[] = "-supported <exec_file_in>"; |
| 41 const char kUsageDis[] = "-dis <exec_file_in> <assembly_file_out>"; |
| 42 const char kUsageAsm[] = "-asm <assembly_file_in> <exec_file_out>"; |
| 43 const char kUsageDisadj[] = "-disadj <old_in> <new_in> <new_assembly_file_out>"; |
| 44 const char kUsageGen1[] = "-gen1[au] <old_in> <new_in> <patch_base_out>"; |
| 45 |
| 46 /******** Utilities to print help and exit ********/ |
| 47 |
| 28 void PrintHelp() { | 48 void PrintHelp() { |
| 29 fprintf(stderr, | 49 fprintf(stderr, "Main Usage:\n"); |
| 30 "Usage:\n" | 50 for (auto usage : |
| 31 " courgette -supported <executable_file>\n" | 51 {kUsageGen, kUsageApply, kUsageGenbsdiff, kUsageApplybsdiff}) { |
| 32 " courgette -dis <executable_file> <binary_assembly_file>\n" | 52 fprintf(stderr, " courgette %s\n", usage); |
| 33 " courgette -asm <binary_assembly_file> <executable_file>\n" | 53 } |
| 34 " courgette -disadj <executable_file> <reference> <binary_assembly_file>\n" | 54 fprintf(stderr, "Diagnosis Usage:\n"); |
| 35 " courgette -gen <v1> <v2> <patch>\n" | 55 for (auto usage : |
| 36 " courgette -apply <v1> <patch> <v2>\n" | 56 {kUsageSupported, kUsageDis, kUsageAsm, kUsageDisadj, kUsageGen1}) { |
| 37 "\n"); | 57 fprintf(stderr, " courgette %s\n", usage); |
| 58 } |
| 38 } | 59 } |
| 39 | 60 |
| 40 void UsageProblem(const char* message) { | 61 void UsageProblem(const char* message) { |
| 41 fprintf(stderr, "%s", message); | 62 fprintf(stderr, "%s", message); |
| 42 fprintf(stderr, "\n"); | 63 fprintf(stderr, "\n"); |
| 43 PrintHelp(); | 64 PrintHelp(); |
| 44 exit(1); | 65 exit(1); |
| 45 } | 66 } |
| 46 | 67 |
| 47 void Problem(const char* format, ...) { | 68 void Problem(const char* format, ...) { |
| 48 va_list args; | 69 va_list args; |
| 49 va_start(args, format); | 70 va_start(args, format); |
| 50 vfprintf(stderr, format, args); | 71 vfprintf(stderr, format, args); |
| 51 fprintf(stderr, "\n"); | 72 fprintf(stderr, "\n"); |
| 52 va_end(args); | 73 va_end(args); |
| 53 exit(1); | 74 exit(1); |
| 54 } | 75 } |
| 55 | 76 |
| 77 /******** BufferedFileReader ********/ |
| 78 |
| 56 // A file reader that calls Problem() on failure. | 79 // A file reader that calls Problem() on failure. |
| 57 class BufferedFileReader { | 80 class BufferedFileReader : public courgette::BasicBuffer { |
| 58 public: | 81 public: |
| 59 BufferedFileReader(const base::FilePath& file_name, const char* kind) { | 82 BufferedFileReader(const base::FilePath& file_name, const char* kind) { |
| 60 if (!buffer_.Initialize(file_name)) | 83 if (!buffer_.Initialize(file_name)) |
| 61 Problem("Can't read %s file.", kind); | 84 Problem("Can't read %s file.", kind); |
| 62 } | 85 } |
| 63 const uint8_t* data() const { return buffer_.data(); } | 86 ~BufferedFileReader() override {} |
| 64 size_t length() const { return buffer_.length(); } | 87 |
| 88 // courgette::BasicBuffer: |
| 89 const uint8_t* data() const override { return buffer_.data(); } |
| 90 size_t length() const override { return buffer_.length(); } |
| 65 | 91 |
| 66 private: | 92 private: |
| 67 base::MemoryMappedFile buffer_; | 93 base::MemoryMappedFile buffer_; |
| 94 |
| 95 DISALLOW_COPY_AND_ASSIGN(BufferedFileReader); |
| 68 }; | 96 }; |
| 69 | 97 |
| 98 /******** Various helpers ********/ |
| 99 |
| 70 void WriteSinkToFile(const courgette::SinkStream *sink, | 100 void WriteSinkToFile(const courgette::SinkStream *sink, |
| 71 const base::FilePath& output_file) { | 101 const base::FilePath& output_file) { |
| 72 int count = | 102 int count = |
| 73 base::WriteFile(output_file, | 103 base::WriteFile(output_file, |
| 74 reinterpret_cast<const char*>(sink->Buffer()), | 104 reinterpret_cast<const char*>(sink->Buffer()), |
| 75 static_cast<int>(sink->Length())); | 105 static_cast<int>(sink->Length())); |
| 76 if (count == -1) | 106 if (count == -1) |
| 77 Problem("Can't write output."); | 107 Problem("Can't write output."); |
| 78 if (static_cast<size_t>(count) != sink->Length()) | 108 if (static_cast<size_t>(count) != sink->Length()) |
| 79 Problem("Incomplete write."); | 109 Problem("Incomplete write."); |
| 80 } | 110 } |
| 81 | 111 |
| 82 void Disassemble(const base::FilePath& input_file, | |
| 83 const base::FilePath& output_file) { | |
| 84 BufferedFileReader buffer(input_file, "input"); | |
| 85 | |
| 86 std::unique_ptr<courgette::AssemblyProgram> program; | |
| 87 const courgette::Status parse_status = courgette::ParseDetectedExecutable( | |
| 88 buffer.data(), buffer.length(), &program); | |
| 89 if (parse_status != courgette::C_OK) | |
| 90 Problem("Can't parse input (code = %d).", parse_status); | |
| 91 | |
| 92 std::unique_ptr<courgette::EncodedProgram> encoded; | |
| 93 const courgette::Status encode_status = Encode(*program, &encoded); | |
| 94 if (encode_status != courgette::C_OK) | |
| 95 Problem("Can't encode program."); | |
| 96 | |
| 97 program.reset(); | |
| 98 | |
| 99 courgette::SinkStreamSet sinks; | |
| 100 const courgette::Status write_status = | |
| 101 courgette::WriteEncodedProgram(encoded.get(), &sinks); | |
| 102 if (write_status != courgette::C_OK) | |
| 103 Problem("Can't serialize encoded program."); | |
| 104 | |
| 105 encoded.reset(); | |
| 106 | |
| 107 courgette::SinkStream sink; | |
| 108 if (!sinks.CopyTo(&sink)) | |
| 109 Problem("Can't combine serialized encoded program streams."); | |
| 110 | |
| 111 WriteSinkToFile(&sink, output_file); | |
| 112 } | |
| 113 | |
| 114 bool Supported(const base::FilePath& input_file) { | 112 bool Supported(const base::FilePath& input_file) { |
| 115 bool result = false; | 113 bool result = false; |
| 116 | 114 |
| 117 BufferedFileReader buffer(input_file, "input"); | 115 BufferedFileReader buffer(input_file, "input"); |
| 118 | 116 |
| 119 courgette::ExecutableType type; | 117 courgette::ExecutableType type; |
| 120 size_t detected_length; | 118 size_t detected_length; |
| 121 | 119 |
| 122 DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length); | 120 DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length); |
| 123 | 121 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 146 case courgette::EXE_WIN_32_X64: | 144 case courgette::EXE_WIN_32_X64: |
| 147 format = "Windows 64 PE"; | 145 format = "Windows 64 PE"; |
| 148 result = true; | 146 result = true; |
| 149 break; | 147 break; |
| 150 } | 148 } |
| 151 | 149 |
| 152 printf("%s Executable\n", format.c_str()); | 150 printf("%s Executable\n", format.c_str()); |
| 153 return result; | 151 return result; |
| 154 } | 152 } |
| 155 | 153 |
| 156 void DisassembleAndAdjust(const base::FilePath& program_file, | 154 void Disassemble(const base::FilePath& input_file, |
| 157 const base::FilePath& model_file, | 155 const base::FilePath& output_file) { |
| 158 const base::FilePath& output_file) { | 156 CourgetteFlow flow; |
| 159 BufferedFileReader program_buffer(program_file, "program"); | 157 BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY)); |
| 160 BufferedFileReader model_buffer(model_file, "model"); | 158 flow.ReadAssemblyProgramFromBuffer(flow.ONLY, input_buffer, false); |
| 161 | 159 flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY); |
| 162 std::unique_ptr<courgette::AssemblyProgram> program; | 160 flow.DestroyAssemblyProgram(flow.ONLY); |
| 163 const courgette::Status parse_program_status = | 161 flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY); |
| 164 courgette::ParseDetectedExecutable(program_buffer.data(), | 162 flow.DestroyEncodedProgram(flow.ONLY); |
| 165 program_buffer.length(), &program); | |
| 166 if (parse_program_status != courgette::C_OK) | |
| 167 Problem("Can't parse program input (code = %d).", parse_program_status); | |
| 168 | |
| 169 std::unique_ptr<courgette::AssemblyProgram> model; | |
| 170 const courgette::Status parse_model_status = | |
| 171 courgette::ParseDetectedExecutable(model_buffer.data(), | |
| 172 model_buffer.length(), &model); | |
| 173 if (parse_model_status != courgette::C_OK) | |
| 174 Problem("Can't parse model input (code = %d).", parse_model_status); | |
| 175 | |
| 176 const courgette::Status adjust_status = Adjust(*model, program.get()); | |
| 177 if (adjust_status != courgette::C_OK) | |
| 178 Problem("Can't adjust program."); | |
| 179 | |
| 180 model.reset(); | |
| 181 | |
| 182 std::unique_ptr<courgette::EncodedProgram> encoded; | |
| 183 const courgette::Status encode_status = Encode(*program, &encoded); | |
| 184 if (encode_status != courgette::C_OK) | |
| 185 Problem("Can't encode program."); | |
| 186 | |
| 187 program.reset(); | |
| 188 | |
| 189 courgette::SinkStreamSet sinks; | |
| 190 const courgette::Status write_status = | |
| 191 courgette::WriteEncodedProgram(encoded.get(), &sinks); | |
| 192 if (write_status != courgette::C_OK) | |
| 193 Problem("Can't serialize encoded program."); | |
| 194 | |
| 195 encoded.reset(); | |
| 196 | |
| 197 courgette::SinkStream sink; | 163 courgette::SinkStream sink; |
| 198 if (!sinks.CopyTo(&sink)) | 164 flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink); |
| 199 Problem("Can't combine serialized encoded program streams."); | 165 if (flow.failed()) |
| 166 Problem(flow.message().c_str()); |
| 200 | 167 |
| 201 WriteSinkToFile(&sink, output_file); | 168 WriteSinkToFile(&sink, output_file); |
| 202 } | 169 } |
| 170 |
| 171 void DisassembleAndAdjust(const base::FilePath& old_file, |
| 172 const base::FilePath& new_file, |
| 173 const base::FilePath& output_file) { |
| 174 CourgetteFlow flow; |
| 175 BufferedFileReader old_buffer(old_file, flow.name(flow.OLD)); |
| 176 BufferedFileReader new_buffer(new_file, flow.name(flow.NEW)); |
| 177 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, true); |
| 178 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, true); |
| 179 flow.AdjustNewAssemblyProgramToMatchOld(); |
| 180 flow.DestroyAssemblyProgram(flow.OLD); |
| 181 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); |
| 182 flow.DestroyAssemblyProgram(flow.NEW); |
| 183 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW); |
| 184 flow.DestroyEncodedProgram(flow.NEW); |
| 185 courgette::SinkStream sink; |
| 186 flow.WriteSinkStreamFromSinkStreamSet(flow.NEW, &sink); |
| 187 if (flow.failed()) |
| 188 Problem(flow.message().c_str()); |
| 189 |
| 190 WriteSinkToFile(&sink, output_file); |
| 191 } |
| 203 | 192 |
| 204 // Diffs two executable files, write a set of files for the diff, one file per | 193 // Diffs two executable files, write a set of files for the diff, one file per |
| 205 // stream of the EncodedProgram format. Each file is the bsdiff between the | 194 // stream of the EncodedProgram format. Each file is the bsdiff between the |
| 206 // original file's stream and the new file's stream. This is completely | 195 // original file's stream and the new file's stream. This is completely |
| 207 // uninteresting to users, but it is handy for seeing how much each which | 196 // uninteresting to users, but it is handy for seeing how much each which |
| 208 // streams are contributing to the final file size. Adjustment is optional. | 197 // streams are contributing to the final file size. Adjustment is optional. |
| 209 void DisassembleAdjustDiff(const base::FilePath& model_file, | 198 void DisassembleAdjustDiff(const base::FilePath& old_file, |
| 210 const base::FilePath& program_file, | 199 const base::FilePath& new_file, |
| 211 const base::FilePath& output_file_root, | 200 const base::FilePath& output_file_root, |
| 212 bool adjust) { | 201 bool adjust) { |
| 213 BufferedFileReader model_buffer(model_file, "old"); | 202 CourgetteFlow flow; |
| 214 BufferedFileReader program_buffer(program_file, "new"); | 203 BufferedFileReader old_buffer(old_file, flow.name(flow.OLD)); |
| 215 | 204 BufferedFileReader new_buffer(new_file, flow.name(flow.NEW)); |
| 216 auto parser = adjust ? courgette::ParseDetectedExecutableWithAnnotation | 205 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, adjust); |
| 217 : courgette::ParseDetectedExecutable; | 206 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, adjust); |
| 218 | 207 if (adjust) |
| 219 std::unique_ptr<courgette::AssemblyProgram> model; | 208 flow.AdjustNewAssemblyProgramToMatchOld(); |
| 220 const courgette::Status parse_model_status = | 209 flow.CreateEncodedProgramFromAssemblyProgram(flow.OLD); |
| 221 parser(model_buffer.data(), model_buffer.length(), &model); | 210 flow.DestroyAssemblyProgram(flow.OLD); |
| 222 if (parse_model_status != courgette::C_OK) | 211 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); |
| 223 Problem("Can't parse model input (code = %d).", parse_model_status); | 212 flow.DestroyAssemblyProgram(flow.NEW); |
| 224 | 213 flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD); |
| 225 std::unique_ptr<courgette::AssemblyProgram> program; | 214 flow.DestroyEncodedProgram(flow.OLD); |
| 226 const courgette::Status parse_program_status = | 215 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW); |
| 227 parser(program_buffer.data(), program_buffer.length(), &program); | 216 flow.DestroyEncodedProgram(flow.NEW); |
| 228 if (parse_program_status != courgette::C_OK) | 217 if (flow.failed()) |
| 229 Problem("Can't parse program input (code = %d).", parse_program_status); | 218 Problem(flow.message().c_str()); |
| 230 | |
| 231 if (adjust) { | |
| 232 const courgette::Status adjust_status = Adjust(*model, program.get()); | |
| 233 if (adjust_status != courgette::C_OK) | |
| 234 Problem("Can't adjust program."); | |
| 235 } | |
| 236 | |
| 237 std::unique_ptr<courgette::EncodedProgram> encoded_program; | |
| 238 const courgette::Status encode_program_status = | |
| 239 Encode(*program, &encoded_program); | |
| 240 if (encode_program_status != courgette::C_OK) | |
| 241 Problem("Can't encode program."); | |
| 242 | |
| 243 program.reset(); | |
| 244 | |
| 245 std::unique_ptr<courgette::EncodedProgram> encoded_model; | |
| 246 const courgette::Status encode_model_status = Encode(*model, &encoded_model); | |
| 247 if (encode_model_status != courgette::C_OK) | |
| 248 Problem("Can't encode model."); | |
| 249 | |
| 250 model.reset(); | |
| 251 | |
| 252 courgette::SinkStreamSet program_sinks; | |
| 253 const courgette::Status write_program_status = | |
| 254 courgette::WriteEncodedProgram(encoded_program.get(), &program_sinks); | |
| 255 if (write_program_status != courgette::C_OK) | |
| 256 Problem("Can't serialize encoded program."); | |
| 257 | |
| 258 encoded_program.reset(); | |
| 259 | |
| 260 courgette::SinkStreamSet model_sinks; | |
| 261 const courgette::Status write_model_status = | |
| 262 courgette::WriteEncodedProgram(encoded_model.get(), &model_sinks); | |
| 263 if (write_model_status != courgette::C_OK) | |
| 264 Problem("Can't serialize encoded model."); | |
| 265 | |
| 266 encoded_model.reset(); | |
| 267 | 219 |
| 268 courgette::SinkStream empty_sink; | 220 courgette::SinkStream empty_sink; |
| 269 for (int i = 0; ; ++i) { | 221 for (int i = 0; ; ++i) { |
| 270 courgette::SinkStream* old_stream = model_sinks.stream(i); | 222 courgette::SinkStream* old_stream = flow.data(flow.OLD)->sinks.stream(i); |
| 271 courgette::SinkStream* new_stream = program_sinks.stream(i); | 223 courgette::SinkStream* new_stream = flow.data(flow.NEW)->sinks.stream(i); |
| 272 if (old_stream == NULL && new_stream == NULL) | 224 if (old_stream == NULL && new_stream == NULL) |
| 273 break; | 225 break; |
| 274 | 226 |
| 275 courgette::SourceStream old_source; | 227 courgette::SourceStream old_source; |
| 276 courgette::SourceStream new_source; | 228 courgette::SourceStream new_source; |
| 277 old_source.Init(old_stream ? *old_stream : empty_sink); | 229 old_source.Init(old_stream ? *old_stream : empty_sink); |
| 278 new_source.Init(new_stream ? *new_stream : empty_sink); | 230 new_source.Init(new_stream ? *new_stream : empty_sink); |
| 279 courgette::SinkStream patch_stream; | 231 courgette::SinkStream patch_stream; |
| 280 bsdiff::BSDiffStatus status = | 232 bsdiff::BSDiffStatus status = |
| 281 bsdiff::CreateBinaryPatch(&old_source, &new_source, &patch_stream); | 233 bsdiff::CreateBinaryPatch(&old_source, &new_source, &patch_stream); |
| 282 if (status != bsdiff::OK) | 234 if (status != bsdiff::OK) |
| 283 Problem("-xxx failed."); | 235 Problem("-xxx failed."); |
| 284 | 236 |
| 285 std::string append = std::string("-") + base::IntToString(i); | 237 std::string append = std::string("-") + base::IntToString(i); |
| 286 | 238 |
| 287 WriteSinkToFile(&patch_stream, | 239 WriteSinkToFile(&patch_stream, |
| 288 output_file_root.InsertBeforeExtensionASCII(append)); | 240 output_file_root.InsertBeforeExtensionASCII(append)); |
| 289 } | 241 } |
| 290 } | 242 } |
| 291 | 243 |
| 292 void Assemble(const base::FilePath& input_file, | 244 void Assemble(const base::FilePath& input_file, |
| 293 const base::FilePath& output_file) { | 245 const base::FilePath& output_file) { |
| 294 BufferedFileReader buffer(input_file, "input"); | 246 CourgetteFlow flow; |
| 295 | 247 BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY)); |
| 296 courgette::SourceStreamSet sources; | 248 flow.ReadSourceStreamSetFromBuffer(flow.ONLY, input_buffer); |
| 297 if (!sources.Init(buffer.data(), buffer.length())) | 249 flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY); |
| 298 Problem("Bad input file."); | |
| 299 | |
| 300 std::unique_ptr<courgette::EncodedProgram> encoded; | |
| 301 const courgette::Status read_status = | |
| 302 courgette::ReadEncodedProgram(&sources, &encoded); | |
| 303 if (read_status != courgette::C_OK) | |
| 304 Problem("Bad encoded program."); | |
| 305 | |
| 306 courgette::SinkStream sink; | 250 courgette::SinkStream sink; |
| 307 | 251 flow.WriteExecutableFromEncodedProgram(flow.ONLY, &sink); |
| 308 const courgette::Status assemble_status = | 252 if (flow.failed()) |
| 309 courgette::Assemble(encoded.get(), &sink); | 253 Problem(flow.message().c_str()); |
| 310 if (assemble_status != courgette::C_OK) | |
| 311 Problem("Can't assemble."); | |
| 312 | 254 |
| 313 WriteSinkToFile(&sink, output_file); | 255 WriteSinkToFile(&sink, output_file); |
| 314 } | 256 } |
| 315 | 257 |
| 316 void GenerateEnsemblePatch(const base::FilePath& old_file, | 258 void GenerateEnsemblePatch(const base::FilePath& old_file, |
| 317 const base::FilePath& new_file, | 259 const base::FilePath& new_file, |
| 318 const base::FilePath& patch_file) { | 260 const base::FilePath& patch_file) { |
| 319 BufferedFileReader old_buffer(old_file, "'old' input"); | 261 BufferedFileReader old_buffer(old_file, "'old' input"); |
| 320 BufferedFileReader new_buffer(new_file, "'new' input"); | 262 BufferedFileReader new_buffer(new_file, "'new' input"); |
| 321 | 263 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 courgette::SinkStream new_stream; | 365 courgette::SinkStream new_stream; |
| 424 bsdiff::BSDiffStatus status = | 366 bsdiff::BSDiffStatus status = |
| 425 bsdiff::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream); | 367 bsdiff::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream); |
| 426 | 368 |
| 427 if (status != bsdiff::OK) | 369 if (status != bsdiff::OK) |
| 428 Problem("-applybsdiff failed."); | 370 Problem("-applybsdiff failed."); |
| 429 | 371 |
| 430 WriteSinkToFile(&new_stream, new_file); | 372 WriteSinkToFile(&new_stream, new_file); |
| 431 } | 373 } |
| 432 | 374 |
| 375 } // namespace |
| 376 |
| 433 int main(int argc, const char* argv[]) { | 377 int main(int argc, const char* argv[]) { |
| 434 base::AtExitManager at_exit_manager; | 378 base::AtExitManager at_exit_manager; |
| 435 base::CommandLine::Init(argc, argv); | 379 base::CommandLine::Init(argc, argv); |
| 436 const base::CommandLine& command_line = | 380 const base::CommandLine& command_line = |
| 437 *base::CommandLine::ForCurrentProcess(); | 381 *base::CommandLine::ForCurrentProcess(); |
| 438 | 382 |
| 439 logging::LoggingSettings settings; | 383 logging::LoggingSettings settings; |
| 440 settings.logging_dest = logging::LOG_TO_ALL; | 384 settings.logging_dest = logging::LOG_TO_ALL; |
| 441 settings.log_file = FILE_PATH_LITERAL("courgette.log"); | 385 settings.log_file = FILE_PATH_LITERAL("courgette.log"); |
| 442 (void)logging::InitLogging(settings); | 386 (void)logging::InitLogging(settings); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 461 | 405 |
| 462 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and | 406 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and |
| 463 // bugs in cleanup. | 407 // bugs in cleanup. |
| 464 int repeat_count = 1; | 408 int repeat_count = 1; |
| 465 std::string repeat_switch = command_line.GetSwitchValueASCII("repeat"); | 409 std::string repeat_switch = command_line.GetSwitchValueASCII("repeat"); |
| 466 if (!repeat_switch.empty()) | 410 if (!repeat_switch.empty()) |
| 467 if (!base::StringToInt(repeat_switch, &repeat_count)) | 411 if (!base::StringToInt(repeat_switch, &repeat_count)) |
| 468 repeat_count = 1; | 412 repeat_count = 1; |
| 469 | 413 |
| 470 if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + | 414 if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + |
| 471 cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + | 415 cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + |
| 472 cmd_spread_1_adjusted + cmd_spread_1_unadjusted | 416 cmd_spread_1_adjusted + cmd_spread_1_unadjusted != |
| 473 != 1) | 417 1) { |
| 474 UsageProblem( | 418 UsageProblem( |
| 475 "Must have exactly one of:\n" | 419 "First argument must be one of:\n" |
| 476 " -supported -asm, -dis, -disadj, -gen or -apply, -genbsdiff" | 420 " -supported, -asm, -dis, -disadj, -gen, -apply, -genbsdiff," |
| 477 " or -applybsdiff."); | 421 " -applybsdiff, or -gen1[au]."); |
| 422 } |
| 478 | 423 |
| 479 while (repeat_count-- > 0) { | 424 while (repeat_count-- > 0) { |
| 480 if (cmd_sup) { | 425 if (cmd_sup) { |
| 481 if (values.size() != 1) | 426 if (values.size() != 1) |
| 482 UsageProblem("-supported <executable_file>"); | 427 UsageProblem(kUsageSupported); |
| 483 return !Supported(values[0]); | 428 return !Supported(values[0]); |
| 484 } else if (cmd_dis) { | 429 } else if (cmd_dis) { |
| 485 if (values.size() != 2) | 430 if (values.size() != 2) |
| 486 UsageProblem("-dis <executable_file> <courgette_file>"); | 431 UsageProblem(kUsageDis); |
| 487 Disassemble(values[0], values[1]); | 432 Disassemble(values[0], values[1]); |
| 488 } else if (cmd_asm) { | 433 } else if (cmd_asm) { |
| 489 if (values.size() != 2) | 434 if (values.size() != 2) |
| 490 UsageProblem("-asm <courgette_file_input> <executable_file_output>"); | 435 UsageProblem(kUsageAsm); |
| 491 Assemble(values[0], values[1]); | 436 Assemble(values[0], values[1]); |
| 492 } else if (cmd_disadj) { | 437 } else if (cmd_disadj) { |
| 493 if (values.size() != 3) | 438 if (values.size() != 3) |
| 494 UsageProblem("-disadj <executable_file> <model> <courgette_file>"); | 439 UsageProblem(kUsageDisadj); |
| 495 DisassembleAndAdjust(values[0], values[1], values[2]); | 440 DisassembleAndAdjust(values[0], values[1], values[2]); |
| 496 } else if (cmd_make_patch) { | 441 } else if (cmd_make_patch) { |
| 497 if (values.size() != 3) | 442 if (values.size() != 3) |
| 498 UsageProblem("-gen <old_file> <new_file> <patch_file>"); | 443 UsageProblem(kUsageGen); |
| 499 GenerateEnsemblePatch(values[0], values[1], values[2]); | 444 GenerateEnsemblePatch(values[0], values[1], values[2]); |
| 500 } else if (cmd_apply_patch) { | 445 } else if (cmd_apply_patch) { |
| 501 if (values.size() != 3) | 446 if (values.size() != 3) |
| 502 UsageProblem("-apply <old_file> <patch_file> <new_file>"); | 447 UsageProblem(kUsageApply); |
| 503 ApplyEnsemblePatch(values[0], values[1], values[2]); | 448 ApplyEnsemblePatch(values[0], values[1], values[2]); |
| 504 } else if (cmd_make_bsdiff_patch) { | 449 } else if (cmd_make_bsdiff_patch) { |
| 505 if (values.size() != 3) | 450 if (values.size() != 3) |
| 506 UsageProblem("-genbsdiff <old_file> <new_file> <patch_file>"); | 451 UsageProblem(kUsageGenbsdiff); |
| 507 GenerateBSDiffPatch(values[0], values[1], values[2]); | 452 GenerateBSDiffPatch(values[0], values[1], values[2]); |
| 508 } else if (cmd_apply_bsdiff_patch) { | 453 } else if (cmd_apply_bsdiff_patch) { |
| 509 if (values.size() != 3) | 454 if (values.size() != 3) |
| 510 UsageProblem("-applybsdiff <old_file> <patch_file> <new_file>"); | 455 UsageProblem(kUsageApplybsdiff); |
| 511 ApplyBSDiffPatch(values[0], values[1], values[2]); | 456 ApplyBSDiffPatch(values[0], values[1], values[2]); |
| 512 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { | 457 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { |
| 513 if (values.size() != 3) | 458 if (values.size() != 3) |
| 514 UsageProblem("-gen1[au] <old_file> <new_file> <patch_files_root>"); | 459 UsageProblem(kUsageGen1); |
| 515 DisassembleAdjustDiff(values[0], values[1], values[2], | 460 DisassembleAdjustDiff(values[0], values[1], values[2], |
| 516 cmd_spread_1_adjusted); | 461 cmd_spread_1_adjusted); |
| 517 } else { | 462 } else { |
| 518 UsageProblem("No operation specified"); | 463 UsageProblem("No operation specified"); |
| 519 } | 464 } |
| 520 } | 465 } |
| 521 | 466 |
| 522 return 0; | 467 return 0; |
| 523 } | 468 } |
| OLD | NEW |