1*33f37583SAndroid Build Coastguard Worker //
2*33f37583SAndroid Build Coastguard Worker // Copyright (C) 2022 The Android Open Source Project
3*33f37583SAndroid Build Coastguard Worker //
4*33f37583SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*33f37583SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*33f37583SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*33f37583SAndroid Build Coastguard Worker //
8*33f37583SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
9*33f37583SAndroid Build Coastguard Worker //
10*33f37583SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*33f37583SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*33f37583SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*33f37583SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*33f37583SAndroid Build Coastguard Worker // limitations under the License.
15*33f37583SAndroid Build Coastguard Worker //
16*33f37583SAndroid Build Coastguard Worker
17*33f37583SAndroid Build Coastguard Worker #include <action.h>
18*33f37583SAndroid Build Coastguard Worker #include <action_manager.h>
19*33f37583SAndroid Build Coastguard Worker #include <action_parser.h>
20*33f37583SAndroid Build Coastguard Worker #include <android-base/file.h>
21*33f37583SAndroid Build Coastguard Worker #include <android-base/logging.h>
22*33f37583SAndroid Build Coastguard Worker #include <android-base/parseint.h>
23*33f37583SAndroid Build Coastguard Worker #include <android-base/result.h>
24*33f37583SAndroid Build Coastguard Worker #include <android-base/strings.h>
25*33f37583SAndroid Build Coastguard Worker #include <apex_file.h>
26*33f37583SAndroid Build Coastguard Worker #include <getopt.h>
27*33f37583SAndroid Build Coastguard Worker #include <parser.h>
28*33f37583SAndroid Build Coastguard Worker #include <pwd.h>
29*33f37583SAndroid Build Coastguard Worker #include <service_list.h>
30*33f37583SAndroid Build Coastguard Worker #include <service_parser.h>
31*33f37583SAndroid Build Coastguard Worker #include <stdio.h>
32*33f37583SAndroid Build Coastguard Worker #include <stdlib.h>
33*33f37583SAndroid Build Coastguard Worker
34*33f37583SAndroid Build Coastguard Worker #include <iostream>
35*33f37583SAndroid Build Coastguard Worker #include <string_view>
36*33f37583SAndroid Build Coastguard Worker
37*33f37583SAndroid Build Coastguard Worker using ::apex::proto::ApexManifest;
38*33f37583SAndroid Build Coastguard Worker
39*33f37583SAndroid Build Coastguard Worker // Fake getpwnam for host execution, used by the init::ServiceParser.
getpwnam(const char *)40*33f37583SAndroid Build Coastguard Worker passwd* getpwnam(const char*) {
41*33f37583SAndroid Build Coastguard Worker static char fake_buf[] = "fake";
42*33f37583SAndroid Build Coastguard Worker static passwd fake_passwd = {
43*33f37583SAndroid Build Coastguard Worker .pw_name = fake_buf,
44*33f37583SAndroid Build Coastguard Worker .pw_dir = fake_buf,
45*33f37583SAndroid Build Coastguard Worker .pw_shell = fake_buf,
46*33f37583SAndroid Build Coastguard Worker .pw_uid = 123,
47*33f37583SAndroid Build Coastguard Worker .pw_gid = 123,
48*33f37583SAndroid Build Coastguard Worker };
49*33f37583SAndroid Build Coastguard Worker return &fake_passwd;
50*33f37583SAndroid Build Coastguard Worker }
51*33f37583SAndroid Build Coastguard Worker
52*33f37583SAndroid Build Coastguard Worker namespace android {
53*33f37583SAndroid Build Coastguard Worker namespace apex {
54*33f37583SAndroid Build Coastguard Worker namespace {
55*33f37583SAndroid Build Coastguard Worker
56*33f37583SAndroid Build Coastguard Worker static const std::vector<std::string> partitions = {"system", "system_ext",
57*33f37583SAndroid Build Coastguard Worker "product", "vendor", "odm"};
58*33f37583SAndroid Build Coastguard Worker
PrintUsage(const std::string & msg="")59*33f37583SAndroid Build Coastguard Worker void PrintUsage(const std::string& msg = "") {
60*33f37583SAndroid Build Coastguard Worker if (msg != "") {
61*33f37583SAndroid Build Coastguard Worker std::cerr << "Error: " << msg << "\n";
62*33f37583SAndroid Build Coastguard Worker }
63*33f37583SAndroid Build Coastguard Worker printf(R"(usage: host_apex_verifier [options]
64*33f37583SAndroid Build Coastguard Worker
65*33f37583SAndroid Build Coastguard Worker Tests APEX file(s) for correctness.
66*33f37583SAndroid Build Coastguard Worker
67*33f37583SAndroid Build Coastguard Worker Options:
68*33f37583SAndroid Build Coastguard Worker --deapexer=PATH Use the deapexer binary at this path when extracting APEXes.
69*33f37583SAndroid Build Coastguard Worker --debugfs=PATH Use the debugfs binary at this path when extracting APEXes.
70*33f37583SAndroid Build Coastguard Worker --fsckerofs=PATH Use the fsck.erofs binary at this path when extracting APEXes.
71*33f37583SAndroid Build Coastguard Worker --sdk_version=INT The active system SDK version used when filtering versioned
72*33f37583SAndroid Build Coastguard Worker init.rc files.
73*33f37583SAndroid Build Coastguard Worker for checking all APEXes:
74*33f37583SAndroid Build Coastguard Worker --out_system=DIR Path to the factory APEX directory for the system partition.
75*33f37583SAndroid Build Coastguard Worker --out_system_ext=DIR Path to the factory APEX directory for the system_ext partition.
76*33f37583SAndroid Build Coastguard Worker --out_product=DIR Path to the factory APEX directory for the product partition.
77*33f37583SAndroid Build Coastguard Worker --out_vendor=DIR Path to the factory APEX directory for the vendor partition.
78*33f37583SAndroid Build Coastguard Worker --out_odm=DIR Path to the factory APEX directory for the odm partition.
79*33f37583SAndroid Build Coastguard Worker
80*33f37583SAndroid Build Coastguard Worker for checking a single APEX:
81*33f37583SAndroid Build Coastguard Worker --apex=PATH Path to the target APEX.
82*33f37583SAndroid Build Coastguard Worker --partition_tag=[system|vendor|...] Partition for the target APEX.
83*33f37583SAndroid Build Coastguard Worker )");
84*33f37583SAndroid Build Coastguard Worker }
85*33f37583SAndroid Build Coastguard Worker
86*33f37583SAndroid Build Coastguard Worker // Use this for better error message when unavailable keyword is used.
87*33f37583SAndroid Build Coastguard Worker class NotAvailableParser : public init::SectionParser {
88*33f37583SAndroid Build Coastguard Worker public:
NotAvailableParser(const std::string & keyword)89*33f37583SAndroid Build Coastguard Worker NotAvailableParser(const std::string& keyword) : keyword_(keyword) {}
ParseSection(std::vector<std::string> &&,const std::string &,int)90*33f37583SAndroid Build Coastguard Worker base::Result<void> ParseSection(std::vector<std::string>&&,
91*33f37583SAndroid Build Coastguard Worker const std::string&, int) override {
92*33f37583SAndroid Build Coastguard Worker return base::Error() << "'" << keyword_ << "' is not available.";
93*33f37583SAndroid Build Coastguard Worker }
94*33f37583SAndroid Build Coastguard Worker
95*33f37583SAndroid Build Coastguard Worker private:
96*33f37583SAndroid Build Coastguard Worker std::string keyword_;
97*33f37583SAndroid Build Coastguard Worker };
98*33f37583SAndroid Build Coastguard Worker
99*33f37583SAndroid Build Coastguard Worker // Validate any init rc files inside the APEX.
CheckInitRc(const std::string & apex_dir,const ApexManifest & manifest,int sdk_version,bool is_vendor)100*33f37583SAndroid Build Coastguard Worker void CheckInitRc(const std::string& apex_dir, const ApexManifest& manifest,
101*33f37583SAndroid Build Coastguard Worker int sdk_version, bool is_vendor) {
102*33f37583SAndroid Build Coastguard Worker init::Parser parser;
103*33f37583SAndroid Build Coastguard Worker if (is_vendor) {
104*33f37583SAndroid Build Coastguard Worker init::InitializeHostSubcontext({apex_dir});
105*33f37583SAndroid Build Coastguard Worker }
106*33f37583SAndroid Build Coastguard Worker init::ServiceList service_list = init::ServiceList();
107*33f37583SAndroid Build Coastguard Worker parser.AddSectionParser("service", std::make_unique<init::ServiceParser>(
108*33f37583SAndroid Build Coastguard Worker &service_list, init::GetSubcontext()));
109*33f37583SAndroid Build Coastguard Worker const init::BuiltinFunctionMap& function_map = init::GetBuiltinFunctionMap();
110*33f37583SAndroid Build Coastguard Worker init::Action::set_function_map(&function_map);
111*33f37583SAndroid Build Coastguard Worker init::ActionManager action_manager = init::ActionManager();
112*33f37583SAndroid Build Coastguard Worker if (is_vendor) {
113*33f37583SAndroid Build Coastguard Worker parser.AddSectionParser("on", std::make_unique<init::ActionParser>(
114*33f37583SAndroid Build Coastguard Worker &action_manager, init::GetSubcontext()));
115*33f37583SAndroid Build Coastguard Worker } else {
116*33f37583SAndroid Build Coastguard Worker // "on" keyword is not available in non-vendor APEXes.
117*33f37583SAndroid Build Coastguard Worker parser.AddSectionParser("on", std::make_unique<NotAvailableParser>("on"));
118*33f37583SAndroid Build Coastguard Worker }
119*33f37583SAndroid Build Coastguard Worker
120*33f37583SAndroid Build Coastguard Worker std::string init_dir_path = apex_dir + "/etc";
121*33f37583SAndroid Build Coastguard Worker std::vector<std::string> init_configs;
122*33f37583SAndroid Build Coastguard Worker std::unique_ptr<DIR, decltype(&closedir)> init_dir(
123*33f37583SAndroid Build Coastguard Worker opendir(init_dir_path.c_str()), closedir);
124*33f37583SAndroid Build Coastguard Worker if (init_dir) {
125*33f37583SAndroid Build Coastguard Worker dirent* entry;
126*33f37583SAndroid Build Coastguard Worker while ((entry = readdir(init_dir.get()))) {
127*33f37583SAndroid Build Coastguard Worker if (base::EndsWith(entry->d_name, "rc")) {
128*33f37583SAndroid Build Coastguard Worker init_configs.push_back(init_dir_path + "/" + entry->d_name);
129*33f37583SAndroid Build Coastguard Worker }
130*33f37583SAndroid Build Coastguard Worker }
131*33f37583SAndroid Build Coastguard Worker }
132*33f37583SAndroid Build Coastguard Worker // TODO(b/225380016): Extend this tool to check all init.rc files
133*33f37583SAndroid Build Coastguard Worker // in the APEX, possibly including different requirements depending
134*33f37583SAndroid Build Coastguard Worker // on the SDK version.
135*33f37583SAndroid Build Coastguard Worker for (const auto& c :
136*33f37583SAndroid Build Coastguard Worker init::FilterVersionedConfigs(init_configs, sdk_version)) {
137*33f37583SAndroid Build Coastguard Worker auto result = parser.ParseConfigFile(c);
138*33f37583SAndroid Build Coastguard Worker if (!result.ok()) {
139*33f37583SAndroid Build Coastguard Worker LOG(FATAL) << result.error();
140*33f37583SAndroid Build Coastguard Worker }
141*33f37583SAndroid Build Coastguard Worker }
142*33f37583SAndroid Build Coastguard Worker
143*33f37583SAndroid Build Coastguard Worker for (const auto& service : service_list) {
144*33f37583SAndroid Build Coastguard Worker // Ensure the service path points inside this APEX.
145*33f37583SAndroid Build Coastguard Worker auto service_path = service->args()[0];
146*33f37583SAndroid Build Coastguard Worker if (!base::StartsWith(service_path, "/apex/" + manifest.name())) {
147*33f37583SAndroid Build Coastguard Worker LOG(FATAL) << "Service " << service->name()
148*33f37583SAndroid Build Coastguard Worker << " has path outside of the APEX: " << service_path;
149*33f37583SAndroid Build Coastguard Worker }
150*33f37583SAndroid Build Coastguard Worker LOG(INFO) << service->name() << ": " << service_path;
151*33f37583SAndroid Build Coastguard Worker }
152*33f37583SAndroid Build Coastguard Worker
153*33f37583SAndroid Build Coastguard Worker // The parser will fail if there are any unsupported actions.
154*33f37583SAndroid Build Coastguard Worker if (parser.parse_error_count() > 0) {
155*33f37583SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
156*33f37583SAndroid Build Coastguard Worker }
157*33f37583SAndroid Build Coastguard Worker }
158*33f37583SAndroid Build Coastguard Worker
159*33f37583SAndroid Build Coastguard Worker // Extract and validate a single APEX.
ScanApex(const std::string & deapexer,int sdk_version,const std::string & apex_path,const std::string & partition_tag)160*33f37583SAndroid Build Coastguard Worker void ScanApex(const std::string& deapexer, int sdk_version,
161*33f37583SAndroid Build Coastguard Worker const std::string& apex_path, const std::string& partition_tag) {
162*33f37583SAndroid Build Coastguard Worker LOG(INFO) << "Checking APEX " << apex_path;
163*33f37583SAndroid Build Coastguard Worker
164*33f37583SAndroid Build Coastguard Worker auto apex = OR_FATAL(ApexFile::Open(apex_path));
165*33f37583SAndroid Build Coastguard Worker ApexManifest manifest = apex.GetManifest();
166*33f37583SAndroid Build Coastguard Worker
167*33f37583SAndroid Build Coastguard Worker auto extracted_apex = TemporaryDir();
168*33f37583SAndroid Build Coastguard Worker std::string extracted_apex_dir = extracted_apex.path;
169*33f37583SAndroid Build Coastguard Worker std::string deapexer_command =
170*33f37583SAndroid Build Coastguard Worker deapexer + " extract " + apex_path + " " + extracted_apex_dir;
171*33f37583SAndroid Build Coastguard Worker auto code = system(deapexer_command.c_str());
172*33f37583SAndroid Build Coastguard Worker if (code != 0) {
173*33f37583SAndroid Build Coastguard Worker LOG(FATAL) << "Error running deapexer command \"" << deapexer_command
174*33f37583SAndroid Build Coastguard Worker << "\": " << code;
175*33f37583SAndroid Build Coastguard Worker }
176*33f37583SAndroid Build Coastguard Worker bool is_vendor = partition_tag == "vendor" || partition_tag == "odm";
177*33f37583SAndroid Build Coastguard Worker CheckInitRc(extracted_apex_dir, manifest, sdk_version, is_vendor);
178*33f37583SAndroid Build Coastguard Worker }
179*33f37583SAndroid Build Coastguard Worker
180*33f37583SAndroid Build Coastguard Worker // Scan the factory APEX files in the partition apex dir.
181*33f37583SAndroid Build Coastguard Worker // Scans APEX files directly, rather than flattened ${PRODUCT_OUT}/apex/
182*33f37583SAndroid Build Coastguard Worker // directories. This allows us to check:
183*33f37583SAndroid Build Coastguard Worker // - Prebuilt APEXes which do not flatten to that path.
184*33f37583SAndroid Build Coastguard Worker // - Multi-installed APEXes, where only the default
185*33f37583SAndroid Build Coastguard Worker // APEX may flatten to that path.
186*33f37583SAndroid Build Coastguard Worker // - Extracted target_files archives which may not contain
187*33f37583SAndroid Build Coastguard Worker // flattened <PARTITON>/apex/ directories.
ScanPartitionApexes(const std::string & deapexer,int sdk_version,const std::string & partition_dir,const std::string & partition_tag)188*33f37583SAndroid Build Coastguard Worker void ScanPartitionApexes(const std::string& deapexer, int sdk_version,
189*33f37583SAndroid Build Coastguard Worker const std::string& partition_dir,
190*33f37583SAndroid Build Coastguard Worker const std::string& partition_tag) {
191*33f37583SAndroid Build Coastguard Worker LOG(INFO) << "Scanning " << partition_dir << " for factory APEXes in "
192*33f37583SAndroid Build Coastguard Worker << partition_tag;
193*33f37583SAndroid Build Coastguard Worker
194*33f37583SAndroid Build Coastguard Worker std::unique_ptr<DIR, decltype(&closedir)> apex_dir(
195*33f37583SAndroid Build Coastguard Worker opendir(partition_dir.c_str()), closedir);
196*33f37583SAndroid Build Coastguard Worker if (!apex_dir) {
197*33f37583SAndroid Build Coastguard Worker LOG(WARNING) << "Unable to open dir " << partition_dir;
198*33f37583SAndroid Build Coastguard Worker return;
199*33f37583SAndroid Build Coastguard Worker }
200*33f37583SAndroid Build Coastguard Worker
201*33f37583SAndroid Build Coastguard Worker dirent* entry;
202*33f37583SAndroid Build Coastguard Worker while ((entry = readdir(apex_dir.get()))) {
203*33f37583SAndroid Build Coastguard Worker if (base::EndsWith(entry->d_name, ".apex") ||
204*33f37583SAndroid Build Coastguard Worker base::EndsWith(entry->d_name, ".capex")) {
205*33f37583SAndroid Build Coastguard Worker ScanApex(deapexer, sdk_version, partition_dir + "/" + entry->d_name,
206*33f37583SAndroid Build Coastguard Worker partition_tag);
207*33f37583SAndroid Build Coastguard Worker }
208*33f37583SAndroid Build Coastguard Worker }
209*33f37583SAndroid Build Coastguard Worker }
210*33f37583SAndroid Build Coastguard Worker
211*33f37583SAndroid Build Coastguard Worker } // namespace
212*33f37583SAndroid Build Coastguard Worker
main(int argc,char ** argv)213*33f37583SAndroid Build Coastguard Worker int main(int argc, char** argv) {
214*33f37583SAndroid Build Coastguard Worker android::base::SetMinimumLogSeverity(android::base::ERROR);
215*33f37583SAndroid Build Coastguard Worker android::base::InitLogging(argv, &android::base::StdioLogger);
216*33f37583SAndroid Build Coastguard Worker
217*33f37583SAndroid Build Coastguard Worker std::string deapexer, debugfs, fsckerofs;
218*33f37583SAndroid Build Coastguard Worker // Use ANDROID_HOST_OUT for convenience
219*33f37583SAndroid Build Coastguard Worker const char* host_out = getenv("ANDROID_HOST_OUT");
220*33f37583SAndroid Build Coastguard Worker if (host_out) {
221*33f37583SAndroid Build Coastguard Worker deapexer = std::string(host_out) + "/bin/deapexer";
222*33f37583SAndroid Build Coastguard Worker debugfs = std::string(host_out) + "/bin/debugfs_static";
223*33f37583SAndroid Build Coastguard Worker fsckerofs = std::string(host_out) + "/bin/fsck.erofs";
224*33f37583SAndroid Build Coastguard Worker }
225*33f37583SAndroid Build Coastguard Worker int sdk_version = INT_MAX;
226*33f37583SAndroid Build Coastguard Worker std::map<std::string, std::string> partition_map;
227*33f37583SAndroid Build Coastguard Worker std::string apex;
228*33f37583SAndroid Build Coastguard Worker std::string partition_tag;
229*33f37583SAndroid Build Coastguard Worker
230*33f37583SAndroid Build Coastguard Worker while (true) {
231*33f37583SAndroid Build Coastguard Worker static const struct option long_options[] = {
232*33f37583SAndroid Build Coastguard Worker {"help", no_argument, nullptr, 'h'},
233*33f37583SAndroid Build Coastguard Worker {"deapexer", required_argument, nullptr, 0},
234*33f37583SAndroid Build Coastguard Worker {"debugfs", required_argument, nullptr, 0},
235*33f37583SAndroid Build Coastguard Worker {"fsckerofs", required_argument, nullptr, 0},
236*33f37583SAndroid Build Coastguard Worker {"sdk_version", required_argument, nullptr, 0},
237*33f37583SAndroid Build Coastguard Worker {"out_system", required_argument, nullptr, 0},
238*33f37583SAndroid Build Coastguard Worker {"out_system_ext", required_argument, nullptr, 0},
239*33f37583SAndroid Build Coastguard Worker {"out_product", required_argument, nullptr, 0},
240*33f37583SAndroid Build Coastguard Worker {"out_vendor", required_argument, nullptr, 0},
241*33f37583SAndroid Build Coastguard Worker {"out_odm", required_argument, nullptr, 0},
242*33f37583SAndroid Build Coastguard Worker {"apex", required_argument, nullptr, 0},
243*33f37583SAndroid Build Coastguard Worker {"partition_tag", required_argument, nullptr, 0},
244*33f37583SAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
245*33f37583SAndroid Build Coastguard Worker };
246*33f37583SAndroid Build Coastguard Worker
247*33f37583SAndroid Build Coastguard Worker int option_index;
248*33f37583SAndroid Build Coastguard Worker int arg = getopt_long(argc, argv, "h", long_options, &option_index);
249*33f37583SAndroid Build Coastguard Worker
250*33f37583SAndroid Build Coastguard Worker if (arg == -1) {
251*33f37583SAndroid Build Coastguard Worker break;
252*33f37583SAndroid Build Coastguard Worker }
253*33f37583SAndroid Build Coastguard Worker
254*33f37583SAndroid Build Coastguard Worker switch (arg) {
255*33f37583SAndroid Build Coastguard Worker case 0: {
256*33f37583SAndroid Build Coastguard Worker std::string_view name(long_options[option_index].name);
257*33f37583SAndroid Build Coastguard Worker if (name == "deapexer") {
258*33f37583SAndroid Build Coastguard Worker deapexer = optarg;
259*33f37583SAndroid Build Coastguard Worker }
260*33f37583SAndroid Build Coastguard Worker if (name == "debugfs") {
261*33f37583SAndroid Build Coastguard Worker debugfs = optarg;
262*33f37583SAndroid Build Coastguard Worker }
263*33f37583SAndroid Build Coastguard Worker if (name == "fsckerofs") {
264*33f37583SAndroid Build Coastguard Worker fsckerofs = optarg;
265*33f37583SAndroid Build Coastguard Worker }
266*33f37583SAndroid Build Coastguard Worker if (name == "sdk_version") {
267*33f37583SAndroid Build Coastguard Worker if (!base::ParseInt(optarg, &sdk_version)) {
268*33f37583SAndroid Build Coastguard Worker PrintUsage();
269*33f37583SAndroid Build Coastguard Worker return EXIT_FAILURE;
270*33f37583SAndroid Build Coastguard Worker }
271*33f37583SAndroid Build Coastguard Worker }
272*33f37583SAndroid Build Coastguard Worker if (name == "apex") {
273*33f37583SAndroid Build Coastguard Worker apex = optarg;
274*33f37583SAndroid Build Coastguard Worker }
275*33f37583SAndroid Build Coastguard Worker if (name == "partition_tag") {
276*33f37583SAndroid Build Coastguard Worker partition_tag = optarg;
277*33f37583SAndroid Build Coastguard Worker }
278*33f37583SAndroid Build Coastguard Worker for (const auto& p : partitions) {
279*33f37583SAndroid Build Coastguard Worker if (name == "out_" + p) {
280*33f37583SAndroid Build Coastguard Worker partition_map[p] = optarg;
281*33f37583SAndroid Build Coastguard Worker }
282*33f37583SAndroid Build Coastguard Worker }
283*33f37583SAndroid Build Coastguard Worker break;
284*33f37583SAndroid Build Coastguard Worker }
285*33f37583SAndroid Build Coastguard Worker case 'h':
286*33f37583SAndroid Build Coastguard Worker PrintUsage();
287*33f37583SAndroid Build Coastguard Worker return EXIT_SUCCESS;
288*33f37583SAndroid Build Coastguard Worker default:
289*33f37583SAndroid Build Coastguard Worker LOG(ERROR) << "getopt returned invalid result: " << arg;
290*33f37583SAndroid Build Coastguard Worker return EXIT_FAILURE;
291*33f37583SAndroid Build Coastguard Worker }
292*33f37583SAndroid Build Coastguard Worker }
293*33f37583SAndroid Build Coastguard Worker
294*33f37583SAndroid Build Coastguard Worker argc -= optind;
295*33f37583SAndroid Build Coastguard Worker argv += optind;
296*33f37583SAndroid Build Coastguard Worker
297*33f37583SAndroid Build Coastguard Worker if (argc != 0) {
298*33f37583SAndroid Build Coastguard Worker PrintUsage();
299*33f37583SAndroid Build Coastguard Worker return EXIT_FAILURE;
300*33f37583SAndroid Build Coastguard Worker }
301*33f37583SAndroid Build Coastguard Worker if (deapexer.empty() || debugfs.empty() || fsckerofs.empty()) {
302*33f37583SAndroid Build Coastguard Worker PrintUsage();
303*33f37583SAndroid Build Coastguard Worker return EXIT_FAILURE;
304*33f37583SAndroid Build Coastguard Worker }
305*33f37583SAndroid Build Coastguard Worker deapexer += " --debugfs_path " + debugfs;
306*33f37583SAndroid Build Coastguard Worker deapexer += " --fsckerofs_path " + fsckerofs;
307*33f37583SAndroid Build Coastguard Worker
308*33f37583SAndroid Build Coastguard Worker if (!!apex.empty() + !!partition_map.empty() != 1) {
309*33f37583SAndroid Build Coastguard Worker PrintUsage("use either --apex or --out_<partition>.\n");
310*33f37583SAndroid Build Coastguard Worker return EXIT_FAILURE;
311*33f37583SAndroid Build Coastguard Worker }
312*33f37583SAndroid Build Coastguard Worker if (!apex.empty()) {
313*33f37583SAndroid Build Coastguard Worker if (std::find(partitions.begin(), partitions.end(), partition_tag) ==
314*33f37583SAndroid Build Coastguard Worker partitions.end()) {
315*33f37583SAndroid Build Coastguard Worker PrintUsage(
316*33f37583SAndroid Build Coastguard Worker "--apex should come with "
317*33f37583SAndroid Build Coastguard Worker "--partition_tag=[system|system_ext|product|vendor|odm].\n");
318*33f37583SAndroid Build Coastguard Worker return EXIT_FAILURE;
319*33f37583SAndroid Build Coastguard Worker }
320*33f37583SAndroid Build Coastguard Worker }
321*33f37583SAndroid Build Coastguard Worker
322*33f37583SAndroid Build Coastguard Worker if (!partition_map.empty()) {
323*33f37583SAndroid Build Coastguard Worker for (const auto& [partition, dir] : partition_map) {
324*33f37583SAndroid Build Coastguard Worker ScanPartitionApexes(deapexer, sdk_version, dir, partition);
325*33f37583SAndroid Build Coastguard Worker }
326*33f37583SAndroid Build Coastguard Worker } else {
327*33f37583SAndroid Build Coastguard Worker ScanApex(deapexer, sdk_version, apex, partition_tag);
328*33f37583SAndroid Build Coastguard Worker }
329*33f37583SAndroid Build Coastguard Worker return EXIT_SUCCESS;
330*33f37583SAndroid Build Coastguard Worker }
331*33f37583SAndroid Build Coastguard Worker
332*33f37583SAndroid Build Coastguard Worker } // namespace apex
333*33f37583SAndroid Build Coastguard Worker } // namespace android
334*33f37583SAndroid Build Coastguard Worker
main(int argc,char ** argv)335*33f37583SAndroid Build Coastguard Worker int main(int argc, char** argv) { return android::apex::main(argc, argv); }
336