Loading cmds/idmap2/idmap2/Lookup.cpp +27 −28 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include "idmap2/CommandLineOptions.h" #include "idmap2/Idmap.h" #include "idmap2/Result.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" Loading @@ -53,39 +54,40 @@ using android::base::StringPrintf; using android::idmap2::CommandLineOptions; using android::idmap2::IdmapHeader; using android::idmap2::ResourceId; using android::idmap2::Result; using android::idmap2::Xml; using android::idmap2::ZipFile; using android::util::Utf16ToUtf8; namespace { std::pair<bool, ResourceId> WARN_UNUSED ParseResReference(const AssetManager2& am, const std::string& res, Result<ResourceId> WARN_UNUSED ParseResReference(const AssetManager2& am, const std::string& res, const std::string& fallback_package) { // first, try to parse as a hex number char* endptr = nullptr; ResourceId resid; resid = strtol(res.c_str(), &endptr, 16); if (*endptr == '\0') { return std::make_pair(true, resid); return {resid}; } // next, try to parse as a package:type/name string resid = am.GetResourceId(res, "", fallback_package); if (is_valid_resid(resid)) { return std::make_pair(true, resid); return {resid}; } // end of the road: res could not be parsed return std::make_pair(false, 0); return {}; } std::pair<bool, std::string> WARN_UNUSED GetValue(const AssetManager2& am, ResourceId resid) { Result<std::string> WARN_UNUSED GetValue(const AssetManager2& am, ResourceId resid) { Res_value value; ResTable_config config; uint32_t flags; ApkAssetsCookie cookie = am.GetResource(resid, false, 0, &value, &config, &flags); if (cookie == kInvalidCookie) { return std::make_pair(false, ""); return {}; } std::string out; Loading Loading @@ -123,31 +125,31 @@ std::pair<bool, std::string> WARN_UNUSED GetValue(const AssetManager2& am, Resou out.append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); break; } return std::make_pair(true, out); return {out}; } std::pair<bool, std::string> GetTargetPackageNameFromManifest(const std::string& apk_path) { Result<std::string> GetTargetPackageNameFromManifest(const std::string& apk_path) { const auto zip = ZipFile::Open(apk_path); if (!zip) { return std::make_pair(false, ""); return {}; } const auto entry = zip->Uncompress("AndroidManifest.xml"); if (!entry) { return std::make_pair(false, ""); return {}; } const auto xml = Xml::Create(entry->buf, entry->size); if (!xml) { return std::make_pair(false, ""); return {}; } const auto tag = xml->FindTag("overlay"); if (!tag) { return std::make_pair(false, ""); return {}; } const auto iter = tag->find("targetPackage"); if (iter == tag->end()) { return std::make_pair(false, ""); return {}; } return std::make_pair(true, iter->second); return {iter->second}; } } // namespace Loading Loading @@ -195,14 +197,14 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { } apk_assets.push_back(std::move(target_apk)); bool lookup_ok; std::tie(lookup_ok, target_package_name) = const Result<std::string> package_name = GetTargetPackageNameFromManifest(idmap_header->GetOverlayPath().to_string()); if (!lookup_ok) { if (!package_name) { out_error << "error: failed to parse android:targetPackage from overlay manifest" << std::endl; return false; } target_package_name = *package_name; } else if (target_path != idmap_header->GetTargetPath()) { out_error << "error: different target APKs (expected target APK " << target_path << " but " << idmap_path << " has target APK " << idmap_header->GetTargetPath() << ")" Loading @@ -227,21 +229,18 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { am.SetApkAssets(raw_pointer_apk_assets); am.SetConfiguration(config); ResourceId resid; bool lookup_ok; std::tie(lookup_ok, resid) = ParseResReference(am, resid_str, target_package_name); if (!lookup_ok) { const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name); if (!resid) { out_error << "error: failed to parse resource ID" << std::endl; return false; } std::string value; std::tie(lookup_ok, value) = GetValue(am, resid); if (!lookup_ok) { out_error << StringPrintf("error: resource 0x%08x not found", resid) << std::endl; const Result<std::string> value = GetValue(am, *resid); if (!value) { out_error << StringPrintf("error: resource 0x%08x not found", *resid) << std::endl; return false; } std::cout << value << std::endl; std::cout << *value << std::endl; return true; } cmds/idmap2/include/idmap2/ResourceUtils.h +2 −3 Original line number Diff line number Diff line Loading @@ -18,19 +18,18 @@ #define IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_ #include <string> #include <utility> #include "android-base/macros.h" #include "androidfw/AssetManager2.h" #include "idmap2/Idmap.h" #include "idmap2/Result.h" namespace android { namespace idmap2 { namespace utils { std::pair<bool, std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid); Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid); } // namespace utils } // namespace idmap2 Loading cmds/idmap2/include/idmap2/Result.h 0 → 100644 +31 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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. */ #ifndef IDMAP2_INCLUDE_IDMAP2_RESULT_H_ #define IDMAP2_INCLUDE_IDMAP2_RESULT_H_ #include <optional> namespace android::idmap2 { template <typename T> using Result = std::optional<T>; static constexpr std::nullopt_t kResultError = std::nullopt; } // namespace android::idmap2 #endif // IDMAP2_INCLUDE_IDMAP2_RESULT_H_ cmds/idmap2/include/idmap2/ZipFile.h +2 −2 Original line number Diff line number Diff line Loading @@ -19,10 +19,10 @@ #include <memory> #include <string> #include <utility> #include "android-base/macros.h" #include "ziparchive/zip_archive.h" #include "idmap2/Result.h" namespace android { namespace idmap2 { Loading @@ -43,7 +43,7 @@ class ZipFile { static std::unique_ptr<const ZipFile> Open(const std::string& path); std::unique_ptr<const MemoryChunk> Uncompress(const std::string& entryPath) const; std::pair<bool, uint32_t> Crc(const std::string& entryPath) const; Result<uint32_t> Crc(const std::string& entryPath) const; ~ZipFile(); Loading cmds/idmap2/libidmap2/Idmap.cpp +22 −22 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "idmap2/Idmap.h" #include "idmap2/ResourceUtils.h" #include "idmap2/Result.h" #include "idmap2/ZipFile.h" namespace android { Loading Loading @@ -143,18 +144,16 @@ bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { return false; } bool status; uint32_t target_crc; std::tie(status, target_crc) = target_zip->Crc("resources.arsc"); if (!status) { Result<uint32_t> target_crc = target_zip->Crc("resources.arsc"); if (!target_crc) { out_error << "error: failed to get target crc" << std::endl; return false; } if (target_crc_ != target_crc) { if (target_crc_ != *target_crc) { out_error << base::StringPrintf( "error: bad target crc: idmap version 0x%08x, file system version 0x%08x", target_crc_, target_crc) target_crc_, *target_crc) << std::endl; return false; } Loading @@ -165,17 +164,16 @@ bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { return false; } uint32_t overlay_crc; std::tie(status, overlay_crc) = overlay_zip->Crc("resources.arsc"); if (!status) { Result<uint32_t> overlay_crc = overlay_zip->Crc("resources.arsc"); if (!overlay_crc) { out_error << "error: failed to get overlay crc" << std::endl; return false; } if (overlay_crc_ != overlay_crc) { if (overlay_crc_ != *overlay_crc) { out_error << base::StringPrintf( "error: bad overlay crc: idmap version 0x%08x, file system version 0x%08x", overlay_crc_, overlay_crc) overlay_crc_, *overlay_crc) << std::endl; return false; } Loading Loading @@ -322,17 +320,20 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_ std::unique_ptr<IdmapHeader> header(new IdmapHeader()); header->magic_ = kIdmapMagic; header->version_ = kIdmapCurrentVersion; bool crc_status; std::tie(crc_status, header->target_crc_) = target_zip->Crc("resources.arsc"); if (!crc_status) { Result<uint32_t> crc = target_zip->Crc("resources.arsc"); if (!crc) { out_error << "error: failed to get zip crc for target" << std::endl; return nullptr; } std::tie(crc_status, header->overlay_crc_) = overlay_zip->Crc("resources.arsc"); if (!crc_status) { header->target_crc_ = *crc; crc = overlay_zip->Crc("resources.arsc"); if (!crc) { out_error << "error: failed to get zip crc for overlay" << std::endl; return nullptr; } header->overlay_crc_ = *crc; if (target_apk_path.size() > sizeof(header->target_path_)) { out_error << "error: target apk path \"" << target_apk_path << "\" longer that maximum size " Loading @@ -358,15 +359,14 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_ const auto end = overlay_pkg->end(); for (auto iter = overlay_pkg->begin(); iter != end; ++iter) { const ResourceId overlay_resid = *iter; bool lookup_ok; std::string name; std::tie(lookup_ok, name) = utils::ResToTypeEntryName(overlay_asset_manager, overlay_resid); if (!lookup_ok) { Result<std::string> name = utils::ResToTypeEntryName(overlay_asset_manager, overlay_resid); if (!name) { continue; } // prepend "<package>:" to turn name into "<package>:<type>/<name>" name = base::StringPrintf("%s:%s", target_pkg->GetPackageName().c_str(), name.c_str()); const ResourceId target_resid = NameToResid(target_asset_manager, name); const std::string full_name = base::StringPrintf("%s:%s", target_pkg->GetPackageName().c_str(), name->c_str()); const ResourceId target_resid = NameToResid(target_asset_manager, full_name); if (target_resid == 0) { continue; } Loading Loading
cmds/idmap2/idmap2/Lookup.cpp +27 −28 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ #include "idmap2/CommandLineOptions.h" #include "idmap2/Idmap.h" #include "idmap2/Result.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" Loading @@ -53,39 +54,40 @@ using android::base::StringPrintf; using android::idmap2::CommandLineOptions; using android::idmap2::IdmapHeader; using android::idmap2::ResourceId; using android::idmap2::Result; using android::idmap2::Xml; using android::idmap2::ZipFile; using android::util::Utf16ToUtf8; namespace { std::pair<bool, ResourceId> WARN_UNUSED ParseResReference(const AssetManager2& am, const std::string& res, Result<ResourceId> WARN_UNUSED ParseResReference(const AssetManager2& am, const std::string& res, const std::string& fallback_package) { // first, try to parse as a hex number char* endptr = nullptr; ResourceId resid; resid = strtol(res.c_str(), &endptr, 16); if (*endptr == '\0') { return std::make_pair(true, resid); return {resid}; } // next, try to parse as a package:type/name string resid = am.GetResourceId(res, "", fallback_package); if (is_valid_resid(resid)) { return std::make_pair(true, resid); return {resid}; } // end of the road: res could not be parsed return std::make_pair(false, 0); return {}; } std::pair<bool, std::string> WARN_UNUSED GetValue(const AssetManager2& am, ResourceId resid) { Result<std::string> WARN_UNUSED GetValue(const AssetManager2& am, ResourceId resid) { Res_value value; ResTable_config config; uint32_t flags; ApkAssetsCookie cookie = am.GetResource(resid, false, 0, &value, &config, &flags); if (cookie == kInvalidCookie) { return std::make_pair(false, ""); return {}; } std::string out; Loading Loading @@ -123,31 +125,31 @@ std::pair<bool, std::string> WARN_UNUSED GetValue(const AssetManager2& am, Resou out.append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); break; } return std::make_pair(true, out); return {out}; } std::pair<bool, std::string> GetTargetPackageNameFromManifest(const std::string& apk_path) { Result<std::string> GetTargetPackageNameFromManifest(const std::string& apk_path) { const auto zip = ZipFile::Open(apk_path); if (!zip) { return std::make_pair(false, ""); return {}; } const auto entry = zip->Uncompress("AndroidManifest.xml"); if (!entry) { return std::make_pair(false, ""); return {}; } const auto xml = Xml::Create(entry->buf, entry->size); if (!xml) { return std::make_pair(false, ""); return {}; } const auto tag = xml->FindTag("overlay"); if (!tag) { return std::make_pair(false, ""); return {}; } const auto iter = tag->find("targetPackage"); if (iter == tag->end()) { return std::make_pair(false, ""); return {}; } return std::make_pair(true, iter->second); return {iter->second}; } } // namespace Loading Loading @@ -195,14 +197,14 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { } apk_assets.push_back(std::move(target_apk)); bool lookup_ok; std::tie(lookup_ok, target_package_name) = const Result<std::string> package_name = GetTargetPackageNameFromManifest(idmap_header->GetOverlayPath().to_string()); if (!lookup_ok) { if (!package_name) { out_error << "error: failed to parse android:targetPackage from overlay manifest" << std::endl; return false; } target_package_name = *package_name; } else if (target_path != idmap_header->GetTargetPath()) { out_error << "error: different target APKs (expected target APK " << target_path << " but " << idmap_path << " has target APK " << idmap_header->GetTargetPath() << ")" Loading @@ -227,21 +229,18 @@ bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) { am.SetApkAssets(raw_pointer_apk_assets); am.SetConfiguration(config); ResourceId resid; bool lookup_ok; std::tie(lookup_ok, resid) = ParseResReference(am, resid_str, target_package_name); if (!lookup_ok) { const Result<ResourceId> resid = ParseResReference(am, resid_str, target_package_name); if (!resid) { out_error << "error: failed to parse resource ID" << std::endl; return false; } std::string value; std::tie(lookup_ok, value) = GetValue(am, resid); if (!lookup_ok) { out_error << StringPrintf("error: resource 0x%08x not found", resid) << std::endl; const Result<std::string> value = GetValue(am, *resid); if (!value) { out_error << StringPrintf("error: resource 0x%08x not found", *resid) << std::endl; return false; } std::cout << value << std::endl; std::cout << *value << std::endl; return true; }
cmds/idmap2/include/idmap2/ResourceUtils.h +2 −3 Original line number Diff line number Diff line Loading @@ -18,19 +18,18 @@ #define IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_ #include <string> #include <utility> #include "android-base/macros.h" #include "androidfw/AssetManager2.h" #include "idmap2/Idmap.h" #include "idmap2/Result.h" namespace android { namespace idmap2 { namespace utils { std::pair<bool, std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid); Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid); } // namespace utils } // namespace idmap2 Loading
cmds/idmap2/include/idmap2/Result.h 0 → 100644 +31 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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. */ #ifndef IDMAP2_INCLUDE_IDMAP2_RESULT_H_ #define IDMAP2_INCLUDE_IDMAP2_RESULT_H_ #include <optional> namespace android::idmap2 { template <typename T> using Result = std::optional<T>; static constexpr std::nullopt_t kResultError = std::nullopt; } // namespace android::idmap2 #endif // IDMAP2_INCLUDE_IDMAP2_RESULT_H_
cmds/idmap2/include/idmap2/ZipFile.h +2 −2 Original line number Diff line number Diff line Loading @@ -19,10 +19,10 @@ #include <memory> #include <string> #include <utility> #include "android-base/macros.h" #include "ziparchive/zip_archive.h" #include "idmap2/Result.h" namespace android { namespace idmap2 { Loading @@ -43,7 +43,7 @@ class ZipFile { static std::unique_ptr<const ZipFile> Open(const std::string& path); std::unique_ptr<const MemoryChunk> Uncompress(const std::string& entryPath) const; std::pair<bool, uint32_t> Crc(const std::string& entryPath) const; Result<uint32_t> Crc(const std::string& entryPath) const; ~ZipFile(); Loading
cmds/idmap2/libidmap2/Idmap.cpp +22 −22 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "idmap2/Idmap.h" #include "idmap2/ResourceUtils.h" #include "idmap2/Result.h" #include "idmap2/ZipFile.h" namespace android { Loading Loading @@ -143,18 +144,16 @@ bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { return false; } bool status; uint32_t target_crc; std::tie(status, target_crc) = target_zip->Crc("resources.arsc"); if (!status) { Result<uint32_t> target_crc = target_zip->Crc("resources.arsc"); if (!target_crc) { out_error << "error: failed to get target crc" << std::endl; return false; } if (target_crc_ != target_crc) { if (target_crc_ != *target_crc) { out_error << base::StringPrintf( "error: bad target crc: idmap version 0x%08x, file system version 0x%08x", target_crc_, target_crc) target_crc_, *target_crc) << std::endl; return false; } Loading @@ -165,17 +164,16 @@ bool IdmapHeader::IsUpToDate(std::ostream& out_error) const { return false; } uint32_t overlay_crc; std::tie(status, overlay_crc) = overlay_zip->Crc("resources.arsc"); if (!status) { Result<uint32_t> overlay_crc = overlay_zip->Crc("resources.arsc"); if (!overlay_crc) { out_error << "error: failed to get overlay crc" << std::endl; return false; } if (overlay_crc_ != overlay_crc) { if (overlay_crc_ != *overlay_crc) { out_error << base::StringPrintf( "error: bad overlay crc: idmap version 0x%08x, file system version 0x%08x", overlay_crc_, overlay_crc) overlay_crc_, *overlay_crc) << std::endl; return false; } Loading Loading @@ -322,17 +320,20 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_ std::unique_ptr<IdmapHeader> header(new IdmapHeader()); header->magic_ = kIdmapMagic; header->version_ = kIdmapCurrentVersion; bool crc_status; std::tie(crc_status, header->target_crc_) = target_zip->Crc("resources.arsc"); if (!crc_status) { Result<uint32_t> crc = target_zip->Crc("resources.arsc"); if (!crc) { out_error << "error: failed to get zip crc for target" << std::endl; return nullptr; } std::tie(crc_status, header->overlay_crc_) = overlay_zip->Crc("resources.arsc"); if (!crc_status) { header->target_crc_ = *crc; crc = overlay_zip->Crc("resources.arsc"); if (!crc) { out_error << "error: failed to get zip crc for overlay" << std::endl; return nullptr; } header->overlay_crc_ = *crc; if (target_apk_path.size() > sizeof(header->target_path_)) { out_error << "error: target apk path \"" << target_apk_path << "\" longer that maximum size " Loading @@ -358,15 +359,14 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_ const auto end = overlay_pkg->end(); for (auto iter = overlay_pkg->begin(); iter != end; ++iter) { const ResourceId overlay_resid = *iter; bool lookup_ok; std::string name; std::tie(lookup_ok, name) = utils::ResToTypeEntryName(overlay_asset_manager, overlay_resid); if (!lookup_ok) { Result<std::string> name = utils::ResToTypeEntryName(overlay_asset_manager, overlay_resid); if (!name) { continue; } // prepend "<package>:" to turn name into "<package>:<type>/<name>" name = base::StringPrintf("%s:%s", target_pkg->GetPackageName().c_str(), name.c_str()); const ResourceId target_resid = NameToResid(target_asset_manager, name); const std::string full_name = base::StringPrintf("%s:%s", target_pkg->GetPackageName().c_str(), name->c_str()); const ResourceId target_resid = NameToResid(target_asset_manager, full_name); if (target_resid == 0) { continue; } Loading