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