15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/courgette.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/streams.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "courgette/third_party/bsdiff.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrintHelp() { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Usage:\n" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " courgette -supported <executable_file>\n" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " courgette -dis <executable_file> <binary_assembly_file>\n" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " courgette -asm <binary_assembly_file> <executable_file>\n" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " courgette -disadj <executable_file> <reference> <binary_assembly_file>\n" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " courgette -gen <v1> <v2> <patch>\n" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " courgette -apply <v1> <patch> <v2>\n" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\n"); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UsageProblem(const char* message) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "%s", message); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "\n"); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintHelp(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Problem(const char* format, ...) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_list args; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_start(args, format); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vfprintf(stderr, format, args); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fprintf(stderr, "\n"); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_end(args); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit(1); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string ReadOrFail(const base::FilePath& file_name, const char* kind) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 file_size = 0; 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::GetFileSize(file_name, &file_size)) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't read %s file.", kind); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string buffer; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer.reserve(static_cast<size_t>(file_size)); 5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!base::ReadFileToString(file_name, &buffer)) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't read %s file.", kind); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffer; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WriteSinkToFile(const courgette::SinkStream *sink, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& output_file) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WriteFile(output_file, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(sink->Buffer()), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(sink->Length())); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count == -1) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't write output."); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (static_cast<size_t>(count) != sink->Length()) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Incomplete write."); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Disassemble(const base::FilePath& input_file, 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& output_file) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string buffer = ReadOrFail(input_file, "input"); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::AssemblyProgram* program = NULL; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status parse_status = 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::ParseDetectedExecutable(buffer.c_str(), buffer.length(), 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &program); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parse_status != courgette::C_OK) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't parse input."); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::EncodedProgram* encoded = NULL; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status encode_status = Encode(program, &encoded); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::DeleteAssemblyProgram(program); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encode_status != courgette::C_OK) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't encode program."); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStreamSet sinks; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status write_status = 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::WriteEncodedProgram(encoded, &sinks); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (write_status != courgette::C_OK) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't serialize encoded program."); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::DeleteEncodedProgram(encoded); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream sink; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sinks.CopyTo(&sink)) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't combine serialized encoded program streams."); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSinkToFile(&sink, output_file); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Supported(const base::FilePath& input_file) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string buffer = ReadOrFail(input_file, "input"); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::ExecutableType type; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t detected_length; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DetectExecutableType(buffer.c_str(), buffer.length(), 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &type, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &detected_length); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the detection fails, we just fall back on UNKNOWN 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string format = "Unsupported"; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case courgette::EXE_UNKNOWN: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case courgette::EXE_WIN_32_X86: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format = "Windows 32 PE"; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case courgette::EXE_ELF_32_X86: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format = "ELF 32 X86"; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = true; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case courgette::EXE_ELF_32_ARM: 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch format = "ELF 32 ARM"; 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result = true; 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) case courgette::EXE_WIN_32_X64: 14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) format = "Windows 64 PE"; 14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) result = true; 14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) break; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printf("%s Executable\n", format.c_str()); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisassembleAndAdjust(const base::FilePath& program_file, 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& model_file, 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& output_file) { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string program_buffer = ReadOrFail(program_file, "program"); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string model_buffer = ReadOrFail(model_file, "reference"); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::AssemblyProgram* program = NULL; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status parse_program_status = 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::ParseDetectedExecutable(program_buffer.c_str(), 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) program_buffer.length(), 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &program); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parse_program_status != courgette::C_OK) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't parse program input."); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::AssemblyProgram* model = NULL; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status parse_model_status = 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::ParseDetectedExecutable(model_buffer.c_str(), 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_buffer.length(), 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &model); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parse_model_status != courgette::C_OK) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't parse model input."); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status adjust_status = Adjust(*model, program); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adjust_status != courgette::C_OK) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't adjust program."); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::EncodedProgram* encoded = NULL; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status encode_status = Encode(program, &encoded); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::DeleteAssemblyProgram(program); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encode_status != courgette::C_OK) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't encode program."); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStreamSet sinks; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status write_status = 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::WriteEncodedProgram(encoded, &sinks); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (write_status != courgette::C_OK) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't serialize encoded program."); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::DeleteEncodedProgram(encoded); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream sink; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sinks.CopyTo(&sink)) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't combine serialized encoded program streams."); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSinkToFile(&sink, output_file); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Diffs two executable files, write a set of files for the diff, one file per 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stream of the EncodedProgram format. Each file is the bsdiff between the 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// original file's stream and the new file's stream. This is completely 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// uninteresting to users, but it is handy for seeing how much each which 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// streams are contributing to the final file size. Adjustment is optional. 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisassembleAdjustDiff(const base::FilePath& model_file, 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& program_file, 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& output_file_root, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool adjust) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string model_buffer = ReadOrFail(model_file, "'old'"); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string program_buffer = ReadOrFail(program_file, "'new'"); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::AssemblyProgram* model = NULL; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status parse_model_status = 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::ParseDetectedExecutable(model_buffer.c_str(), 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_buffer.length(), 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &model); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parse_model_status != courgette::C_OK) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't parse model input."); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::AssemblyProgram* program = NULL; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status parse_program_status = 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::ParseDetectedExecutable(program_buffer.c_str(), 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) program_buffer.length(), 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &program); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parse_program_status != courgette::C_OK) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't parse program input."); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adjust) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status adjust_status = Adjust(*model, program); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (adjust_status != courgette::C_OK) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't adjust program."); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::EncodedProgram* encoded_program = NULL; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status encode_program_status = 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Encode(program, &encoded_program); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::DeleteAssemblyProgram(program); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encode_program_status != courgette::C_OK) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't encode program."); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::EncodedProgram* encoded_model = NULL; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status encode_model_status = Encode(model, &encoded_model); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::DeleteAssemblyProgram(model); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encode_model_status != courgette::C_OK) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't encode model."); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStreamSet program_sinks; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status write_program_status = 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::WriteEncodedProgram(encoded_program, &program_sinks); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (write_program_status != courgette::C_OK) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't serialize encoded program."); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::DeleteEncodedProgram(encoded_program); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStreamSet model_sinks; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status write_model_status = 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::WriteEncodedProgram(encoded_model, &model_sinks); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (write_model_status != courgette::C_OK) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't serialize encoded model."); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::DeleteEncodedProgram(encoded_model); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream empty_sink; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; ; ++i) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream* old_stream = model_sinks.stream(i); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream* new_stream = program_sinks.stream(i); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_stream == NULL && new_stream == NULL) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStream old_source; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStream new_source; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_source.Init(old_stream ? *old_stream : empty_sink); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_source.Init(new_stream ? *new_stream : empty_sink); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream patch_stream; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::BSDiffStatus status = 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::CreateBinaryPatch(&old_source, &new_source, &patch_stream); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != courgette::OK) Problem("-xxx failed."); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string append = std::string("-") + base::IntToString(i); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSinkToFile(&patch_stream, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_file_root.InsertBeforeExtensionASCII(append)); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Assemble(const base::FilePath& input_file, 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& output_file) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string buffer = ReadOrFail(input_file, "input"); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStreamSet sources; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sources.Init(buffer.c_str(), buffer.length())) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Bad input file."); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::EncodedProgram* encoded = NULL; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status read_status = ReadEncodedProgram(&sources, &encoded); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_status != courgette::C_OK) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Bad encoded program."); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream sink; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const courgette::Status assemble_status = courgette::Assemble(encoded, &sink); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (assemble_status != courgette::C_OK) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't assemble."); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSinkToFile(&sink, output_file); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GenerateEnsemblePatch(const base::FilePath& old_file, 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& new_file, 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& patch_file) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_buffer = ReadOrFail(old_file, "'old' input"); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string new_buffer = ReadOrFail(new_file, "'new' input"); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStream old_stream; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStream new_stream; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_stream.Init(old_buffer); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_stream.Init(new_buffer); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream patch_stream; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::Status status = 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::GenerateEnsemblePatch(&old_stream, &new_stream, &patch_stream); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != courgette::C_OK) Problem("-gen failed."); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSinkToFile(&patch_stream, patch_file); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ApplyEnsemblePatch(const base::FilePath& old_file, 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& patch_file, 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& new_file) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We do things a little differently here in order to call the same Courgette 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entry point as the installer. That entry point point takes file names and 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns an status code but does not output any diagnostics. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::Status status = 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::ApplyEnsemblePatch(old_file.value().c_str(), 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) patch_file.value().c_str(), 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_file.value().c_str()); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == courgette::C_OK) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Diagnose the error. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case courgette::C_BAD_ENSEMBLE_MAGIC: 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Not a courgette patch"); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case courgette::C_BAD_ENSEMBLE_VERSION: 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Wrong version patch"); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case courgette::C_BAD_ENSEMBLE_HEADER: 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Corrupt patch"); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case courgette::C_DISASSEMBLY_FAILED: 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Disassembly failed (could be because of memory issues)"); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case courgette::C_STREAM_ERROR: 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Stream error (likely out of memory or disk space)"); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we failed due to a missing input file, this will 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // print the message. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_buffer = ReadOrFail(old_file, "'old' input"); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_buffer.clear(); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string patch_buffer = ReadOrFail(patch_file, "'patch' input"); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) patch_buffer.clear(); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-input related errors: 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == courgette::C_WRITE_OPEN_ERROR) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't open output"); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == courgette::C_WRITE_ERROR) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("Can't write output"); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Problem("-apply failed."); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GenerateBSDiffPatch(const base::FilePath& old_file, 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& new_file, 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& patch_file) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_buffer = ReadOrFail(old_file, "'old' input"); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string new_buffer = ReadOrFail(new_file, "'new' input"); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStream old_stream; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStream new_stream; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_stream.Init(old_buffer); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_stream.Init(new_buffer); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream patch_stream; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::BSDiffStatus status = 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::CreateBinaryPatch(&old_stream, &new_stream, &patch_stream); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != courgette::OK) Problem("-genbsdiff failed."); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSinkToFile(&patch_stream, patch_file); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ApplyBSDiffPatch(const base::FilePath& old_file, 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& patch_file, 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& new_file) { 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_buffer = ReadOrFail(old_file, "'old' input"); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string patch_buffer = ReadOrFail(patch_file, "'patch' input"); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStream old_stream; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SourceStream patch_stream; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_stream.Init(old_buffer); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) patch_stream.Init(patch_buffer); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::SinkStream new_stream; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::BSDiffStatus status = 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) courgette::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != courgette::OK) Problem("-applybsdiff failed."); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSinkToFile(&new_stream, new_file); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, const char* argv[]) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AtExitManager at_exit_manager; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::Init(argc, argv); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch logging::LoggingSettings settings; 433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch settings.logging_dest = logging::LOG_TO_ALL; 434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch settings.log_file = FILE_PATH_LITERAL("courgette.log"); 435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (void)logging::InitLogging(settings); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging::SetMinLogLevel(logging::LOG_VERBOSE); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_sup = command_line.HasSwitch("supported"); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_dis = command_line.HasSwitch("dis"); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_asm = command_line.HasSwitch("asm"); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_disadj = command_line.HasSwitch("disadj"); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_make_patch = command_line.HasSwitch("gen"); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_apply_patch = command_line.HasSwitch("apply"); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_make_bsdiff_patch = command_line.HasSwitch("genbsdiff"); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_apply_bsdiff_patch = command_line.HasSwitch("applybsdiff"); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_spread_1_adjusted = command_line.HasSwitch("gen1a"); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cmd_spread_1_unadjusted = command_line.HasSwitch("gen1u"); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::FilePath> values; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine::StringVector& args = command_line.GetArgs(); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < args.size(); ++i) { 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) values.push_back(base::FilePath(args[i])); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // '-repeat=N' is for debugging. Running many iterations can reveal leaks and 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bugs in cleanup. 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int repeat_count = 1; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string repeat_switch = command_line.GetSwitchValueASCII("repeat"); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!repeat_switch.empty()) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt(repeat_switch, &repeat_count)) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) repeat_count = 1; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_spread_1_adjusted + cmd_spread_1_unadjusted 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) != 1) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem( 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Must have exactly one of:\n" 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " -supported -asm, -dis, -disadj, -gen or -apply, -genbsdiff" 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " or -applybsdiff."); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (repeat_count-- > 0) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd_sup) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 1) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-supported <executable_file>"); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !Supported(values[0]); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_dis) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 2) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-dis <executable_file> <courgette_file>"); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Disassemble(values[0], values[1]); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_asm) { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 2) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-asm <courgette_file_input> <executable_file_output>"); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Assemble(values[0], values[1]); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_disadj) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 3) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-disadj <executable_file> <model> <courgette_file>"); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisassembleAndAdjust(values[0], values[1], values[2]); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_make_patch) { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 3) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-gen <old_file> <new_file> <patch_file>"); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateEnsemblePatch(values[0], values[1], values[2]); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_apply_patch) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 3) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-apply <old_file> <patch_file> <new_file>"); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ApplyEnsemblePatch(values[0], values[1], values[2]); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_make_bsdiff_patch) { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 3) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-genbsdiff <old_file> <new_file> <patch_file>"); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateBSDiffPatch(values[0], values[1], values[2]); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_apply_bsdiff_patch) { 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 3) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-applybsdiff <old_file> <patch_file> <new_file>"); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ApplyBSDiffPatch(values[0], values[1], values[2]); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (values.size() != 3) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("-gen1[au] <old_file> <new_file> <patch_files_root>"); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisassembleAdjustDiff(values[0], values[1], values[2], 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_spread_1_adjusted); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsageProblem("No operation specified"); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 517