1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // Convert objects from and to strings.
18
19 #include "parse_string.h"
20
21 #include <android-base/parseint.h>
22 #include <android-base/strings.h>
23
24 #include "constants-private.h"
25
26 namespace android {
27 using base::ParseUint;
28
29 namespace vintf {
30
SplitString(const std::string & s,char c)31 std::vector<std::string> SplitString(const std::string &s, char c) {
32 std::vector<std::string> components;
33
34 size_t startPos = 0;
35 size_t matchPos;
36 while ((matchPos = s.find(c, startPos)) != std::string::npos) {
37 components.push_back(s.substr(startPos, matchPos - startPos));
38 startPos = matchPos + 1;
39 }
40
41 if (startPos <= s.length()) {
42 components.push_back(s.substr(startPos));
43 }
44 return components;
45 }
46
47 template <typename T>
operator <<(std::ostream & os,const std::vector<T> objs)48 std::ostream &operator<<(std::ostream &os, const std::vector<T> objs) {
49 bool first = true;
50 for (const T &v : objs) {
51 if (!first) {
52 os << ",";
53 }
54 os << v;
55 first = false;
56 }
57 return os;
58 }
59
60 template <typename T>
parse(const std::string & s,std::vector<T> * objs)61 bool parse(const std::string &s, std::vector<T> *objs) {
62 std::vector<std::string> v = SplitString(s, ',');
63 objs->resize(v.size());
64 size_t idx = 0;
65 for (const auto &item : v) {
66 T ver;
67 if (!parse(item, &ver)) {
68 return false;
69 }
70 objs->at(idx++) = ver;
71 }
72 return true;
73 }
74
75 template<typename E, typename Array>
parseEnum(const std::string & s,E * e,const Array & strings)76 bool parseEnum(const std::string &s, E *e, const Array &strings) {
77 for (size_t i = 0; i < strings.size(); ++i) {
78 if (s == strings.at(i)) {
79 *e = static_cast<E>(i);
80 return true;
81 }
82 }
83 return false;
84 }
85
86 #define DEFINE_PARSE_STREAMIN_FOR_ENUM(ENUM) \
87 bool parse(const std::string &s, ENUM *hf) { \
88 return parseEnum(s, hf, g##ENUM##Strings); \
89 } \
90 std::ostream &operator<<(std::ostream &os, ENUM hf) { \
91 return os << g##ENUM##Strings.at(static_cast<size_t>(hf)); \
92 } \
93
94 DEFINE_PARSE_STREAMIN_FOR_ENUM(HalFormat)
95 DEFINE_PARSE_STREAMIN_FOR_ENUM(Transport)
96 DEFINE_PARSE_STREAMIN_FOR_ENUM(Arch)
97 DEFINE_PARSE_STREAMIN_FOR_ENUM(KernelConfigType)
98 DEFINE_PARSE_STREAMIN_FOR_ENUM(Tristate)
99 DEFINE_PARSE_STREAMIN_FOR_ENUM(SchemaType)
100 DEFINE_PARSE_STREAMIN_FOR_ENUM(XmlSchemaFormat)
101 DEFINE_PARSE_STREAMIN_FOR_ENUM(ExclusiveTo)
102
103 std::ostream &operator<<(std::ostream &os, const KernelConfigTypedValue &kctv) {
104 switch (kctv.mType) {
105 case KernelConfigType::STRING:
106 return os << kctv.mStringValue;
107 case KernelConfigType::INTEGER:
108 return os << to_string(kctv.mIntegerValue);
109 case KernelConfigType::RANGE:
110 return os << to_string(kctv.mRangeValue.first) << "-"
111 << to_string(kctv.mRangeValue.second);
112 case KernelConfigType::TRISTATE:
113 return os << to_string(kctv.mTristateValue);
114 }
115 }
116
parse(const std::string & s,Level * l)117 bool parse(const std::string& s, Level* l) {
118 if (s.empty()) {
119 *l = Level::UNSPECIFIED;
120 return true;
121 }
122 if (s == "legacy") {
123 *l = Level::LEGACY;
124 return true;
125 }
126 size_t value;
127 if (!ParseUint(s, &value)) {
128 return false;
129 }
130 *l = static_cast<Level>(value);
131 if (!IsValid(*l)) {
132 return false;
133 }
134 return true;
135 }
136
operator <<(std::ostream & os,Level l)137 std::ostream& operator<<(std::ostream& os, Level l) {
138 if (l == Level::UNSPECIFIED) {
139 return os;
140 }
141 if (l == Level::LEGACY) {
142 return os << "legacy";
143 }
144 return os << static_cast<size_t>(l);
145 }
146
147 // Notice that strtoull is used even though KernelConfigIntValue is signed int64_t,
148 // because strtoull can accept negative values as well.
149 // Notice that according to man strtoul, strtoull can actually accept
150 // -2^64 + 1 to 2^64 - 1, with the 65th bit truncated.
151 // ParseInt / ParseUint are not used because they do not handle signed hex very well.
152 template <typename T>
parseKernelConfigIntHelper(const std::string & s,T * i)153 bool parseKernelConfigIntHelper(const std::string &s, T *i) {
154 char *end;
155 errno = 0;
156 unsigned long long int ulli = strtoull(s.c_str(), &end, 0 /* base */);
157 // It is implementation defined that what value will be returned by strtoull
158 // in the error case, so we are checking errno directly here.
159 if (errno == 0 && s.c_str() != end && *end == '\0') {
160 *i = static_cast<T>(ulli);
161 return true;
162 }
163 return false;
164 }
165
parseKernelConfigInt(const std::string & s,int64_t * i)166 bool parseKernelConfigInt(const std::string &s, int64_t *i) {
167 return parseKernelConfigIntHelper(s, i);
168 }
169
parseKernelConfigInt(const std::string & s,uint64_t * i)170 bool parseKernelConfigInt(const std::string &s, uint64_t *i) {
171 return parseKernelConfigIntHelper(s, i);
172 }
173
parseRange(const std::string & s,KernelConfigRangeValue * range)174 bool parseRange(const std::string &s, KernelConfigRangeValue *range) {
175 auto pos = s.find('-');
176 if (pos == std::string::npos) {
177 return false;
178 }
179 return parseKernelConfigInt(s.substr(0, pos), &range->first)
180 && parseKernelConfigInt(s.substr(pos + 1), &range->second);
181 }
182
parse(const std::string & s,KernelConfigKey * key)183 bool parse(const std::string &s, KernelConfigKey *key) {
184 *key = s;
185 return true;
186 }
187
parseKernelConfigValue(const std::string & s,KernelConfigTypedValue * kctv)188 bool parseKernelConfigValue(const std::string &s, KernelConfigTypedValue *kctv) {
189 switch (kctv->mType) {
190 case KernelConfigType::STRING:
191 kctv->mStringValue = s;
192 return true;
193 case KernelConfigType::INTEGER:
194 return parseKernelConfigInt(s, &kctv->mIntegerValue);
195 case KernelConfigType::RANGE:
196 return parseRange(s, &kctv->mRangeValue);
197 case KernelConfigType::TRISTATE:
198 return parse(s, &kctv->mTristateValue);
199 }
200 }
201
parseKernelConfigTypedValue(const std::string & s,KernelConfigTypedValue * kctv)202 bool parseKernelConfigTypedValue(const std::string& s, KernelConfigTypedValue* kctv) {
203 if (s.size() > 1 && s[0] == '"' && s.back() == '"') {
204 kctv->mType = KernelConfigType::STRING;
205 kctv->mStringValue = s.substr(1, s.size()-2);
206 return true;
207 }
208 if (parseKernelConfigInt(s, &kctv->mIntegerValue)) {
209 kctv->mType = KernelConfigType::INTEGER;
210 return true;
211 }
212 if (parse(s, &kctv->mTristateValue)) {
213 kctv->mType = KernelConfigType::TRISTATE;
214 return true;
215 }
216 // Do not test for KernelConfigType::RANGE.
217 return false;
218 }
219
parse(const std::string & s,Version * ver)220 bool parse(const std::string &s, Version *ver) {
221 std::vector<std::string> v = SplitString(s, '.');
222 if (v.size() != 2) {
223 return false;
224 }
225 size_t major, minor;
226 if (!ParseUint(v[0], &major)) {
227 return false;
228 }
229 if (!ParseUint(v[1], &minor)) {
230 return false;
231 }
232 *ver = Version(major, minor);
233 return true;
234 }
235
parse(const std::string & s,SepolicyVersion * sepolicyVer)236 bool parse(const std::string& s, SepolicyVersion* sepolicyVer) {
237 size_t major;
238 // vFRC versioning
239 if (ParseUint(s, &major)) {
240 *sepolicyVer = SepolicyVersion(major, std::nullopt);
241 return true;
242 }
243 // fall back to normal Version
244 Version ver;
245 if (!parse(s, &ver)) return false;
246 *sepolicyVer = SepolicyVersion(ver.majorVer, ver.minorVer);
247 return true;
248 }
249
operator <<(std::ostream & os,const Version & ver)250 std::ostream &operator<<(std::ostream &os, const Version &ver) {
251 return os << ver.majorVer << "." << ver.minorVer;
252 }
253
operator <<(std::ostream & os,const SepolicyVersion & ver)254 std::ostream& operator<<(std::ostream& os, const SepolicyVersion& ver) {
255 os << ver.majorVer;
256 if (ver.minorVer.has_value()) os << "." << ver.minorVer.value();
257 return os;
258 }
259
260 // Helper for parsing a VersionRange object. versionParser defines how the first half
261 // (before the '-' character) of the string is parsed.
parseVersionRange(const std::string & s,VersionRange * vr,const std::function<bool (const std::string &,Version *)> & versionParser)262 static bool parseVersionRange(
263 const std::string& s, VersionRange* vr,
264 const std::function<bool(const std::string&, Version*)>& versionParser) {
265 std::vector<std::string> v = SplitString(s, '-');
266 if (v.size() != 1 && v.size() != 2) {
267 return false;
268 }
269 Version minVer;
270 if (!versionParser(v[0], &minVer)) {
271 return false;
272 }
273 if (v.size() == 1) {
274 *vr = VersionRange(minVer.majorVer, minVer.minorVer);
275 } else {
276 size_t maxMinor;
277 if (!ParseUint(v[1], &maxMinor)) {
278 return false;
279 }
280 *vr = VersionRange(minVer.majorVer, minVer.minorVer, maxMinor);
281 }
282 return true;
283 }
284
parse(const std::string & s,VersionRange * vr)285 bool parse(const std::string& s, VersionRange* vr) {
286 bool (*versionParser)(const std::string&, Version*) = parse;
287 return parseVersionRange(s, vr, versionParser);
288 }
289
290 // TODO(b/314010177): Add unit tests for this function.
parse(const std::string & s,SepolicyVersionRange * svr)291 bool parse(const std::string& s, SepolicyVersionRange* svr) {
292 SepolicyVersion sepolicyVersion;
293 if (parse(s, &sepolicyVersion)) {
294 *svr = SepolicyVersionRange(sepolicyVersion.majorVer, sepolicyVersion.minorVer);
295 return true;
296 }
297 // fall back to normal VersionRange
298 VersionRange vr;
299 if (parse(s, &vr)) {
300 *svr = SepolicyVersionRange(vr.majorVer, vr.minMinor, vr.maxMinor);
301 return true;
302 }
303 return false;
304 }
305
operator <<(std::ostream & os,const VersionRange & vr)306 std::ostream &operator<<(std::ostream &os, const VersionRange &vr) {
307 if (vr.isSingleVersion()) {
308 return os << vr.minVer();
309 }
310 return os << vr.minVer() << "-" << vr.maxMinor;
311 }
312
operator <<(std::ostream & os,const SepolicyVersionRange & svr)313 std::ostream& operator<<(std::ostream& os, const SepolicyVersionRange& svr) {
314 if (svr.maxMinor.has_value()) {
315 return os << VersionRange(svr.majorVer, svr.minMinor.value_or(0), svr.maxMinor.value());
316 }
317
318 return os << SepolicyVersion(svr.majorVer, svr.minMinor);
319 }
320
321 #pragma clang diagnostic push
322 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
parse(const std::string & s,VndkVersionRange * vr)323 bool parse(const std::string &s, VndkVersionRange *vr) {
324 std::vector<std::string> v = SplitString(s, '-');
325 if (v.size() != 1 && v.size() != 2) {
326 return false;
327 }
328 std::vector<std::string> minVector = SplitString(v[0], '.');
329 if (minVector.size() != 3) {
330 return false;
331 }
332 if (!ParseUint(minVector[0], &vr->sdk) ||
333 !ParseUint(minVector[1], &vr->vndk) ||
334 !ParseUint(minVector[2], &vr->patchMin)) {
335 return false;
336 }
337 if (v.size() == 1) {
338 vr->patchMax = vr->patchMin;
339 return true;
340 } else {
341 return ParseUint(v[1], &vr->patchMax);
342 }
343 }
344
operator <<(std::ostream & os,const VndkVersionRange & vr)345 std::ostream &operator<<(std::ostream &os, const VndkVersionRange &vr) {
346 os << vr.sdk << "." << vr.vndk << "." << vr.patchMin;
347 if (!vr.isSingleVersion()) {
348 os << "-" << vr.patchMax;
349 }
350 return os;
351 }
352 #pragma clang diagnostic pop
353
parse(const std::string & s,KernelVersion * kernelVersion)354 bool parse(const std::string &s, KernelVersion *kernelVersion) {
355 std::vector<std::string> v = SplitString(s, '.');
356 if (v.size() != 3) {
357 return false;
358 }
359 size_t version, major, minor;
360 if (!ParseUint(v[0], &version)) {
361 return false;
362 }
363 if (!ParseUint(v[1], &major)) {
364 return false;
365 }
366 if (!ParseUint(v[2], &minor)) {
367 return false;
368 }
369 *kernelVersion = KernelVersion(version, major, minor);
370 return true;
371 }
372
operator <<(std::ostream & os,const TransportArch & ta)373 std::ostream &operator<<(std::ostream &os, const TransportArch &ta) {
374 return os << to_string(ta.transport) << to_string(ta.arch);
375 }
376
operator <<(std::ostream & os,const KernelVersion & ver)377 std::ostream &operator<<(std::ostream &os, const KernelVersion &ver) {
378 return os << ver.version << "." << ver.majorRev << "." << ver.minorRev;
379 }
380
operator <<(std::ostream & os,const ManifestHal & hal)381 std::ostream &operator<<(std::ostream &os, const ManifestHal &hal) {
382 return os << hal.format << "/"
383 << hal.name << "/"
384 << hal.transportArch << "/"
385 << hal.versions;
386 }
387
expandInstances(const MatrixHal & req,const VersionRange & vr,bool brace)388 std::string expandInstances(const MatrixHal& req, const VersionRange& vr, bool brace) {
389 std::string s;
390 size_t count = 0;
391 req.forEachInstance(vr, [&](const auto& matrixInstance) {
392 if (count > 0) s += " AND ";
393 auto instance = matrixInstance.isRegex() ? matrixInstance.regexPattern()
394 : matrixInstance.exactInstance();
395 switch (req.format) {
396 case HalFormat::AIDL: {
397 s += toFQNameString(matrixInstance.interface(), instance) + " (@" +
398 aidlVersionRangeToString(vr) + ")";
399 } break;
400 case HalFormat::HIDL:
401 [[fallthrough]];
402 case HalFormat::NATIVE: {
403 s += toFQNameString(vr, matrixInstance.interface(), instance);
404 } break;
405 }
406 count++;
407 return true;
408 });
409 if (count == 0) {
410 s += "@" + to_string(vr);
411 }
412 if (count >= 2 && brace) {
413 s = "(" + s + ")";
414 }
415 return s;
416 }
417
expandInstances(const MatrixHal & req)418 std::vector<std::string> expandInstances(const MatrixHal& req) {
419 size_t count = req.instancesCount();
420 if (count == 0) {
421 return {};
422 }
423 if (count == 1) {
424 return {expandInstances(req, req.versionRanges.front(), false /* brace */)};
425 }
426 std::vector<std::string> ss;
427 for (const auto& vr : req.versionRanges) {
428 if (!ss.empty()) {
429 ss.back() += " OR";
430 }
431 ss.push_back(expandInstances(req, vr, true /* brace */));
432 }
433 return ss;
434 }
435
operator <<(std::ostream & os,KernelSepolicyVersion ksv)436 std::ostream &operator<<(std::ostream &os, KernelSepolicyVersion ksv){
437 return os << ksv.value;
438 }
439
parse(const std::string & s,KernelSepolicyVersion * ksv)440 bool parse(const std::string &s, KernelSepolicyVersion *ksv){
441 return ParseUint(s, &ksv->value);
442 }
443
dump(const HalManifest & vm)444 std::string dump(const HalManifest &vm) {
445 std::ostringstream oss;
446 bool first = true;
447 for (const auto &hal : vm.getHals()) {
448 if (!first) {
449 oss << ":";
450 }
451 oss << hal;
452 first = false;
453 }
454 return oss.str();
455 }
456
dump(const RuntimeInfo & ki,bool verbose)457 std::string dump(const RuntimeInfo& ki, bool verbose) {
458 std::ostringstream oss;
459
460 oss << "kernel = " << ki.osName() << "/" << ki.nodeName() << "/" << ki.osRelease() << "/"
461 << ki.osVersion() << "/" << ki.hardwareId() << ";" << ki.mBootAvbVersion << "/"
462 << ki.mBootVbmetaAvbVersion << ";"
463 << "kernelSepolicyVersion = " << ki.kernelSepolicyVersion() << ";";
464
465 if (verbose) {
466 oss << "\n\ncpu info:\n" << ki.cpuInfo();
467 }
468
469 oss << "\n#CONFIG's loaded = " << ki.kernelConfigs().size() << ";\n";
470
471 if (verbose) {
472 for (const auto& pair : ki.kernelConfigs()) {
473 oss << pair.first << "=" << pair.second << "\n";
474 }
475 }
476
477 return oss.str();
478 }
479
toFQNameString(const std::string & package,const std::string & version,const std::string & interface,const std::string & instance)480 std::string toFQNameString(const std::string& package, const std::string& version,
481 const std::string& interface, const std::string& instance) {
482 std::stringstream ss;
483 ss << package << "@" << version;
484 if (!interface.empty()) {
485 ss << "::" << interface;
486 }
487 if (!instance.empty()) {
488 ss << "/" << instance;
489 }
490 return ss.str();
491 }
492
toFQNameString(const std::string & package,const Version & version,const std::string & interface,const std::string & instance)493 std::string toFQNameString(const std::string& package, const Version& version,
494 const std::string& interface, const std::string& instance) {
495 return toFQNameString(package, to_string(version), interface, instance);
496 }
497
toFQNameString(const Version & version,const std::string & interface,const std::string & instance)498 std::string toFQNameString(const Version& version, const std::string& interface,
499 const std::string& instance) {
500 return toFQNameString("", version, interface, instance);
501 }
502
503 // [email protected]::IFoo/default.
504 // Note that the format is extended to support a range of versions.
toFQNameString(const std::string & package,const VersionRange & range,const std::string & interface,const std::string & instance)505 std::string toFQNameString(const std::string& package, const VersionRange& range,
506 const std::string& interface, const std::string& instance) {
507 return toFQNameString(package, to_string(range), interface, instance);
508 }
509
toFQNameString(const VersionRange & range,const std::string & interface,const std::string & instance)510 std::string toFQNameString(const VersionRange& range, const std::string& interface,
511 const std::string& instance) {
512 return toFQNameString("", range, interface, instance);
513 }
514
toFQNameString(const std::string & interface,const std::string & instance)515 std::string toFQNameString(const std::string& interface, const std::string& instance) {
516 return interface + "/" + instance;
517 }
518
operator <<(std::ostream & os,const FqInstance & fqInstance)519 std::ostream& operator<<(std::ostream& os, const FqInstance& fqInstance) {
520 return os << fqInstance.string();
521 }
522
parse(const std::string & s,FqInstance * fqInstance)523 bool parse(const std::string& s, FqInstance* fqInstance) {
524 return fqInstance->setTo(s);
525 }
526
toAidlFqnameString(const std::string & package,const std::string & interface,const std::string & instance)527 std::string toAidlFqnameString(const std::string& package, const std::string& interface,
528 const std::string& instance) {
529 std::stringstream ss;
530 ss << package << "." << interface;
531 if (!instance.empty()) {
532 ss << "/" << instance;
533 }
534 return ss.str();
535 }
536
aidlVersionToString(const Version & v)537 std::string aidlVersionToString(const Version& v) {
538 return to_string(v.minorVer);
539 }
parseAidlVersion(const std::string & s,Version * version)540 bool parseAidlVersion(const std::string& s, Version* version) {
541 version->majorVer = details::kFakeAidlMajorVersion;
542 return android::base::ParseUint(s, &version->minorVer);
543 }
544
aidlVersionRangeToString(const VersionRange & vr)545 std::string aidlVersionRangeToString(const VersionRange& vr) {
546 if (vr.isSingleVersion()) {
547 return to_string(vr.minMinor);
548 }
549 return to_string(vr.minMinor) + "-" + to_string(vr.maxMinor);
550 }
551
parseAidlVersionRange(const std::string & s,VersionRange * vr)552 bool parseAidlVersionRange(const std::string& s, VersionRange* vr) {
553 return parseVersionRange(s, vr, parseAidlVersion);
554 }
555
parseApexName(std::string_view path)556 std::string_view parseApexName(std::string_view path) {
557 if (base::ConsumePrefix(&path, "/apex/")) {
558 return path.substr(0, path.find('/'));
559 }
560 return {};
561 }
562
563 } // namespace vintf
564 } // namespace android
565