/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "applypatch_modes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "applypatch/applypatch.h" #include "edify/expr.h" static int CheckMode(const std::string& target_emmc) { std::string err; auto target = Partition::Parse(target_emmc, &err); if (!target) { LOG(ERROR) << "Failed to parse target \"" << target_emmc << "\": " << err; return 2; } return CheckPartition(target) ? 0 : 1; } static int FlashMode(const std::string& target_emmc, const std::string& source_file) { std::string err; auto target = Partition::Parse(target_emmc, &err); if (!target) { LOG(ERROR) << "Failed to parse target \"" << target_emmc << "\": " << err; return 2; } return FlashPartition(target, source_file) ? 0 : 1; } static int PatchMode(const std::string& target_emmc, const std::string& source_emmc, const std::string& patch_file, const std::string& bonus_file) { std::string err; auto target = Partition::Parse(target_emmc, &err); if (!target) { LOG(ERROR) << "Failed to parse target \"" << target_emmc << "\": " << err; return 2; } auto source = Partition::Parse(source_emmc, &err); if (!source) { LOG(ERROR) << "Failed to parse source \"" << source_emmc << "\": " << err; return 2; } std::string patch_contents; if (!android::base::ReadFileToString(patch_file, &patch_contents)) { PLOG(ERROR) << "Failed to read patch file \"" << patch_file << "\""; return 1; } Value patch(Value::Type::BLOB, std::move(patch_contents)); std::unique_ptr bonus; if (!bonus_file.empty()) { std::string bonus_contents; if (!android::base::ReadFileToString(bonus_file, &bonus_contents)) { PLOG(ERROR) << "Failed to read bonus file \"" << bonus_file << "\""; return 1; } bonus = std::make_unique(Value::Type::BLOB, std::move(bonus_contents)); } return PatchPartition(target, source, patch, bonus.get()) ? 0 : 1; } static void Usage() { printf( "Usage: \n" "check mode\n" " applypatch --check EMMC:::\n\n" "flash mode\n" " applypatch --flash \n" " --target EMMC:::\n\n" "patch mode\n" " applypatch [--bonus ]\n" " --patch \n" " --target EMMC:::\n" " --source EMMC:::\n\n" "show license\n" " applypatch --license\n" "\n\n"); } int applypatch_modes(int argc, char* argv[]) { static constexpr struct option OPTIONS[]{ // clang-format off { "bonus", required_argument, nullptr, 0 }, { "check", required_argument, nullptr, 0 }, { "flash", required_argument, nullptr, 0 }, { "license", no_argument, nullptr, 0 }, { "patch", required_argument, nullptr, 0 }, { "source", required_argument, nullptr, 0 }, { "target", required_argument, nullptr, 0 }, { nullptr, 0, nullptr, 0 }, // clang-format on }; std::string check_target; std::string source; std::string target; std::string patch; std::string bonus; bool check_mode = false; bool flash_mode = false; bool patch_mode = false; optind = 1; int arg; int option_index; while ((arg = getopt_long(argc, argv, "", OPTIONS, &option_index)) != -1) { switch (arg) { case 0: { std::string option = OPTIONS[option_index].name; if (option == "bonus") { bonus = optarg; } else if (option == "check") { check_target = optarg; check_mode = true; } else if (option == "flash") { source = optarg; flash_mode = true; } else if (option == "license") { return ShowLicenses(); } else if (option == "patch") { patch = optarg; patch_mode = true; } else if (option == "source") { source = optarg; } else if (option == "target") { target = optarg; } break; } case '?': default: LOG(ERROR) << "Invalid argument"; Usage(); return 2; } } if (check_mode) { return CheckMode(check_target); } if (flash_mode) { if (!bonus.empty()) { LOG(ERROR) << "bonus file not supported in flash mode"; return 1; } return FlashMode(target, source); } if (patch_mode) { return PatchMode(target, source, patch, bonus); } Usage(); return 2; }